fix(ext): handle stopped lifecycle state

This commit is contained in:
Simon
2026-06-11 19:53:30 +08:00
parent e270ba15b5
commit edb769b826
4 changed files with 21 additions and 15 deletions

View File

@@ -131,7 +131,7 @@ export type Execute = (task: string, config: ExecuteConfig) => Promise<Execution
`AgentStatus` `AgentStatus`
```typescript ```typescript
type AgentStatus = 'idle' | 'running' | 'completed' | 'error' type AgentStatus = 'idle' | 'running' | 'completed' | 'error' | 'stopped'
``` ```
`AgentActivity` `AgentActivity`

View File

@@ -39,6 +39,18 @@ export class MultiPageAgent extends PageAgentCore {
const includeInitialTab = config.includeInitialTab ?? true const includeInitialTab = config.includeInitialTab ?? true
const experimentalIncludeAllTabs = config.experimentalIncludeAllTabs ?? false const experimentalIncludeAllTabs = config.experimentalIncludeAllTabs ?? false
/**
* Project agent status into chrome.storage. The content script polls
* `isAgentRunning` + `agentHeartbeat` (eventually consistent by design).
*
* 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: number | null = null
super({ super({
...config, ...config,
pageController: pageController as any, pageController: pageController as any,
@@ -56,22 +68,16 @@ export class MultiPageAgent extends PageAgentCore {
}, },
onDispose: () => { onDispose: () => {
if (heartBeatInterval) {
clearInterval(heartBeatInterval)
heartBeatInterval = null
}
chrome.storage.local.set({ isAgentRunning: false }).catch(console.error)
tabsController.dispose() tabsController.dispose()
}, },
}) })
/**
* Project agent status into chrome.storage. The content script polls
* `isAgentRunning` + `agentHeartbeat` (eventually consistent by design).
*
* 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: number | null = null
this.addEventListener('statuschange', () => { this.addEventListener('statuschange', () => {
const running = this.status === 'running' const running = this.status === 'running'

View File

@@ -39,7 +39,7 @@ export default function App() {
if ( if (
prev === 'running' && prev === 'running' &&
(status === 'completed' || status === 'error') && (status === 'completed' || status === 'error' || status === 'stopped') &&
history.length > 0 && history.length > 0 &&
currentTask currentTask
) { ) {

View File

@@ -8,7 +8,7 @@ export interface SessionRecord {
id: string id: string
task: string task: string
history: HistoricalEvent[] history: HistoricalEvent[]
status: 'completed' | 'error' status: 'completed' | 'error' | 'stopped'
createdAt: number createdAt: number
} }