Public: anyone can read this; the crew can change it.
A /talk reply in progress survives a reload and shows on another device mid-stream #8833
Check · Review · Land · Live done — Landed and live in production.
This pull adds the test the issue asks for. It changes no app code, because the behaviour the issue describes was already in place.
shipped production is serving it deploy 47e6991
This pull adds the test the issue asks for. It changes no app code, because the behaviour the issue describes was already in place.
What I found
GET /talk/streamalready sends each stored turn withid: <turn id>. It resumes from?after=or from theLast-Event-IDheader.- The conversation stores each agent and tool turn as it is said, so a reload renders what has streamed so far.
/talkrendersdata-running="1"withdata-lastas the cursor, and the client script reconnects from that cursor. A second device opening mid-reply therefore sees the same turns.- The one thing missing was a test that proves it end to end.
What changed
test/conversation-turn.test.tshas one new test, plus agatemode in the stand-inclaudethat holds mid-turn until a file appears.- The test starts a real turn and reads
/talk/streamuntil the person's message and the tool call have arrived, then drops the connection. - A second client, standing in for another device, opens the stream mid-turn and gets the same two turns.
- The turn then finishes. A reconnect with
Last-Event-IDset to the last id seen gets exactly the remaining turn (the agent's answer) and thendone. Nothing is repeated and nothing is lost.
Checks: bun test test/conversation-turn.test.ts (20 pass), bun test test/talk-page.test.ts (22 pass), bun x tsc --noEmit and bun scripts/gate.ts are clean.
Left alone
- A second device sitting on
/talkwith no reply running does not learn that the first device started a new one until it reloads or sends. Fixing that means a periodic check from the page, which goes against #8719's quiet rules and the issue's "small script", so I did not add it. - Streaming partial text inside a message would mean changing the turn model. Messages are stored whole, as before.
Test-only pull, honest about it: GET /talk/stream already ids each turn and resumes from ?after= or Last-Event-ID (src/web/pages/talk.ts:208), and /talk renders data-running and data-last as the cursor. The new gated-stub test proves drop-halfway, second device, and exact-rest-then-done end to end. Preview /talk answers 303 for me (no session), so I judged the page path from source. Next two things: (1) add a /talk page-level assertion that a mid-turn render carries data-running=1 and data-last equal to the last stored turn id, so box 1 is pinned on the page and not only the stream; (2) the gate file poll in the stub is a 50ms shell loop with no timeout; add a bounded wait so a failed test cannot leave a stray claude process.
This pull adds the test the issue asks for. It changes no app code, because the behaviour the issue describes was already in place.
What I found
GET /talk/streamalready sends each stored turn withid: <turn id>. It resumes from?after=or from theLast-Event-IDheader./talkrendersdata-running="1"withdata-lastas the cursor, and the client script reconnects from that cursor. A second device opening mid-reply therefore sees the same turns.What changed
test/conversation-turn.test.tshas one new test, plus agatemode in the stand-inclaudethat holds mid-turn until a file appears./talk/streamuntil the person's message and the tool call have arrived, then drops the connection.Last-Event-IDset to the last id seen gets exactly the remaining turn (the agent's answer) and thendone. Nothing is repeated and nothing is lost.Checks:
bun test test/conversation-turn.test.ts(20 pass),bun test test/talk-page.test.ts(22 pass),bun x tsc --noEmitandbun scripts/gate.tsare clean.Left alone
/talkwith no reply running does not learn that the first device started a new one until it reloads or sends. Fixing that means a periodic check from the page, which goes against #8719's quiet rules and the issue's "small script", so I did not add it.Closes #8815