@mastra/ai-sdk 0.0.0-dynamic-model-router-20251010230835 → 0.0.0-extract-tool-ui-inp-playground-ui-20251023135343

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
@@ -3,6 +3,13 @@ import { createUIMessageStream, createUIMessageStreamResponse } from 'ai';
3
3
  import { DefaultGeneratedFile, DefaultGeneratedFileWithType } from '@mastra/core/stream';
4
4
 
5
5
  // src/chat-route.ts
6
+
7
+ // src/utils.ts
8
+ var isDataChunkType = (chunk) => {
9
+ return chunk && typeof chunk === "object" && "type" in chunk && chunk.type?.startsWith("data-");
10
+ };
11
+
12
+ // src/helpers.ts
6
13
  function convertMastraChunkToAISDKv5({
7
14
  chunk,
8
15
  mode = "stream"
@@ -208,6 +215,9 @@ function convertMastraChunkToAISDKv5({
208
215
  ...chunk.payload || {}
209
216
  };
210
217
  }
218
+ if ("type" in chunk && chunk.type?.startsWith("data-")) {
219
+ return chunk;
220
+ }
211
221
  return;
212
222
  }
213
223
  }
@@ -221,7 +231,7 @@ function convertFullStreamChunkToUIMessageStream({
221
231
  sendFinish,
222
232
  responseMessageId
223
233
  }) {
224
- const partType = part.type;
234
+ const partType = part?.type;
225
235
  switch (partType) {
226
236
  case "text-start": {
227
237
  return {
@@ -378,8 +388,16 @@ function convertFullStreamChunkToUIMessageStream({
378
388
  return;
379
389
  }
380
390
  default: {
381
- const exhaustiveCheck = partType;
382
- throw new Error(`Unknown chunk type: ${exhaustiveCheck}`);
391
+ if (isDataChunkType(part)) {
392
+ if (!("data" in part)) {
393
+ throw new Error(
394
+ `UI Messages require a data property when using data- prefixed chunks
395
+ ${JSON.stringify(part)}`
396
+ );
397
+ }
398
+ return part;
399
+ }
400
+ return;
383
401
  }
384
402
  }
385
403
  }
@@ -390,24 +408,35 @@ function WorkflowStreamToAISDKTransformer() {
390
408
  return new TransformStream({
391
409
  start(controller) {
392
410
  controller.enqueue({
393
- data: JSON.stringify({
394
- type: "start",
395
- messageId: "1"
396
- })
411
+ type: "start"
397
412
  });
398
413
  },
399
414
  flush(controller) {
400
415
  controller.enqueue({
401
- data: JSON.stringify({
402
- type: "finish"
403
- })
416
+ type: "finish"
404
417
  });
418
+ },
419
+ transform(chunk, controller) {
420
+ const transformed = transformWorkflow(chunk, bufferedWorkflows);
421
+ if (transformed) controller.enqueue(transformed);
422
+ }
423
+ });
424
+ }
425
+ function AgentNetworkToAISDKTransformer() {
426
+ const bufferedNetworks = /* @__PURE__ */ new Map();
427
+ return new TransformStream({
428
+ start(controller) {
405
429
  controller.enqueue({
406
- data: "[DONE]"
430
+ type: "start"
431
+ });
432
+ },
433
+ flush(controller) {
434
+ controller.enqueue({
435
+ type: "finish"
407
436
  });
408
437
  },
409
438
  transform(chunk, controller) {
410
- const transformed = transformWorkflow(chunk, bufferedWorkflows);
439
+ const transformed = transformNetwork(chunk, bufferedNetworks);
411
440
  if (transformed) controller.enqueue(transformed);
412
441
  }
413
442
  });
@@ -435,11 +464,11 @@ function AgentStreamToAISDKTransformer() {
435
464
  if (agentTransformed) controller.enqueue(agentTransformed);
436
465
  } else if (transformedChunk.type === "tool-workflow") {
437
466
  const payload = transformedChunk.payload;
438
- const workflowChunk = transformWorkflow(payload, bufferedSteps);
467
+ const workflowChunk = transformWorkflow(payload, bufferedSteps, true);
439
468
  if (workflowChunk) controller.enqueue(workflowChunk);
440
469
  } else if (transformedChunk.type === "tool-network") {
441
470
  const payload = transformedChunk.payload;
442
- const networkChunk = transformNetwork(payload, bufferedSteps);
471
+ const networkChunk = transformNetwork(payload, bufferedSteps, true);
443
472
  if (networkChunk) controller.enqueue(networkChunk);
444
473
  } else {
445
474
  controller.enqueue(transformedChunk);
@@ -584,7 +613,7 @@ function transformAgent(payload, bufferedSteps) {
584
613
  }
585
614
  return null;
586
615
  }
587
- function transformWorkflow(payload, bufferedWorkflows) {
616
+ function transformWorkflow(payload, bufferedWorkflows, isNested) {
588
617
  switch (payload.type) {
589
618
  case "workflow-start":
590
619
  bufferedWorkflows.set(payload.runId, {
@@ -592,7 +621,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
592
621
  steps: {}
593
622
  });
594
623
  return {
595
- type: "data-workflow",
624
+ type: isNested ? "data-tool-workflow" : "data-workflow",
596
625
  id: payload.runId,
597
626
  data: {
598
627
  name: bufferedWorkflows.get(payload.runId).name,
@@ -611,7 +640,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
611
640
  };
612
641
  bufferedWorkflows.set(payload.runId, current);
613
642
  return {
614
- type: "data-workflow",
643
+ type: isNested ? "data-tool-workflow" : "data-workflow",
615
644
  id: payload.runId,
616
645
  data: {
617
646
  name: current.name,
@@ -630,7 +659,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
630
659
  output: payload.payload.output ?? null
631
660
  };
632
661
  return {
633
- type: "data-workflow",
662
+ type: isNested ? "data-tool-workflow" : "data-workflow",
634
663
  id: payload.runId,
635
664
  data: {
636
665
  name: current.name,
@@ -644,7 +673,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
644
673
  const current = bufferedWorkflows.get(payload.runId);
645
674
  if (!current) return null;
646
675
  return {
647
- type: "data-workflow",
676
+ type: isNested ? "data-tool-workflow" : "data-workflow",
648
677
  id: payload.runId,
649
678
  data: {
650
679
  name: current.name,
@@ -654,19 +683,31 @@ function transformWorkflow(payload, bufferedWorkflows) {
654
683
  }
655
684
  };
656
685
  }
657
- default:
686
+ default: {
687
+ if (isDataChunkType(payload)) {
688
+ if (!("data" in payload)) {
689
+ throw new Error(
690
+ `UI Messages require a data property when using data- prefixed chunks
691
+ ${JSON.stringify(payload)}`
692
+ );
693
+ }
694
+ return payload;
695
+ }
658
696
  return null;
697
+ }
659
698
  }
660
699
  }
661
- function transformNetwork(payload, bufferedNetworks) {
700
+ function transformNetwork(payload, bufferedNetworks, isNested) {
662
701
  switch (payload.type) {
663
702
  case "routing-agent-start": {
664
- bufferedNetworks.set(payload.payload.runId, {
665
- name: payload.payload.agentId,
666
- steps: []
667
- });
703
+ if (!bufferedNetworks.has(payload.payload.runId)) {
704
+ bufferedNetworks.set(payload.payload.runId, {
705
+ name: payload.payload.agentId,
706
+ steps: []
707
+ });
708
+ }
668
709
  return {
669
- type: "data-network",
710
+ type: isNested ? "data-tool-network" : "data-network",
670
711
  id: payload.payload.runId,
671
712
  data: {
672
713
  name: bufferedNetworks.get(payload.payload.runId).name,
@@ -676,6 +717,23 @@ function transformNetwork(payload, bufferedNetworks) {
676
717
  }
677
718
  };
678
719
  }
720
+ case "routing-agent-text-start": {
721
+ const current = bufferedNetworks.get(payload.runId);
722
+ if (!current) return null;
723
+ return {
724
+ type: "text-start",
725
+ id: payload.runId
726
+ };
727
+ }
728
+ case "routing-agent-text-delta": {
729
+ const current = bufferedNetworks.get(payload.runId);
730
+ if (!current) return null;
731
+ return {
732
+ type: "text-delta",
733
+ id: payload.runId,
734
+ delta: payload.payload.text
735
+ };
736
+ }
679
737
  case "agent-execution-start": {
680
738
  const current = bufferedNetworks.get(payload.payload.runId) || { name: "", steps: [] };
681
739
  current.steps.push({
@@ -686,7 +744,7 @@ function transformNetwork(payload, bufferedNetworks) {
686
744
  });
687
745
  bufferedNetworks.set(payload.payload.runId, current);
688
746
  return {
689
- type: "data-network",
747
+ type: isNested ? "data-tool-network" : "data-network",
690
748
  id: payload.payload.runId,
691
749
  data: {
692
750
  name: current.name,
@@ -706,7 +764,7 @@ function transformNetwork(payload, bufferedNetworks) {
706
764
  });
707
765
  bufferedNetworks.set(payload.payload.runId, current);
708
766
  return {
709
- type: "data-network",
767
+ type: isNested ? "data-tool-network" : "data-network",
710
768
  id: payload.payload.runId,
711
769
  data: {
712
770
  name: current.name,
@@ -726,7 +784,7 @@ function transformNetwork(payload, bufferedNetworks) {
726
784
  });
727
785
  bufferedNetworks.set(payload.payload.runId, current);
728
786
  return {
729
- type: "data-network",
787
+ type: isNested ? "data-tool-network" : "data-network",
730
788
  id: payload.payload.runId,
731
789
  data: {
732
790
  name: current.name,
@@ -736,32 +794,63 @@ function transformNetwork(payload, bufferedNetworks) {
736
794
  }
737
795
  };
738
796
  }
739
- case "agent-execution-end":
797
+ case "agent-execution-end": {
798
+ const current = bufferedNetworks.get(payload.runId);
799
+ if (!current) return null;
800
+ current.steps.push({
801
+ name: payload.payload.agentId,
802
+ status: "success",
803
+ input: null,
804
+ output: payload.payload.result
805
+ });
806
+ return {
807
+ type: isNested ? "data-tool-network" : "data-network",
808
+ id: payload.runId,
809
+ data: {
810
+ name: current.name,
811
+ status: "running",
812
+ steps: current.steps,
813
+ output: payload.payload.result ?? null
814
+ }
815
+ };
816
+ }
740
817
  case "tool-execution-end": {
741
818
  const current = bufferedNetworks.get(payload.runId);
742
819
  if (!current) return null;
820
+ current.steps.push({
821
+ name: payload.payload.toolName,
822
+ status: "success",
823
+ input: null,
824
+ output: payload.payload.result
825
+ });
743
826
  return {
744
- type: "data-network",
827
+ type: isNested ? "data-tool-network" : "data-network",
745
828
  id: payload.runId,
746
829
  data: {
747
830
  name: current.name,
748
831
  status: "running",
749
832
  steps: current.steps,
750
- output: null
833
+ output: payload.payload.result ?? null
751
834
  }
752
835
  };
753
836
  }
754
837
  case "workflow-execution-end": {
755
838
  const current = bufferedNetworks.get(payload.runId);
756
839
  if (!current) return null;
840
+ current.steps.push({
841
+ name: payload.payload.name,
842
+ status: "success",
843
+ input: null,
844
+ output: payload.payload.result
845
+ });
757
846
  return {
758
- type: "data-network",
847
+ type: isNested ? "data-tool-network" : "data-network",
759
848
  id: payload.runId,
760
849
  data: {
761
850
  name: current.name,
762
851
  status: "running",
763
852
  steps: current.steps,
764
- output: null
853
+ output: payload.payload.result ?? null
765
854
  }
766
855
  };
767
856
  }
@@ -769,7 +858,7 @@ function transformNetwork(payload, bufferedNetworks) {
769
858
  const current = bufferedNetworks.get(payload.payload.runId);
770
859
  if (!current) return null;
771
860
  return {
772
- type: "data-network",
861
+ type: isNested ? "data-tool-network" : "data-network",
773
862
  id: payload.payload.runId,
774
863
  data: {
775
864
  name: current.name,
@@ -783,7 +872,7 @@ function transformNetwork(payload, bufferedNetworks) {
783
872
  const current = bufferedNetworks.get(payload.payload.runId);
784
873
  if (!current) return null;
785
874
  return {
786
- type: "data-network",
875
+ type: isNested ? "data-tool-network" : "data-network",
787
876
  id: payload.payload.runId,
788
877
  data: {
789
878
  name: current.name,
@@ -797,7 +886,7 @@ function transformNetwork(payload, bufferedNetworks) {
797
886
  const current = bufferedNetworks.get(payload.runId);
798
887
  if (!current) return null;
799
888
  return {
800
- type: "data-network",
889
+ type: isNested ? "data-tool-network" : "data-network",
801
890
  id: payload.runId,
802
891
  data: {
803
892
  name: current.name,
@@ -807,14 +896,32 @@ function transformNetwork(payload, bufferedNetworks) {
807
896
  }
808
897
  };
809
898
  }
810
- default:
899
+ default: {
900
+ if (isDataChunkType(payload)) {
901
+ if (!("data" in payload)) {
902
+ throw new Error(
903
+ `UI Messages require a data property when using data- prefixed chunks
904
+ ${JSON.stringify(payload)}`
905
+ );
906
+ }
907
+ return payload;
908
+ }
811
909
  return null;
910
+ }
812
911
  }
813
912
  }
814
913
 
815
914
  // src/to-ai-sdk-format.ts
816
- function toAISdkFormat(stream) {
817
- return stream.fullStream.pipeThrough(AgentStreamToAISDKTransformer());
915
+ function toAISdkFormat(stream, options = { from: "agent" }) {
916
+ const from = options?.from;
917
+ if (from === "workflow") {
918
+ return stream.pipeThrough(WorkflowStreamToAISDKTransformer());
919
+ }
920
+ if (from === "network") {
921
+ return stream.pipeThrough(AgentNetworkToAISDKTransformer());
922
+ }
923
+ const agentReadable = "fullStream" in stream ? stream.fullStream : stream;
924
+ return agentReadable.pipeThrough(AgentStreamToAISDKTransformer());
818
925
  }
819
926
 
820
927
  // src/chat-route.ts
@@ -949,8 +1056,9 @@ function chatRoute({
949
1056
  runtimeContext: runtimeContext || defaultOptions?.runtimeContext
950
1057
  });
951
1058
  const uiMessageStream = createUIMessageStream({
1059
+ originalMessages: messages,
952
1060
  execute: async ({ writer }) => {
953
- for await (const part of toAISdkFormat(result)) {
1061
+ for await (const part of toAISdkFormat(result, { from: "agent" })) {
954
1062
  writer.write(part);
955
1063
  }
956
1064
  }
@@ -961,7 +1069,183 @@ function chatRoute({
961
1069
  }
962
1070
  });
963
1071
  }
1072
+ function workflowRoute({
1073
+ path = "/api/workflows/:workflowId/stream",
1074
+ workflow
1075
+ }) {
1076
+ if (!workflow && !path.includes("/:workflowId")) {
1077
+ throw new Error("Path must include :workflowId to route to the correct workflow or pass the workflow explicitly");
1078
+ }
1079
+ return registerApiRoute(path, {
1080
+ method: "POST",
1081
+ openapi: {
1082
+ summary: "Stream a workflow in AI SDK format",
1083
+ description: "Starts a workflow run and streams events as AI SDK UIMessage chunks",
1084
+ tags: ["ai-sdk"],
1085
+ parameters: [
1086
+ {
1087
+ name: "workflowId",
1088
+ in: "path",
1089
+ required: true,
1090
+ description: "The ID of the workflow to stream",
1091
+ schema: { type: "string" }
1092
+ }
1093
+ ],
1094
+ requestBody: {
1095
+ required: true,
1096
+ content: {
1097
+ "application/json": {
1098
+ schema: {
1099
+ type: "object",
1100
+ properties: {
1101
+ inputData: { type: "object", additionalProperties: true },
1102
+ runtimeContext: { type: "object", additionalProperties: true },
1103
+ tracingOptions: { type: "object", additionalProperties: true }
1104
+ }
1105
+ }
1106
+ }
1107
+ }
1108
+ },
1109
+ responses: {
1110
+ "200": {
1111
+ description: "Workflow UIMessage event stream",
1112
+ content: {
1113
+ "text/plain": {
1114
+ schema: { type: "string", description: "SSE stream" }
1115
+ }
1116
+ }
1117
+ }
1118
+ }
1119
+ },
1120
+ handler: async (c) => {
1121
+ const { inputData, ...rest } = await c.req.json();
1122
+ const mastra = c.get("mastra");
1123
+ let workflowToUse = workflow;
1124
+ if (!workflow) {
1125
+ const workflowId = c.req.param("workflowId");
1126
+ workflowToUse = workflowId;
1127
+ }
1128
+ if (c.req.param("workflowId") && workflow) {
1129
+ mastra.getLogger()?.warn(
1130
+ `Fixed workflow ID was set together with a workflowId path parameter. This can lead to unexpected behavior.`
1131
+ );
1132
+ }
1133
+ if (!workflowToUse) {
1134
+ throw new Error("Workflow ID is required");
1135
+ }
1136
+ const workflowObj = mastra.getWorkflow(workflowToUse);
1137
+ if (!workflowObj) {
1138
+ throw new Error(`Workflow ${workflowToUse} not found`);
1139
+ }
1140
+ const run = await workflowObj.createRunAsync();
1141
+ const stream = run.streamVNext({ inputData, ...rest });
1142
+ const uiMessageStream = createUIMessageStream({
1143
+ execute: async ({ writer }) => {
1144
+ for await (const part of toAISdkFormat(stream, { from: "workflow" })) {
1145
+ writer.write(part);
1146
+ }
1147
+ }
1148
+ });
1149
+ return createUIMessageStreamResponse({ stream: uiMessageStream });
1150
+ }
1151
+ });
1152
+ }
1153
+ function networkRoute({
1154
+ path = "/network/:agentId",
1155
+ agent,
1156
+ defaultOptions
1157
+ }) {
1158
+ if (!agent && !path.includes("/:agentId")) {
1159
+ throw new Error("Path must include :agentId to route to the correct agent or pass the agent explicitly");
1160
+ }
1161
+ return registerApiRoute(path, {
1162
+ method: "POST",
1163
+ openapi: {
1164
+ summary: "Execute an agent network and stream AI SDK events",
1165
+ description: "Routes a request to an agent network and streams UIMessage chunks in AI SDK format",
1166
+ tags: ["ai-sdk"],
1167
+ parameters: [
1168
+ {
1169
+ name: "agentId",
1170
+ in: "path",
1171
+ required: true,
1172
+ description: "The ID of the routing agent to execute as a network",
1173
+ schema: { type: "string" }
1174
+ }
1175
+ ],
1176
+ requestBody: {
1177
+ required: true,
1178
+ content: {
1179
+ "application/json": {
1180
+ schema: {
1181
+ type: "object",
1182
+ properties: {
1183
+ messages: { type: "array", items: { type: "object" } },
1184
+ runtimeContext: { type: "object", additionalProperties: true },
1185
+ runId: { type: "string" },
1186
+ maxSteps: { type: "number" },
1187
+ threadId: { type: "string" },
1188
+ resourceId: { type: "string" },
1189
+ modelSettings: { type: "object", additionalProperties: true },
1190
+ telemetry: { type: "object", additionalProperties: true },
1191
+ tools: { type: "array", items: { type: "object" } }
1192
+ },
1193
+ required: ["messages"]
1194
+ }
1195
+ }
1196
+ }
1197
+ },
1198
+ responses: {
1199
+ "200": {
1200
+ description: "Streaming AI SDK UIMessage event stream for the agent network",
1201
+ content: { "text/plain": { schema: { type: "string", description: "SSE stream" } } }
1202
+ },
1203
+ "404": {
1204
+ description: "Agent not found",
1205
+ content: {
1206
+ "application/json": {
1207
+ schema: { type: "object", properties: { error: { type: "string" } } }
1208
+ }
1209
+ }
1210
+ }
1211
+ }
1212
+ },
1213
+ handler: async (c) => {
1214
+ const { messages, ...rest } = await c.req.json();
1215
+ const mastra = c.get("mastra");
1216
+ let agentToUse = agent;
1217
+ if (!agent) {
1218
+ const agentId = c.req.param("agentId");
1219
+ agentToUse = agentId;
1220
+ }
1221
+ if (c.req.param("agentId") && agent) {
1222
+ mastra.getLogger()?.warn(
1223
+ `Fixed agent ID was set together with an agentId path parameter. This can lead to unexpected behavior.`
1224
+ );
1225
+ }
1226
+ if (!agentToUse) {
1227
+ throw new Error("Agent ID is required");
1228
+ }
1229
+ const agentObj = mastra.getAgent(agentToUse);
1230
+ if (!agentObj) {
1231
+ throw new Error(`Agent ${agentToUse} not found`);
1232
+ }
1233
+ const result = await agentObj.network(messages, {
1234
+ ...defaultOptions,
1235
+ ...rest
1236
+ });
1237
+ const uiMessageStream = createUIMessageStream({
1238
+ execute: async ({ writer }) => {
1239
+ for await (const part of toAISdkFormat(result, { from: "network" })) {
1240
+ writer.write(part);
1241
+ }
1242
+ }
1243
+ });
1244
+ return createUIMessageStreamResponse({ stream: uiMessageStream });
1245
+ }
1246
+ });
1247
+ }
964
1248
 
965
- export { WorkflowStreamToAISDKTransformer, chatRoute, toAISdkFormat };
1249
+ export { chatRoute, networkRoute, toAISdkFormat, workflowRoute };
966
1250
  //# sourceMappingURL=index.js.map
967
1251
  //# sourceMappingURL=index.js.map