@mastra/ai-sdk 1.7.2 → 1.8.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # @mastra/ai-sdk
2
2
 
3
+ ## 1.8.0-alpha.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed the finish reason dropping out of AI SDK UI message streams. The final `finish` chunk from `handleChatStream` and `toAISdkStream` now carries `finishReason`, so clients can tell `stop`, `length`, `content-filter`, `tool-calls` and `other` apart. This matches the AI SDK behavior. Fixes #20562. ([#20983](https://github.com/mastra-ai/mastra/pull/20983))
8
+
9
+ - Updated dependencies [[`cdd5c33`](https://github.com/mastra-ai/mastra/commit/cdd5c33ac6c7118a9f139e6dc0e14e6a8ae31658), [`d7cf7fa`](https://github.com/mastra-ai/mastra/commit/d7cf7fafc1ae1b50bd8462dd0e6c671a8606db93), [`0f9a448`](https://github.com/mastra-ai/mastra/commit/0f9a448502157e59f7b76f24360ad497168f5ef8), [`289f4ce`](https://github.com/mastra-ai/mastra/commit/289f4ce16e3293370440172132c52ee787cbc09f), [`4f16ff8`](https://github.com/mastra-ai/mastra/commit/4f16ff824bf2f9b0ddc93f210477c10c8a4fb1ab), [`1c67d85`](https://github.com/mastra-ai/mastra/commit/1c67d85e9da8285662f4dbbf47e0378c3fee0747), [`ba24be6`](https://github.com/mastra-ai/mastra/commit/ba24be662439c331ab23a600041f93803c89eca8), [`842b5fe`](https://github.com/mastra-ai/mastra/commit/842b5fe22b6a7fa811bd14e48eb9af523ac989f2), [`80bdf3a`](https://github.com/mastra-ai/mastra/commit/80bdf3ae16ade6ff63bde0cb16fa2df8ab7dd4dd), [`9ba1247`](https://github.com/mastra-ai/mastra/commit/9ba12470c77f1c03642d720ce67e517e878f666e), [`fd96298`](https://github.com/mastra-ai/mastra/commit/fd96298a8367622f4ebfcaa97b5b6c1fbbd14564), [`6a84954`](https://github.com/mastra-ai/mastra/commit/6a84954a2667f85b6d59da652dab1bbff007ccb0), [`52d8ef0`](https://github.com/mastra-ai/mastra/commit/52d8ef03801f1deb7ee48532fc4190dd4a33916c), [`cdd5c33`](https://github.com/mastra-ai/mastra/commit/cdd5c33ac6c7118a9f139e6dc0e14e6a8ae31658), [`efd5c81`](https://github.com/mastra-ai/mastra/commit/efd5c81cc25fde3c2ddd86fc1178deb4ec176e19), [`0976933`](https://github.com/mastra-ai/mastra/commit/0976933142333ec78451feef265b68bcb45aa5e7), [`242b945`](https://github.com/mastra-ai/mastra/commit/242b94558777bfbdeb42cbfea84afff0b6ad0633), [`fea5cae`](https://github.com/mastra-ai/mastra/commit/fea5caedc7e2cfea51784a15e015952692027abf), [`4b59f78`](https://github.com/mastra-ai/mastra/commit/4b59f786cbc9a7d1ef07a07517dbd4b96865e99d), [`7010c5d`](https://github.com/mastra-ai/mastra/commit/7010c5d15728bf9c5dfe4fb6b1bf80ce23bf143a)]:
10
+ - @mastra/core@1.58.0-alpha.3
11
+
12
+ ## 1.8.0-alpha.1
13
+
14
+ ### Patch Changes
15
+
16
+ - Enqueue a `tool-output-denied` chunk when a `requireApproval` tool is declined so live AI SDK clients resolve the pending tool call instead of hanging. Persistence as `output-denied` already worked; only the stream path was missing. ([#20886](https://github.com/mastra-ai/mastra/pull/20886))
17
+
18
+ ```ts
19
+ for await (const part of toAISdkStream(result.fullStream, { from: 'agent' })) {
20
+ if (part.type === 'tool-output-denied') {
21
+ // Clears the pending requireApproval tool call on the client
22
+ console.log('denied', part.toolCallId);
23
+ }
24
+ }
25
+ ```
26
+
27
+ - Updated dependencies [[`b4c89b4`](https://github.com/mastra-ai/mastra/commit/b4c89b4371b0c86da57403ad1a3b3ef0681f3128), [`e44e8f3`](https://github.com/mastra-ai/mastra/commit/e44e8f370b66c339ddcaba946d33da6d3c3f06cd), [`c967a5e`](https://github.com/mastra-ai/mastra/commit/c967a5eec150c5dc5418c4a4388982d1fb7ad27c), [`f53d5bd`](https://github.com/mastra-ai/mastra/commit/f53d5bd4885b29e4ac29a428a6044088ea8d6aa3), [`bda2235`](https://github.com/mastra-ai/mastra/commit/bda22353ee28f2df0eaea555f7cae1549f979c0b), [`a7eb4a1`](https://github.com/mastra-ai/mastra/commit/a7eb4a11450f6170274ed5141bffe821d4fdd5a6), [`2f9ef3f`](https://github.com/mastra-ai/mastra/commit/2f9ef3f4ca06fc2dcdd5088c26b7f4da6a016791), [`e7eefcb`](https://github.com/mastra-ai/mastra/commit/e7eefcb162cda7c493e8c3bf43050ead0efbcb2c), [`4d7aca2`](https://github.com/mastra-ai/mastra/commit/4d7aca2fe75f225c83d1502d63079568e6ec163f), [`c4ec889`](https://github.com/mastra-ai/mastra/commit/c4ec889561c0264c43f66d04d587bee4ce35e792), [`9be8878`](https://github.com/mastra-ai/mastra/commit/9be8878dcf0388e84fc4873e0eec27bd49b881a4)]:
28
+ - @mastra/core@1.58.0-alpha.2
29
+
30
+ ## 1.8.0-alpha.0
31
+
32
+ ### Minor Changes
33
+
34
+ - Added optional SSE heartbeats to `chatRoute()` so streams can remain active through infrastructure with idle timeouts. ([#20852](https://github.com/mastra-ai/mastra/pull/20852))
35
+
36
+ ```typescript
37
+ chatRoute({
38
+ path: '/chat/:agentId',
39
+ heartbeatMs: 15_000,
40
+ });
41
+ ```
42
+
43
+ - Fixed nested agent streams to emit compact snapshots until each step completes, and added `data-tool-agent-step` as a new stream part type (exported as `AgentStepDataPart`) that carries the full completed-step detail for consumers that observe suspension without a finish event. ([#20576](https://github.com/mastra-ai/mastra/pull/20576))
44
+
45
+ ### Patch Changes
46
+
47
+ - Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
48
+ - @mastra/core@1.58.0-alpha.1
49
+
3
50
  ## 1.7.2
4
51
 
5
52
  ### Patch Changes
@@ -96,6 +96,8 @@ export type chatRouteOptions<OUTPUT = undefined> = {
96
96
  sendFinish?: boolean;
97
97
  sendReasoning?: boolean;
98
98
  sendSources?: boolean;
99
+ /** Target interval for periodic SSE comment heartbeats. Values up to 0 disable heartbeats. `NaN`, positive infinity, and values above 2,147,483,647 throw a `RangeError`. */
100
+ heartbeatMs?: number;
99
101
  onError?: (error: unknown) => string;
100
102
  };
101
103
  /**
@@ -111,11 +113,13 @@ export type chatRouteOptions<OUTPUT = undefined> = {
111
113
  * @param {boolean} [options.sendFinish=true] - Whether to send finish events in the stream
112
114
  * @param {boolean} [options.sendReasoning=false] - Whether to include reasoning steps in the stream
113
115
  * @param {boolean} [options.sendSources=false] - Whether to include source citations in the stream
116
+ * @param {number} [options.heartbeatMs] - Target interval for periodic SSE comment heartbeats. Already-buffered source events and stream lifecycle signals take priority. Values up to 0 disable heartbeats. `NaN`, positive infinity, and values above 2,147,483,647 throw a `RangeError`.
114
117
  * @param {(error: unknown) => string} [options.onError] - Custom error serializer streamed to the client. When omitted, errors are passed through a default serializer that strips sensitive fields (e.g. `APICallError.requestBodyValues`, which holds the system prompt) before they reach the client.
115
118
  *
116
119
  * @returns {ReturnType<typeof registerApiRoute>} A registered API route handler
117
120
  *
118
121
  * @throws {Error} When path doesn't include `:agentId` and no fixed agent is specified
122
+ * @throws {RangeError} When `heartbeatMs` is `NaN`, positive infinity, or greater than 2,147,483,647
119
123
  * @throws {Error} When agent ID is missing at runtime
120
124
  * @throws {Error} When specified agent is not found in Mastra instance
121
125
  *
@@ -138,10 +142,10 @@ export type chatRouteOptions<OUTPUT = undefined> = {
138
142
  * @remarks
139
143
  * - The route handler expects a JSON body with a `messages` array
140
144
  * - Messages should follow the format: `{ role: 'user' | 'assistant' | 'system', content: string }`
141
- * - The response is a Server-Sent Events (SSE) stream compatible with AI SDK v5
145
+ * - The response is a Server-Sent Events (SSE) stream compatible with the selected AI SDK version
142
146
  * - If both `agent` and `:agentId` are present, a warning is logged and the fixed `agent` takes precedence
143
147
  * - Request context from the incoming request overrides `defaultOptions.requestContext` if both are present
144
148
  */
145
- export declare function chatRoute<OUTPUT = undefined>({ path, agent, defaultOptions, experimentalTransform, version, agentVersion, sendStart, sendFinish, sendReasoning, sendSources, onError, }: chatRouteOptions<OUTPUT>): ReturnType<typeof registerApiRoute>;
149
+ export declare function chatRoute<OUTPUT = undefined>({ path, agent, defaultOptions, experimentalTransform, version, agentVersion, sendStart, sendFinish, sendReasoning, sendSources, heartbeatMs, onError, }: chatRouteOptions<OUTPUT>): ReturnType<typeof registerApiRoute>;
146
150
  export {};
147
151
  //# sourceMappingURL=chat-route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat-route.d.ts","sourceRoot":"","sources":["../src/chat-route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-route.d.ts","sourceRoot":"","sources":["../src/chat-route.ts"],"names":[],"mappings":"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"}
package/dist/helpers.d.ts CHANGED
@@ -15,6 +15,13 @@ export declare const APPROVAL_ID_SEPARATOR = "::";
15
15
  */
16
16
  export declare function toAISDKFinishReason(reason: MastraFinishReason): FinishReason;
17
17
  export type OutputChunkType<OUTPUT = undefined> = TextStreamPart<ToolSet> | ObjectStreamPart<Partial<OUTPUT>> | ToolApprovalRequest | DataChunkType | undefined;
18
+ type AISDKToolOutputDenied = {
19
+ type: 'tool-output-denied';
20
+ toolCallId: string;
21
+ toolName: string;
22
+ providerExecuted?: boolean;
23
+ dynamic?: boolean;
24
+ };
18
25
  export type ToolAgentChunkType = {
19
26
  type: 'tool-agent';
20
27
  toolCallId: string;
@@ -47,9 +54,9 @@ export declare function toAISDKFinishReasonV6(reason: MastraFinishReason): Finis
47
54
  export declare function convertMastraChunkToAISDKv6<OUTPUT = undefined>({ chunk, mode, }: {
48
55
  chunk: ChunkType<OUTPUT>;
49
56
  mode?: 'generate' | 'stream';
50
- }): OutputChunkType<OUTPUT> | OutputChunkType<OUTPUT>[];
57
+ }): OutputChunkType<OUTPUT> | AISDKToolOutputDenied | OutputChunkType<OUTPUT>[];
51
58
  export declare function convertFullStreamChunkToUIMessageStream<UI_MESSAGE extends UIMessage>({ part, messageMetadataValue, sendReasoning, sendSources, onError, sendStart, sendFinish, responseMessageId, }: {
52
- part: TextStreamPart<ToolSet> | DataChunkType | ToolApprovalRequest | {
59
+ part: TextStreamPart<ToolSet> | AISDKToolOutputDenied | DataChunkType | ToolApprovalRequest | {
53
60
  type: 'tool-output';
54
61
  toolCallId: string;
55
62
  output: any;
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -8863,6 +8863,7 @@ const isMastraTextStreamChunk = (chunk) => {
8863
8863
  "tool-call",
8864
8864
  "tool-result",
8865
8865
  "tool-error",
8866
+ "tool-output-denied",
8866
8867
  "error",
8867
8868
  "start-step",
8868
8869
  "finish-step",
@@ -9215,6 +9216,11 @@ function normalizeV6Usage(usage) {
9215
9216
  };
9216
9217
  }
9217
9218
  function convertMastraChunkToAISDKv6({ chunk, mode = "stream" }) {
9219
+ if (chunk.type === "tool-output-denied") return {
9220
+ type: "tool-output-denied",
9221
+ toolCallId: chunk.payload.toolCallId,
9222
+ toolName: chunk.payload.toolName
9223
+ };
9218
9224
  if (chunk.type === "tool-call-approval") {
9219
9225
  const displayTransform = getTransformedToolPayload(chunk.metadata, "display", "approval");
9220
9226
  return [{
@@ -9343,6 +9349,10 @@ function convertFullStreamChunkToUIMessageStream({ part, messageMetadataValue, s
9343
9349
  ...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
9344
9350
  ...part.dynamic != null ? { dynamic: part.dynamic } : {}
9345
9351
  };
9352
+ case "tool-output-denied": return {
9353
+ type: "tool-output-denied",
9354
+ toolCallId: part.toolCallId
9355
+ };
9346
9356
  case "tool-output":
9347
9357
  if (part.output.from === "AGENT") return {
9348
9358
  type: "tool-agent",
@@ -9395,6 +9405,7 @@ function convertFullStreamChunkToUIMessageStream({ part, messageMetadataValue, s
9395
9405
  case "finish":
9396
9406
  if (sendFinish) return {
9397
9407
  type: "finish",
9408
+ ...part.finishReason != null ? { finishReason: part.finishReason } : {},
9398
9409
  ...messageMetadataValue != null ? { messageMetadata: messageMetadataValue } : {}
9399
9410
  };
9400
9411
  return;
@@ -9427,6 +9438,7 @@ function convertFullStreamChunkToUIMessageStream({ part, messageMetadataValue, s
9427
9438
  //#endregion
9428
9439
  //#region src/transformers.ts
9429
9440
  const PRIMITIVE_CACHE_SYMBOL = Symbol("primitive-cache");
9441
+ const COMPLETED_STEPS_SYMBOL = Symbol("completed-steps-cache");
9430
9442
  function cloneWorkflowStep(step, includeOutput) {
9431
9443
  return {
9432
9444
  name: step.name,
@@ -9554,7 +9566,8 @@ function createAgentStreamToAISDKTransformer(convertMastraChunkToAISDK, { lastMe
9554
9566
  if (transformedChunk) if (transformedChunk.type === "tool-agent") {
9555
9567
  const payload = transformedChunk.payload;
9556
9568
  const agentTransformed = transformAgent(payload, bufferedSteps);
9557
- if (agentTransformed) controller.enqueue(agentTransformed);
9569
+ if (agentTransformed) if (Array.isArray(agentTransformed)) for (const part of agentTransformed) controller.enqueue(part);
9570
+ else controller.enqueue(agentTransformed);
9558
9571
  } else if (transformedChunk.type === "tool-workflow") {
9559
9572
  const payload = transformedChunk.payload;
9560
9573
  const workflowChunk = transformWorkflow(payload, bufferedSteps, true, void 0, void 0, convertMastraChunkToAISDK);
@@ -9637,30 +9650,7 @@ function AgentStreamToAISDKV6Transformer({ lastMessageId, sendStart = true, send
9637
9650
  });
9638
9651
  }
9639
9652
  function ensureAgentRunState(bufferedSteps, runId) {
9640
- if (!bufferedSteps.has(runId)) bufferedSteps.set(runId, {
9641
- id: "",
9642
- object: null,
9643
- finishReason: null,
9644
- usage: null,
9645
- warnings: [],
9646
- text: "",
9647
- reasoning: [],
9648
- sources: [],
9649
- files: [],
9650
- toolCalls: [],
9651
- pendingToolCalls: [],
9652
- toolResults: [],
9653
- request: {},
9654
- response: {
9655
- id: "",
9656
- timestamp: /* @__PURE__ */ new Date(),
9657
- modelId: "",
9658
- messages: []
9659
- },
9660
- providerMetadata: void 0,
9661
- steps: [],
9662
- status: "running"
9663
- });
9653
+ if (!bufferedSteps.has(runId)) bufferedSteps.set(runId, createAgentRunState());
9664
9654
  return bufferedSteps.get(runId);
9665
9655
  }
9666
9656
  function upsertPendingToolCall(pendingToolCalls = [], toolCallId, updates) {
@@ -9696,36 +9686,109 @@ function appendPendingToolCallArgs(pendingToolCalls = [], payload) {
9696
9686
  function removePendingToolCall(pendingToolCalls = [], toolCallId) {
9697
9687
  return pendingToolCalls.filter((call) => call.toolCallId !== toolCallId);
9698
9688
  }
9689
+ function createAgentResponseState() {
9690
+ return {
9691
+ id: "",
9692
+ timestamp: /* @__PURE__ */ new Date(),
9693
+ modelId: "",
9694
+ messages: []
9695
+ };
9696
+ }
9697
+ function createAgentRunState(id = "") {
9698
+ return {
9699
+ id,
9700
+ object: null,
9701
+ finishReason: null,
9702
+ usage: null,
9703
+ warnings: [],
9704
+ text: "",
9705
+ reasoning: [],
9706
+ sources: [],
9707
+ files: [],
9708
+ toolCalls: [],
9709
+ pendingToolCalls: [],
9710
+ toolResults: [],
9711
+ request: {},
9712
+ response: createAgentResponseState(),
9713
+ providerMetadata: void 0,
9714
+ steps: [],
9715
+ status: "running"
9716
+ };
9717
+ }
9718
+ function cloneAgentResponse(response, { includeMessages }) {
9719
+ if (!response) return response;
9720
+ return {
9721
+ ...response,
9722
+ ...Object.prototype.hasOwnProperty.call(response, "messages") ? { messages: includeMessages ? response.messages : [] } : {},
9723
+ ...Object.prototype.hasOwnProperty.call(response, "dbMessages") ? { dbMessages: includeMessages ? response.dbMessages : [] } : {},
9724
+ ...Object.prototype.hasOwnProperty.call(response, "uiMessages") ? { uiMessages: includeMessages ? response.uiMessages : [] } : {}
9725
+ };
9726
+ }
9727
+ function cloneAgentStep(step, { includeDetails }) {
9728
+ if (includeDetails) return {
9729
+ ...step,
9730
+ response: cloneAgentResponse(step.response, { includeMessages: true })
9731
+ };
9732
+ return {
9733
+ ...step,
9734
+ object: null,
9735
+ files: [],
9736
+ sources: [],
9737
+ toolCalls: [],
9738
+ pendingToolCalls: [],
9739
+ toolResults: [],
9740
+ dynamicToolCalls: [],
9741
+ dynamicToolResults: [],
9742
+ staticToolCalls: [],
9743
+ staticToolResults: [],
9744
+ text: "",
9745
+ reasoning: [],
9746
+ content: Array.isArray(step.content) ? [] : step.content,
9747
+ reasoningText: typeof step.reasoningText === "string" ? "" : step.reasoningText,
9748
+ response: cloneAgentResponse(step.response, { includeMessages: false })
9749
+ };
9750
+ }
9751
+ function serializeAgentRun(current, { includeCompletedStepDetails, includeResponseMessages }) {
9752
+ const { _textOffset: _to, _reasoningOffset: _ro, ...data } = current;
9753
+ return {
9754
+ ...data,
9755
+ response: cloneAgentResponse(data.response, { includeMessages: includeResponseMessages }),
9756
+ steps: data.steps.map((step) => cloneAgentStep(step, { includeDetails: includeCompletedStepDetails }))
9757
+ };
9758
+ }
9759
+ function createAgentDataPart(args) {
9760
+ const { current, runId, includeCompletedStepDetails, includeResponseMessages } = args;
9761
+ return {
9762
+ type: "data-tool-agent",
9763
+ id: runId,
9764
+ data: serializeAgentRun(current, {
9765
+ includeCompletedStepDetails,
9766
+ includeResponseMessages
9767
+ })
9768
+ };
9769
+ }
9770
+ function createAgentStepDataPart(args) {
9771
+ const { runId, stepIndex, step } = args;
9772
+ return {
9773
+ type: "data-tool-agent-step",
9774
+ id: `${runId}:${stepIndex}`,
9775
+ data: {
9776
+ runId,
9777
+ stepIndex,
9778
+ step: cloneAgentStep(step, { includeDetails: true })
9779
+ }
9780
+ };
9781
+ }
9699
9782
  function transformAgent(payload, bufferedSteps) {
9700
9783
  let hasChanged = false;
9784
+ let completedStep = null;
9701
9785
  switch (payload.type) {
9702
- case "start":
9703
- bufferedSteps.set(payload.runId, {
9704
- id: payload.payload.id,
9705
- object: null,
9706
- finishReason: null,
9707
- usage: null,
9708
- warnings: [],
9709
- text: "",
9710
- reasoning: [],
9711
- sources: [],
9712
- files: [],
9713
- toolCalls: [],
9714
- pendingToolCalls: [],
9715
- toolResults: [],
9716
- request: {},
9717
- response: {
9718
- id: "",
9719
- timestamp: /* @__PURE__ */ new Date(),
9720
- modelId: "",
9721
- messages: []
9722
- },
9723
- providerMetadata: void 0,
9724
- steps: [],
9725
- status: "running"
9726
- });
9786
+ case "start": {
9787
+ const startState = createAgentRunState(payload.payload.id);
9788
+ bufferedSteps.set(payload.runId, startState);
9727
9789
  hasChanged = true;
9728
9790
  break;
9791
+ }
9729
9792
  case "tool-call-input-streaming-start": {
9730
9793
  const toolInputStartRun = ensureAgentRunState(bufferedSteps, payload.runId);
9731
9794
  const existing = toolInputStartRun.pendingToolCalls?.find((call) => call.toolCallId === payload.payload.toolCallId);
@@ -9856,6 +9919,7 @@ function transformAgent(payload, bufferedSteps) {
9856
9919
  break;
9857
9920
  case "step-finish": {
9858
9921
  const stepRun = ensureAgentRunState(bufferedSteps, payload.runId);
9922
+ const stepIndex = stepRun.steps.length;
9859
9923
  const { steps: _steps, _textOffset, _reasoningOffset, ...stepRunWithoutSteps } = stepRun;
9860
9924
  const textOffset = _textOffset || 0;
9861
9925
  const reasoningOffset = _reasoningOffset || 0;
@@ -9897,18 +9961,28 @@ function transformAgent(payload, bufferedSteps) {
9897
9961
  _textOffset: stepRun.text.length,
9898
9962
  _reasoningOffset: stepRun.reasoning.length
9899
9963
  });
9964
+ completedStep = {
9965
+ stepIndex,
9966
+ step: stepResult
9967
+ };
9900
9968
  hasChanged = true;
9901
9969
  break;
9902
9970
  }
9903
9971
  default: break;
9904
9972
  }
9905
9973
  if (hasChanged) {
9906
- const { _textOffset: _to, _reasoningOffset: _ro, ...data } = bufferedSteps.get(payload.runId);
9907
- return {
9908
- type: "data-tool-agent",
9909
- id: payload.runId,
9910
- data
9911
- };
9974
+ const snapshot = createAgentDataPart({
9975
+ current: bufferedSteps.get(payload.runId),
9976
+ runId: payload.runId,
9977
+ includeCompletedStepDetails: payload.type === "finish",
9978
+ includeResponseMessages: payload.type === "finish"
9979
+ });
9980
+ if (completedStep) return [snapshot, createAgentStepDataPart({
9981
+ runId: payload.runId,
9982
+ stepIndex: completedStep.stepIndex,
9983
+ step: completedStep.step
9984
+ })];
9985
+ return snapshot;
9912
9986
  }
9913
9987
  return null;
9914
9988
  }
@@ -10334,10 +10408,24 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
10334
10408
  const step = current.steps.find((step) => step.id === stepId);
10335
10409
  if (!step) return null;
10336
10410
  step[PRIMITIVE_CACHE_SYMBOL] = step[PRIMITIVE_CACHE_SYMBOL] || /* @__PURE__ */ new Map();
10411
+ if (payload.payload.type === "start") delete step[COMPLETED_STEPS_SYMBOL];
10337
10412
  const result = transformAgent(payload.payload, step[PRIMITIVE_CACHE_SYMBOL]);
10338
- if (result) {
10339
- const { request, response, ...data } = result.data;
10413
+ const snapshot = Array.isArray(result) ? result[0] : result;
10414
+ if (snapshot) {
10415
+ const { request, response, ...data } = snapshot.data;
10416
+ if (Array.isArray(result)) {
10417
+ const { stepIndex, step: completedStepDetail } = result[1].data;
10418
+ step[COMPLETED_STEPS_SYMBOL] = step[COMPLETED_STEPS_SYMBOL] || /* @__PURE__ */ new Map();
10419
+ step[COMPLETED_STEPS_SYMBOL].set(stepIndex, completedStepDetail);
10420
+ }
10340
10421
  step.task = data;
10422
+ const completedSteps = step[COMPLETED_STEPS_SYMBOL];
10423
+ if (completedSteps && completedSteps.size > 0 && Array.isArray(data.steps)) {
10424
+ for (const [stepIndex, completedStepDetail] of completedSteps) if (stepIndex < data.steps.length) data.steps[stepIndex] = {
10425
+ ...data.steps[stepIndex],
10426
+ ...completedStepDetail
10427
+ };
10428
+ }
10341
10429
  }
10342
10430
  bufferedNetworks.set(payload.runId, current);
10343
10431
  return {
@@ -10461,6 +10549,124 @@ function toAISdkStream(stream, options = {
10461
10549
  }));
10462
10550
  }
10463
10551
  //#endregion
10552
+ //#region src/sse-heartbeat.ts
10553
+ const SSE_HEARTBEAT_BYTES = new TextEncoder().encode(": heartbeat\n\n");
10554
+ const LF_BYTE = 10;
10555
+ const MAX_TIMEOUT_MS = 2147483647;
10556
+ /** Throws when an enabled heartbeat interval cannot be scheduled with a timer. */
10557
+ function assertValidHeartbeatMs(heartbeatMs) {
10558
+ if (heartbeatMs !== void 0 && !(heartbeatMs <= 0) && (!Number.isFinite(heartbeatMs) || heartbeatMs > MAX_TIMEOUT_MS)) throw new RangeError(`heartbeatMs must be a finite number no greater than ${MAX_TIMEOUT_MS}`);
10559
+ }
10560
+ /**
10561
+ * Adds periodic SSE comment heartbeats to an AI SDK response body.
10562
+ * AI SDK serialization uses LF-delimited frames, which this private wrapper preserves and relies on.
10563
+ */
10564
+ function withSseHeartbeat(response, heartbeatMs) {
10565
+ assertValidHeartbeatMs(heartbeatMs);
10566
+ if (heartbeatMs === void 0 || heartbeatMs <= 0 || !response.body) return response;
10567
+ const reader = response.body.getReader();
10568
+ let heartbeatTimeout;
10569
+ let wakePull;
10570
+ let readResult;
10571
+ let readError;
10572
+ let hasReadError = false;
10573
+ let reading = false;
10574
+ let finished = false;
10575
+ let readerReleased = false;
10576
+ let atFrameBoundary = true;
10577
+ let lastByte;
10578
+ let nextHeartbeatAt = performance.now() + heartbeatMs;
10579
+ const clearHeartbeat = () => {
10580
+ if (heartbeatTimeout !== void 0) {
10581
+ clearTimeout(heartbeatTimeout);
10582
+ heartbeatTimeout = void 0;
10583
+ }
10584
+ };
10585
+ const releaseReader = () => {
10586
+ if (readerReleased) return;
10587
+ readerReleased = true;
10588
+ reader.releaseLock();
10589
+ };
10590
+ const updateFrameBoundary = (chunk) => {
10591
+ if (chunk.byteLength === 0) return;
10592
+ atFrameBoundary = chunk.byteLength === 1 ? lastByte === LF_BYTE && chunk[0] === LF_BYTE : chunk[chunk.byteLength - 2] === LF_BYTE && chunk[chunk.byteLength - 1] === LF_BYTE;
10593
+ lastByte = chunk[chunk.byteLength - 1];
10594
+ };
10595
+ const startRead = () => {
10596
+ if (reading || readResult || hasReadError || finished) return;
10597
+ reading = true;
10598
+ reader.read().then((result) => {
10599
+ reading = false;
10600
+ readResult = result;
10601
+ wakePull?.("read");
10602
+ }, (error) => {
10603
+ reading = false;
10604
+ readError = error;
10605
+ hasReadError = true;
10606
+ wakePull?.("read");
10607
+ });
10608
+ };
10609
+ const forwardRead = (controller) => {
10610
+ if (hasReadError) {
10611
+ finished = true;
10612
+ releaseReader();
10613
+ controller.error(readError);
10614
+ return;
10615
+ }
10616
+ if (!readResult) return;
10617
+ const result = readResult;
10618
+ readResult = void 0;
10619
+ if (result.done) {
10620
+ finished = true;
10621
+ releaseReader();
10622
+ controller.close();
10623
+ return;
10624
+ }
10625
+ updateFrameBoundary(result.value);
10626
+ controller.enqueue(result.value);
10627
+ };
10628
+ const stream = new ReadableStream({
10629
+ async pull(controller) {
10630
+ if (finished) return;
10631
+ startRead();
10632
+ if (readResult || hasReadError) {
10633
+ forwardRead(controller);
10634
+ return;
10635
+ }
10636
+ const next = await new Promise((resolve) => {
10637
+ wakePull = resolve;
10638
+ if (atFrameBoundary) heartbeatTimeout = setTimeout(() => resolve("heartbeat"), Math.max(0, nextHeartbeatAt - performance.now()));
10639
+ });
10640
+ wakePull = void 0;
10641
+ clearHeartbeat();
10642
+ if (finished) return;
10643
+ if (readResult || hasReadError) {
10644
+ forwardRead(controller);
10645
+ return;
10646
+ }
10647
+ if (next === "heartbeat") {
10648
+ controller.enqueue(SSE_HEARTBEAT_BYTES.slice());
10649
+ nextHeartbeatAt = performance.now() + heartbeatMs;
10650
+ }
10651
+ },
10652
+ async cancel(reason) {
10653
+ if (finished) return;
10654
+ finished = true;
10655
+ clearHeartbeat();
10656
+ try {
10657
+ await reader.cancel(reason);
10658
+ } finally {
10659
+ releaseReader();
10660
+ }
10661
+ }
10662
+ });
10663
+ return new Response(stream, {
10664
+ status: response.status,
10665
+ statusText: response.statusText,
10666
+ headers: response.headers
10667
+ });
10668
+ }
10669
+ //#endregion
10464
10670
  //#region src/chat-route.ts
10465
10671
  /**
10466
10672
  * Collects every approval response across all assistant messages in a v6
@@ -10663,11 +10869,13 @@ async function handleChatStream({ mastra, agentId, agentVersion, params, default
10663
10869
  * @param {boolean} [options.sendFinish=true] - Whether to send finish events in the stream
10664
10870
  * @param {boolean} [options.sendReasoning=false] - Whether to include reasoning steps in the stream
10665
10871
  * @param {boolean} [options.sendSources=false] - Whether to include source citations in the stream
10872
+ * @param {number} [options.heartbeatMs] - Target interval for periodic SSE comment heartbeats. Already-buffered source events and stream lifecycle signals take priority. Values up to 0 disable heartbeats. `NaN`, positive infinity, and values above 2,147,483,647 throw a `RangeError`.
10666
10873
  * @param {(error: unknown) => string} [options.onError] - Custom error serializer streamed to the client. When omitted, errors are passed through a default serializer that strips sensitive fields (e.g. `APICallError.requestBodyValues`, which holds the system prompt) before they reach the client.
10667
10874
  *
10668
10875
  * @returns {ReturnType<typeof registerApiRoute>} A registered API route handler
10669
10876
  *
10670
10877
  * @throws {Error} When path doesn't include `:agentId` and no fixed agent is specified
10878
+ * @throws {RangeError} When `heartbeatMs` is `NaN`, positive infinity, or greater than 2,147,483,647
10671
10879
  * @throws {Error} When agent ID is missing at runtime
10672
10880
  * @throws {Error} When specified agent is not found in Mastra instance
10673
10881
  *
@@ -10690,12 +10898,13 @@ async function handleChatStream({ mastra, agentId, agentVersion, params, default
10690
10898
  * @remarks
10691
10899
  * - The route handler expects a JSON body with a `messages` array
10692
10900
  * - Messages should follow the format: `{ role: 'user' | 'assistant' | 'system', content: string }`
10693
- * - The response is a Server-Sent Events (SSE) stream compatible with AI SDK v5
10901
+ * - The response is a Server-Sent Events (SSE) stream compatible with the selected AI SDK version
10694
10902
  * - If both `agent` and `:agentId` are present, a warning is logged and the fixed `agent` takes precedence
10695
10903
  * - Request context from the incoming request overrides `defaultOptions.requestContext` if both are present
10696
10904
  */
10697
- function chatRoute({ path = "/chat/:agentId", agent, defaultOptions, experimentalTransform, version = "v5", agentVersion, sendStart = true, sendFinish = true, sendReasoning = false, sendSources = false, onError }) {
10905
+ function chatRoute({ path = "/chat/:agentId", agent, defaultOptions, experimentalTransform, version = "v5", agentVersion, sendStart = true, sendFinish = true, sendReasoning = false, sendSources = false, heartbeatMs, onError }) {
10698
10906
  if (!agent && !path.includes("/:agentId")) throw new Error("Path must include :agentId to route to the correct agent or pass the agent explicitly");
10907
+ assertValidHeartbeatMs(heartbeatMs);
10699
10908
  return (0, _mastra_core_server.registerApiRoute)(path, {
10700
10909
  method: "POST",
10701
10910
  openapi: {
@@ -10824,11 +11033,13 @@ function chatRoute({ path = "/chat/:agentId", agent, defaultOptions, experimenta
10824
11033
  sendSources,
10825
11034
  onError
10826
11035
  };
10827
- if (version === "v6") return createUIMessageStreamResponse({ stream: await handleChatStream({
11036
+ let response;
11037
+ if (version === "v6") response = createUIMessageStreamResponse({ stream: await handleChatStream({
10828
11038
  ...handlerOptions,
10829
11039
  version: "v6"
10830
11040
  }) });
10831
- return createUIMessageStreamResponse$1({ stream: await handleChatStream(handlerOptions) });
11041
+ else response = createUIMessageStreamResponse$1({ stream: await handleChatStream(handlerOptions) });
11042
+ return withSseHeartbeat(response, heartbeatMs);
10832
11043
  }
10833
11044
  });
10834
11045
  }