@mastra/react 0.0.0-fix-runtimeContext-passing-chatRoute-20251008220150 → 0.0.0-unified-sidebar-20251010130811

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.js CHANGED
@@ -25,165 +25,6 @@ const MastraReactProvider = ({ children, baseUrl, headers }) => {
25
25
  return /* @__PURE__ */ jsxRuntime.jsx(MastraClientProvider, { baseUrl, headers, children });
26
26
  };
27
27
 
28
- const useChat = ({ agentId, initializeMessages }) => {
29
- const [messages, setMessages] = react.useState(initializeMessages || []);
30
- const baseClient = useMastraClient();
31
- const [isRunning, setIsRunning] = react.useState(false);
32
- const generate = async ({
33
- coreUserMessages,
34
- runtimeContext,
35
- threadId,
36
- modelSettings,
37
- signal,
38
- onFinish
39
- }) => {
40
- const {
41
- frequencyPenalty,
42
- presencePenalty,
43
- maxRetries,
44
- maxTokens,
45
- temperature,
46
- topK,
47
- topP,
48
- instructions,
49
- providerOptions
50
- } = modelSettings || {};
51
- setIsRunning(true);
52
- const clientWithAbort = new clientJs.MastraClient({
53
- ...baseClient.options,
54
- abortSignal: signal
55
- });
56
- const agent = clientWithAbort.getAgent(agentId);
57
- const response = await agent.generate({
58
- messages: coreUserMessages,
59
- runId: agentId,
60
- modelSettings: {
61
- frequencyPenalty,
62
- presencePenalty,
63
- maxRetries,
64
- maxOutputTokens: maxTokens,
65
- temperature,
66
- topK,
67
- topP
68
- },
69
- instructions,
70
- runtimeContext,
71
- ...threadId ? { threadId, resourceId: agentId } : {},
72
- providerOptions
73
- });
74
- setIsRunning(false);
75
- const uiMessages = response && "uiMessages" in response.response && response.response.uiMessages ? response.response.uiMessages : [];
76
- const formatted = onFinish({ messages: uiMessages, tripwireReason: response.tripwireReason });
77
- setMessages((prev) => [...prev, ...formatted]);
78
- };
79
- const stream = async ({
80
- coreUserMessages,
81
- runtimeContext,
82
- threadId,
83
- onChunk,
84
- modelSettings,
85
- signal
86
- }) => {
87
- const {
88
- frequencyPenalty,
89
- presencePenalty,
90
- maxRetries,
91
- maxTokens,
92
- temperature,
93
- topK,
94
- topP,
95
- instructions,
96
- providerOptions
97
- } = modelSettings || {};
98
- setIsRunning(true);
99
- const clientWithAbort = new clientJs.MastraClient({
100
- ...baseClient.options,
101
- abortSignal: signal
102
- });
103
- const agent = clientWithAbort.getAgent(agentId);
104
- const response = await agent.stream({
105
- messages: coreUserMessages,
106
- runId: agentId,
107
- modelSettings: {
108
- frequencyPenalty,
109
- presencePenalty,
110
- maxRetries,
111
- maxOutputTokens: maxTokens,
112
- temperature,
113
- topK,
114
- topP
115
- },
116
- instructions,
117
- runtimeContext,
118
- ...threadId ? { threadId, resourceId: agentId } : {},
119
- providerOptions
120
- });
121
- if (!response.body) {
122
- setIsRunning(false);
123
- throw new Error("[Stream] No response body");
124
- }
125
- await response.processDataStream({
126
- onChunk: (chunk) => {
127
- reactDom.flushSync(() => {
128
- setMessages((prev) => onChunk(chunk, prev));
129
- });
130
- return Promise.resolve();
131
- }
132
- });
133
- setIsRunning(false);
134
- };
135
- const network = async ({
136
- coreUserMessages,
137
- runtimeContext,
138
- threadId,
139
- onNetworkChunk,
140
- modelSettings,
141
- signal
142
- }) => {
143
- const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
144
- setIsRunning(true);
145
- const clientWithAbort = new clientJs.MastraClient({
146
- ...baseClient.options,
147
- abortSignal: signal
148
- });
149
- const agent = clientWithAbort.getAgent(agentId);
150
- const response = await agent.network({
151
- messages: coreUserMessages,
152
- maxSteps,
153
- modelSettings: {
154
- frequencyPenalty,
155
- presencePenalty,
156
- maxRetries,
157
- maxOutputTokens: maxTokens,
158
- temperature,
159
- topK,
160
- topP
161
- },
162
- runId: agentId,
163
- runtimeContext,
164
- ...threadId ? { thread: threadId, resourceId: agentId } : {}
165
- });
166
- await response.processDataStream({
167
- onChunk: (chunk) => {
168
- reactDom.flushSync(() => {
169
- setMessages((prev) => onNetworkChunk(chunk, prev));
170
- });
171
- return Promise.resolve();
172
- }
173
- });
174
- setIsRunning(false);
175
- };
176
- return {
177
- network,
178
- stream,
179
- generate,
180
- isRunning,
181
- messages,
182
- setMessages,
183
- cancelRun: () => setIsRunning(false)
184
- };
185
- };
186
-
187
28
  const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
