@mastra/ai-sdk 0.2.0-alpha.0 → 0.2.0-alpha.2

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
@@ -390,24 +390,35 @@ function WorkflowStreamToAISDKTransformer() {
390
390
  return new TransformStream({
391
391
  start(controller) {
392
392
  controller.enqueue({
393
- data: JSON.stringify({
394
- type: "start",
395
- messageId: "1"
396
- })
393
+ type: "start"
397
394
  });
398
395
  },
399
396
  flush(controller) {
400
397
  controller.enqueue({
401
- data: JSON.stringify({
402
- type: "finish"
403
- })
398
+ type: "finish"
399
+ });
400
+ },
401
+ transform(chunk, controller) {
402
+ const transformed = transformWorkflow(chunk, bufferedWorkflows);
403
+ if (transformed) controller.enqueue(transformed);
404
+ }
405
+ });
406
+ }
407
+ function AgentNetworkToAISDKTransformer() {
408
+ const bufferedNetworks = /* @__PURE__ */ new Map();
409
+ return new TransformStream({
410
+ start(controller) {
411
+ controller.enqueue({
412
+ type: "start"
404
413
  });
414
+ },
415
+ flush(controller) {
405
416
  controller.enqueue({
406
- data: "[DONE]"
417
+ type: "finish"
407
418
  });
408
419
  },
409
420
  transform(chunk, controller) {
410
- const transformed = transformWorkflow(chunk, bufferedWorkflows);
421
+ const transformed = transformNetwork(chunk, bufferedNetworks);
411
422
  if (transformed) controller.enqueue(transformed);
412
423
  }
413
424
  });
@@ -435,11 +446,11 @@ function AgentStreamToAISDKTransformer() {
435
446
  if (agentTransformed) controller.enqueue(agentTransformed);
436
447
  } else if (transformedChunk.type === "tool-workflow") {
437
448
  const payload = transformedChunk.payload;
438
- const workflowChunk = transformWorkflow(payload, bufferedSteps);
449
+ const workflowChunk = transformWorkflow(payload, bufferedSteps, true);
439
450
  if (workflowChunk) controller.enqueue(workflowChunk);
440
451
  } else if (transformedChunk.type === "tool-network") {
441
452
  const payload = transformedChunk.payload;
442
- const networkChunk = transformNetwork(payload, bufferedSteps);
453
+ const networkChunk = transformNetwork(payload, bufferedSteps, true);
443
454
  if (networkChunk) controller.enqueue(networkChunk);
444
455
  } else {
445
456
  controller.enqueue(transformedChunk);
@@ -584,7 +595,7 @@ function transformAgent(payload, bufferedSteps) {
584
595
  }
585
596
  return null;
586
597
  }
587
- function transformWorkflow(payload, bufferedWorkflows) {
598
+ function transformWorkflow(payload, bufferedWorkflows, isNested) {
588
599
  switch (payload.type) {
589
600
  case "workflow-start":
590
601
  bufferedWorkflows.set(payload.runId, {
@@ -592,7 +603,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
592
603
  steps: {}
593
604
  });
594
605
  return {
595
- type: "data-workflow",
606
+ type: isNested ? "data-tool-workflow" : "data-workflow",
596
607
  id: payload.runId,
597
608
  data: {
598
609
  name: bufferedWorkflows.get(payload.runId).name,
@@ -611,7 +622,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
611
622
  };
612
623
  bufferedWorkflows.set(payload.runId, current);
613
624
  return {
614
- type: "data-workflow",
625
+ type: isNested ? "data-tool-workflow" : "data-workflow",
615
626
  id: payload.runId,
616
627
  data: {
617
628
  name: current.name,
@@ -630,7 +641,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
630
641
  output: payload.payload.output ?? null
631
642
  };
632
643
  return {
633
- type: "data-workflow",
644
+ type: isNested ? "data-tool-workflow" : "data-workflow",
634
645
  id: payload.runId,
635
646
  data: {
636
647
  name: current.name,
@@ -644,7 +655,7 @@ function transformWorkflow(payload, bufferedWorkflows) {
644
655
  const current = bufferedWorkflows.get(payload.runId);
645
656
  if (!current) return null;
646
657
  return {
647
- type: "data-workflow",
658
+ type: isNested ? "data-tool-workflow" : "data-workflow",
648
659
  id: payload.runId,
649
660
  data: {
650
661
  name: current.name,
@@ -658,15 +669,17 @@ function transformWorkflow(payload, bufferedWorkflows) {
658
669
  return null;
659
670
  }
660
671
  }
661
- function transformNetwork(payload, bufferedNetworks) {
672
+ function transformNetwork(payload, bufferedNetworks, isNested) {
662
673
  switch (payload.type) {
663
674
  case "routing-agent-start": {
664
- bufferedNetworks.set(payload.payload.runId, {
665
- name: payload.payload.agentId,
666
- steps: []
667
- });
675
+ if (!bufferedNetworks.has(payload.payload.runId)) {
676
+ bufferedNetworks.set(payload.payload.runId, {
677
+ name: payload.payload.agentId,
678
+ steps: []
679
+ });
680
+ }
668
681
  return {
669
- type: "data-network",
682
+ type: isNested ? "data-tool-network" : "data-network",
670
683
  id: payload.payload.runId,
671
684
  data: {
672
685
  name: bufferedNetworks.get(payload.payload.runId).name,
@@ -686,7 +699,7 @@ function transformNetwork(payload, bufferedNetworks) {
686
699
  });
687
700
  bufferedNetworks.set(payload.payload.runId, current);
688
701
  return {
689
- type: "data-network",
702
+ type: isNested ? "data-tool-network" : "data-network",
690
703
  id: payload.payload.runId,
691
704
  data: {
692
705
  name: current.name,
@@ -706,7 +719,7 @@ function transformNetwork(payload, bufferedNetworks) {
706
719
  });
707
720
  bufferedNetworks.set(payload.payload.runId, current);
708
721
  return {
709
- type: "data-network",
722
+ type: isNested ? "data-tool-network" : "data-network",
710
723
  id: payload.payload.runId,
711
724
  data: {
712
725
  name: current.name,
@@ -726,7 +739,7 @@ function transformNetwork(payload, bufferedNetworks) {
726
739
  });
727
740
  bufferedNetworks.set(payload.payload.runId, current);
728
741
  return {
729
- type: "data-network",
742
+ type: isNested ? "data-tool-network" : "data-network",
730
743
  id: payload.payload.runId,
731
744
  data: {
732
745
  name: current.name,
@@ -736,32 +749,63 @@ function transformNetwork(payload, bufferedNetworks) {
736
749
  }
737
750
  };
738
751
  }
739
- case "agent-execution-end":
752
+ case "agent-execution-end": {
753
+ const current = bufferedNetworks.get(payload.runId);
754
+ if (!current) return null;
755
+ current.steps.push({
756
+ name: payload.payload.agentId,
757
+ status: "success",
758
+ input: null,
759
+ output: payload.payload.result
760
+ });
761
+ return {
762
+ type: isNested ? "data-tool-network" : "data-network",
763
+ id: payload.runId,
764
+ data: {
765
+ name: current.name,
766
+ status: "running",
767
+ steps: current.steps,
768
+ output: payload.payload.result ?? null
769
+ }
770
+ };
771
+ }
740
772
  case "tool-execution-end": {
741
773
  const current = bufferedNetworks.get(payload.runId);
742
774
  if (!current) return null;
775
+ current.steps.push({
776
+ name: payload.payload.toolName,
777
+ status: "success",
778
+ input: null,
779
+ output: payload.payload.result
780
+ });
743
781
  return {
744
- type: "data-network",
782
+ type: isNested ? "data-tool-network" : "data-network",
745
783
  id: payload.runId,
746
784
  data: {
747
785
  name: current.name,
748
786
  status: "running",
749
787
  steps: current.steps,
750
- output: null
788
+ output: payload.payload.result ?? null
751
789
  }
752
790
  };
753
791
  }
754
792
  case "workflow-execution-end": {
755
793
  const current = bufferedNetworks.get(payload.runId);
756
794
  if (!current) return null;
795
+ current.steps.push({
796
+ name: payload.payload.name,
797
+ status: "success",
798
+ input: null,
799
+ output: payload.payload.result
800
+ });
757
801
  return {
758
- type: "data-network",
802
+ type: isNested ? "data-tool-network" : "data-network",
759
803
  id: payload.runId,
760
804
  data: {
761
805
  name: current.name,
762
806
  status: "running",
763
807
  steps: current.steps,
764
- output: null
808
+ output: payload.payload.result ?? null
765
809
  }
766
810
  };
767
811
  }
@@ -769,7 +813,7 @@ function transformNetwork(payload, bufferedNetworks) {
769
813
  const current = bufferedNetworks.get(payload.payload.runId);
770
814
  if (!current) return null;
771
815
  return {
772
- type: "data-network",
816
+ type: isNested ? "data-tool-network" : "data-network",
773
817
  id: payload.payload.runId,
774
818
  data: {
775
819
  name: current.name,
@@ -783,7 +827,7 @@ function transformNetwork(payload, bufferedNetworks) {
783
827
  const current = bufferedNetworks.get(payload.payload.runId);
784
828
  if (!current) return null;
785
829
  return {
786
- type: "data-network",
830
+ type: isNested ? "data-tool-network" : "data-network",
787
831
  id: payload.payload.runId,
788
832
  data: {
789
833
  name: current.name,
@@ -797,7 +841,7 @@ function transformNetwork(payload, bufferedNetworks) {
797
841
  const current = bufferedNetworks.get(payload.runId);
798
842
  if (!current) return null;
799
843
  return {
800
- type: "data-network",
844
+ type: isNested ? "data-tool-network" : "data-network",
801
845
  id: payload.runId,
802
846
  data: {
803
847
  name: current.name,
@@ -813,8 +857,16 @@ function transformNetwork(payload, bufferedNetworks) {
813
857
  }
814
858
 
815
859
  // src/to-ai-sdk-format.ts
816
- function toAISdkFormat(stream) {
817
- return stream.fullStream.pipeThrough(AgentStreamToAISDKTransformer());
860
+ function toAISdkFormat(stream, options = { from: "agent" }) {
861
+ const from = options?.from;
862
+ if (from === "workflow") {
863
+ return stream.pipeThrough(WorkflowStreamToAISDKTransformer());
864
+ }
865
+ if (from === "network") {
866
+ return stream.pipeThrough(AgentNetworkToAISDKTransformer());
867
+ }
868
+ const agentReadable = "fullStream" in stream ? stream.fullStream : stream;
869
+ return agentReadable.pipeThrough(AgentStreamToAISDKTransformer());
818
870
  }
819
871
 
820
872
  // src/chat-route.ts
@@ -922,6 +974,7 @@ function chatRoute({
922
974
  handler: async (c) => {
923
975
  const { messages, ...rest } = await c.req.json();
924
976
  const mastra = c.get("mastra");
977
+ const runtimeContext = c.get("runtimeContext");
925
978
  let agentToUse = agent;
926
979
  if (!agent) {
927
980
  const agentId = c.req.param("agentId");
@@ -932,6 +985,9 @@ function chatRoute({
932
985
  `Fixed agent ID was set together with an agentId path parameter. This can lead to unexpected behavior.`
933
986
  );
934
987
  }
988
+ if (runtimeContext && defaultOptions?.runtimeContext) {
989
+ mastra.getLogger()?.warn(`"runtimeContext" set in the route options will be overridden by the request's "runtimeContext".`);
990
+ }
935
991
  if (!agentToUse) {
936
992
  throw new Error("Agent ID is required");
937
993
  }
@@ -941,11 +997,12 @@ function chatRoute({
941
997
  }
942
998
  const result = await agentObj.stream(messages, {
943
999
  ...defaultOptions,
944
- ...rest
1000
+ ...rest,
1001
+ runtimeContext: runtimeContext || defaultOptions?.runtimeContext
945
1002
  });
946
1003
  const uiMessageStream = createUIMessageStream({
947
1004
  execute: async ({ writer }) => {
948
- for await (const part of toAISdkFormat(result)) {
1005
+ for await (const part of toAISdkFormat(result, { from: "agent" })) {
949
1006
  writer.write(part);
950
1007
  }
951
1008
  }
@@ -956,7 +1013,183 @@ function chatRoute({
956
1013
  }
957
1014
  });
958
1015
  }
1016
+ function workflowRoute({
1017
+ path = "/api/workflows/:workflowId/stream",
1018
+ workflow
1019
+ }) {
1020
+ if (!workflow && !path.includes("/:workflowId")) {
1021
+ throw new Error("Path must include :workflowId to route to the correct workflow or pass the workflow explicitly");
1022
+ }
1023
+ return registerApiRoute(path, {
1024
+ method: "POST",
1025
+ openapi: {
1026
+ summary: "Stream a workflow in AI SDK format",
1027
+ description: "Starts a workflow run and streams events as AI SDK UIMessage chunks",
1028
+ tags: ["ai-sdk"],
1029
+ parameters: [
1030
+ {
1031
+ name: "workflowId",
1032
+ in: "path",
1033
+ required: true,
1034
+ description: "The ID of the workflow to stream",
1035
+ schema: { type: "string" }
1036
+ }
1037
+ ],
1038
+ requestBody: {
1039
+ required: true,
1040
+ content: {
1041
+ "application/json": {
1042
+ schema: {
1043
+ type: "object",
1044
+ properties: {
1045
+ inputData: { type: "object", additionalProperties: true },
1046
+ runtimeContext: { type: "object", additionalProperties: true },
1047
+ tracingOptions: { type: "object", additionalProperties: true }
1048
+ }
1049
+ }
1050
+ }
1051
+ }
1052
+ },
1053
+ responses: {
1054
+ "200": {
1055
+ description: "Workflow UIMessage event stream",
1056
+ content: {
1057
+ "text/plain": {
1058
+ schema: { type: "string", description: "SSE stream" }
1059
+ }
1060
+ }
1061
+ }
1062
+ }
1063
+ },
1064
+ handler: async (c) => {
1065
+ const { inputData, ...rest } = await c.req.json();
1066
+ const mastra = c.get("mastra");
1067
+ let workflowToUse = workflow;
1068
+ if (!workflow) {
1069
+ const workflowId = c.req.param("workflowId");
1070
+ workflowToUse = workflowId;
1071
+ }
1072
+ if (c.req.param("workflowId") && workflow) {
1073
+ mastra.getLogger()?.warn(
1074
+ `Fixed workflow ID was set together with a workflowId path parameter. This can lead to unexpected behavior.`
1075
+ );
1076
+ }
1077
+ if (!workflowToUse) {
1078
+ throw new Error("Workflow ID is required");
1079
+ }
1080
+ const workflowObj = mastra.getWorkflow(workflowToUse);
1081
+ if (!workflowObj) {
1082
+ throw new Error(`Workflow ${workflowToUse} not found`);
1083
+ }
1084
+ const run = await workflowObj.createRunAsync();
1085
+ const stream = run.streamVNext({ inputData, ...rest });
1086
+ const uiMessageStream = createUIMessageStream({
1087
+ execute: async ({ writer }) => {
1088
+ for await (const part of toAISdkFormat(stream, { from: "workflow" })) {
1089
+ writer.write(part);
1090
+ }
1091
+ }
1092
+ });
1093
+ return createUIMessageStreamResponse({ stream: uiMessageStream });
1094
+ }
1095
+ });
1096
+ }
1097
+ function networkRoute({
1098
+ path = "/network/:agentId",
1099
+ agent,
1100
+ defaultOptions
1101
+ }) {
1102
+ if (!agent && !path.includes("/:agentId")) {
1103
+ throw new Error("Path must include :agentId to route to the correct agent or pass the agent explicitly");
1104
+ }
1105
+ return registerApiRoute(path, {
1106
+ method: "POST",
1107
+ openapi: {
1108
+ summary: "Execute an agent network and stream AI SDK events",
1109
+ description: "Routes a request to an agent network and streams UIMessage chunks in AI SDK format",
1110
+ tags: ["ai-sdk"],
1111
+ parameters: [
1112
+ {
1113
+ name: "agentId",
1114
+ in: "path",
1115
+ required: true,
1116
+ description: "The ID of the routing agent to execute as a network",
1117
+ schema: { type: "string" }
1118
+ }
1119
+ ],
1120
+ requestBody: {
1121
+ required: true,
1122
+ content: {
1123
+ "application/json": {
1124
+ schema: {
1125
+ type: "object",
1126
+ properties: {
1127
+ messages: { type: "array", items: { type: "object" } },
1128
+ runtimeContext: { type: "object", additionalProperties: true },
1129
+ runId: { type: "string" },
1130
+ maxSteps: { type: "number" },
1131
+ threadId: { type: "string" },
1132
+ resourceId: { type: "string" },
1133
+ modelSettings: { type: "object", additionalProperties: true },
1134
+ telemetry: { type: "object", additionalProperties: true },
1135
+ tools: { type: "array", items: { type: "object" } }
1136
+ },
1137
+ required: ["messages"]
1138
+ }
1139
+ }
1140
+ }
1141
+ },
1142
+ responses: {
1143
+ "200": {
1144
+ description: "Streaming AI SDK UIMessage event stream for the agent network",
1145
+ content: { "text/plain": { schema: { type: "string", description: "SSE stream" } } }
1146
+ },
1147
+ "404": {
1148
+ description: "Agent not found",
1149
+ content: {
1150
+ "application/json": {
1151
+ schema: { type: "object", properties: { error: { type: "string" } } }
1152
+ }
1153
+ }
1154
+ }
1155
+ }
1156
+ },
1157
+ handler: async (c) => {
1158
+ const { messages, ...rest } = await c.req.json();
1159
+ const mastra = c.get("mastra");
1160
+ let agentToUse = agent;
1161
+ if (!agent) {
1162
+ const agentId = c.req.param("agentId");
1163
+ agentToUse = agentId;
1164
+ }
1165
+ if (c.req.param("agentId") && agent) {
1166
+ mastra.getLogger()?.warn(
1167
+ `Fixed agent ID was set together with an agentId path parameter. This can lead to unexpected behavior.`
1168
+ );
1169
+ }
1170
+ if (!agentToUse) {
1171
+ throw new Error("Agent ID is required");
1172
+ }
1173
+ const agentObj = mastra.getAgent(agentToUse);
1174
+ if (!agentObj) {
1175
+ throw new Error(`Agent ${agentToUse} not found`);
1176
+ }
1177
+ const result = await agentObj.network(messages, {
1178
+ ...defaultOptions,
1179
+ ...rest
1180
+ });
1181
+ const uiMessageStream = createUIMessageStream({
1182
+ execute: async ({ writer }) => {
1183
+ for await (const part of toAISdkFormat(result, { from: "network" })) {
1184
+ writer.write(part);
1185
+ }
1186
+ }
1187
+ });
1188
+ return createUIMessageStreamResponse({ stream: uiMessageStream });
1189
+ }
1190
+ });
1191
+ }
959
1192
 
960
- export { WorkflowStreamToAISDKTransformer, chatRoute, toAISdkFormat };
1193
+ export { chatRoute, networkRoute, toAISdkFormat, workflowRoute };
961
1194
  //# sourceMappingURL=index.js.map
962
1195
  //# sourceMappingURL=index.js.map