Skip to content

Keep non-text response segments when a stream finalizes - #16

Open
ActuallyTaylor wants to merge 1 commit into
mainfrom
fix/preserve-response-segments-on-stream-finalize
Open

Keep non-text response segments when a stream finalizes#16
ActuallyTaylor wants to merge 1 commit into
mainfrom
fix/preserve-response-segments-on-stream-finalize

Conversation

@ActuallyTaylor

Copy link
Copy Markdown
Collaborator

Problem

Transcript.finalizeStreamedTranscript replaced the trailing response entry's entire segments array with a single text segment, discarding every segment ahead of the streamed text the moment the stream ended.

This is reachable today. appendStreamingResponse appends a new text segment whenever the trailing segment isn't text, so a response entry that already carried a structure or image segment arrives at finalization with two segments — and loses the first one.

It also blocks upcoming work: surfacing model reasoning as a separate segment on the response is pointless while finalization deletes it.

Fix

Mirror appendStreamingResponse: replace the trailing text segment in place, carrying its ID over, or append a new one when the trailing segment isn't text — and leave every earlier segment untouched. Mutating the Response in place also preserves id structurally instead of re-plumbing it by hand.

Tests

Neither streaming mutator had any coverage. Four cases added; the first fails against the old implementation (expects 2 segments, old code produced 1), the rest guard the paths this touches.

Verification

swift test — 329 tests across 37 suites. The 13 failures are pre-existing and environmental, not from this change:

  • 12 Ollama: model 'qwen3:8b' not found (404 from the local server — the model isn't pulled).
  • 1 Gemini withClientTools: live API 400. Confirmed by stashing the change and re-running the Gemini suite on a clean tree, where it also fails — and that run additionally flaked multimodalWithImageURL, which passed in the run with the change. Those live tests are unstable independent of this work.

🤖 Generated with Claude Code

finalizeStreamedTranscript replaced the trailing response entry's whole segments array with a single text segment, so every segment ahead of the streamed text was dropped the moment the stream ended.

appendStreamingResponse appends a new text segment whenever the trailing segment is not text, so a response that already carried a structure or image segment reaches finalization with two segments and loses the first one. Mirror appendStreamingResponse instead: replace the trailing text segment in place, carrying its ID over, or append a new one when the trailing segment is not text, and leave everything earlier untouched.

Neither streaming mutator had test coverage, so cover both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@ActuallyTaylor ActuallyTaylor left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants