@mastra/react 0.0.2-alpha.1

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.
@@ -0,0 +1,856 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { createContext, useContext, useState } from 'react';
3
+ import { MastraClient } from '@mastra/client-js';
4
+ import { flushSync } from 'react-dom';
5
+
6
+ const MastraClientContext = createContext({});
7
+ const MastraClientProvider = ({ children, baseUrl, headers }) => {
8
+ const client = createMastraClient(baseUrl, headers);
9
+ return /* @__PURE__ */ jsx(MastraClientContext.Provider, { value: client, children });
10
+ };
11
+ const useMastraClient = () => useContext(MastraClientContext);
12
+ const createMastraClient = (baseUrl, mastraClientHeaders = {}) => {
13
+ return new MastraClient({
14
+ baseUrl: baseUrl || "",
15
+ // only add the header if the baseUrl is not provided i.e it's a local dev environment
16
+ headers: !baseUrl ? { ...mastraClientHeaders, "x-mastra-dev-playground": "true" } : mastraClientHeaders
17
+ });
18
+ };
19
+
20
+ const MastraReactProvider = ({ children, baseUrl, headers }) => {
21
+ return /* @__PURE__ */ jsx(MastraClientProvider, { baseUrl, headers, children });
22
+ };
23
+
24
+ const useChat = ({ agentId, initializeMessages }) => {
25
+ const [messages, setMessages] = useState(initializeMessages || []);
26
+ const baseClient = useMastraClient();
27
+ const [isRunning, setIsRunning] = useState(false);
28
+ const streamVNext = async ({
29
+ coreUserMessages,
30
+ runtimeContext,
31
+ threadId,
32
+ onChunk,
33
+ modelSettings,
34
+ signal
35
+ }) => {
36
+ const {
37
+ frequencyPenalty,
38
+ presencePenalty,
39
+ maxRetries,
40
+ maxTokens,
41
+ temperature,
42
+ topK,
43
+ topP,
44
+ instructions,
45
+ providerOptions
46
+ } = modelSettings || {};
47
+ setIsRunning(true);
48
+ const clientWithAbort = new MastraClient({
49
+ ...baseClient.options,
50
+ abortSignal: signal
51
+ });
52
+ const agent = clientWithAbort.getAgent(agentId);
53
+ const response = await agent.streamVNext({
54
+ messages: coreUserMessages,
55
+ runId: agentId,
56
+ modelSettings: {
57
+ frequencyPenalty,
58
+ presencePenalty,
59
+ maxRetries,
60
+ maxOutputTokens: maxTokens,
61
+ temperature,
62
+ topK,
63
+ topP
64
+ },
65
+ instructions,
66
+ runtimeContext,
67
+ ...threadId ? { threadId, resourceId: agentId } : {},
68
+ providerOptions
69
+ });
70
+ if (!response.body) {
71
+ setIsRunning(false);
72
+ throw new Error("[StreamVNext] No response body");
73
+ }
74
+ await response.processDataStream({
75
+ onChunk: (chunk) => {
76
+ flushSync(() => {
77
+ setMessages((prev) => onChunk(chunk, prev));
78
+ });
79
+ return Promise.resolve();
80
+ }
81
+ });
82
+ setIsRunning(false);
83
+ };
84
+ const network = async ({
85
+ coreUserMessages,
86
+ runtimeContext,
87
+ threadId,
88
+ onNetworkChunk,
89
+ modelSettings,
90
+ signal
91
+ }) => {
92
+ const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
93
+ setIsRunning(true);
94
+ const clientWithAbort = new MastraClient({
95
+ ...baseClient.options,
96
+ abortSignal: signal
97
+ });
98
+ const agent = clientWithAbort.getAgent(agentId);
99
+ const response = await agent.network({
100
+ messages: coreUserMessages,
101
+ maxSteps,
102
+ modelSettings: {
103
+ frequencyPenalty,
104
+ presencePenalty,
105
+ maxRetries,
106
+ maxOutputTokens: maxTokens,
107
+ temperature,
108
+ topK,
109
+ topP
110
+ },
111
+ runId: agentId,
112
+ runtimeContext,
113
+ ...threadId ? { thread: threadId, resourceId: agentId } : {}
114
+ });
115
+ await response.processDataStream({
116
+ onChunk: (chunk) => {
117
+ flushSync(() => {
118
+ setMessages((prev) => onNetworkChunk(chunk, prev));
119
+ });
120
+ return Promise.resolve();
121
+ }
122
+ });
123
+ setIsRunning(false);
124
+ };
125
+ return {
126
+ network,
127
+ streamVNext,
128
+ isRunning,
129
+ messages,
130
+ setMessages,
131
+ cancelRun: () => setIsRunning(false)
132
+ };
133
+ };
134
+
135
+ const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
136
+ if (chunk.type === "workflow-start") {
137
+ return {
138
+ ...prev,
139
+ runId: chunk.runId,
140
+ eventTimestamp: /* @__PURE__ */ new Date(),
141
+ payload: {
142
+ ...prev?.payload || {},
143
+ workflowState: {
144
+ ...prev?.payload?.workflowState,
145
+ status: "running",
146
+ steps: {}
147
+ }
148
+ }
149
+ };
150
+ }
151
+ if (chunk.type === "workflow-step-start") {
152
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
153
+ return {
154
+ ...prev,
155
+ payload: {
156
+ ...prev.payload,
157
+ currentStep: {
158
+ id: chunk.payload.id,
159
+ ...chunk.payload
160
+ },
161
+ workflowState: {
162
+ ...prev?.payload?.workflowState,
163
+ steps: {
164
+ ...prev?.payload?.workflowState?.steps,
165
+ [chunk.payload.id]: {
166
+ ...current || {},
167
+ ...chunk.payload
168
+ }
169
+ }
170
+ }
171
+ },
172
+ eventTimestamp: /* @__PURE__ */ new Date()
173
+ };
174
+ }
175
+ if (chunk.type === "workflow-step-suspended") {
176
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
177
+ return {
178
+ ...prev,
179
+ payload: {
180
+ ...prev?.payload,
181
+ currentStep: {
182
+ id: chunk.payload.id,
183
+ ...prev?.payload?.currentStep,
184
+ ...chunk.payload
185
+ },
186
+ workflowState: {
187
+ ...prev?.payload?.workflowState,
188
+ status: "suspended",
189
+ steps: {
190
+ ...prev?.payload?.workflowState?.steps,
191
+ [chunk.payload.id]: {
192
+ ...current || {},
193
+ ...chunk.payload
194
+ }
195
+ }
196
+ }
197
+ },
198
+ eventTimestamp: /* @__PURE__ */ new Date()
199
+ };
200
+ }
201
+ if (chunk.type === "workflow-step-waiting") {
202
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
203
+ return {
204
+ ...prev,
205
+ payload: {
206
+ ...prev?.payload,
207
+ currentStep: {
208
+ id: chunk.payload.id,
209
+ ...prev?.payload?.currentStep || {},
210
+ ...chunk.payload
211
+ },
212
+ workflowState: {
213
+ ...prev?.payload?.workflowState,
214
+ status: "waiting",
215
+ steps: {
216
+ ...prev?.payload?.workflowState?.steps,
217
+ [chunk.payload.id]: {
218
+ ...current,
219
+ ...chunk.payload
220
+ }
221
+ }
222
+ }
223
+ },
224
+ eventTimestamp: /* @__PURE__ */ new Date()
225
+ };
226
+ }
227
+ if (chunk.type === "workflow-step-result") {
228
+ const status = chunk.payload.status;
229
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
230
+ const next = {
231
+ ...prev,
232
+ payload: {
233
+ ...prev?.payload,
234
+ currentStep: {
235
+ id: chunk.payload.id,
236
+ ...prev?.payload?.currentStep || {},
237
+ ...chunk.payload
238
+ },
239
+ workflowState: {
240
+ ...prev?.payload?.workflowState,
241
+ status,
242
+ steps: {
243
+ ...prev?.payload?.workflowState?.steps,
244
+ [chunk.payload.id]: {
245
+ ...current,
246
+ ...chunk.payload
247
+ }
248
+ }
249
+ }
250
+ },
251
+ eventTimestamp: /* @__PURE__ */ new Date()
252
+ };
253
+ return next;
254
+ }
255
+ if (chunk.type === "workflow-canceled") {
256
+ return {
257
+ ...prev,
258
+ payload: {
259
+ ...prev?.payload,
260
+ workflowState: {
261
+ ...prev?.payload?.workflowState,
262
+ status: "canceled"
263
+ }
264
+ },
265
+ eventTimestamp: /* @__PURE__ */ new Date()
266
+ };
267
+ }
268
+ if (chunk.type === "workflow-finish") {
269
+ return {
270
+ ...prev,
271
+ payload: {
272
+ ...prev?.payload,
273
+ currentStep: void 0,
274
+ workflowState: {
275
+ ...prev?.payload?.workflowState,
276
+ status: chunk.payload.workflowStatus
277
+ }
278
+ },
279
+ eventTimestamp: /* @__PURE__ */ new Date()
280
+ };
281
+ }
282
+ return prev;
283
+ };
284
+ const toUIMessage = ({
285
+ chunk,
286
+ conversation
287
+ }) => {
288
+ const result = [...conversation];
289
+ switch (chunk.type) {
290
+ case "start": {
291
+ const newMessage = {
292
+ id: chunk.runId,
293
+ role: "assistant",
294
+ parts: []
295
+ };
296
+ return [...result, newMessage];
297
+ }
298
+ case "text-start":
299
+ case "text-delta": {
300
+ const lastMessage = result[result.length - 1];
301
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
302
+ const parts = [...lastMessage.parts];
303
+ let textPartIndex = parts.findIndex((part) => part.type === "text");
304
+ if (chunk.type === "text-start") {
305
+ if (textPartIndex === -1) {
306
+ parts.push({
307
+ type: "text",
308
+ text: "",
309
+ state: "streaming",
310
+ providerMetadata: chunk.payload.providerMetadata
311
+ });
312
+ }
313
+ } else {
314
+ if (textPartIndex === -1) {
315
+ parts.push({
316
+ type: "text",
317
+ text: chunk.payload.text,
318
+ state: "streaming",
319
+ providerMetadata: chunk.payload.providerMetadata
320
+ });
321
+ } else {
322
+ const textPart = parts[textPartIndex];
323
+ if (textPart.type === "text") {
324
+ parts[textPartIndex] = {
325
+ ...textPart,
326
+ text: textPart.text + chunk.payload.text,
327
+ state: "streaming"
328
+ };
329
+ }
330
+ }
331
+ }
332
+ return [
333
+ ...result.slice(0, -1),
334
+ {
335
+ ...lastMessage,
336
+ parts
337
+ }
338
+ ];
339
+ }
340
+ case "reasoning-delta": {
341
+ const lastMessage = result[result.length - 1];
342
+ if (!lastMessage || lastMessage.role !== "assistant") {
343
+ const newMessage = {
344
+ id: chunk.runId,
345
+ role: "assistant",
346
+ parts: [
347
+ {
348
+ type: "reasoning",
349
+ text: chunk.payload.text,
350
+ state: "streaming",
351
+ providerMetadata: chunk.payload.providerMetadata
352
+ }
353
+ ]
354
+ };
355
+ return [...result, newMessage];
356
+ }
357
+ const parts = [...lastMessage.parts];
358
+ let reasoningPartIndex = parts.findIndex((part) => part.type === "reasoning");
359
+ if (reasoningPartIndex === -1) {
360
+ parts.push({
361
+ type: "reasoning",
362
+ text: chunk.payload.text,
363
+ state: "streaming",
364
+ providerMetadata: chunk.payload.providerMetadata
365
+ });
366
+ } else {
367
+ const reasoningPart = parts[reasoningPartIndex];
368
+ if (reasoningPart.type === "reasoning") {
369
+ parts[reasoningPartIndex] = {
370
+ ...reasoningPart,
371
+ text: reasoningPart.text + chunk.payload.text,
372
+ state: "streaming"
373
+ };
374
+ }
375
+ }
376
+ return [
377
+ ...result.slice(0, -1),
378
+ {
379
+ ...lastMessage,
380
+ parts
381
+ }
382
+ ];
383
+ }
384
+ case "tool-call": {
385
+ const lastMessage = result[result.length - 1];
386
+ if (!lastMessage || lastMessage.role !== "assistant") {
387
+ const newMessage = {
388
+ id: chunk.runId,
389
+ role: "assistant",
390
+ parts: [
391
+ {
392
+ type: "dynamic-tool",
393
+ toolName: chunk.payload.toolName,
394
+ toolCallId: chunk.payload.toolCallId,
395
+ state: "input-available",
396
+ input: chunk.payload.args,
397
+ callProviderMetadata: chunk.payload.providerMetadata
398
+ }
399
+ ]
400
+ };
401
+ return [...result, newMessage];
402
+ }
403
+ const parts = [...lastMessage.parts];
404
+ parts.push({
405
+ type: "dynamic-tool",
406
+ toolName: chunk.payload.toolName,
407
+ toolCallId: chunk.payload.toolCallId,
408
+ state: "input-available",
409
+ input: chunk.payload.args,
410
+ callProviderMetadata: chunk.payload.providerMetadata
411
+ });
412
+ return [
413
+ ...result.slice(0, -1),
414
+ {
415
+ ...lastMessage,
416
+ parts
417
+ }
418
+ ];
419
+ }
420
+ case "tool-result": {
421
+ const lastMessage = result[result.length - 1];
422
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
423
+ const parts = [...lastMessage.parts];
424
+ const toolPartIndex = parts.findIndex(
425
+ (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
426
+ );
427
+ if (toolPartIndex !== -1) {
428
+ const toolPart = parts[toolPartIndex];
429
+ if (toolPart.type === "dynamic-tool") {
430
+ if (chunk.payload.isError) {
431
+ parts[toolPartIndex] = {
432
+ type: "dynamic-tool",
433
+ toolName: toolPart.toolName,
434
+ toolCallId: toolPart.toolCallId,
435
+ state: "output-error",
436
+ input: toolPart.input,
437
+ errorText: String(chunk.payload.result),
438
+ callProviderMetadata: chunk.payload.providerMetadata
439
+ };
440
+ } else {
441
+ parts[toolPartIndex] = {
442
+ type: "dynamic-tool",
443
+ toolName: toolPart.toolName,
444
+ toolCallId: toolPart.toolCallId,
445
+ state: "output-available",
446
+ input: toolPart.input,
447
+ output: toolPart.output,
448
+ callProviderMetadata: chunk.payload.providerMetadata
449
+ };
450
+ }
451
+ }
452
+ }
453
+ return [
454
+ ...result.slice(0, -1),
455
+ {
456
+ ...lastMessage,
457
+ parts
458
+ }
459
+ ];
460
+ }
461
+ case "tool-output": {
462
+ const lastMessage = result[result.length - 1];
463
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
464
+ const parts = [...lastMessage.parts];
465
+ const toolPartIndex = parts.findIndex(
466
+ (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
467
+ );
468
+ if (toolPartIndex !== -1) {
469
+ const toolPart = parts[toolPartIndex];
470
+ if (toolPart.type === "dynamic-tool") {
471
+ if (chunk.payload.output?.type?.startsWith("workflow-")) {
472
+ const currentOutput = toolPart.output || {};
473
+ const existingWorkflowState = currentOutput || {};
474
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
475
+ existingWorkflowState,
476
+ chunk.payload.output
477
+ );
478
+ parts[toolPartIndex] = {
479
+ ...toolPart,
480
+ output: updatedWorkflowState
481
+ };
482
+ } else {
483
+ const currentOutput = toolPart.output || [];
484
+ const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
485
+ parts[toolPartIndex] = {
486
+ ...toolPart,
487
+ output: [...existingOutput, chunk.payload.output]
488
+ };
489
+ }
490
+ }
491
+ }
492
+ return [
493
+ ...result.slice(0, -1),
494
+ {
495
+ ...lastMessage,
496
+ parts
497
+ }
498
+ ];
499
+ }
500
+ case "source": {
501
+ const lastMessage = result[result.length - 1];
502
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
503
+ const parts = [...lastMessage.parts];
504
+ if (chunk.payload.sourceType === "url") {
505
+ parts.push({
506
+ type: "source-url",
507
+ sourceId: chunk.payload.id,
508
+ url: chunk.payload.url || "",
509
+ title: chunk.payload.title,
510
+ providerMetadata: chunk.payload.providerMetadata
511
+ });
512
+ } else if (chunk.payload.sourceType === "document") {
513
+ parts.push({
514
+ type: "source-document",
515
+ sourceId: chunk.payload.id,
516
+ mediaType: chunk.payload.mimeType || "application/octet-stream",
517
+ title: chunk.payload.title,
518
+ filename: chunk.payload.filename,
519
+ providerMetadata: chunk.payload.providerMetadata
520
+ });
521
+ }
522
+ return [
523
+ ...result.slice(0, -1),
524
+ {
525
+ ...lastMessage,
526
+ parts
527
+ }
528
+ ];
529
+ }
530
+ case "file": {
531
+ const lastMessage = result[result.length - 1];
532
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
533
+ const parts = [...lastMessage.parts];
534
+ let url;
535
+ if (typeof chunk.payload.data === "string") {
536
+ url = chunk.payload.base64 ? `data:${chunk.payload.mimeType};base64,${chunk.payload.data}` : `data:${chunk.payload.mimeType},${encodeURIComponent(chunk.payload.data)}`;
537
+ } else {
538
+ const base64 = btoa(String.fromCharCode(...chunk.payload.data));
539
+ url = `data:${chunk.payload.mimeType};base64,${base64}`;
540
+ }
541
+ parts.push({
542
+ type: "file",
543
+ mediaType: chunk.payload.mimeType,
544
+ url,
545
+ providerMetadata: chunk.payload.providerMetadata
546
+ });
547
+ return [
548
+ ...result.slice(0, -1),
549
+ {
550
+ ...lastMessage,
551
+ parts
552
+ }
553
+ ];
554
+ }
555
+ case "finish": {
556
+ const lastMessage = result[result.length - 1];
557
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
558
+ const parts = lastMessage.parts.map((part) => {
559
+ if (part.type === "text" && part.state === "streaming") {
560
+ return { ...part, state: "done" };
561
+ }
562
+ if (part.type === "reasoning" && part.state === "streaming") {
563
+ return { ...part, state: "done" };
564
+ }
565
+ return part;
566
+ });
567
+ return [
568
+ ...result.slice(0, -1),
569
+ {
570
+ ...lastMessage,
571
+ parts
572
+ }
573
+ ];
574
+ }
575
+ case "error": {
576
+ return result;
577
+ }
578
+ // For all other chunk types, return conversation unchanged
579
+ default:
580
+ return result;
581
+ }
582
+ };
583
+
584
+ const toNetworkUIMessage = ({
585
+ chunk,
586
+ conversation
587
+ }) => {
588
+ const result = [...conversation];
589
+ if (chunk.type === "agent-execution-start" || chunk.type === "workflow-execution-start") {
590
+ const primitiveId = chunk.payload?.args?.primitiveId;
591
+ const runId = chunk.payload.runId;
592
+ if (!primitiveId || !runId) return result;
593
+ const newMessage = {
594
+ id: runId,
595
+ role: "assistant",
596
+ parts: [
597
+ {
598
+ type: "dynamic-tool",
599
+ toolName: primitiveId,
600
+ toolCallId: runId,
601
+ state: "input-available",
602
+ input: chunk.payload.args,
603
+ output: {
604
+ networkMetadata: {
605
+ selectionReason: chunk.payload?.args?.selectionReason || "",
606
+ from: chunk.type === "agent-execution-start" ? "AGENT" : "WORKFLOW"
607
+ },
608
+ result: void 0
609
+ }
610
+ }
611
+ ]
612
+ };
613
+ return [...result, newMessage];
614
+ }
615
+ if (chunk.type.startsWith("agent-execution-event-")) {
616
+ const agentChunk = chunk.payload;
617
+ const lastMessage = result[result.length - 1];
618
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
619
+ const parts = [...lastMessage.parts];
620
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
621
+ if (toolPartIndex === -1) return result;
622
+ const toolPart = parts[toolPartIndex];
623
+ if (toolPart.type !== "dynamic-tool") return result;
624
+ if (agentChunk.type === "text-delta") {
625
+ const currentInput = toolPart.input;
626
+ const messages = currentInput?.messages || [];
627
+ const lastMessage2 = messages[messages.length - 1];
628
+ const nextMessages = lastMessage2?.type === "text" ? [
629
+ ...messages.slice(0, -1),
630
+ { type: "text", content: (lastMessage2?.content || "") + agentChunk.payload.text }
631
+ ] : [...messages, { type: "text", content: agentChunk.payload.text }];
632
+ parts[toolPartIndex] = {
633
+ ...toolPart,
634
+ input: {
635
+ ...currentInput,
636
+ messages: nextMessages
637
+ }
638
+ };
639
+ } else if (agentChunk.type === "tool-call") {
640
+ const currentInput = toolPart.input;
641
+ const messages = currentInput?.messages || [];
642
+ parts[toolPartIndex] = {
643
+ ...toolPart,
644
+ input: {
645
+ ...currentInput,
646
+ messages: [
647
+ ...messages,
648
+ {
649
+ type: "tool",
650
+ toolCallId: agentChunk.payload.toolCallId,
651
+ toolName: agentChunk.payload.toolName,
652
+ toolInput: agentChunk.payload.args
653
+ }
654
+ ]
655
+ }
656
+ };
657
+ } else if (agentChunk.type === "tool-result") {
658
+ const currentInput = toolPart.input;
659
+ const messages = currentInput?.messages || [];
660
+ const lastToolIndex = messages.length - 1;
661
+ if (lastToolIndex >= 0 && messages[lastToolIndex]?.type === "tool") {
662
+ parts[toolPartIndex] = {
663
+ ...toolPart,
664
+ input: {
665
+ ...currentInput,
666
+ messages: [
667
+ ...messages.slice(0, -1),
668
+ {
669
+ ...messages[lastToolIndex],
670
+ toolOutput: agentChunk.payload.result
671
+ }
672
+ ]
673
+ }
674
+ };
675
+ }
676
+ } else if (agentChunk.type === "tool-output") {
677
+ if (agentChunk.payload?.output?.type?.startsWith("workflow-")) {
678
+ const currentOutput = toolPart.output || {};
679
+ const existingWorkflowState = currentOutput.result || {};
680
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
681
+ existingWorkflowState,
682
+ agentChunk.payload.output
683
+ );
684
+ parts[toolPartIndex] = {
685
+ ...toolPart,
686
+ output: {
687
+ networkMetadata: currentOutput.networkMetadata,
688
+ result: updatedWorkflowState
689
+ }
690
+ };
691
+ }
692
+ }
693
+ return [
694
+ ...result.slice(0, -1),
695
+ {
696
+ ...lastMessage,
697
+ parts
698
+ }
699
+ ];
700
+ }
701
+ if (chunk.type.startsWith("workflow-execution-event-")) {
702
+ const workflowChunk = chunk.payload;
703
+ const lastMessage = result[result.length - 1];
704
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
705
+ const parts = [...lastMessage.parts];
706
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
707
+ if (toolPartIndex === -1) return result;
708
+ const toolPart = parts[toolPartIndex];
709
+ if (toolPart.type !== "dynamic-tool") return result;
710
+ const currentOutput = toolPart.output || {};
711
+ const existingWorkflowState = currentOutput.result || {};
712
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, workflowChunk);
713
+ parts[toolPartIndex] = {
714
+ ...toolPart,
715
+ output: {
716
+ networkMetadata: currentOutput.networkMetadata,
717
+ result: updatedWorkflowState
718
+ }
719
+ };
720
+ return [
721
+ ...result.slice(0, -1),
722
+ {
723
+ ...lastMessage,
724
+ parts
725
+ }
726
+ ];
727
+ }
728
+ if (chunk.type === "tool-execution-start") {
729
+ const { args: argsData } = chunk.payload;
730
+ const lastMessage = result[result.length - 1];
731
+ const nestedArgs = argsData.args || {};
732
+ if (!lastMessage || lastMessage.role !== "assistant") {
733
+ const newMessage = {
734
+ id: chunk.runId,
735
+ role: "assistant",
736
+ parts: [
737
+ {
738
+ type: "dynamic-tool",
739
+ toolName: argsData.toolName || "unknown",
740
+ toolCallId: argsData.toolCallId || "unknown",
741
+ state: "input-available",
742
+ input: nestedArgs,
743
+ output: {
744
+ networkMetadata: {
745
+ selectionReason: argsData.selectionReason || ""
746
+ },
747
+ result: void 0
748
+ }
749
+ }
750
+ ]
751
+ };
752
+ return [...result, newMessage];
753
+ }
754
+ const parts = [...lastMessage.parts];
755
+ parts.push({
756
+ type: "dynamic-tool",
757
+ toolName: argsData.toolName || "unknown",
758
+ toolCallId: argsData.toolCallId || "unknown",
759
+ state: "input-available",
760
+ input: nestedArgs,
761
+ output: {
762
+ networkMetadata: {
763
+ selectionReason: argsData.selectionReason || ""
764
+ },
765
+ result: void 0
766
+ }
767
+ });
768
+ return [
769
+ ...result.slice(0, -1),
770
+ {
771
+ ...lastMessage,
772
+ parts
773
+ }
774
+ ];
775
+ }
776
+ if (chunk.type === "tool-execution-end") {
777
+ const lastMessage = result[result.length - 1];
778
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
779
+ const parts = [...lastMessage.parts];
780
+ const toolPartIndex = parts.findIndex(
781
+ (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
782
+ );
783
+ if (toolPartIndex !== -1) {
784
+ const toolPart = parts[toolPartIndex];
785
+ if (toolPart.type === "dynamic-tool") {
786
+ const currentOutput = toolPart.output;
787
+ parts[toolPartIndex] = {
788
+ type: "dynamic-tool",
789
+ toolName: toolPart.toolName,
790
+ toolCallId: toolPart.toolCallId,
791
+ state: "output-available",
792
+ input: toolPart.input,
793
+ output: {
794
+ networkMetadata: currentOutput?.networkMetadata,
795
+ result: chunk.payload.result
796
+ }
797
+ };
798
+ }
799
+ }
800
+ return [
801
+ ...result.slice(0, -1),
802
+ {
803
+ ...lastMessage,
804
+ parts
805
+ }
806
+ ];
807
+ }
808
+ if (chunk.type === "agent-execution-end" || chunk.type === "workflow-execution-end") {
809
+ const lastMessage = result[result.length - 1];
810
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
811
+ const parts = [...lastMessage.parts];
812
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
813
+ if (toolPartIndex !== -1) {
814
+ const toolPart = parts[toolPartIndex];
815
+ if (toolPart.type === "dynamic-tool") {
816
+ const currentOutput = toolPart.output;
817
+ parts[toolPartIndex] = {
818
+ type: "dynamic-tool",
819
+ toolName: toolPart.toolName,
820
+ toolCallId: toolPart.toolCallId,
821
+ state: "output-available",
822
+ input: toolPart.input,
823
+ output: {
824
+ networkMetadata: currentOutput?.networkMetadata,
825
+ result: currentOutput?.result || chunk.payload?.result || ""
826
+ }
827
+ };
828
+ }
829
+ }
830
+ return [
831
+ ...result.slice(0, -1),
832
+ {
833
+ ...lastMessage,
834
+ parts
835
+ }
836
+ ];
837
+ }
838
+ if (chunk.type === "network-execution-event-step-finish") {
839
+ const newMessage = {
840
+ id: chunk.runId,
841
+ role: "assistant",
842
+ parts: [
843
+ {
844
+ type: "text",
845
+ text: chunk.payload?.result || "",
846
+ state: "done"
847
+ }
848
+ ]
849
+ };
850
+ return [...result, newMessage];
851
+ }
852
+ return result;
853
+ };
854
+
855
+ export { MastraReactProvider, mapWorkflowStreamChunkToWatchResult, toNetworkUIMessage, toUIMessage, useChat, useMastraClient };
856
+ //# sourceMappingURL=index.es.js.map