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