Fix stop() for tool continuation streams; fix orphaned continuation hibernation#1234
Merged
threepointone merged 2 commits intomainfrom Mar 31, 2026
Merged
Conversation
🦋 Changeset detectedLatest commit: 8320dd1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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: |
Always call transport.abortActiveToolContinuation when stopping (wrap stop() in finally) and enhance WebSocket transport abort logic to handle pre-handshake aborts and keep request IDs for server cleanup. Adds an abortRequested flag and closes the stream if the handshake hasn't completed so late STREAM_RESUMING is ignored, and keeps the requestId in activeIds until server signals done. Also adds tests covering: keeping requestId for cleanup, abort semantics when no continuation or already completed, and abort-before-handshake behavior to prevent late resumes.
dca7901 to
8320dd1
Compare
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.
Summary
useAgentChat().stop()for client-side tool continuations by cancelling the active server continuation request id instead of only aborting the local AI SDK responseWebSocketChatTransportto track and cancel an active tool continuation stream after the resume handshake attaches it to the server request idSTREAM_RESUMINGarrives) by closing the stream and clearing resolvers so late resumes are ignoredtry/finallyin the stop wrapper so the server-side cancel fires even if the AI SDK'sstop()throws_persistOrphanedStreamto handle continuation streams wheremessageIdwas stripped (ai-chat: tool continuation sends new messageId in start chunk, causing duplicate assistant message #1229) — fall back to the last assistant message and merge parts/metadata instead of creating a duplicate@cloudflare/ai-chatCloses #1233
Testing
npm run test(392 worker tests including new transport abort + orphaned continuation tests)npm run test:react(77 React tests including new stop-during-continuation test)npx tsc --noEmit -p packages/ai-chat/src/tests/tsconfig.jsonReviewer Notes
sendMessage(): continuations go throughresumeStream()/reconnectToStream(), and AI SDK does not provide an abort signal to that transport path. That meansstop()aborted local client state but never sentCF_AGENT_CHAT_REQUEST_CANCELfor the server continuation request.CF_AGENT_STREAM_RESUMING, so the transport now captures that id and exposes a narrowabortActiveToolContinuation()helper.useAgentChat.stop()calls the normal AI SDK stop first, then invokes that transport helper.STREAM_RESUMINGarrives (requestIdis still null), the stream is closed immediately and resolvers are cleared so late resumes become no-ops.@cloudflare/ai-chatclient code. There is no server-side protocol change and no change to the standard request-cancel path for normal submits._persistOrphanedStreamfix is a separate hibernation-safety issue found during review: ai-chat: tool continuation sends new messageId in start chunk, causing duplicate assistant message #1229'smessageIdstripping broke orphaned stream recovery for continuations, causing duplicate assistant messages after hibernation. The fix falls back to the last assistant message ID and merges existing parts with stream parts.