75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
import { type PageAgentConfig, PageAgentCore } from '@page-agent/core'
|
|
|
|
import { RemotePageController } from './RemotePageController'
|
|
import { TabsController } from './TabsController'
|
|
import SYSTEM_PROMPT from './system_prompt.md?raw'
|
|
import { createTabTools } from './tabTools'
|
|
|
|
/**
|
|
* MultiPageAgent
|
|
* - use with extension
|
|
* - can be used from a side panel or a content script
|
|
*/
|
|
export class MultiPageAgent extends PageAgentCore {
|
|
constructor(config: Omit<PageAgentConfig, 'pageController'>) {
|
|
const tabsController = new TabsController()
|
|
const pageController = new RemotePageController(tabsController)
|
|
const customTools = createTabTools(tabsController)
|
|
|
|
/**
|
|
* When the agent is in side-panel and user closed the side-panel.
|
|
* There is no chance for isAgentRunning to be set false.
|
|
* (unload event doesn't work well in side panel.)
|
|
* (I'm trying not to use long-lived connection because the lifecycle of a sw is hard to predict.)
|
|
* This heartbeat mechanism acts as a backup.
|
|
*/
|
|
let heartBeatInterval: null | number = null
|
|
|
|
super({
|
|
...config,
|
|
pageController: pageController as any,
|
|
customTools: customTools,
|
|
customSystemPrompt: SYSTEM_PROMPT,
|
|
|
|
onBeforeTask: async (agent) => {
|
|
await tabsController.init(agent.task)
|
|
|
|
heartBeatInterval = window.setInterval(() => {
|
|
chrome.storage.local.set({
|
|
agentHeartbeat: Date.now(),
|
|
})
|
|
}, 1_000)
|
|
|
|
await chrome.storage.local.set({
|
|
isAgentRunning: true,
|
|
})
|
|
},
|
|
|
|
onAfterTask: async () => {
|
|
if (heartBeatInterval) {
|
|
window.clearInterval(heartBeatInterval)
|
|
heartBeatInterval = null
|
|
}
|
|
|
|
await chrome.storage.local.set({
|
|
isAgentRunning: false,
|
|
})
|
|
},
|
|
|
|
onDispose: () => {
|
|
if (heartBeatInterval) {
|
|
window.clearInterval(heartBeatInterval)
|
|
heartBeatInterval = null
|
|
}
|
|
|
|
chrome.storage.local.set({
|
|
isAgentRunning: false,
|
|
})
|
|
|
|
// no need to dispose tabsController and pageController
|
|
// as they do not keep references
|
|
},
|
|
})
|
|
}
|
|
}
|