Skip to content

Fix auto-continuation stream resume race - #1608

Merged
cjol merged 3 commits into
mainfrom
fix/client-tool-continuation-stream
May 29, 2026
Merged

cjol merged 3 commits into
mainfrom
fix/client-tool-continuation-stream

Conversation

@cjol

@cjol cjol commented May 28, 2026 •

Copy link
Copy Markdown
Member

This PR fixes a race in Think auto-continuation streaming after client-side tool output.

When a client calls addToolOutput(...) with autoContinue: true, the client immediately asks to resume/attach to the continuation stream. Think was only creating ContinuationState.pending after the 50ms coalescing timer fired, so the immediate cf_agent_stream_resume_request could arrive while there was no active stream and no pending continuation. The server would reply cf_agent_stream_resume_none, causing the client’s deferred stream to close and leaving the user with no live assistant chunks until end-of-turn replay.

The fix keeps the existing 50ms coalescing delay for starting the continuation turn, but registers the continuation as pending synchronously:

  • pending now exists before the coalescing timer fires, so an immediate resume request is held in awaitingConnections instead of getting cf_agent_stream_resume_none.
  • The timer fires the continuation from the latest pending connection, avoiding a stale captured connection if the pending continuation is updated during the coalescing window.
  • _fireAutoContinuation now consumes the already-registered pending state instead of creating it late.
  • ContinuationState is now generic over the concrete connection type, so Think and AIChatAgent can store full Connection objects without casts while keeping the shared chat primitive decoupled from the Agents connection type.

The regression test sends cf_agent_tool_result with autoContinue: true and immediately follows it with cf_agent_stream_resume_request. It failed before this patch, and passes now. It asserts that the server responds with cf_agent_stream_resuming, not cf_agent_stream_resume_none, which captures the broken timing from #1586.

Fixes #1586


Open in Devin Review

Register Think auto-continuations as pending before the coalescing timer fires so an immediate cf_agent_stream_resume_request after a client tool result is held for the pending stream instead of receiving cf_agent_stream_resume_none.

Keep the 50ms coalescing delay for starting the continuation turn, but make pending state visible synchronously and fire the continuation from the latest pending connection when the timer elapses. This preserves coalescing while avoiding a stale captured connection.

Add a regression test that sends cf_agent_tool_result with autoContinue followed immediately by cf_agent_stream_resume_request and asserts that the server responds with cf_agent_stream_resuming rather than cf_agent_stream_resume_none.

Make ContinuationState generic over its concrete connection type so Think and AIChatAgent can store full Connection objects without casts while keeping the shared chat primitive decoupled from agents' Connection type.
@changeset-bot

changeset-bot Bot commented May 28, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 89b67fc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@cloudflare/think Patch
@cloudflare/ai-chat Patch
agents Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented May 28, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@1608

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@1608

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@1608

hono-agents

npm i https://pkg.pr.new/hono-agents@1608

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@1608

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@1608

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@1608

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@1608

commit: 89b67fc

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@cjol
cjol requested a review from threepointone May 28, 2026 16:55
Co-authored-by: Cursor <cursoragent@cursor.com>

@threepointone threepointone left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm, added a small edge case fix

@cjol
cjol merged commit 7c17736 into main May 29, 2026
4 checks passed
@cjol
cjol deleted the fix/client-tool-continuation-stream branch May 29, 2026 08:38
@github-actions github-actions Bot mentioned this pull request May 28, 2026
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.

addToolOutput / client-tool auto-continuations don't attach to the response stream — delivered only as an end-of-turn replay

2 participants