fix: resolve session race condition and follow-up turn output loss
Two bugs fixed: 1. agent-runner error path race condition: when agent process exited with error, the promise resolved immediately without waiting for outputChain, allowing a late wrappedOnOutput to re-persist a stale session ID after clearSession had already run. 2. follow-up turn state not resetting: when a follow-up IPC message joined an active run, turn-level flags (finalOutputSentToUser, sawNonProgressOutput) from the first turn prevented the last progress from being promoted to a final message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -252,4 +252,54 @@ describe('agent-runner timeout behavior', () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('waits for queued streamed output before resolving an error exit', async () => {
|
||||
let releaseOutputs: (() => void) | undefined;
|
||||
const outputsFlushed = new Promise<void>((resolve) => {
|
||||
releaseOutputs = resolve;
|
||||
});
|
||||
const onOutput = vi.fn(async () => {
|
||||
await outputsFlushed;
|
||||
});
|
||||
const resultPromise = runAgentProcess(
|
||||
testGroup,
|
||||
testInput,
|
||||
() => {},
|
||||
onOutput,
|
||||
);
|
||||
|
||||
emitOutputMarker(fakeProc, {
|
||||
status: 'error',
|
||||
result: null,
|
||||
error: 'No conversation found with session ID: stale',
|
||||
});
|
||||
emitOutputMarker(fakeProc, {
|
||||
status: 'error',
|
||||
result: null,
|
||||
error: 'Claude Code process exited with code 1',
|
||||
newSessionId: 'stale-session',
|
||||
});
|
||||
|
||||
await vi.advanceTimersByTimeAsync(10);
|
||||
fakeProc.emit('close', 1);
|
||||
|
||||
let settled = false;
|
||||
resultPromise.then(() => {
|
||||
settled = true;
|
||||
});
|
||||
|
||||
await vi.advanceTimersByTimeAsync(10);
|
||||
expect(settled).toBe(false);
|
||||
|
||||
releaseOutputs?.();
|
||||
await vi.advanceTimersByTimeAsync(10);
|
||||
|
||||
const result = await resultPromise;
|
||||
expect(result.status).toBe('error');
|
||||
expect(onOutput).toHaveBeenCalledTimes(2);
|
||||
expect(onOutput).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
expect.objectContaining({ newSessionId: 'stale-session' }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user