From 0ed7ea698a24c1fcc40a45dc1d835fbe17417e4b Mon Sep 17 00:00:00 2001 From: user Date: Sun, 11 Jan 2026 06:17:15 +0000 Subject: [PATCH] fix(subagent): wait for completion before announce The previous immediate probe (timeoutMs: 0) only caught already-completed runs. Cross-process spawns need to actually wait via agent.wait RPC for the gateway to signal completion, then trigger the announce flow. - Rename probeImmediateCompletion to waitForSubagentCompletion - Use 10 minute wait timeout for agent.wait RPC - Remove leftover debug console.log statements --- src/agents/subagent-registry.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/agents/subagent-registry.ts b/src/agents/subagent-registry.ts index 3f9a9a5c3..14dca3f03 100644 --- a/src/agents/subagent-registry.ts +++ b/src/agents/subagent-registry.ts @@ -68,7 +68,9 @@ function ensureListener() { onAgentEvent((evt) => { if (!evt || evt.stream !== "lifecycle") return; const entry = subagentRuns.get(evt.runId); - if (!entry) return; + if (!entry) { + return; + } const phase = evt.data?.phase; if (phase === "start") { const startedAt = @@ -148,18 +150,23 @@ export function registerSubagentRun(params: { }); ensureListener(); if (archiveAfterMs) startSweeper(); - void probeImmediateCompletion(params.runId); + // Wait for subagent completion via gateway RPC (cross-process). + // The in-process lifecycle listener is a fallback for embedded runs. + void waitForSubagentCompletion(params.runId); } -async function probeImmediateCompletion(runId: string) { +// Default wait timeout: 10 minutes. This covers most subagent runs. +const DEFAULT_SUBAGENT_WAIT_TIMEOUT_MS = 10 * 60 * 1000; + +async function waitForSubagentCompletion(runId: string) { try { const wait = (await callGateway({ method: "agent.wait", params: { runId, - timeoutMs: 0, + timeoutMs: DEFAULT_SUBAGENT_WAIT_TIMEOUT_MS, }, - timeoutMs: 2000, + timeoutMs: DEFAULT_SUBAGENT_WAIT_TIMEOUT_MS + 10_000, })) as { status?: string; startedAt?: number; endedAt?: number }; if (wait?.status !== "ok" && wait?.status !== "error") return; const entry = subagentRuns.get(runId);