From 2ec25cb32a3b8646f63b3d91aff5860731189733 Mon Sep 17 00:00:00 2001 From: yushen Date: Thu, 5 Feb 2026 14:12:53 +0800 Subject: [PATCH] fix(session): flush session writes before subagent result delivery The subagent announce flow reads the child's session file to extract results, but saveMessage() is fire-and-forget (void enqueue). When agent.run() completes, pending appendEntry writes may not have flushed to disk yet, causing readLatestAssistantReply() to find no entries. Add SessionManager.flush() and call it in AsyncAgent.write() after agent.run() returns. This ensures waitForIdle() won't resolve until all session data is on disk, fixing the "no return content" issue. Co-Authored-By: Claude Opus 4.5 --- src/agent/async-agent.ts | 3 +++ src/agent/runner.ts | 7 +++++++ src/agent/session/session-manager.ts | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/src/agent/async-agent.ts b/src/agent/async-agent.ts index 4fdfb616..ebc06317 100644 --- a/src/agent/async-agent.ts +++ b/src/agent/async-agent.ts @@ -42,6 +42,9 @@ export class AsyncAgent { .then(async () => { if (this._closed) return; const result = await this.agent.run(content); + // Flush pending session writes so waitForIdle() callers + // can safely read session data from disk. + await this.agent.flushSession(); // Normal text is delivered via message_end event; only handle errors here if (result.error) { this.channel.send({ id: uuidv7(), content: `[error] ${result.error}` }); diff --git a/src/agent/runner.ts b/src/agent/runner.ts index 98f233d9..00c0e3b2 100644 --- a/src/agent/runner.ts +++ b/src/agent/runner.ts @@ -455,6 +455,13 @@ export class Agent { } } + /** + * Wait for all pending session storage writes to complete. + */ + async flushSession(): Promise { + await this.session.flush(); + } + /** * Reload tools from profile config. * Call this after updating tool status to apply changes diff --git a/src/agent/session/session-manager.ts b/src/agent/session/session-manager.ts index ec1c7cd6..9ff19614 100644 --- a/src/agent/session/session-manager.ts +++ b/src/agent/session/session-manager.ts @@ -272,6 +272,13 @@ export class SessionManager { return result; } + /** + * Wait for all pending storage writes to complete. + */ + async flush(): Promise { + await this.queue; + } + private enqueue(task: () => Promise) { this.queue = this.queue.then(task, task).catch(() => { // Swallow storage errors to prevent unhandled rejections.