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