@mastra/ai-sdk 1.0.0-beta.3 → 1.0.0-beta.5

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
@@ -10,6 +10,31 @@ var stream = require('@mastra/core/stream');
10
10
  var isDataChunkType = (chunk) => {
11
11
  return chunk && typeof chunk === "object" && "type" in chunk && chunk.type?.startsWith("data-");
12
12
  };
13
+ var isMastraTextStreamChunk = (chunk) => {
14
+ return chunk && typeof chunk === "object" && "type" in chunk && typeof chunk.type === "string" && [
15
+ "text-start",
16
+ "text-delta",
17
+ "text-end",
18
+ "reasoning-start",
19
+ "reasoning-delta",
20
+ "reasoning-end",
21
+ "file",
22
+ "source",
23
+ "tool-input-start",
24
+ "tool-input-delta",
25
+ "tool-call",
26
+ "tool-result",
27
+ "tool-error",
28
+ "error",
29
+ "start-step",
30
+ "finish-step",
31
+ "start",
32
+ "finish",
33
+ "abort",
34
+ "tool-input-end",
35
+ "raw"
36
+ ].includes(chunk.type);
37
+ };
13
38
  function safeParseErrorObject(obj) {
14
39
  if (typeof obj !== "object" || obj === null) {
15
40
  return String(obj);
@@ -140,6 +165,28 @@ function convertMastraChunkToAISDKv5({
140
165
  toolName: chunk.payload.toolName,
141
166
  input: chunk.payload.args
142
167
  };
168
+ case "tool-call-approval":
169
+ return {
170
+ type: "data-tool-call-approval",
171
+ id: chunk.payload.toolCallId,
172
+ data: {
173
+ runId: chunk.runId,
174
+ toolCallId: chunk.payload.toolCallId,
175
+ toolName: chunk.payload.toolName,
176
+ args: chunk.payload.args
177
+ }
178
+ };
179
+ case "tool-call-suspended":
180
+ return {
181
+ type: "data-tool-call-suspended",
182
+ id: chunk.payload.toolCallId,
183
+ data: {
184
+ runId: chunk.runId,
185
+ toolCallId: chunk.payload.toolCallId,
186
+ toolName: chunk.payload.toolName,
187
+ suspendPayload: chunk.payload.suspendPayload
188
+ }
189
+ };
143
190
  case "tool-call-input-streaming-start":
144
191
  return {
145
192
  type: "tool-input-start",
@@ -469,7 +516,10 @@ function convertFullStreamChunkToUIMessageStream({
469
516
  }
470
517
 
471
518
  // src/transformers.ts
472
- function WorkflowStreamToAISDKTransformer() {
519
+ var PRIMITIVE_CACHE_SYMBOL = Symbol("primitive-cache");
520
+ function WorkflowStreamToAISDKTransformer({
521
+ includeTextStreamParts
522
+ } = {}) {
473
523
  const bufferedWorkflows = /* @__PURE__ */ new Map();
474
524
  return new TransformStream({
475
525
  start(controller) {
@@ -483,7 +533,7 @@ function WorkflowStreamToAISDKTransformer() {
483
533
  });
484
534
  },
485
535
  transform(chunk, controller) {
486
- const transformed = transformWorkflow(chunk, bufferedWorkflows);
536
+ const transformed = transformWorkflow(chunk, bufferedWorkflows, false, includeTextStreamParts);
487
537
  if (transformed) controller.enqueue(transformed);
488
538
  }
489
539
  });
@@ -512,7 +562,9 @@ function AgentStreamToAISDKTransformer({
512
562
  sendStart,
513
563
  sendFinish,
514
564
  sendReasoning,
515
- sendSources
565
+ sendSources,
566
+ messageMetadata,
567
+ onError
516
568
  }) {
517
569
  let bufferedSteps = /* @__PURE__ */ new Map();
518
570
  let tripwireOccurred = false;
@@ -530,11 +582,12 @@ function AgentStreamToAISDKTransformer({
530
582
  part,
531
583
  sendReasoning,
532
584
  sendSources,
585
+ messageMetadataValue: messageMetadata?.({ part }),
533
586
  sendStart,
534
587
  sendFinish,
535
588
  responseMessageId: lastMessageId,
536
589
  onError(error) {
537
- return safeParseErrorObject(error);
590
+ return onError ? onError(error) : safeParseErrorObject(error);
538
591
  }
539
592
  });
540
593
  if (transformedChunk) {
@@ -701,7 +754,7 @@ function transformAgent(payload, bufferedSteps) {
701
754
  }
702
755
  return null;
703
756
  }
704
- function transformWorkflow(payload, bufferedWorkflows, isNested) {
757
+ function transformWorkflow(payload, bufferedWorkflows, isNested, includeTextStreamParts) {
705
758
  switch (payload.type) {
706
759
  case "workflow-start":
707
760
  bufferedWorkflows.set(payload.runId, {
@@ -794,6 +847,29 @@ function transformWorkflow(payload, bufferedWorkflows, isNested) {
794
847
  }
795
848
  };
796
849
  }
850
+ case "workflow-step-output": {
851
+ const output = payload.payload.output;
852
+ if (includeTextStreamParts && output && isMastraTextStreamChunk(output)) {
853
+ const part = convertMastraChunkToAISDKv5({ chunk: output, mode: "stream" });
854
+ const transformedChunk = convertFullStreamChunkToUIMessageStream({
855
+ part,
856
+ onError(error) {
857
+ return safeParseErrorObject(error);
858
+ }
859
+ });
860
+ return transformedChunk;
861
+ }
862
+ if (output && isDataChunkType(output)) {
863
+ if (!("data" in output)) {
864
+ throw new Error(
865
+ `UI Messages require a data property when using data- prefixed chunks
866
+ ${JSON.stringify(output)}`
867
+ );
868
+ }
869
+ return output;
870
+ }
871
+ return null;
872
+ }
797
873
  default: {
798
874
  if (isDataChunkType(payload)) {
799
875
  if (!("data" in payload)) {
@@ -813,12 +889,29 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
813
889
  case "routing-agent-start": {
814
890
  if (!bufferedNetworks.has(payload.runId)) {
815
891
  bufferedNetworks.set(payload.runId, {
816
- name: payload.payload.agentId,
892
+ name: payload.payload.networkId,
817
893
  steps: [],
818
894
  usage: null,
819
895
  output: null
820
896
  });
821
897
  }
898
+ const current = bufferedNetworks.get(payload.runId);
899
+ current.steps.push({
900
+ id: payload.payload.runId,
901
+ name: payload.payload.agentId,
902
+ status: "running",
903
+ iteration: payload.payload.inputData.iteration,
904
+ input: {
905
+ task: payload.payload.inputData.task,
906
+ threadId: payload.payload.inputData.threadId,
907
+ threadResourceId: payload.payload.inputData.threadResourceId
908
+ },
909
+ output: "",
910
+ task: null,
911
+ suspendPayload: null,
912
+ resumePayload: null,
913
+ [PRIMITIVE_CACHE_SYMBOL]: /* @__PURE__ */ new Map()
914
+ });
822
915
  return {
823
916
  type: isNested ? "data-tool-network" : "data-network",
824
917
  id: payload.runId,
@@ -849,14 +942,19 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
849
942
  };
850
943
  }
851
944
  case "agent-execution-start": {
852
- const current = bufferedNetworks.get(payload.runId) || { name: "", steps: [], usage: null, output: null };
945
+ const current = bufferedNetworks.get(payload.runId);
946
+ if (!current) return null;
853
947
  current.steps.push({
948
+ id: payload.payload.runId,
854
949
  name: payload.payload.agentId,
855
950
  status: "running",
856
- input: payload.payload.args || null,
951
+ iteration: payload.payload.args?.iteration ?? 0,
952
+ input: { prompt: payload.payload.args?.prompt ?? "" },
857
953
  output: null,
954
+ task: null,
858
955
  suspendPayload: null,
859
- resumePayload: null
956
+ resumePayload: null,
957
+ [PRIMITIVE_CACHE_SYMBOL]: /* @__PURE__ */ new Map()
860
958
  });
861
959
  bufferedNetworks.set(payload.runId, current);
862
960
  return {
@@ -869,14 +967,19 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
869
967
  };
870
968
  }
871
969
  case "workflow-execution-start": {
872
- const current = bufferedNetworks.get(payload.runId) || { name: "", steps: [], usage: null, output: null };
970
+ const current = bufferedNetworks.get(payload.runId);
971
+ if (!current) return null;
873
972
  current.steps.push({
874
- name: payload.payload.name,
973
+ id: payload.payload.runId,
974
+ name: payload.payload.workflowId,
875
975
  status: "running",
876
- input: payload.payload.args || null,
976
+ iteration: payload.payload.args?.iteration ?? 0,
977
+ input: { prompt: payload.payload.args?.prompt ?? "" },
877
978
  output: null,
979
+ task: null,
878
980
  suspendPayload: null,
879
- resumePayload: null
981
+ resumePayload: null,
982
+ [PRIMITIVE_CACHE_SYMBOL]: /* @__PURE__ */ new Map()
880
983
  });
881
984
  bufferedNetworks.set(payload.runId, current);
882
985
  return {
@@ -889,14 +992,21 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
889
992
  };
890
993
  }
891
994
  case "tool-execution-start": {
892
- const current = bufferedNetworks.get(payload.runId) || { name: "", steps: [], usage: null, output: null };
995
+ const current = bufferedNetworks.get(payload.runId);
996
+ if (!current) return null;
893
997
  current.steps.push({
998
+ id: payload.payload.args.toolCallId,
894
999
  name: payload.payload.args?.toolName,
895
1000
  status: "running",
1001
+ iteration: payload.payload.args?.iteration ? Number(payload.payload.args.iteration) : 0,
1002
+ task: {
1003
+ id: payload.payload.args?.toolName
1004
+ },
896
1005
  input: payload.payload.args?.args || null,
897
1006
  output: null,
898
1007
  suspendPayload: null,
899
- resumePayload: null
1008
+ resumePayload: null,
1009
+ [PRIMITIVE_CACHE_SYMBOL]: /* @__PURE__ */ new Map()
900
1010
  });
901
1011
  bufferedNetworks.set(payload.runId, current);
902
1012
  return {
@@ -911,14 +1021,13 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
911
1021
  case "agent-execution-end": {
912
1022
  const current = bufferedNetworks.get(payload.runId);
913
1023
  if (!current) return null;
914
- current.steps.push({
915
- name: payload.payload.agentId,
916
- status: "success",
917
- input: null,
918
- output: payload.payload.result,
919
- suspendPayload: null,
920
- resumePayload: null
921
- });
1024
+ const stepId = payload.payload.runId;
1025
+ const step = current.steps.find((step2) => step2.id === stepId);
1026
+ if (!step) {
1027
+ return null;
1028
+ }
1029
+ step.status = "success";
1030
+ step.output = payload.payload.result;
922
1031
  return {
923
1032
  type: isNested ? "data-tool-network" : "data-network",
924
1033
  id: payload.runId,
@@ -933,14 +1042,13 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
933
1042
  case "tool-execution-end": {
934
1043
  const current = bufferedNetworks.get(payload.runId);
935
1044
  if (!current) return null;
936
- current.steps.push({
937
- name: payload.payload.toolName,
938
- status: "success",
939
- input: null,
940
- output: payload.payload.result,
941
- suspendPayload: null,
942
- resumePayload: null
943
- });
1045
+ const stepId = payload.payload.toolCallId;
1046
+ const step = current.steps.find((step2) => step2.id === stepId);
1047
+ if (!step) {
1048
+ return null;
1049
+ }
1050
+ step.status = "success";
1051
+ step.output = payload.payload.result;
944
1052
  return {
945
1053
  type: isNested ? "data-tool-network" : "data-network",
946
1054
  id: payload.runId,
@@ -954,14 +1062,13 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
954
1062
  case "workflow-execution-end": {
955
1063
  const current = bufferedNetworks.get(payload.runId);
956
1064
  if (!current) return null;
957
- current.steps.push({
958
- name: payload.payload.name,
959
- status: "success",
960
- input: null,
961
- output: payload.payload.result,
962
- suspendPayload: null,
963
- resumePayload: null
964
- });
1065
+ const stepId = payload.payload.runId;
1066
+ const step = current.steps.find((step2) => step2.id === stepId);
1067
+ if (!step) {
1068
+ return null;
1069
+ }
1070
+ step.status = "success";
1071
+ step.output = payload.payload.result;
965
1072
  return {
966
1073
  type: isNested ? "data-tool-network" : "data-network",
967
1074
  id: payload.runId,
@@ -976,12 +1083,24 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
976
1083
  case "routing-agent-end": {
977
1084
  const current = bufferedNetworks.get(payload.runId);
978
1085
  if (!current) return null;
1086
+ const stepId = payload.payload.runId;
1087
+ const step = current.steps.find((step2) => step2.id === stepId);
1088
+ if (!step) {
1089
+ return null;
1090
+ }
1091
+ step.status = "success";
1092
+ step.task = {
1093
+ id: payload.payload.primitiveId,
1094
+ type: payload.payload.primitiveType,
1095
+ name: payload.payload.task,
1096
+ reason: payload.payload.selectionReason
1097
+ };
1098
+ step.output = payload.payload.result;
979
1099
  return {
980
1100
  type: isNested ? "data-tool-network" : "data-network",
981
1101
  id: payload.runId,
982
1102
  data: {
983
1103
  ...current,
984
- status: "finished",
985
1104
  usage: payload.payload?.usage ?? current.usage,
986
1105
  output: payload.payload?.result ?? current.output
987
1106
  }
@@ -1015,6 +1134,39 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
1015
1134
  };
1016
1135
  }
1017
1136
  default: {
1137
+ if (payload.type.startsWith("agent-execution-event-")) {
1138
+ const stepId = payload.payload.runId;
1139
+ const current = bufferedNetworks.get(payload.runId);
1140
+ if (!current) return null;
1141
+ const step = current.steps.find((step2) => step2.id === stepId);
1142
+ if (!step) {
1143
+ return null;
1144
+ }
1145
+ step[PRIMITIVE_CACHE_SYMBOL] = step[PRIMITIVE_CACHE_SYMBOL] || /* @__PURE__ */ new Map();
1146
+ const result = transformAgent(payload.payload, step[PRIMITIVE_CACHE_SYMBOL]);
1147
+ if (result) {
1148
+ const { request, response, ...data } = result.data;
1149
+ step.task = data;
1150
+ }
1151
+ }
1152
+ if (payload.type.startsWith("workflow-execution-event-")) {
1153
+ const stepId = payload.payload.runId;
1154
+ const current = bufferedNetworks.get(payload.runId);
1155
+ if (!current) return null;
1156
+ const step = current.steps.find((step2) => step2.id === stepId);
1157
+ if (!step) {
1158
+ return null;
1159
+ }
1160
+ step[PRIMITIVE_CACHE_SYMBOL] = step[PRIMITIVE_CACHE_SYMBOL] || /* @__PURE__ */ new Map();
1161
+ const result = transformWorkflow(payload.payload, step[PRIMITIVE_CACHE_SYMBOL]);
1162
+ if (result && "data" in result) {
1163
+ const data = result.data;
1164
+ step.task = data;
1165
+ if (data.name && step.task) {
1166
+ step.task.id = data.name;
1167
+ }
1168
+ }
1169
+ }
1018
1170
  if (isDataChunkType(payload)) {
1019
1171
  if (!("data" in payload)) {
1020
1172
  throw new Error(
@@ -1022,7 +1174,8 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
1022
1174
  ${JSON.stringify(payload)}`
1023
1175
  );
1024
1176
  }
1025
- return payload;
1177
+ const { type, data } = payload;
1178
+ return { type, data };
1026
1179
  }
1027
1180
  if (isAgentExecutionDataChunkType(payload)) {
1028
1181
  if (!("data" in payload.payload)) {
@@ -1031,7 +1184,8 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
1031
1184
  ${JSON.stringify(payload)}`
1032
1185
  );
1033
1186
  }
1034
- return payload.payload;
1187
+ const { type, data } = payload.payload;
1188
+ return { type, data };
1035
1189
  }
1036
1190
  if (isWorkflowExecutionDataChunkType(payload)) {
1037
1191
  if (!("data" in payload.payload)) {
@@ -1040,7 +1194,8 @@ function transformNetwork(payload, bufferedNetworks, isNested) {
1040
1194
  ${JSON.stringify(payload)}`
1041
1195
  );
1042
1196
  }
1043
- return payload.payload;
1197
+ const { type, data } = payload.payload;
1198
+ return { type, data };
1044
1199
  }
1045
1200
  return null;
1046
1201
  }
@@ -1055,7 +1210,10 @@ function toAISdkV5Stream(stream, options = {
1055
1210
  }) {
1056
1211
  const from = options?.from;
1057
1212
  if (from === "workflow") {
1058
- return stream.pipeThrough(WorkflowStreamToAISDKTransformer());
1213
+ const includeTextStreamParts = options?.includeTextStreamParts ?? true;
1214
+ return stream.pipeThrough(
1215
+ WorkflowStreamToAISDKTransformer({ includeTextStreamParts })
1216
+ );
1059
1217
  }
1060
1218
  if (from === "network") {
1061
1219
  return stream.pipeThrough(AgentNetworkToAISDKTransformer());
@@ -1067,12 +1225,65 @@ function toAISdkV5Stream(stream, options = {
1067
1225
  sendStart: options?.sendStart,
1068
1226
  sendFinish: options?.sendFinish,
1069
1227
  sendReasoning: options?.sendReasoning,
1070
- sendSources: options?.sendSources
1228
+ sendSources: options?.sendSources,
1229
+ messageMetadata: options?.messageMetadata,
1230
+ onError: options?.onError
1071
1231
  })
1072
1232
  );
1073
1233
  }
1074
1234
 
1075
1235
  // src/chat-route.ts
1236
+ async function handleChatStream({
1237
+ mastra,
1238
+ agentId,
1239
+ params,
1240
+ defaultOptions,
1241
+ sendStart = true,
1242
+ sendFinish = true,
1243
+ sendReasoning = false,
1244
+ sendSources = false
1245
+ }) {
1246
+ const { messages, resumeData, runId, requestContext, ...rest } = params;
1247
+ if (resumeData && !runId) {
1248
+ throw new Error("runId is required when resumeData is provided");
1249
+ }
1250
+ const agentObj = mastra.getAgentById(agentId);
1251
+ if (!agentObj) {
1252
+ throw new Error(`Agent ${agentId} not found`);
1253
+ }
1254
+ if (!Array.isArray(messages)) {
1255
+ throw new Error("Messages must be an array of UIMessage objects");
1256
+ }
1257
+ const mergedOptions = {
1258
+ ...defaultOptions,
1259
+ ...rest,
1260
+ ...runId && { runId },
1261
+ requestContext: requestContext || defaultOptions?.requestContext
1262
+ };
1263
+ const result = resumeData ? await agentObj.resumeStream(resumeData, mergedOptions) : await agentObj.stream(messages, mergedOptions);
1264
+ let lastMessageId;
1265
+ if (messages.length) {
1266
+ const lastMessage = messages[messages.length - 1];
1267
+ if (lastMessage?.role === "assistant") {
1268
+ lastMessageId = lastMessage.id;
1269
+ }
1270
+ }
1271
+ return ai.createUIMessageStream({
1272
+ originalMessages: messages,
1273
+ execute: async ({ writer }) => {
1274
+ for await (const part of toAISdkV5Stream(result, {
1275
+ from: "agent",
1276
+ lastMessageId,
1277
+ sendStart,
1278
+ sendFinish,
1279
+ sendReasoning,
1280
+ sendSources
1281
+ })) {
1282
+ writer.write(part);
1283
+ }
1284
+ }
1285
+ });
1286
+ }
1076
1287
  function chatRoute({
1077
1288
  path = "/chat/:agentId",
1078
1289
  agent,
@@ -1109,6 +1320,14 @@ function chatRoute({
1109
1320
  schema: {
1110
1321
  type: "object",
1111
1322
  properties: {
1323
+ resumeData: {
1324
+ type: "object",
1325
+ description: "Resume data for the agent"
1326
+ },
1327
+ runId: {
1328
+ type: "string",
1329
+ description: "The run ID required when resuming an agent execution"
1330
+ },
1112
1331
  messages: {
1113
1332
  type: "array",
1114
1333
  description: "Array of messages in the conversation",
@@ -1179,9 +1398,9 @@ function chatRoute({
1179
1398
  }
1180
1399
  },
1181
1400
  handler: async (c) => {
1182
- const { messages, ...rest } = await c.req.json();
1401
+ const params = await c.req.json();
1183
1402
  const mastra = c.get("mastra");
1184
- const requestContext = c.get("requestContext");
1403
+ const contextRequestContext = c.get("requestContext");
1185
1404
  let agentToUse = agent;
1186
1405
  if (!agent) {
1187
1406
  const agentId = c.req.param("agentId");
@@ -1192,39 +1411,24 @@ function chatRoute({
1192
1411
  `Fixed agent ID was set together with an agentId path parameter. This can lead to unexpected behavior.`
1193
1412
  );
1194
1413
  }
1195
- if (requestContext && defaultOptions?.requestContext) {
1414
+ if (contextRequestContext && defaultOptions?.requestContext) {
1196
1415
  mastra.getLogger()?.warn(`"requestContext" set in the route options will be overridden by the request's "requestContext".`);
1197
1416
  }
1198
1417
  if (!agentToUse) {
1199
1418
  throw new Error("Agent ID is required");
1200
1419
  }
1201
- const agentObj = mastra.getAgent(agentToUse);
1202
- if (!agentObj) {
1203
- throw new Error(`Agent ${agentToUse} not found`);
1204
- }
1205
- const result = await agentObj.stream(messages, {
1206
- ...defaultOptions,
1207
- ...rest,
1208
- requestContext: requestContext || defaultOptions?.requestContext
1209
- });
1210
- let lastMessageId;
1211
- if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
1212
- lastMessageId = messages[messages.length - 1].id;
1213
- }
1214
- const uiMessageStream = ai.createUIMessageStream({
1215
- originalMessages: messages,
1216
- execute: async ({ writer }) => {
1217
- for await (const part of toAISdkV5Stream(result, {
1218
- from: "agent",
1219
- lastMessageId,
1220
- sendStart,
1221
- sendFinish,
1222
- sendReasoning,
1223
- sendSources
1224
- })) {
1225
- writer.write(part);
1226
- }
1227
- }
1420
+ const uiMessageStream = await handleChatStream({
1421
+ mastra,
1422
+ agentId: agentToUse,
1423
+ params: {
1424
+ ...params,
1425
+ requestContext: contextRequestContext || params.requestContext
1426
+ },
1427
+ defaultOptions,
1428
+ sendStart,
1429
+ sendFinish,
1430
+ sendReasoning,
1431
+ sendSources
1228
1432
  });
1229
1433
  return ai.createUIMessageStreamResponse({
1230
1434
  stream: uiMessageStream
@@ -1232,9 +1436,31 @@ function chatRoute({
1232
1436
  }
1233
1437
  });
1234
1438
  }
1439
+ async function handleWorkflowStream({
1440
+ mastra,
1441
+ workflowId,
1442
+ params,
1443
+ includeTextStreamParts = true
1444
+ }) {
1445
+ const { runId, resourceId, inputData, resumeData, requestContext, ...rest } = params;
1446
+ const workflowObj = mastra.getWorkflowById(workflowId);
1447
+ if (!workflowObj) {
1448
+ throw new Error(`Workflow ${workflowId} not found`);
1449
+ }
1450
+ const run = await workflowObj.createRun({ runId, resourceId, ...rest });
1451
+ const stream = resumeData ? run.resumeStream({ resumeData, ...rest, requestContext }) : run.stream({ inputData, ...rest, requestContext });
1452
+ return ai.createUIMessageStream({
1453
+ execute: async ({ writer }) => {
1454
+ for await (const part of toAISdkV5Stream(stream, { from: "workflow", includeTextStreamParts })) {
1455
+ writer.write(part);
1456
+ }
1457
+ }
1458
+ });
1459
+ }
1235
1460
  function workflowRoute({
1236
1461
  path = "/api/workflows/:workflowId/stream",
1237
- workflow
1462
+ workflow,
1463
+ includeTextStreamParts = true
1238
1464
  }) {
1239
1465
  if (!workflow && !path.includes("/:workflowId")) {
1240
1466
  throw new Error("Path must include :workflowId to route to the correct workflow or pass the workflow explicitly");
@@ -1285,8 +1511,9 @@ function workflowRoute({
1285
1511
  }
1286
1512
  },
1287
1513
  handler: async (c) => {
1288
- const { runId, resourceId, inputData, resumeData, ...rest } = await c.req.json();
1514
+ const params = await c.req.json();
1289
1515
  const mastra = c.get("mastra");
1516
+ const contextRequestContext = c.get("requestContext");
1290
1517
  let workflowToUse = workflow;
1291
1518
  if (!workflow) {
1292
1519
  const workflowId = c.req.param("workflowId");
@@ -1300,23 +1527,47 @@ function workflowRoute({
1300
1527
  if (!workflowToUse) {
1301
1528
  throw new Error("Workflow ID is required");
1302
1529
  }
1303
- const workflowObj = mastra.getWorkflow(workflowToUse);
1304
- if (!workflowObj) {
1305
- throw new Error(`Workflow ${workflowToUse} not found`);
1530
+ if (contextRequestContext && params.requestContext) {
1531
+ mastra.getLogger()?.warn(
1532
+ `"requestContext" from the request body will be ignored because "requestContext" is already set in the route options.`
1533
+ );
1306
1534
  }
1307
- const run = await workflowObj.createRun({ runId, resourceId, ...rest });
1308
- const stream = resumeData ? run.resumeStream({ resumeData, ...rest }) : run.stream({ inputData, ...rest });
1309
- const uiMessageStream = ai.createUIMessageStream({
1310
- execute: async ({ writer }) => {
1311
- for await (const part of toAISdkV5Stream(stream, { from: "workflow" })) {
1312
- writer.write(part);
1313
- }
1314
- }
1535
+ const uiMessageStream = await handleWorkflowStream({
1536
+ mastra,
1537
+ workflowId: workflowToUse,
1538
+ params: {
1539
+ ...params,
1540
+ requestContext: contextRequestContext || params.requestContext
1541
+ },
1542
+ includeTextStreamParts
1315
1543
  });
1316
1544
  return ai.createUIMessageStreamResponse({ stream: uiMessageStream });
1317
1545
  }
1318
1546
  });
1319
1547
  }
1548
+ async function handleNetworkStream({
1549
+ mastra,
1550
+ agentId,
1551
+ params,
1552
+ defaultOptions
1553
+ }) {
1554
+ const { messages, ...rest } = params;
1555
+ const agentObj = mastra.getAgentById(agentId);
1556
+ if (!agentObj) {
1557
+ throw new Error(`Agent ${agentId} not found`);
1558
+ }
1559
+ const result = await agentObj.network(messages, {
1560
+ ...defaultOptions,
1561
+ ...rest
1562
+ });
1563
+ return ai.createUIMessageStream({
1564
+ execute: async ({ writer }) => {
1565
+ for await (const part of toAISdkV5Stream(result, { from: "network" })) {
1566
+ writer.write(part);
1567
+ }
1568
+ }
1569
+ });
1570
+ }
1320
1571
  function networkRoute({
1321
1572
  path = "/network/:agentId",
1322
1573
  agent,
@@ -1377,7 +1628,7 @@ function networkRoute({
1377
1628
  }
1378
1629
  },
1379
1630
  handler: async (c) => {
1380
- const { messages, ...rest } = await c.req.json();
1631
+ const params = await c.req.json();
1381
1632
  const mastra = c.get("mastra");
1382
1633
  let agentToUse = agent;
1383
1634
  if (!agent) {
@@ -1392,20 +1643,11 @@ function networkRoute({
1392
1643
  if (!agentToUse) {
1393
1644
  throw new Error("Agent ID is required");
1394
1645
  }
1395
- const agentObj = mastra.getAgent(agentToUse);
1396
- if (!agentObj) {
1397
- throw new Error(`Agent ${agentToUse} not found`);
1398
- }
1399
- const result = await agentObj.network(messages, {
1400
- ...defaultOptions,
1401
- ...rest
1402
- });
1403
- const uiMessageStream = ai.createUIMessageStream({
1404
- execute: async ({ writer }) => {
1405
- for await (const part of toAISdkV5Stream(result, { from: "network" })) {
1406
- writer.write(part);
1407
- }
1408
- }
1646
+ const uiMessageStream = await handleNetworkStream({
1647
+ mastra,
1648
+ agentId: agentToUse,
1649
+ params,
1650
+ defaultOptions
1409
1651
  });
1410
1652
  return ai.createUIMessageStreamResponse({ stream: uiMessageStream });
1411
1653
  }
@@ -1420,6 +1662,9 @@ function toAISdkFormat() {
1420
1662
  }
1421
1663
 
1422
1664
  exports.chatRoute = chatRoute;
1665
+ exports.handleChatStream = handleChatStream;
1666
+ exports.handleNetworkStream = handleNetworkStream;
1667
+ exports.handleWorkflowStream = handleWorkflowStream;
1423
1668
  exports.networkRoute = networkRoute;
1424
1669
  exports.toAISdkFormat = toAISdkFormat;
1425
1670
  exports.toAISdkStream = toAISdkV5Stream;