-
Notifications
You must be signed in to change notification settings - Fork 111
[ai] Fix "start" and "finish" chunk events in DurableAgent
#378
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 7fda66f 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 |
DurableAgent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additional Suggestion:
The removal of the finish message chunk breaks downstream consumers that depend on this message to determine when a stream has completed. This will cause unnecessary reconnection attempts and incorrect behavior in chat applications.
View Details
📝 Patch Details
diff --git a/packages/ai/src/agent/do-stream-step.ts b/packages/ai/src/agent/do-stream-step.ts
index ba04f07..2aa33a5 100644
--- a/packages/ai/src/agent/do-stream-step.ts
+++ b/packages/ai/src/agent/do-stream-step.ts
@@ -73,6 +73,9 @@ export async function doStreamStep(
controller.enqueue({
type: 'finish-step',
});
+ controller.enqueue({
+ type: 'finish',
+ });
},
transform: async (part, controller) => {
const partType = part.type;
Analysis
Missing 'finish' chunk in doStreamStep breaks WorkflowChatTransport stream completion detection
What fails: doStreamStep() in packages/ai/src/agent/do-stream-step.ts removed the {type: 'finish'} chunk from its flush() method, causing downstream consumers like WorkflowChatTransport to incorrectly trigger reconnection logic when the stream completes normally.
How to reproduce:
- Create a
DurableAgentand callagent.stream()which usesdoStreamStep() - Wire the output stream to a backend HTTP response handler that serializes it
- Use
WorkflowChatTransporton the client to consume the response stream - Expected: Stream completes normally with onChatEnd callback
- Actual: Without 'finish' chunk, the gotFinish flag is never set, causing reconnectToStream() to be called and onChatEnd callback never fires
Code evidence:
doStreamStep()transforms LLM stream parts to UIMessageChunks via a TransformStream- The flush() method at
packages/ai/src/agent/do-stream-step.ts:72-76was modified to only emit 'finish-step' WorkflowChatTransport.sendMessagesIterator()atpackages/ai/src/workflow-chat-transport.ts:232-241explicitly checks forchunk.value.type === 'finish'to setgotFinish = true- Without this check passing, line 248 triggers reconnection logic instead of completing
- Per AI SDK stream protocol documentation, the stream protocol includes a final 'finish' chunk
Verification: Created test scenario showing stream without 'finish' chunk triggers 2 fetch calls (POST + reconnection GET), while stream with 'finish' chunk triggers only 1 call (POST only)
Fix applied: Restored the controller.enqueue({type: 'finish'}) call to the flush() method in the TransformStream, ensuring the 'finish' chunk is always emitted when the stream ends.
DurableAgentDurableAgent
We were always sending
startandfinishchunk more than necessary. This fixes it