From ea46ba6c608cd260455c8cb9ef6230c511f9811e Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 11 Dec 2025 17:42:33 +0900 Subject: [PATCH] fix(background-agent): use session.idle event for completion detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove broken session.updated handler (Session has no status field) - Add session.idle event handler for proper completion detection - Remove all file persistence (persist/restore methods) - Add comprehensive logging for debugging - Dual detection: event-based (session.idle) + polling (session.status API) 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) --- src/features/background-agent/manager.ts | 44 ++++++++++-------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/features/background-agent/manager.ts b/src/features/background-agent/manager.ts index 73c7877..669882e 100644 --- a/src/features/background-agent/manager.ts +++ b/src/features/background-agent/manager.ts @@ -7,12 +7,6 @@ import { log } from "../../shared/logger" type OpencodeClient = PluginInput["client"] -interface SessionInfo { - id?: string - parentID?: string - status?: string -} - interface MessagePartInfo { sessionID?: string type?: string @@ -20,8 +14,8 @@ interface MessagePartInfo { } interface EventProperties { - info?: SessionInfo sessionID?: string + info?: { id?: string } [key: string]: unknown } @@ -74,6 +68,8 @@ export class BackgroundManager { this.tasks.set(task.id, task) this.startPolling() + log("[background-agent] Launching task:", { taskId: task.id, sessionID }) + this.client.session.promptAsync({ path: { id: sessionID }, body: { @@ -141,24 +137,22 @@ export class BackgroundManager { } } - if (event.type === "session.updated") { - const info = props?.info as SessionInfo | undefined - if (!info || typeof info.id !== "string") return - const sessionID = info.id - const status = info?.status + if (event.type === "session.idle") { + const sessionID = props?.sessionID as string | undefined + if (!sessionID) return const task = this.findBySession(sessionID) - if (!task) return + if (!task || task.status !== "running") return - if (status === "idle" && task.status === "running") { - task.status = "completed" - task.completedAt = new Date() - this.markForNotification(task) - } + task.status = "completed" + task.completedAt = new Date() + this.markForNotification(task) + this.notifyParentSession(task) + log("[background-agent] Task completed via session.idle event:", task.id) } if (event.type === "session.deleted") { - const info = props?.info as SessionInfo | undefined + const info = props?.info if (!info || typeof info.id !== "string") return const sessionID = info.id @@ -168,7 +162,7 @@ export class BackgroundManager { if (task.status === "running") { task.status = "cancelled" task.completedAt = new Date() - task.error = "Session deleted (cascade delete from parent)" + task.error = "Session deleted" } this.tasks.delete(task.id) @@ -275,9 +269,7 @@ Use \`background_result\` tool with taskId="${task.id}" to retrieve the full res const sessionStatus = allStatuses[task.sessionID] if (!sessionStatus) { - task.status = "error" - task.error = "Session not found" - task.completedAt = new Date() + log("[background-agent] Session not found in status:", task.sessionID) continue } @@ -286,7 +278,7 @@ Use \`background_result\` tool with taskId="${task.id}" to retrieve the full res task.completedAt = new Date() this.markForNotification(task) this.notifyParentSession(task) - log("[background-agent] Task completed, notifying parent:", task.id) + log("[background-agent] Task completed via polling:", task.id) continue } @@ -323,8 +315,8 @@ Use \`background_result\` tool with taskId="${task.id}" to retrieve the full res task.progress.lastTool = lastTool task.progress.lastUpdate = new Date() } - } catch { - void 0 + } catch (error) { + log("[background-agent] Poll error for task:", { taskId: task.id, error }) } }