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 <noreply@anthropic.com>
This commit is contained in:
yushen 2026-02-05 14:12:53 +08:00
parent 3039e3b34c
commit 2ec25cb32a
3 changed files with 17 additions and 0 deletions

View file

@ -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}` });

View file

@ -455,6 +455,13 @@ export class Agent {
}
}
/**
* Wait for all pending session storage writes to complete.
*/
async flushSession(): Promise<void> {
await this.session.flush();
}
/**
* Reload tools from profile config.
* Call this after updating tool status to apply changes

View file

@ -272,6 +272,13 @@ export class SessionManager {
return result;
}
/**
* Wait for all pending storage writes to complete.
*/
async flush(): Promise<void> {
await this.queue;
}
private enqueue(task: () => Promise<void>) {
this.queue = this.queue.then(task, task).catch(() => {
// Swallow storage errors to prevent unhandled rejections.