fix(agents): add waitForIdle to all flushPendingToolResults call sites
The original fix only covered the main run finally block, but there are two additional call sites that can trigger flushPendingToolResults while tools are still executing: 1. The catch block in attempt.ts (session setup error handler) 2. The finally block in compact.ts (compaction teardown) Both now await agent.waitForIdle() with a 30s timeout before flushing, matching the pattern already applied to the main finally block. Production testing on VPS with debug logging confirmed these additional paths can fire during sub-agent runs, producing spurious synthetic 'missing tool result' errors.
This commit is contained in:
@@ -464,6 +464,18 @@ export async function compactEmbeddedPiSessionDirect(
|
||||
},
|
||||
};
|
||||
} finally {
|
||||
// Wait for agent idle before flushing to prevent inserting synthetic
|
||||
// "missing tool result" errors while tools are still executing.
|
||||
if (session?.agent?.waitForIdle) {
|
||||
try {
|
||||
await Promise.race([
|
||||
session.agent.waitForIdle(),
|
||||
new Promise<void>((resolve) => setTimeout(resolve, 30_000)),
|
||||
]);
|
||||
} catch {
|
||||
/* best-effort */
|
||||
}
|
||||
}
|
||||
sessionManager.flushPendingToolResults?.();
|
||||
session.dispose();
|
||||
}
|
||||
|
||||
@@ -565,6 +565,18 @@ export async function runEmbeddedAttempt(
|
||||
activeSession.agent.replaceMessages(limited);
|
||||
}
|
||||
} catch (err) {
|
||||
// Wait for agent idle before flushing to avoid the same race condition
|
||||
// as the main finally block (see comment below).
|
||||
if (activeSession?.agent?.waitForIdle) {
|
||||
try {
|
||||
await Promise.race([
|
||||
activeSession.agent.waitForIdle(),
|
||||
new Promise<void>((resolve) => setTimeout(resolve, 30_000)),
|
||||
]);
|
||||
} catch {
|
||||
/* best-effort */
|
||||
}
|
||||
}
|
||||
sessionManager.flushPendingToolResults?.();
|
||||
activeSession.dispose();
|
||||
throw err;
|
||||
|
||||
Reference in New Issue
Block a user