Repository navigation
Fix auto-continuation stream resume race - #1608
Merged
Merged
Conversation
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 detectedLatest commit: 89b67fc The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
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 |
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
Co-authored-by: Cursor <cursoragent@cursor.com>
threepointone
approved these changes
May 28, 2026
threepointone
left a comment
Contributor
There was a problem hiding this comment.
lgtm, added a small edge case fix
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR fixes a race in Think auto-continuation streaming after client-side tool output.
When a client calls
addToolOutput(...)withautoContinue: true, the client immediately asks to resume/attach to the continuation stream. Think was only creatingContinuationState.pendingafter the 50ms coalescing timer fired, so the immediatecf_agent_stream_resume_requestcould arrive while there was no active stream and no pending continuation. The server would replycf_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:
pendingnow exists before the coalescing timer fires, so an immediate resume request is held inawaitingConnectionsinstead of gettingcf_agent_stream_resume_none._fireAutoContinuationnow consumes the already-registered pending state instead of creating it late.ContinuationStateis now generic over the concrete connection type, so Think and AIChatAgent can store fullConnectionobjects without casts while keeping the shared chat primitive decoupled from the Agents connection type.The regression test sends
cf_agent_tool_resultwithautoContinue: trueand immediately follows it withcf_agent_stream_resume_request. It failed before this patch, and passes now. It asserts that the server responds withcf_agent_stream_resuming, notcf_agent_stream_resume_none, which captures the broken timing from #1586.Fixes #1586