@mastra/ai-sdk 0.0.0-fix-thread-list-20251105222841 → 0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939

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/dist/index.cjs CHANGED
@@ -140,6 +140,28 @@ function convertMastraChunkToAISDKv5({
140
140
  toolName: chunk.payload.toolName,
141
141
  input: chunk.payload.args
142
142
  };
143
+ case "tool-call-approval":
144
+ return {
145
+ type: "data-tool-call-approval",
146
+ id: chunk.payload.toolCallId,
147
+ data: {
148
+ runId: chunk.runId,
149
+ toolCallId: chunk.payload.toolCallId,
150
+ toolName: chunk.payload.toolName,
151
+ args: chunk.payload.args
152
+ }
153
+ };
154
+ case "tool-call-suspended":
155
+ return {
156
+ type: "data-tool-call-suspended",
157
+ id: chunk.payload.toolCallId,
158
+ data: {
159
+ runId: chunk.runId,
160
+ toolCallId: chunk.payload.toolCallId,
161
+ toolName: chunk.payload.toolName,
162
+ suspendPayload: chunk.payload.suspendPayload
163
+ }
164
+ };
143
165
  case "tool-call-input-streaming-start":
144
166
  return {
145
167
  type: "tool-input-start",
@@ -230,6 +252,13 @@ function convertMastraChunkToAISDKv5({
230
252
  type: "object",
231
253
  object: chunk.object
232
254
  };
255
+ case "tripwire":
256
+ return {
257
+ type: "data-tripwire",
258
+ data: {
259
+ tripwireReason: chunk.payload.tripwireReason
260
+ }
261
+ };
233
262
  default:
234
263
  if (chunk.type && "payload" in chunk && chunk.payload) {
235
264
  return {
@@ -285,6 +314,14 @@ function convertFullStreamChunkToUIMessageStream({
285
314
  };
286
315
  }
287
316
  case "reasoning-delta": {
317
+ if (sendReasoning) {
318
+ return {
319
+ type: "reasoning-delta",
320
+ id: part.id,
321
+ delta: part.text,
322
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
323
+ };
324
+ }
288
325
  return;
289
326
  }
290
327
  case "reasoning-end": {
@@ -302,6 +339,25 @@ function convertFullStreamChunkToUIMessageStream({
302
339
  };
303
340
  }
304
341
  case "source": {
342
+ if (sendSources && part.sourceType === "url") {
343
+ return {
344
+ type: "source-url",
345
+ sourceId: part.id,
346
+ url: part.url,
347
+ title: part.title,
348
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
349
+ };
350
+ }
351
+ if (sendSources && part.sourceType === "document") {
352
+ return {
353
+ type: "source-document",
354
+ sourceId: part.id,
355
+ mediaType: part.mediaType,
356
+ title: part.title,
357
+ filename: part.filename,
358
+ ...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
359
+ };
360
+ }
305
361
  return;
306
362
  }
307
363
  case "tool-input-start": {
@@ -359,6 +415,14 @@ function convertFullStreamChunkToUIMessageStream({
359
415
  toolCallId: part.toolCallId,
360
416
  payload: part.output
361
417
  };
418
+ } else if (isDataChunkType(part.output)) {
419
+ if (!("data" in part.output)) {
420
+ throw new Error(
421
+ `UI Messages require a data property when using data- prefixed chunks
422
+ ${JSON.stringify(part)}`
423
+ );
424
+ }
425
+ return part.output;
362
426
  }
363
427
  return;
364
428
  }
@@ -384,21 +448,23 @@ function convertFullStreamChunkToUIMessageStream({
384
448
  return { type: "finish-step" };
385
449
  }
386
450
  case "start": {
387
- {
451
+ if (sendStart) {
388
452
  return {
389
453
  type: "start",
390
454
  ...messageMetadataValue != null ? { messageMetadata: messageMetadataValue } : {},
391
455
  ...responseMessageId != null ? { messageId: responseMessageId } : {}
392
456
  };
393
457
  }
458
+ return;
394
459
  }
395
460
  case "finish": {
396
- {
461
+ if (sendFinish) {
397
462
  return {
398
463
  type: "finish",
399
464
  ...messageMetadataValue != null ? { messageMetadata: messageMetadataValue } : {}
400
465
  };
401
466
  }
467
+ return;
402
468
  }
403
469
  case "abort": {
404
470
  return part;
@@ -463,20 +529,37 @@ function AgentNetworkToAISDKTransformer() {
463
529
  }
464
530
  });
465
531
  }
466
- function AgentStreamToAISDKTransformer(lastMessageId) {
532
+ function AgentStreamToAISDKTransformer({
533
+ lastMessageId,
534
+ sendStart,
535
+ sendFinish,
536
+ sendReasoning,
537
+ sendSources,
538
+ messageMetadata,
539
+ onError
540
+ }) {
467
541
  let bufferedSteps = /* @__PURE__ */ new Map();
542
+ let tripwireOccurred = false;
543
+ let finishEventSent = false;
468
544
  return new TransformStream({
469
545
  transform(chunk, controller) {
546
+ if (chunk.type === "tripwire") {
547
+ tripwireOccurred = true;
548
+ }
549
+ if (chunk.type === "finish") {
550
+ finishEventSent = true;
551
+ }
470
552
  const part = convertMastraChunkToAISDKv5({ chunk, mode: "stream" });
471
553
  const transformedChunk = convertFullStreamChunkToUIMessageStream({
472
554
  part,
473
- sendReasoning: false,
474
- sendSources: false,
475
- sendStart: true,
476
- sendFinish: true,
555
+ sendReasoning,
556
+ sendSources,
557
+ messageMetadataValue: messageMetadata?.({ part }),
558
+ sendStart,
559
+ sendFinish,
477
560
  responseMessageId: lastMessageId,
478
561
  onError(error) {
479
- return safeParseErrorObject(error);
562
+ return onError ? onError(error) : safeParseErrorObject(error);
480
563
  }
481
564
  });
482
565
  if (transformedChunk) {
@@ -496,6 +579,14 @@ function AgentStreamToAISDKTransformer(lastMessageId) {
496
579
  controller.enqueue(transformedChunk);
497
580
  }
498
581
  }
582
+ },
583
+ flush(controller) {
584
+ if (tripwireOccurred && !finishEventSent && sendFinish) {
585
+ controller.enqueue({
586
+ type: "finish",
587
+ finishReason: "other"
588
+ });
589
+ }
499
590
  }
500
591
  });
501
592
  }
@@ -728,6 +819,19 @@ function transformWorkflow(payload, bufferedWorkflows, isNested) {
728
819
  }
729
820
  };
730
821
  }
822
+ case "workflow-step-output": {
823
+ const output = payload.payload.output;
824
+ if (output && isDataChunkType(output)) {
825
+ if (!("data" in output)) {
826
+ throw new Error(
827
+ `UI Messages require a data property when using data- prefixed chunks
828
+ ${JSON.stringify(output)}`
829
+ );
830
+ }
831
+ return output;
832
+ }
833
+ return null;
834
+ }
731
835
  default: {
732
836
  if (isDataChunkType(payload)) {
733
837
  if (!("data" in payload)) {
@@ -982,7 +1086,11 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
982
1086
  }
983
1087
 
984
1088
  // src/convert-streams.ts
985
- function toAISdkV5Stream(stream, options = { from: "agent" }) {
1089
+ function toAISdkV5Stream(stream, options = {
1090
+ from: "agent",
1091
+ sendStart: true,
1092
+ sendFinish: true
1093
+ }) {
986
1094
  const from = options?.from;
987
1095
  if (from === "workflow") {
988
1096
  return stream.pipeThrough(WorkflowStreamToAISDKTransformer());
@@ -991,14 +1099,28 @@ function toAISdkV5Stream(stream, options = { from: "agent" }) {
991
1099
  return stream.pipeThrough(AgentNetworkToAISDKTransformer());
992
1100
  }
993
1101
  const agentReadable = "fullStream" in stream ? stream.fullStream : stream;
994
- return agentReadable.pipeThrough(AgentStreamToAISDKTransformer(options?.lastMessageId));
1102
+ return agentReadable.pipeThrough(
1103
+ AgentStreamToAISDKTransformer({
1104
+ lastMessageId: options?.lastMessageId,
1105
+ sendStart: options?.sendStart,
1106
+ sendFinish: options?.sendFinish,
1107
+ sendReasoning: options?.sendReasoning,
1108
+ sendSources: options?.sendSources,
1109
+ messageMetadata: options?.messageMetadata,
1110
+ onError: options?.onError
1111
+ })
1112
+ );
995
1113
  }
996
1114
 
997
1115
  // src/chat-route.ts
998
1116
  function chatRoute({
999
1117
  path = "/chat/:agentId",
1000
1118
  agent,
1001
- defaultOptions
1119
+ defaultOptions,
1120
+ sendStart = true,
1121
+ sendFinish = true,
1122
+ sendReasoning = false,
1123
+ sendSources = false
1002
1124
  }) {
1003
1125
  if (!agent && !path.includes("/:agentId")) {
1004
1126
  throw new Error("Path must include :agentId to route to the correct agent or pass the agent explicitly");
@@ -1132,7 +1254,14 @@ function chatRoute({
1132
1254
  const uiMessageStream = ai.createUIMessageStream({
1133
1255
  originalMessages: messages,
1134
1256
  execute: async ({ writer }) => {
1135
- for await (const part of toAISdkV5Stream(result, { from: "agent", lastMessageId })) {
1257
+ for await (const part of toAISdkV5Stream(result, {
1258
+ from: "agent",
1259
+ lastMessageId,
1260
+ sendStart,
1261
+ sendFinish,
1262
+ sendReasoning,
1263
+ sendSources
1264
+ })) {
1136
1265
  writer.write(part);
1137
1266
  }
1138
1267
  }
@@ -1172,9 +1301,13 @@ function workflowRoute({
1172
1301
  schema: {
1173
1302
  type: "object",
1174
1303
  properties: {
1304
+ runId: { type: "string" },
1305
+ resourceId: { type: "string" },
1175
1306
  inputData: { type: "object", additionalProperties: true },
1307
+ resumeData: { type: "object", additionalProperties: true },
1176
1308
  requestContext: { type: "object", additionalProperties: true },
1177
- tracingOptions: { type: "object", additionalProperties: true }
1309
+ tracingOptions: { type: "object", additionalProperties: true },
1310
+ step: { type: "string" }
1178
1311
  }
1179
1312
  }
1180
1313
  }
@@ -1192,8 +1325,9 @@ function workflowRoute({
1192
1325
  }
1193
1326
  },
1194
1327
  handler: async (c) => {
1195
- const { inputData, resumeData, ...rest } = await c.req.json();
1328
+ const { runId, resourceId, inputData, resumeData, ...rest } = await c.req.json();
1196
1329
  const mastra = c.get("mastra");
1330
+ const requestContext = c.get("requestContext");
1197
1331
  let workflowToUse = workflow;
1198
1332
  if (!workflow) {
1199
1333
  const workflowId = c.req.param("workflowId");
@@ -1211,8 +1345,13 @@ function workflowRoute({
1211
1345
  if (!workflowObj) {
1212
1346
  throw new Error(`Workflow ${workflowToUse} not found`);
1213
1347
  }
1214
- const run = await workflowObj.createRun();
1215
- const stream = resumeData ? run.resumeStream({ resumeData, ...rest }) : run.stream({ inputData, ...rest });
1348
+ if (requestContext && rest.requestContext) {
1349
+ mastra.getLogger()?.warn(
1350
+ `"requestContext" from the request body will be ignored because "requestContext" is already set in the route options.`
1351
+ );
1352
+ }
1353
+ const run = await workflowObj.createRun({ runId, resourceId, ...rest });
1354
+ const stream = resumeData ? run.resumeStream({ resumeData, ...rest, requestContext: requestContext || rest.requestContext }) : run.stream({ inputData, ...rest, requestContext: requestContext || rest.requestContext });
1216
1355
  const uiMessageStream = ai.createUIMessageStream({
1217
1356
  execute: async ({ writer }) => {
1218
1357
  for await (const part of toAISdkV5Stream(stream, { from: "workflow" })) {