188
29
  if (chunk.type === "workflow-start") {
189
30
  return {
@@ -255,17 +96,32 @@ const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
255
96
  }
256
97
  return prev;
257
98
  };
258
- const toUIMessage = ({
259
- chunk,
260
- conversation
261
- }) => {
99
+ const toUIMessage = ({ chunk, conversation, metadata }) => {
262
100
  const result = [...conversation];
263
101
  switch (chunk.type) {
102
+ case "tripwire": {
103
+ const newMessage = {
104
+ id: `tripwire-${chunk.runId + Date.now()}`,
105
+ role: "assistant",
106
+ parts: [
107
+ {
108
+ type: "text",
109
+ text: chunk.payload.tripwireReason
110
+ }
111
+ ],
112
+ metadata: {
113
+ ...metadata,
114
+ status: "warning"
115
+ }
116
+ };
117
+ return [...result, newMessage];
118
+ }
264
119
  case "start": {
265
120
  const newMessage = {
266
- id: chunk.runId,
121
+ id: `start-${chunk.runId + Date.now()}`,
267
122
  role: "assistant",
268
- parts: []
123
+ parts: [],
124
+ metadata
269
125
  };
270
126
  return [...result, newMessage];
271
127
  }
@@ -315,7 +171,7 @@ const toUIMessage = ({
315
171
  const lastMessage = result[result.length - 1];
316
172
  if (!lastMessage || lastMessage.role !== "assistant") {
317
173
  const newMessage = {
318
- id: chunk.runId,
174
+ id: `reasoning-${chunk.runId + Date.now()}`,
319
175
  role: "assistant",
320
176
  parts: [
321
177
  {
@@ -324,7 +180,8 @@ const toUIMessage = ({
324
180
  state: "streaming",
325
181
  providerMetadata: chunk.payload.providerMetadata
326
182
  }
327
- ]
183
+ ],
184
+ metadata
328
185
  };
329
186
  return [...result, newMessage];
330
187
  }
@@ -359,7 +216,7 @@ const toUIMessage = ({
359
216
  const lastMessage = result[result.length - 1];
360
217
  if (!lastMessage || lastMessage.role !== "assistant") {
361
218
  const newMessage = {
362
- id: chunk.runId,
219
+ id: `tool-call-${chunk.runId + Date.now()}`,
363
220
  role: "assistant",
364
221
  parts: [
365
222
  {
@@ -370,7 +227,8 @@ const toUIMessage = ({
370
227
  input: chunk.payload.args,
371
228
  callProviderMetadata: chunk.payload.providerMetadata
372
229
  }
373
- ]
230
+ ],
231
+ metadata
374
232
  };
375
233
  return [...result, newMessage];
376
234
  }
@@ -412,13 +270,14 @@ const toUIMessage = ({
412
270
  callProviderMetadata: chunk.payload.providerMetadata
413
271
  };
414
272
  } else {
273
+ const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
415
274
  parts[toolPartIndex] = {
416
275
  type: "dynamic-tool",
417
276
  toolName: toolPart.toolName,
418
277
  toolCallId: toolPart.toolCallId,
419
278
  state: "output-available",
420
279
  input: toolPart.input,
421
- output: toolPart.output,
280
+ output: isWorkflow ? chunk.payload.result?.result : chunk.payload.result,
422
281
  callProviderMetadata: chunk.payload.providerMetadata
423
282
  };
424
283
  }
@@ -546,283 +405,26 @@ const toUIMessage = ({
546
405
  ];
547
406
  }
548
407
  case "error": {
549
- return result;
550
- }
551
- // For all other chunk types, return conversation unchanged
552
- default:
553
- return result;
554
- }
555
- };
556
-
557
- const toNetworkUIMessage = ({
558
- chunk,
559
- conversation
560
- }) => {
561
- const result = [...conversation];
562
- if (chunk.type === "agent-execution-start" || chunk.type === "workflow-execution-start") {
563
- const primitiveId = chunk.payload?.args?.primitiveId;
564
- const runId = chunk.payload.runId;
565
- if (!primitiveId || !runId) return result;
566
- const newMessage = {
567
- id: runId,
568
- role: "assistant",
569
- parts: [
570
- {
571
- type: "dynamic-tool",
572
- toolName: primitiveId,
573
- toolCallId: runId,
574
- state: "input-available",
575
- input: chunk.payload.args,
576
- output: {
577
- networkMetadata: {
578
- selectionReason: chunk.payload?.args?.selectionReason || "",
579
- from: chunk.type === "agent-execution-start" ? "AGENT" : "WORKFLOW"
580
- },
581
- result: void 0
582
- }
583
- }
584
- ]
585
- };
586
- return [...result, newMessage];
587
- }
588
- if (chunk.type.startsWith("agent-execution-event-")) {
589
- const agentChunk = chunk.payload;
590
- const lastMessage = result[result.length - 1];
591
- if (!lastMessage || lastMessage.role !== "assistant") return result;
592
- const parts = [...lastMessage.parts];
593
- const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
594
- if (toolPartIndex === -1) return result;
595
- const toolPart = parts[toolPartIndex];
596
- if (toolPart.type !== "dynamic-tool") return result;
597
- if (agentChunk.type === "text-delta") {
598
- const currentInput = toolPart.input;
599
- const messages = currentInput?.messages || [];
600
- const lastMessage2 = messages[messages.length - 1];
601
- const nextMessages = lastMessage2?.type === "text" ? [
602
- ...messages.slice(0, -1),
603
- { type: "text", content: (lastMessage2?.content || "") + agentChunk.payload.text }
604
- ] : [...messages, { type: "text", content: agentChunk.payload.text }];
605
- parts[toolPartIndex] = {
606
- ...toolPart,
607
- input: {
608
- ...currentInput,
609
- messages: nextMessages
610
- }
611
- };
612
- } else if (agentChunk.type === "tool-call") {
613
- const currentInput = toolPart.input;
614
- const messages = currentInput?.messages || [];
615
- parts[toolPartIndex] = {
616
- ...toolPart,
617
- input: {
618
- ...currentInput,
619
- messages: [
620
- ...messages,
621
- {
622
- type: "tool",
623
- toolCallId: agentChunk.payload.toolCallId,
624
- toolName: agentChunk.payload.toolName,
625
- toolInput: agentChunk.payload.args
626
- }
627
- ]
628
- }
629
- };
630
- } else if (agentChunk.type === "tool-result") {
631
- const currentInput = toolPart.input;
632
- const messages = currentInput?.messages || [];
633
- const lastToolIndex = messages.length - 1;
634
- if (lastToolIndex >= 0 && messages[lastToolIndex]?.type === "tool") {
635
- parts[toolPartIndex] = {
636
- ...toolPart,
637
- input: {
638
- ...currentInput,
639
- messages: [
640
- ...messages.slice(0, -1),
641
- {
642
- ...messages[lastToolIndex],
643
- toolOutput: agentChunk.payload.result
644
- }
645
- ]
646
- }
647
- };
648
- }
649
- } else if (agentChunk.type === "tool-output") {
650
- if (agentChunk.payload?.output?.type?.startsWith("workflow-")) {
651
- const currentOutput = toolPart.output || {};
652
- const existingWorkflowState = currentOutput.result || {};
653
- const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
654
- existingWorkflowState,
655
- agentChunk.payload.output
656
- );
657
- parts[toolPartIndex] = {
658
- ...toolPart,
659
- output: {
660
- networkMetadata: currentOutput.networkMetadata,
661
- result: updatedWorkflowState
662
- }
663
- };
664
- }
665
- }
666
- return [
667
- ...result.slice(0, -1),
668
- {
669
- ...lastMessage,
670
- parts
671
- }
672
- ];
673
- }
674
- if (chunk.type.startsWith("workflow-execution-event-")) {
675
- const workflowChunk = chunk.payload;
676
- const lastMessage = result[result.length - 1];
677
- if (!lastMessage || lastMessage.role !== "assistant") return result;
678
- const parts = [...lastMessage.parts];
679
- const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
680
- if (toolPartIndex === -1) return result;
681
- const toolPart = parts[toolPartIndex];
682
- if (toolPart.type !== "dynamic-tool") return result;
683
- const currentOutput = toolPart.output || {};
684
- const existingWorkflowState = currentOutput.result || {};
685
- const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, workflowChunk);
686
- parts[toolPartIndex] = {
687
- ...toolPart,
688
- output: {
689
- networkMetadata: currentOutput.networkMetadata,
690
- result: updatedWorkflowState
691
- }
692
- };
693
- return [
694
- ...result.slice(0, -1),
695
- {
696
- ...lastMessage,
697
- parts
698
- }
699
- ];
700
- }
701
- if (chunk.type === "tool-execution-start") {
702
- const { args: argsData } = chunk.payload;
703
- const lastMessage = result[result.length - 1];
704
- const nestedArgs = argsData.args || {};
705
- if (!lastMessage || lastMessage.role !== "assistant") {
706
408
  const newMessage = {
707
- id: chunk.runId,
409
+ id: `error-${chunk.runId + Date.now()}`,
708
410
  role: "assistant",
709
411
  parts: [
710
412
  {
711
- type: "dynamic-tool",
712
- toolName: argsData.toolName || "unknown",
713
- toolCallId: argsData.toolCallId || "unknown",
714
- state: "input-available",
715
- input: nestedArgs,
716
- output: {
717
- networkMetadata: {
718
- selectionReason: argsData.selectionReason || ""
719
- },
720
- result: void 0
721
- }
413
+ type: "text",
414
+ text: chunk.payload.error
722
415
  }
723
- ]
416
+ ],
417
+ metadata: {
418
+ ...metadata,
419
+ status: "error"
420
+ }
724
421
  };
725
422
  return [...result, newMessage];
726
423
  }
727
- const parts = [...lastMessage.parts];
728
- parts.push({
729
- type: "dynamic-tool",
730
- toolName: argsData.toolName || "unknown",
731
- toolCallId: argsData.toolCallId || "unknown",
732
- state: "input-available",
733
- input: nestedArgs,
734
- output: {
735
- networkMetadata: {
736
- selectionReason: argsData.selectionReason || ""
737
- },
738
- result: void 0
739
- }
740
- });
741
- return [
742
- ...result.slice(0, -1),
743
- {
744
- ...lastMessage,
745
- parts
746
- }
747
- ];
748
- }
749
- if (chunk.type === "tool-execution-end") {
750
- const lastMessage = result[result.length - 1];
751
- if (!lastMessage || lastMessage.role !== "assistant") return result;
752
- const parts = [...lastMessage.parts];
753
- const toolPartIndex = parts.findIndex(
754
- (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
755
- );
756
- if (toolPartIndex !== -1) {
757
- const toolPart = parts[toolPartIndex];
758
- if (toolPart.type === "dynamic-tool") {
759
- const currentOutput = toolPart.output;
760
- parts[toolPartIndex] = {
761
- type: "dynamic-tool",
762
- toolName: toolPart.toolName,
763
- toolCallId: toolPart.toolCallId,
764
- state: "output-available",
765
- input: toolPart.input,
766
- output: {
767
- networkMetadata: currentOutput?.networkMetadata,
768
- result: chunk.payload.result
769
- }
770
- };
771
- }
772
- }
773
- return [
774
- ...result.slice(0, -1),
775
- {
776
- ...lastMessage,
777
- parts
778
- }
779
- ];
780
- }
781
- if (chunk.type === "agent-execution-end" || chunk.type === "workflow-execution-end") {
782
- const lastMessage = result[result.length - 1];
783
- if (!lastMessage || lastMessage.role !== "assistant") return result;
784
- const parts = [...lastMessage.parts];
785
- const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
786
- if (toolPartIndex !== -1) {
787
- const toolPart = parts[toolPartIndex];
788
- if (toolPart.type === "dynamic-tool") {
789
- const currentOutput = toolPart.output;
790
- parts[toolPartIndex] = {
791
- type: "dynamic-tool",
792
- toolName: toolPart.toolName,
793
- toolCallId: toolPart.toolCallId,
794
- state: "output-available",
795
- input: toolPart.input,
796
- output: {
797
- networkMetadata: currentOutput?.networkMetadata,
798
- result: currentOutput?.result || chunk.payload?.result || ""
799
- }
800
- };
801
- }
802
- }
803
- return [
804
- ...result.slice(0, -1),
805
- {
806
- ...lastMessage,
807
- parts
808
- }
809
- ];
810
- }
811
- if (chunk.type === "network-execution-event-step-finish") {
812
- const newMessage = {
813
- id: chunk.runId,
814
- role: "assistant",
815
- parts: [
816
- {
817
- type: "text",
818
- text: chunk.payload?.result || "",
819
- state: "done"
820
- }
821
- ]
822
- };
823
- return [...result, newMessage];
424
+ // For all other chunk types, return conversation unchanged
425
+ default:
426
+ return result;
824
427
  }
825
- return result;
826
428
  };
827
429
 
828
430
  const toAssistantUIMessage = (message) => {
@@ -831,13 +433,15 @@ const toAssistantUIMessage = (message) => {
831
433
  if (part.type === "text") {
832
434
  return {
833
435
  type: "text",
834
- text: part.text
436
+ text: part.text,
437
+ metadata: message.metadata
835
438
  };
836
439
  }
837
440
  if (part.type === "reasoning") {
838
441
  return {
839
442
  type: "reasoning",
840
- text: part.text
443
+ text: part.text,
444
+ metadata: message.metadata
841
445
  };
842
446
  }
843
447
  if (part.type === "source-url") {
@@ -846,7 +450,8 @@ const toAssistantUIMessage = (message) => {
846
450
  sourceType: "url",
847
451
  id: part.sourceId,
848
452
  url: part.url,
849
- title: part.title
453
+ title: part.title,
454
+ metadata: message.metadata
850
455
  };
851
456
  }
852
457
  if (part.type === "source-document") {
@@ -854,16 +459,18 @@ const toAssistantUIMessage = (message) => {
854
459
  type: "file",
855
460
  filename: part.filename,
856
461
  mimeType: part.mediaType,
857
- data: ""
462
+ data: "",
858
463
  // Source documents don't have inline data
464
+ metadata: message.metadata
859
465
  };
860
466
  }
861
467
  if (part.type === "file") {
862
468
  return {
863
469
  type: "file",
864
470
  mimeType: part.mediaType,
865
- data: part.url
471
+ data: part.url,
866
472
  // Use URL as data source
473
+ metadata: message.metadata
867
474
  };
868
475
  }
869
476
  if (part.type === "dynamic-tool") {
@@ -871,22 +478,27 @@ const toAssistantUIMessage = (message) => {
871
478
  type: "tool-call",
872
479
  toolCallId: part.toolCallId,
873
480
  toolName: part.toolName,
874
- argsText: JSON.stringify(part.input)
481
+ argsText: JSON.stringify(part.input),
482
+ args: part.input,
483
+ metadata: message.metadata
875
484
  };
876
- if (part.state === "output-available" && "output" in part) {
877
- return { ...baseToolCall, result: part.output };
878
- } else if (part.state === "output-error" && "errorText" in part) {
485
+ if (part.state === "output-error" && "errorText" in part) {
879
486
  return { ...baseToolCall, result: part.errorText, isError: true };
880
487
  }
488
+ if ("output" in part) {
489
+ return { ...baseToolCall, result: part.output };
490
+ }
881
491
  return baseToolCall;
882
492
  }
883
- if (part.type.startsWith("tool-")) {
493
+ if (part.type.startsWith("tool-") && part.state !== "input-available") {
884
494
  const toolName = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.substring(5);
885
495
  const baseToolCall = {
886
496
  type: "tool-call",
887
497
  toolCallId: "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : "",
888
498
  toolName,
889
- argsText: "input" in part ? JSON.stringify(part.input) : "{}"
499
+ argsText: "input" in part ? JSON.stringify(part.input) : "{}",
500
+ args: "input" in part ? part.input : {},
501
+ metadata: message.metadata
890
502
  };
891
503
  if ("output" in part) {
892
504
  return { ...baseToolCall, result: part.output };
@@ -897,7 +509,8 @@ const toAssistantUIMessage = (message) => {
897
509
  }
898
510
  return {
899
511
  type: "text",
900
- text: ""
512
+ text: "",
513
+ metadata: message.metadata
901
514
  };
902
515
  });
903
516
  let status;
@@ -922,25 +535,574 @@ const toAssistantUIMessage = (message) => {
922
535
  status = { type: "complete", reason: "stop" };
923
536
  }
924
537
  }
925
- const metadata = extendedMessage.metadata ? {
926
- custom: extendedMessage.metadata
927
- } : void 0;
928
538
  const threadMessage = {
929
539
  role: message.role,
930
540
  content,
931
541
  id: message.id,
932
542
  createdAt: extendedMessage.createdAt,
933
543
  status,
934
- metadata,
935
544
  attachments: extendedMessage.experimental_attachments
936
545
  };
937
546
  return threadMessage;
938
547
  };
939
548
 
549
+ class AISdkNetworkTransformer {
550
+ transform({ chunk, conversation, metadata }) {
551
+ const newConversation = [...conversation];
552
+ if (chunk.type.startsWith("agent-execution-")) {
553
+ return this.handleAgentConversation(chunk, newConversation, metadata);
554
+ }
555
+ if (chunk.type.startsWith("workflow-execution-")) {
556
+ return this.handleWorkflowConversation(chunk, newConversation, metadata);
557
+ }
558
+ if (chunk.type.startsWith("tool-execution-")) {
559
+ return this.handleToolConversation(chunk, newConversation, metadata);
560
+ }
561
+ if (chunk.type === "network-execution-event-step-finish") {
562
+ const newMessage = {
563
+ id: `network-execution-event-step-finish-${chunk.runId}-${Date.now()}`,
564
+ role: "assistant",
565
+ parts: [
566
+ {
567
+ type: "text",
568
+ text: chunk.payload?.result || "",
569
+ state: "done"
570
+ }
571
+ ],
572
+ metadata
573
+ };
574
+ return [...newConversation, newMessage];
575
+ }
576
+ return newConversation;
577
+ }
578
+ handleAgentConversation = (chunk, newConversation, metadata) => {
579
+ if (chunk.type === "agent-execution-start") {
580
+ const primitiveId = chunk.payload?.args?.primitiveId;
581
+ const runId = chunk.payload.runId;
582
+ if (!primitiveId || !runId) return newConversation;
583
+ const newMessage = {
584
+ id: `agent-execution-start-${runId}-${Date.now()}`,
585
+ role: "assistant",
586
+ parts: [
587
+ {
588
+ type: "dynamic-tool",
589
+ toolName: primitiveId,
590
+ toolCallId: runId,
591
+ state: "input-available",
592
+ input: chunk.payload.args
593
+ }
594
+ ],
595
+ metadata: {
596
+ ...metadata,
597
+ selectionReason: chunk.payload?.args?.selectionReason || "",
598
+ agentInput: chunk.payload?.args?.task,
599
+ mode: "network",
600
+ from: "AGENT"
601
+ }
602
+ };
603
+ return [...newConversation, newMessage];
604
+ }
605
+ if (chunk.type === "agent-execution-end") {
606
+ const lastMessage = newConversation[newConversation.length - 1];
607
+ if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
608
+ const parts = [...lastMessage.parts];
609
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
610
+ if (toolPartIndex !== -1) {
611
+ const toolPart = parts[toolPartIndex];
612
+ if (toolPart.type === "dynamic-tool") {
613
+ const currentOutput = toolPart.output;
614
+ parts[toolPartIndex] = {
615
+ type: "dynamic-tool",
616
+ toolName: toolPart.toolName,
617
+ toolCallId: toolPart.toolCallId,
618
+ state: "output-available",
619
+ input: toolPart.input,
620
+ output: {
621
+ ...currentOutput,
622
+ result: currentOutput?.result || chunk.payload?.result || ""
623
+ }
624
+ };
625
+ }
626
+ }
627
+ return [
628
+ ...newConversation.slice(0, -1),
629
+ {
630
+ ...lastMessage,
631
+ parts
632
+ }
633
+ ];
634
+ }
635
+ if (chunk.type.startsWith("agent-execution-event-")) {
636
+ const lastMessage = newConversation[newConversation.length - 1];
637
+ if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
638
+ const agentChunk = chunk.payload;
639
+ const parts = [...lastMessage.parts];
640
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
641
+ if (toolPartIndex === -1) return newConversation;
642
+ const toolPart = parts[toolPartIndex];
643
+ if (agentChunk.type === "text-delta") {
644
+ const childMessages = toolPart?.output?.childMessages || [];
645
+ const lastChildMessage = childMessages[childMessages.length - 1];
646
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.payload.text };
647
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
648
+ parts[toolPartIndex] = {
649
+ ...toolPart,
650
+ output: {
651
+ childMessages: nextMessages
652
+ }
653
+ };
654
+ } else if (agentChunk.type === "tool-call") {
655
+ const childMessages = toolPart?.output?.childMessages || [];
656
+ parts[toolPartIndex] = {
657
+ ...toolPart,
658
+ output: {
659
+ ...toolPart?.output,
660
+ childMessages: [
661
+ ...childMessages,
662
+ {
663
+ type: "tool",
664
+ toolCallId: agentChunk.payload.toolCallId,
665
+ toolName: agentChunk.payload.toolName,
666
+ args: agentChunk.payload.args
667
+ }
668
+ ]
669
+ }
670
+ };
671
+ } else if (agentChunk.type === "tool-output") {
672
+ if (agentChunk.payload?.output?.type?.startsWith("workflow-")) {
673
+ const childMessages = toolPart?.output?.childMessages || [];
674
+ const lastToolIndex = childMessages.length - 1;
675
+ const currentMessage = childMessages[lastToolIndex];
676
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
677
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
678
+ actualExistingWorkflowState,
679
+ agentChunk.payload.output
680
+ );
681
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
682
+ parts[toolPartIndex] = {
683
+ ...toolPart,
684
+ output: {
685
+ ...toolPart?.output,
686
+ childMessages: [
687
+ ...childMessages.slice(0, -1),
688
+ {
689
+ ...currentMessage,
690
+ toolOutput: updatedWorkflowState
691
+ }
692
+ ]
693
+ }
694
+ };
695
+ }
696
+ }
697
+ } else if (agentChunk.type === "tool-result") {
698
+ const childMessages = toolPart?.output?.childMessages || [];
699
+ const lastToolIndex = childMessages.length - 1;
700
+ const isWorkflow = Boolean(agentChunk.payload?.result?.result?.steps);
701
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
702
+ parts[toolPartIndex] = {
703
+ ...toolPart,
704
+ output: {
705
+ ...toolPart?.output,
706
+ childMessages: [
707
+ ...childMessages.slice(0, -1),
708
+ {
709
+ ...childMessages[lastToolIndex],
710
+ toolOutput: isWorkflow ? agentChunk.payload.result.result : agentChunk.payload.result
711
+ }
712
+ ]
713
+ }
714
+ };
715
+ }
716
+ }
717
+ return [
718
+ ...newConversation.slice(0, -1),
719
+ {
720
+ ...lastMessage,
721
+ parts
722
+ }
723
+ ];
724
+ }
725
+ return newConversation;
726
+ };
727
+ handleWorkflowConversation = (chunk, newConversation, metadata) => {
728
+ if (chunk.type === "workflow-execution-start") {
729
+ const primitiveId = chunk.payload?.args?.primitiveId;
730
+ const runId = chunk.payload.runId;
731
+ if (!primitiveId || !runId) return newConversation;
732
+ let agentInput;
733
+ try {
734
+ agentInput = JSON.parse(chunk?.payload?.args?.prompt);
735
+ } catch (e) {
736
+ agentInput = chunk?.payload?.args?.prompt;
737
+ }
738
+ const newMessage = {
739
+ id: `workflow-start-${runId}-${Date.now()}`,
740
+ role: "assistant",
741
+ parts: [
742
+ {
743
+ type: "dynamic-tool",
744
+ toolName: primitiveId,
745
+ toolCallId: runId,
746
+ state: "input-available",
747
+ input: chunk.payload.args
748
+ }
749
+ ],
750
+ metadata: {
751
+ ...metadata,
752
+ selectionReason: chunk.payload?.args?.selectionReason || "",
753
+ from: "WORKFLOW",
754
+ mode: "network",
755
+ agentInput
756
+ }
757
+ };
758
+ return [...newConversation, newMessage];
759
+ }
760
+ if (chunk.type.startsWith("workflow-execution-event-")) {
761
+ const lastMessage = newConversation[newConversation.length - 1];
762
+ if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
763
+ const parts = [...lastMessage.parts];
764
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
765
+ if (toolPartIndex === -1) return newConversation;
766
+ const toolPart = parts[toolPartIndex];
767
+ if (toolPart.type !== "dynamic-tool") return newConversation;
768
+ const existingWorkflowState = toolPart.output || {};
769
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload);
770
+ parts[toolPartIndex] = {
771
+ ...toolPart,
772
+ output: updatedWorkflowState
773
+ };
774
+ return [
775
+ ...newConversation.slice(0, -1),
776
+ {
777
+ ...lastMessage,
778
+ parts
779
+ }
780
+ ];
781
+ }
782
+ return newConversation;
783
+ };
784
+ handleToolConversation = (chunk, newConversation, metadata) => {
785
+ if (chunk.type === "tool-execution-start") {
786
+ const { args: argsData } = chunk.payload;
787
+ const lastMessage = newConversation[newConversation.length - 1];
788
+ const nestedArgs = argsData.args || {};
789
+ if (!lastMessage || lastMessage.role !== "assistant") {
790
+ const newMessage = {
791
+ id: `tool-start-${chunk.runId}-${Date.now()}`,
792
+ role: "assistant",
793
+ parts: [
794
+ {
795
+ type: "dynamic-tool",
796
+ toolName: argsData.toolName || "unknown",
797
+ toolCallId: argsData.toolCallId || "unknown",
798
+ state: "input-available",
799
+ input: nestedArgs
800
+ }
801
+ ],
802
+ metadata: {
803
+ ...metadata,
804
+ selectionReason: metadata?.mode === "network" ? metadata.selectionReason || argsData.selectionReason : "",
805
+ mode: "network",
806
+ agentInput: nestedArgs
807
+ }
808
+ };
809
+ return [...newConversation, newMessage];
810
+ }
811
+ const parts = [...lastMessage.parts];
812
+ parts.push({
813
+ type: "dynamic-tool",
814
+ toolName: argsData.toolName || "unknown",
815
+ toolCallId: argsData.toolCallId || "unknown",
816
+ state: "input-available",
817
+ input: nestedArgs
818
+ });
819
+ return [
820
+ ...newConversation.slice(0, -1),
821
+ {
822
+ ...lastMessage,
823
+ parts
824
+ }
825
+ ];
826
+ }
827
+ if (chunk.type === "tool-execution-end") {
828
+ const lastMessage = newConversation[newConversation.length - 1];
829
+ if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
830
+ const parts = [...lastMessage.parts];
831
+ const toolPartIndex = parts.findIndex(
832
+ (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
833
+ );
834
+ if (toolPartIndex !== -1) {
835
+ const toolPart = parts[toolPartIndex];
836
+ if (toolPart.type === "dynamic-tool") {
837
+ const currentOutput = toolPart.output;
838
+ parts[toolPartIndex] = {
839
+ type: "dynamic-tool",
840
+ toolName: toolPart.toolName,
841
+ toolCallId: toolPart.toolCallId,
842
+ state: "output-available",
843
+ input: toolPart.input,
844
+ output: currentOutput?.result || chunk.payload?.result || ""
845
+ };
846
+ }
847
+ }
848
+ return [
849
+ ...newConversation.slice(0, -1),
850
+ {
851
+ ...lastMessage,
852
+ parts
853
+ }
854
+ ];
855
+ }
856
+ return newConversation;
857
+ };
858
+ }
859
+
860
+ const resolveInitialMessages = (messages) => {
861
+ return messages.map((message) => {
862
+ const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
863
+ if (networkPart && networkPart.type === "text") {
864
+ try {
865
+ const json = JSON.parse(networkPart.text);
866
+ if (json.isNetwork === true) {
867
+ const selectionReason = json.selectionReason || "";
868
+ const primitiveType = json.primitiveType || "";
869
+ const primitiveId = json.primitiveId || "";
870
+ const finalResult = json.finalResult;
871
+ const toolCalls = finalResult?.toolCalls || [];
872
+ const childMessages = [];
873
+ for (const toolCall of toolCalls) {
874
+ if (toolCall.type === "tool-call" && toolCall.payload) {
875
+ const toolCallId = toolCall.payload.toolCallId;
876
+ let toolResult;
877
+ for (const message2 of finalResult?.messages || []) {
878
+ for (const part of message2.content || []) {
879
+ if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
880
+ toolResult = part;
881
+ break;
882
+ }
883
+ }
884
+ }
885
+ const isWorkflow = Boolean(toolResult?.result?.result?.steps);
886
+ childMessages.push({
887
+ type: "tool",
888
+ toolCallId: toolCall.payload.toolCallId,
889
+ toolName: toolCall.payload.toolName,
890
+ args: toolCall.payload.args,
891
+ toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
892
+ });
893
+ }
894
+ }
895
+ if (finalResult && finalResult.text) {
896
+ childMessages.push({
897
+ type: "text",
898
+ content: finalResult.text
899
+ });
900
+ }
901
+ const result = {
902
+ childMessages,
903
+ result: finalResult?.text || ""
904
+ };
905
+ console.log("json", json);
906
+ const nextMessage = {
907
+ role: "assistant",
908
+ parts: [
909
+ {
910
+ type: "dynamic-tool",
911
+ toolCallId: primitiveId,
912
+ toolName: primitiveId,
913
+ state: "output-available",
914
+ input: json.input,
915
+ output: result
916
+ }
917
+ ],
918
+ id: message.id,
919
+ metadata: {
920
+ ...message.metadata,
921
+ mode: "network",
922
+ selectionReason,
923
+ agentInput: json.input,
924
+ from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
925
+ }
926
+ };
927
+ return nextMessage;
928
+ }
929
+ } catch (error) {
930
+ return message;
931
+ }
932
+ }
933
+ return message;
934
+ });
935
+ };
936
+
937
+ const useChat = ({ agentId, initializeMessages }) => {
938
+ const [messages, setMessages] = react.useState(
939
+ () => resolveInitialMessages(initializeMessages?.() || [])
940
+ );
941
+ const baseClient = useMastraClient();
942
+ const [isRunning, setIsRunning] = react.useState(false);
943
+ const generate = async ({
944
+ coreUserMessages,
945
+ runtimeContext,
946
+ threadId,
947
+ modelSettings,
948
+ signal,
949
+ onFinish
950
+ }) => {
951
+ const {
952
+ frequencyPenalty,
953
+ presencePenalty,
954
+ maxRetries,
955
+ maxTokens,
956
+ temperature,
957
+ topK,
958
+ topP,
959
+ instructions,
960
+ providerOptions,
961
+ maxSteps
962
+ } = modelSettings || {};
963
+ setIsRunning(true);
964
+ const clientWithAbort = new clientJs.MastraClient({
965
+ ...baseClient.options,
966
+ abortSignal: signal
967
+ });
968
+ const agent = clientWithAbort.getAgent(agentId);
969
+ const response = await agent.generate({
970
+ messages: coreUserMessages,
971
+ runId: agentId,
972
+ maxSteps,
973
+ modelSettings: {
974
+ frequencyPenalty,
975
+ presencePenalty,
976
+ maxRetries,
977
+ maxOutputTokens: maxTokens,
978
+ temperature,
979
+ topK,
980
+ topP
981
+ },
982
+ instructions,
983
+ runtimeContext,
984
+ ...threadId ? { threadId, resourceId: agentId } : {},
985
+ providerOptions
986
+ });
987
+ setIsRunning(false);
988
+ if (response && "uiMessages" in response.response && response.response.uiMessages) {
989
+ onFinish?.(response.response.uiMessages);
990
+ const mastraUIMessages = (response.response.uiMessages || []).map((message) => ({
991
+ ...message,
992
+ metadata: {
993
+ mode: "generate"
994
+ }
995
+ }));
996
+ setMessages((prev) => [...prev, ...mastraUIMessages]);
997
+ }
998
+ };
999
+ const stream = async ({ coreUserMessages, runtimeContext, threadId, onChunk, modelSettings, signal }) => {
1000
+ const {
1001
+ frequencyPenalty,
1002
+ presencePenalty,
1003
+ maxRetries,
1004
+ maxTokens,
1005
+ temperature,
1006
+ topK,
1007
+ topP,
1008
+ instructions,
1009
+ providerOptions,
1010
+ maxSteps
1011
+ } = modelSettings || {};
1012
+ setIsRunning(true);
1013
+ const clientWithAbort = new clientJs.MastraClient({
1014
+ ...baseClient.options,
1015
+ abortSignal: signal
1016
+ });
1017
+ const agent = clientWithAbort.getAgent(agentId);
1018
+ const response = await agent.stream({
1019
+ messages: coreUserMessages,
1020
+ runId: agentId,
1021
+ maxSteps,
1022
+ modelSettings: {
1023
+ frequencyPenalty,
1024
+ presencePenalty,
1025
+ maxRetries,
1026
+ maxOutputTokens: maxTokens,
1027
+ temperature,
1028
+ topK,
1029
+ topP
1030
+ },
1031
+ instructions,
1032
+ runtimeContext,
1033
+ ...threadId ? { threadId, resourceId: agentId } : {},
1034
+ providerOptions
1035
+ });
1036
+ if (!response.body) {
1037
+ setIsRunning(false);
1038
+ throw new Error("[Stream] No response body");
1039
+ }
1040
+ await response.processDataStream({
1041
+ onChunk: async (chunk) => {
1042
+ reactDom.flushSync(() => {
1043
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1044
+ });
1045
+ onChunk?.(chunk);
1046
+ }
1047
+ });
1048
+ setIsRunning(false);
1049
+ };
1050
+ const network = async ({
1051
+ coreUserMessages,
1052
+ runtimeContext,
1053
+ threadId,
1054
+ onNetworkChunk,
1055
+ modelSettings,
1056
+ signal
1057
+ }) => {
1058
+ const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
1059
+ setIsRunning(true);
1060
+ const clientWithAbort = new clientJs.MastraClient({
1061
+ ...baseClient.options,
1062
+ abortSignal: signal
1063
+ });
1064
+ const agent = clientWithAbort.getAgent(agentId);
1065
+ const response = await agent.network({
1066
+ messages: coreUserMessages,
1067
+ maxSteps,
1068
+ modelSettings: {
1069
+ frequencyPenalty,
1070
+ presencePenalty,
1071
+ maxRetries,
1072
+ maxOutputTokens: maxTokens,
1073
+ temperature,
1074
+ topK,
1075
+ topP
1076
+ },
1077
+ runId: agentId,
1078
+ runtimeContext,
1079
+ ...threadId ? { thread: threadId, resourceId: agentId } : {}
1080
+ });
1081
+ const transformer = new AISdkNetworkTransformer();
1082
+ await response.processDataStream({
1083
+ onChunk: async (chunk) => {
1084
+ reactDom.flushSync(() => {
1085
+ setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
1086
+ });
1087
+ onNetworkChunk?.(chunk);
1088
+ }
1089
+ });
1090
+ setIsRunning(false);
1091
+ };
1092
+ return {
1093
+ network,
1094
+ stream,
1095
+ generate,
1096
+ isRunning,
1097
+ messages,
1098
+ setMessages,
1099
+ cancelRun: () => setIsRunning(false)
1100
+ };
1101
+ };
1102
+
940
1103
  exports.MastraReactProvider = MastraReactProvider;
941
1104
  exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
942
1105
  exports.toAssistantUIMessage = toAssistantUIMessage;
943
- exports.toNetworkUIMessage = toNetworkUIMessage;
944
1106
  exports.toUIMessage = toUIMessage;
945
1107
  exports.useChat = useChat;
946
1108
  exports.useMastraClient = useMastraClient;