@mastra/ai-sdk 0.0.0-dynamic-model-router-20251010230835 → 0.0.0-error-handler-fix-20251020202607

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
@@ -208,6 +208,9 @@ function convertMastraChunkToAISDKv5({
208
208
  ...chunk.payload || {}
209
209
  };
210
210
  }
211
+ if ("type" in chunk && chunk.type?.startsWith("data-")) {
212
+ return chunk;
213
+ }
211
214
  return;
212
215
  }
213
216
  }
@@ -221,7 +224,7 @@ function convertFullStreamChunkToUIMessageStream({
221
224
  sendFinish,
222
225
  responseMessageId
223
226
  }) {
224
- const partType = part.type;
227
+ const partType = part?.type;
225
228
  switch (partType) {
226
229
  case "text-start": {
227
230
  return {
@@ -378,8 +381,16 @@ function convertFullStreamChunkToUIMessageStream({
378
381
  return;
379
382
  }
380
383
  default: {
381
- const exhaustiveCheck = partType;
382
- throw new Error(`Unknown chunk type: ${exhaustiveCheck}`);
384
+ if ("type" in part && part.type?.startsWith("data-")) {
385
+ if (!("data" in part)) {
386
+ throw new Error(
387
+ `UI Messages require a data property when using data- prefixed chunks
388
+ ${JSON.stringify(part)}`
389
+ );
390
+ }
391
+ return part;
392
+ }
393
+ return;
383
394
  }
384
395
  }
385
396
  }
@@ -390,24 +401,35 @@ function WorkflowStreamToAISDKTransformer() {
390
401
  return new TransformStream({
391
402
  start(controller) {
392
403
  controller.enqueue({
393
- data: JSON.stringify({
394
- type: "start",
395
- messageId: "1"
396
- })
404
+ type: "start"
397
405
  });
398
406
  },
399
407
  flush(controller) {
400
408
  controller.enqueue({
401
- data: JSON.stringify({
402
- type: "finish"
403
- })
409
+ type: "finish"
410
+ });
411
+ },
412
+ transform(chunk, controller) {
413
+ const transformed = transformWorkflow(chunk, bufferedWorkflows);
414
+ if (transformed) controller.enqueue(transformed);
415
+ }
416
+ });
417
+ }
418
+ function AgentNetworkToAISDKTransformer() {
419
+ const bufferedNetworks = /* @__PURE__ */ new Map();
420
+ return new TransformStream({
421
+ start(controller) {
422
+ controller.enqueue({
423
+ type: "start"
404
424
  });
425
+ },
426
+ flush(controller) {
405
427
  controller.enqueue({
406
- data: "[DONE]"
428
+ type: "finish"
407
429
  });
408
430
  },
409
431
  transform(chunk, controller) {
410
- const transformed = transformWorkflow(chunk, bufferedWorkflows);
432
+ const transformed = transformNetwork(chunk, bufferedNetworks);
411
433
  if (transformed) controller.enqueue(transformed);
412
434
  }
413
435
  });
@@ -435,11 +457,11 @@ function AgentStreamToAISDKTransformer() {
435
457
  if (agentTransformed) controller.enqueue(agentTransformed);
436
458
  } else if (transformedChunk.type === "tool-workflow") {
437
459
  const payload = transformedChunk.payload;
438
- const workflowChunk = transformWorkflow(payload, bufferedSteps);
460
+ const workflowChunk = transformWorkflow(payload, bufferedSteps, true);
439
461
  if (workflowChunk) controller.enqueue(workflowChunk);
440
462
  } else if (transformedChunk.type === "tool-network") {
441
463
  const payload = transformedChunk.payload;
442
- const networkChunk = transformNetwork(payload, bufferedSteps);
464
+ const networkChunk = transformNetwork(payload, bufferedSteps, true);
443
465
  if (networkChunk) controller.enqueue(networkChunk);
444
466
  } else {
445
467
  controller.enqueue(transformedChunk);
@@ -584,7 +606,7 @@ function transformAgent(payload, bufferedSteps) {
584
606
  }
585
607
  return null;
586
608
  }
587
- function transformWorkflow(payload, bufferedWorkflows) {
609
+ function transformWorkflow(payload, bufferedWorkflows, isNested) {
588
610
  switch (payload.type) {
589
611
  case "workflow-start":
590
612
  bufferedWorkflows.set(payload.runId, {
@@ -592,7 +614,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
592
614
  steps: {}
593
615
  });
594
616
  return {
595
- type: "data-workflow",
617
+ type: isNested ? "data-tool-workflow" : "data-workflow",
596
618
  id: payload.runId,
597
619
  data: {
598
620
  name: bufferedWorkflows.get(payload.runId).name,
@@ -611,7 +633,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
611
633
  };
612
634
  bufferedWorkflows.set(payload.runId, current);
613
635
  return {
614
- type: "data-workflow",
636
+ type: isNested ? "data-tool-workflow" : "data-workflow",
615
637
  id: payload.runId,
616
638
  data: {
617
639
  name: current.name,
@@ -630,7 +652,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
630
652
  output: payload.payload.output ?? null
631
653
  };
632
654
  return {
633
- type: "data-workflow",
655
+ type: isNested ? "data-tool-workflow" : "data-workflow",
634
656
  id: payload.runId,
635
657
  data: {
636
658
  name: current.name,
@@ -644,7 +666,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
644
666
  const current = bufferedWorkflows.get(payload.runId);
645
667
  if (!current) return null;
646
668
  return {
647
- type: "data-workflow",
669
+ type: isNested ? "data-tool-workflow" : "data-workflow",
648
670
  id: payload.runId,
649
671
  data: {
650
672
  name: current.name,
@@ -658,15 +680,17 @@ function transformWorkflow(payload, bufferedWorkflows) {
658
680
  return null;
659
681
  }
660
682
  }
661
- function transformNetwork(payload, bufferedNetworks) {
683
+ function transformNetwork(payload, bufferedNetworks, isNested) {
662
684
  switch (payload.type) {
663
685
  case "routing-agent-start": {
664
- bufferedNetworks.set(payload.payload.runId, {
665
- name: payload.payload.agentId,
666
- steps: []
667
- });
686
+ if (!bufferedNetworks.has(payload.payload.runId)) {
687
+ bufferedNetworks.set(payload.payload.runId, {
688
+ name: payload.payload.agentId,
689
+ steps: []
690
+ });
691
+ }
668
692
  return {
669
- type: "data-network",
693
+ type: isNested ? "data-tool-network" : "data-network",
670
694
  id: payload.payload.runId,
671
695
  data: {
672
696
  name: bufferedNetworks.get(payload.payload.runId).name,
@@ -676,6 +700,23 @@ function transformNetwork(payload, bufferedNetworks) {
676
700
  }
677
701
  };
678
702
  }
703
+ case "routing-agent-text-start": {
704
+ const current = bufferedNetworks.get(payload.runId);
705
+ if (!current) return null;
706
+ return {
707
+ type: "text-start",
708
+ id: payload.runId
709
+ };
710
+ }
711
+ case "routing-agent-text-delta": {
712
+ const current = bufferedNetworks.get(payload.runId);
713
+ if (!current) return null;
714
+ return {
715
+ type: "text-delta",
716
+ id: payload.runId,
717
+ delta: payload.payload.text
718
+ };
719
+ }
679
720
  case "agent-execution-start": {
680
721
  const current = bufferedNetworks.get(payload.payload.runId) || { name: "", steps: [] };
681
722
  current.steps.push({
@@ -686,7 +727,7 @@ function transformNetwork(payload, bufferedNetworks) {
686
727
  });
687
728
  bufferedNetworks.set(payload.payload.runId, current);
688
729
  return {
689
- type: "data-network",
730
+ type: isNested ? "data-tool-network" : "data-network",
690
731
  id: payload.payload.runId,
691
732
  data: {
692
733
  name: current.name,
@@ -706,7 +747,7 @@ function transformNetwork(payload, bufferedNetworks) {
706
747
  });
707
748
  bufferedNetworks.set(payload.payload.runId, current);
708
749
  return {
709
- type: "data-network",
750
+ type: isNested ? "data-tool-network" : "data-network",
710
751
  id: payload.payload.runId,
711
752
  data: {
712
753
  name: current.name,
@@ -726,7 +767,7 @@ function transformNetwork(payload, bufferedNetworks) {
726
767
  });
727
768
  bufferedNetworks.set(payload.payload.runId, current);
728
769
  return {
729
- type: "data-network",
770
+ type: isNested ? "data-tool-network" : "data-network",
730
771
  id: payload.payload.runId,
731
772
  data: {
732
773
  name: current.name,
@@ -736,32 +777,63 @@ function transformNetwork(payload, bufferedNetworks) {
736
777
  }
737
778
  };
738
779
  }
739
- case "agent-execution-end":
780
+ case "agent-execution-end": {
781
+ const current = bufferedNetworks.get(payload.runId);
782
+ if (!current) return null;
783
+ current.steps.push({
784
+ name: payload.payload.agentId,
785
+ status: "success",
786
+ input: null,
787
+ output: payload.payload.result
788
+ });
789
+ return {
790
+ type: isNested ? "data-tool-network" : "data-network",
791
+ id: payload.runId,
792
+ data: {
793
+ name: current.name,
794
+ status: "running",
795
+ steps: current.steps,
796
+ output: payload.payload.result ?? null
797
+ }
798
+ };
799
+ }
740
800
  case "tool-execution-end": {
741
801
  const current = bufferedNetworks.get(payload.runId);
742
802
  if (!current) return null;
803
+ current.steps.push({
804
+ name: payload.payload.toolName,
805
+ status: "success",
806
+ input: null,
807
+ output: payload.payload.result
808
+ });
743
809
  return {
744
- type: "data-network",
810
+ type: isNested ? "data-tool-network" : "data-network",
745
811
  id: payload.runId,
746
812
  data: {
747
813
  name: current.name,
748
814
  status: "running",
749
815
  steps: current.steps,
750
- output: null
816
+ output: payload.payload.result ?? null
751
817
  }
752
818
  };
753
819
  }
754
820
  case "workflow-execution-end": {
755
821
  const current = bufferedNetworks.get(payload.runId);
756
822
  if (!current) return null;
823
+ current.steps.push({
824
+ name: payload.payload.name,
825
+ status: "success",
826
+ input: null,
827
+ output: payload.payload.result
828
+ });
757
829
  return {
758
- type: "data-network",
830
+ type: isNested ? "data-tool-network" : "data-network",
759
831
  id: payload.runId,
760
832
  data: {
761
833
  name: current.name,
762
834
  status: "running",
763
835
  steps: current.steps,
764
- output: null
836
+ output: payload.payload.result ?? null
765
837
  }
766
838
  };
767
839
  }
@@ -769,7 +841,7 @@ function transformNetwork(payload, bufferedNetworks) {
769
841
  const current = bufferedNetworks.get(payload.payload.runId);
770
842
  if (!current) return null;
771
843
  return {
772
- type: "data-network",
844
+ type: isNested ? "data-tool-network" : "data-network",
773
845
  id: payload.payload.runId,
774
846
  data: {
775
847
  name: current.name,
@@ -783,7 +855,7 @@ function transformNetwork(payload, bufferedNetworks) {
783
855
  const current = bufferedNetworks.get(payload.payload.runId);
784
856
  if (!current) return null;
785
857
  return {
786
- type: "data-network",
858
+ type: isNested ? "data-tool-network" : "data-network",
787
859
  id: payload.payload.runId,
788
860
  data: {
789
861
  name: current.name,
@@ -797,7 +869,7 @@ function transformNetwork(payload, bufferedNetworks) {
797
869
  const current = bufferedNetworks.get(payload.runId);
798
870
  if (!current) return null;
799
871
  return {
800
- type: "data-network",
872
+ type: isNested ? "data-tool-network" : "data-network",
801
873
  id: payload.runId,
802
874
  data: {
803
875
  name: current.name,
@@ -813,8 +885,16 @@ function transformNetwork(payload, bufferedNetworks) {
813
885
  }
814
886
 
815
887
  // src/to-ai-sdk-format.ts
816
- function toAISdkFormat(stream) {
817
- return stream.fullStream.pipeThrough(AgentStreamToAISDKTransformer());
888
+ function toAISdkFormat(stream, options = { from: "agent" }) {
889
+ const from = options?.from;
890
+ if (from === "workflow") {
891
+ return stream.pipeThrough(WorkflowStreamToAISDKTransformer());
892
+ }
893
+ if (from === "network") {
894
+ return stream.pipeThrough(AgentNetworkToAISDKTransformer());
895
+ }
896
+ const agentReadable = "fullStream" in stream ? stream.fullStream : stream;
897
+ return agentReadable.pipeThrough(AgentStreamToAISDKTransformer());
818
898
  }
819
899
 
820
900
  // src/chat-route.ts
@@ -949,8 +1029,9 @@ function chatRoute({
949
1029
  runtimeContext: runtimeContext || defaultOptions?.runtimeContext
950
1030
  });
951
1031
  const uiMessageStream = createUIMessageStream({
1032
+ originalMessages: messages,
952
1033
  execute: async ({ writer }) => {
953
- for await (const part of toAISdkFormat(result)) {
1034
+ for await (const part of toAISdkFormat(result, { from: "agent" })) {
954
1035
  writer.write(part);
955
1036
  }
956
1037
  }
@@ -961,7 +1042,183 @@ function chatRoute({
961
1042
  }
962
1043
  });
963
1044
  }
1045
+ function workflowRoute({
1046
+ path = "/api/workflows/:workflowId/stream",
1047
+ workflow
1048
+ }) {
1049
+ if (!workflow && !path.includes("/:workflowId")) {
1050
+ throw new Error("Path must include :workflowId to route to the correct workflow or pass the workflow explicitly");
1051
+ }
1052
+ return registerApiRoute(path, {
1053
+ method: "POST",
1054
+ openapi: {
1055
+ summary: "Stream a workflow in AI SDK format",
1056
+ description: "Starts a workflow run and streams events as AI SDK UIMessage chunks",
1057
+ tags: ["ai-sdk"],
1058
+ parameters: [
1059
+ {
1060
+ name: "workflowId",
1061
+ in: "path",
1062
+ required: true,
1063
+ description: "The ID of the workflow to stream",
1064
+ schema: { type: "string" }
1065
+ }
1066
+ ],
1067
+ requestBody: {
1068
+ required: true,
1069
+ content: {
1070
+ "application/json": {
1071
+ schema: {
1072
+ type: "object",
1073
+ properties: {
1074
+ inputData: { type: "object", additionalProperties: true },
1075
+ runtimeContext: { type: "object", additionalProperties: true },
1076
+ tracingOptions: { type: "object", additionalProperties: true }
1077
+ }
1078
+ }
1079
+ }
1080
+ }
1081
+ },
1082
+ responses: {
1083
+ "200": {
1084
+ description: "Workflow UIMessage event stream",
1085
+ content: {
1086
+ "text/plain": {
1087
+ schema: { type: "string", description: "SSE stream" }
1088
+ }
1089
+ }
1090
+ }
1091
+ }
1092
+ },
1093
+ handler: async (c) => {
1094
+ const { inputData, ...rest } = await c.req.json();
1095
+ const mastra = c.get("mastra");
1096
+ let workflowToUse = workflow;
1097
+ if (!workflow) {
1098
+ const workflowId = c.req.param("workflowId");
1099
+ workflowToUse = workflowId;
1100
+ }
1101
+ if (c.req.param("workflowId") && workflow) {
1102
+ mastra.getLogger()?.warn(
1103
+ `Fixed workflow ID was set together with a workflowId path parameter. This can lead to unexpected behavior.`
1104
+ );
1105
+ }
1106
+ if (!workflowToUse) {
1107
+ throw new Error("Workflow ID is required");
1108
+ }
1109
+ const workflowObj = mastra.getWorkflow(workflowToUse);
1110
+ if (!workflowObj) {
1111
+ throw new Error(`Workflow ${workflowToUse} not found`);
1112
+ }
1113
+ const run = await workflowObj.createRunAsync();
1114
+ const stream = run.streamVNext({ inputData, ...rest });
1115
+ const uiMessageStream = createUIMessageStream({
1116
+ execute: async ({ writer }) => {
1117
+ for await (const part of toAISdkFormat(stream, { from: "workflow" })) {
1118
+ writer.write(part);
1119
+ }
1120
+ }
1121
+ });
1122
+ return createUIMessageStreamResponse({ stream: uiMessageStream });
1123
+ }
1124
+ });
1125
+ }
1126
+ function networkRoute({
1127
+ path = "/network/:agentId",
1128
+ agent,
1129
+ defaultOptions
1130
+ }) {
1131
+ if (!agent && !path.includes("/:agentId")) {
1132
+ throw new Error("Path must include :agentId to route to the correct agent or pass the agent explicitly");
1133
+ }
1134
+ return registerApiRoute(path, {
1135
+ method: "POST",
1136
+ openapi: {
1137
+ summary: "Execute an agent network and stream AI SDK events",
1138
+ description: "Routes a request to an agent network and streams UIMessage chunks in AI SDK format",
1139
+ tags: ["ai-sdk"],
1140
+ parameters: [
1141
+ {
1142
+ name: "agentId",
1143
+ in: "path",
1144
+ required: true,
1145
+ description: "The ID of the routing agent to execute as a network",
1146
+ schema: { type: "string" }
1147
+ }
1148
+ ],
1149
+ requestBody: {
1150
+ required: true,
1151
+ content: {
1152
+ "application/json": {
1153
+ schema: {
1154
+ type: "object",
1155
+ properties: {
1156
+ messages: { type: "array", items: { type: "object" } },
1157
+ runtimeContext: { type: "object", additionalProperties: true },
1158
+ runId: { type: "string" },
1159
+ maxSteps: { type: "number" },
1160
+ threadId: { type: "string" },
1161
+ resourceId: { type: "string" },
1162
+ modelSettings: { type: "object", additionalProperties: true },
1163
+ telemetry: { type: "object", additionalProperties: true },
1164
+ tools: { type: "array", items: { type: "object" } }
1165
+ },
1166
+ required: ["messages"]
1167
+ }
1168
+ }
1169
+ }
1170
+ },
1171
+ responses: {
1172
+ "200": {
1173
+ description: "Streaming AI SDK UIMessage event stream for the agent network",
1174
+ content: { "text/plain": { schema: { type: "string", description: "SSE stream" } } }
1175
+ },
1176
+ "404": {
1177
+ description: "Agent not found",
1178
+ content: {
1179
+ "application/json": {
1180
+ schema: { type: "object", properties: { error: { type: "string" } } }
1181
+ }
1182
+ }
1183
+ }
1184
+ }
1185
+ },
1186
+ handler: async (c) => {
1187
+ const { messages, ...rest } = await c.req.json();
1188
+ const mastra = c.get("mastra");
1189
+ let agentToUse = agent;
1190
+ if (!agent) {
1191
+ const agentId = c.req.param("agentId");
1192
+ agentToUse = agentId;
1193
+ }
1194
+ if (c.req.param("agentId") && agent) {
1195
+ mastra.getLogger()?.warn(
1196
+ `Fixed agent ID was set together with an agentId path parameter. This can lead to unexpected behavior.`
1197
+ );
1198
+ }
1199
+ if (!agentToUse) {
1200
+ throw new Error("Agent ID is required");
1201
+ }
1202
+ const agentObj = mastra.getAgent(agentToUse);
1203
+ if (!agentObj) {
1204
+ throw new Error(`Agent ${agentToUse} not found`);
1205
+ }
1206
+ const result = await agentObj.network(messages, {
1207
+ ...defaultOptions,
1208
+ ...rest
1209
+ });
1210
+ const uiMessageStream = createUIMessageStream({
1211
+ execute: async ({ writer }) => {
1212
+ for await (const part of toAISdkFormat(result, { from: "network" })) {
1213
+ writer.write(part);
1214
+ }
1215
+ }
1216
+ });
1217
+ return createUIMessageStreamResponse({ stream: uiMessageStream });
1218
+ }
1219
+ });
1220
+ }
964
1221
 
965
- export { WorkflowStreamToAISDKTransformer, chatRoute, toAISdkFormat };
1222
+ export { chatRoute, networkRoute, toAISdkFormat, workflowRoute };
966
1223
  //# sourceMappingURL=index.js.map
967
1224
  //# sourceMappingURL=index.js.map