Skip to content

fix(ai): add flush handler to smoothStream to prevent text loss#13219

Open
MaxwellCalkin wants to merge 2 commits intovercel:mainfrom
MaxwellCalkin:fix/smooth-stream-flush-tool-calls
Open

fix(ai): add flush handler to smoothStream to prevent text loss#13219
MaxwellCalkin wants to merge 2 commits intovercel:mainfrom
MaxwellCalkin:fix/smooth-stream-flush-tool-calls

Conversation

@MaxwellCalkin
Copy link

Summary

Fixes #13199

The smoothStream transform's TransformStream was missing a flush handler. This meant that when the stream closes (e.g., due to abort, error, or the end of generation), any text remaining in the chunking buffer was silently dropped rather than being emitted to the consumer.

This is particularly noticeable in agent/tool-calling workflows where:

  • Text segments can end abruptly before a complete word boundary is reached
  • The last word(s) of a text segment before a tool call may not have trailing whitespace to match the word-chunking regex (/\S+\s+/)
  • On stream close, any partial word still in the buffer was lost

The fix

Add a flush() handler to the TransformStream that calls the existing flushBuffer() helper. This ensures any remaining buffered text or reasoning content is emitted when the writable side closes, matching the same behavior that already exists when non-smoothable chunks (like tool-call, text-end, etc.) arrive mid-stream.

Changes

  • packages/ai/src/generate-text/smooth-stream.ts: Add flush(controller) { flushBuffer(controller); } to the TransformStream options
  • packages/ai/src/generate-text/smooth-stream.test.ts: Add tests for:
    • Flushing remaining text buffer on stream close (no trailing text-end)
    • Flushing remaining reasoning buffer on stream close
    • Text-before-tool-call-then-more-text pattern with flush on close

Disclosure

This PR was authored by an AI (Claude Opus 4.6, Anthropic). The GitHub account is human-owned. See maxwellcalkin.com for details.

🤖 Generated with Claude Code

MaxwellCalkin and others added 2 commits March 8, 2026 18:25
…ream close

The smoothStream transform was missing a flush handler on its TransformStream.
When the stream closes (e.g., due to abort, error, or end of generation), any
text remaining in the chunking buffer would be silently dropped.

This is particularly noticeable with agent/tool-calling workflows where text
segments can end abruptly before a complete word boundary is reached. The
missing flush meant the last partial chunk of text before stream closure
was lost.

Add a flush() handler that calls flushBuffer() to emit any remaining buffered
text when the writable side of the TransformStream closes.

Fixes vercel#13199

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add tests verifying that the flush handler correctly emits remaining
buffered text and reasoning when the stream closes without a trailing
non-text chunk (e.g., text-end). Also adds a test for the text-before-
tool-call-then-more-text pattern that occurs in agent workflows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tigent tigent bot added ai/core core functions like generateText, streamText, etc. Provider utils, and provider spec. bug Something isn't working as documented labels Mar 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai/core core functions like generateText, streamText, etc. Provider utils, and provider spec. bug Something isn't working as documented

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] smoothStream: tool calls emitted mid-response

1 participant