@mastra/react 0.0.0-model-router-unknown-provider-20251017212006 → 0.0.0-playground-studio-cloud-20251031080052
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/CHANGELOG.md +67 -2
- package/dist/index.cjs +365 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +366 -104
- package/dist/index.js.map +1 -1
- package/dist/react.css +1 -1
- package/dist/src/agent/hooks.d.ts +7 -0
- package/dist/src/agent/types.d.ts +1 -0
- package/dist/src/lib/ai-sdk/index.d.ts +1 -0
- package/dist/src/lib/ai-sdk/memory/resolveInitialMessages.d.ts +10 -0
- package/dist/src/lib/ai-sdk/memory/resolveInitialMessages.test.d.ts +1 -0
- package/dist/src/lib/ai-sdk/transformers/AISdkNetworkTransformer.test.d.ts +1 -0
- package/dist/src/lib/ai-sdk/types.d.ts +7 -0
- package/dist/src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts +10 -0
- package/dist/src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.test.d.ts +1 -0
- package/dist/src/lib/ai-sdk/utils/toUIMessage.test.d.ts +1 -0
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,76 @@
|
|
|
1
1
|
# @mastra/react-hooks
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-playground-studio-cloud-20251031080052
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Add tool call approval ([#8649](https://github.com/mastra-ai/mastra/pull/8649))
|
|
8
|
+
|
|
9
|
+
- Fix multi modal in react sdk ([#9373](https://github.com/mastra-ai/mastra/pull/9373))
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`1ee3411`](https://github.com/mastra-ai/mastra/commit/1ee34113192b11aa8bcdd8d9d5830ae13254b345), [`5df9cce`](https://github.com/mastra-ai/mastra/commit/5df9cce1a753438413f64c11eeef8f845745c2a8), [`c576fc0`](https://github.com/mastra-ai/mastra/commit/c576fc0b100b2085afded91a37c97a0ea0ec09c7), [`ea0b8de`](https://github.com/mastra-ai/mastra/commit/ea0b8dec0d4bc86a72a7e75b2f56c6017c58786d), [`f0f8f12`](https://github.com/mastra-ai/mastra/commit/f0f8f125c308f2d0fd36942ef652fd852df7522f), [`63f2f18`](https://github.com/mastra-ai/mastra/commit/63f2f1863dffe3ad23221d0660ed4e4f2b81789d)]:
|
|
12
|
+
- @mastra/client-js@0.0.0-playground-studio-cloud-20251031080052
|
|
13
|
+
|
|
14
|
+
## 0.0.10
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies []:
|
|
19
|
+
- @mastra/client-js@0.16.4
|
|
20
|
+
|
|
21
|
+
## 0.0.10-alpha.0
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies []:
|
|
26
|
+
- @mastra/client-js@0.16.4-alpha.0
|
|
27
|
+
|
|
28
|
+
## 0.0.9
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies []:
|
|
33
|
+
- @mastra/client-js@0.16.3
|
|
34
|
+
|
|
35
|
+
## 0.0.9-alpha.0
|
|
36
|
+
|
|
37
|
+
### Patch Changes
|
|
38
|
+
|
|
39
|
+
- Updated dependencies []:
|
|
40
|
+
- @mastra/client-js@0.16.3-alpha.0
|
|
41
|
+
|
|
42
|
+
## 0.0.8
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- Fix perf issue: removed flush sync ([#9014](https://github.com/mastra-ai/mastra/pull/9014))
|
|
47
|
+
|
|
48
|
+
- Fix tool result in playground ([#9087](https://github.com/mastra-ai/mastra/pull/9087))
|
|
49
|
+
|
|
50
|
+
- Show agent tool output better in playground ([#9021](https://github.com/mastra-ai/mastra/pull/9021))
|
|
51
|
+
|
|
52
|
+
- Updated dependencies []:
|
|
53
|
+
- @mastra/client-js@0.16.2
|
|
54
|
+
|
|
55
|
+
## 0.0.8-alpha.1
|
|
56
|
+
|
|
57
|
+
### Patch Changes
|
|
58
|
+
|
|
59
|
+
- Fix perf issue: removed flush sync ([#9014](https://github.com/mastra-ai/mastra/pull/9014))
|
|
60
|
+
|
|
61
|
+
- Fix tool result in playground ([#9087](https://github.com/mastra-ai/mastra/pull/9087))
|
|
62
|
+
|
|
63
|
+
- Show agent tool output better in playground ([#9021](https://github.com/mastra-ai/mastra/pull/9021))
|
|
64
|
+
|
|
65
|
+
- Updated dependencies []:
|
|
66
|
+
- @mastra/client-js@0.16.2-alpha.1
|
|
67
|
+
|
|
68
|
+
## 0.0.8-alpha.0
|
|
4
69
|
|
|
5
70
|
### Patch Changes
|
|
6
71
|
|
|
7
72
|
- Updated dependencies []:
|
|
8
|
-
- @mastra/client-js@0.
|
|
73
|
+
- @mastra/client-js@0.16.2-alpha.0
|
|
9
74
|
|
|
10
75
|
## 0.0.7
|
|
11
76
|
|
package/dist/index.cjs
CHANGED
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
5
5
|
const jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
const react = require('react');
|
|
7
7
|
const clientJs = require('@mastra/client-js');
|
|
8
|
-
const reactDom = require('react-dom');
|
|
9
8
|
const lucideReact = require('lucide-react');
|
|
10
9
|
const tailwindMerge = require('tailwind-merge');
|
|
11
10
|
const hastUtilToJsxRuntime = require('hast-util-to-jsx-runtime');
|
|
@@ -254,6 +253,7 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
254
253
|
}
|
|
255
254
|
];
|
|
256
255
|
}
|
|
256
|
+
case "tool-error":
|
|
257
257
|
case "tool-result": {
|
|
258
258
|
const lastMessage = result[result.length - 1];
|
|
259
259
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
@@ -264,25 +264,35 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
264
264
|
if (toolPartIndex !== -1) {
|
|
265
265
|
const toolPart = parts[toolPartIndex];
|
|
266
266
|
if (toolPart.type === "dynamic-tool") {
|
|
267
|
-
if (chunk.payload.isError) {
|
|
267
|
+
if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
|
|
268
|
+
const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
|
|
268
269
|
parts[toolPartIndex] = {
|
|
269
270
|
type: "dynamic-tool",
|
|
270
271
|
toolName: toolPart.toolName,
|
|
271
272
|
toolCallId: toolPart.toolCallId,
|
|
272
273
|
state: "output-error",
|
|
273
274
|
input: toolPart.input,
|
|
274
|
-
errorText: String(
|
|
275
|
+
errorText: String(error),
|
|
275
276
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
276
277
|
};
|
|
277
278
|
} else {
|
|
278
279
|
const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
|
|
280
|
+
const isAgent = chunk?.from === "AGENT";
|
|
281
|
+
let output;
|
|
282
|
+
if (isWorkflow) {
|
|
283
|
+
output = chunk.payload.result?.result;
|
|
284
|
+
} else if (isAgent) {
|
|
285
|
+
output = parts[toolPartIndex].output ?? chunk.payload.result;
|
|
286
|
+
} else {
|
|
287
|
+
output = chunk.payload.result;
|
|
288
|
+
}
|
|
279
289
|
parts[toolPartIndex] = {
|
|
280
290
|
type: "dynamic-tool",
|
|
281
291
|
toolName: toolPart.toolName,
|
|
282
292
|
toolCallId: toolPart.toolCallId,
|
|
283
293
|
state: "output-available",
|
|
284
294
|
input: toolPart.input,
|
|
285
|
-
output
|
|
295
|
+
output,
|
|
286
296
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
287
297
|
};
|
|
288
298
|
}
|
|
@@ -316,6 +326,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
316
326
|
...toolPart,
|
|
317
327
|
output: updatedWorkflowState
|
|
318
328
|
};
|
|
329
|
+
} else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
|
|
330
|
+
return toUIMessageFromAgent(chunk.payload.output, conversation);
|
|
319
331
|
} else {
|
|
320
332
|
const currentOutput = toolPart.output || [];
|
|
321
333
|
const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
|
|
@@ -389,6 +401,29 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
389
401
|
}
|
|
390
402
|
];
|
|
391
403
|
}
|
|
404
|
+
case "tool-call-approval": {
|
|
405
|
+
const lastMessage = result[result.length - 1];
|
|
406
|
+
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
407
|
+
const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "stream" ? lastMessage.metadata?.requireApprovalMetadata : {};
|
|
408
|
+
return [
|
|
409
|
+
...result.slice(0, -1),
|
|
410
|
+
{
|
|
411
|
+
...lastMessage,
|
|
412
|
+
metadata: {
|
|
413
|
+
...lastMessage.metadata,
|
|
414
|
+
mode: "stream",
|
|
415
|
+
requireApprovalMetadata: {
|
|
416
|
+
...lastRequireApprovalMetadata,
|
|
417
|
+
[chunk.payload.toolCallId]: {
|
|
418
|
+
toolCallId: chunk.payload.toolCallId,
|
|
419
|
+
toolName: chunk.payload.toolName,
|
|
420
|
+
args: chunk.payload.args
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
];
|
|
426
|
+
}
|
|
392
427
|
case "finish": {
|
|
393
428
|
const lastMessage = result[result.length - 1];
|
|
394
429
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
@@ -431,6 +466,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
431
466
|
return result;
|
|
432
467
|
}
|
|
433
468
|
};
|
|
469
|
+
const toUIMessageFromAgent = (chunk, conversation, metadata) => {
|
|
470
|
+
const lastMessage = conversation[conversation.length - 1];
|
|
471
|
+
if (!lastMessage || lastMessage.role !== "assistant") return conversation;
|
|
472
|
+
const parts = [...lastMessage.parts];
|
|
473
|
+
if (chunk.type === "text-delta") {
|
|
474
|
+
const agentChunk = chunk.payload;
|
|
475
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
476
|
+
if (toolPartIndex === -1) return conversation;
|
|
477
|
+
const toolPart = parts[toolPartIndex];
|
|
478
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
479
|
+
const lastChildMessage = childMessages[childMessages.length - 1];
|
|
480
|
+
const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
|
|
481
|
+
const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
|
|
482
|
+
parts[toolPartIndex] = {
|
|
483
|
+
...toolPart,
|
|
484
|
+
output: {
|
|
485
|
+
childMessages: nextMessages
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
} else if (chunk.type === "tool-call") {
|
|
489
|
+
const agentChunk = chunk.payload;
|
|
490
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
491
|
+
if (toolPartIndex === -1) return conversation;
|
|
492
|
+
const toolPart = parts[toolPartIndex];
|
|
493
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
494
|
+
parts[toolPartIndex] = {
|
|
495
|
+
...toolPart,
|
|
496
|
+
output: {
|
|
497
|
+
...toolPart?.output,
|
|
498
|
+
childMessages: [
|
|
499
|
+
...childMessages,
|
|
500
|
+
{
|
|
501
|
+
type: "tool",
|
|
502
|
+
toolCallId: agentChunk.toolCallId,
|
|
503
|
+
toolName: agentChunk.toolName,
|
|
504
|
+
args: agentChunk.args
|
|
505
|
+
}
|
|
506
|
+
]
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
} else if (chunk.type === "tool-output") {
|
|
510
|
+
const agentChunk = chunk.payload;
|
|
511
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
512
|
+
if (toolPartIndex === -1) return conversation;
|
|
513
|
+
const toolPart = parts[toolPartIndex];
|
|
514
|
+
if (agentChunk?.output?.type?.startsWith("workflow-")) {
|
|
515
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
516
|
+
const lastToolIndex = childMessages.length - 1;
|
|
517
|
+
const currentMessage = childMessages[lastToolIndex];
|
|
518
|
+
const actualExistingWorkflowState = currentMessage?.toolOutput || {};
|
|
519
|
+
const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
|
|
520
|
+
if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
|
|
521
|
+
parts[toolPartIndex] = {
|
|
522
|
+
...toolPart,
|
|
523
|
+
output: {
|
|
524
|
+
...toolPart?.output,
|
|
525
|
+
childMessages: [
|
|
526
|
+
...childMessages.slice(0, -1),
|
|
527
|
+
{
|
|
528
|
+
...currentMessage,
|
|
529
|
+
toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
|
|
530
|
+
}
|
|
531
|
+
]
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
} else if (chunk.type === "tool-result") {
|
|
537
|
+
const agentChunk = chunk.payload;
|
|
538
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
539
|
+
if (toolPartIndex === -1) return conversation;
|
|
540
|
+
const toolPart = parts[toolPartIndex];
|
|
541
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
542
|
+
const lastToolIndex = childMessages.length - 1;
|
|
543
|
+
const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
|
|
544
|
+
if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
|
|
545
|
+
parts[toolPartIndex] = {
|
|
546
|
+
...toolPart,
|
|
547
|
+
output: {
|
|
548
|
+
...toolPart?.output,
|
|
549
|
+
childMessages: [
|
|
550
|
+
...childMessages.slice(0, -1),
|
|
551
|
+
{
|
|
552
|
+
...childMessages[lastToolIndex],
|
|
553
|
+
toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
|
|
554
|
+
}
|
|
555
|
+
]
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return [
|
|
561
|
+
...conversation.slice(0, -1),
|
|
562
|
+
{
|
|
563
|
+
...lastMessage,
|
|
564
|
+
parts
|
|
565
|
+
}
|
|
566
|
+
];
|
|
567
|
+
};
|
|
434
568
|
|
|
435
569
|
const toAssistantUIMessage = (message) => {
|
|
436
570
|
const extendedMessage = message;
|
|
@@ -470,13 +604,23 @@ const toAssistantUIMessage = (message) => {
|
|
|
470
604
|
};
|
|
471
605
|
}
|
|
472
606
|
if (part.type === "file") {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
607
|
+
const type = part.mediaType.includes("image/") ? "image" : "file";
|
|
608
|
+
if (type === "file") {
|
|
609
|
+
return {
|
|
610
|
+
type,
|
|
611
|
+
mimeType: part.mediaType,
|
|
612
|
+
data: part.url,
|
|
613
|
+
// Use URL as data source
|
|
614
|
+
metadata: message.metadata
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
if (type === "image") {
|
|
618
|
+
return {
|
|
619
|
+
type,
|
|
620
|
+
image: part.url,
|
|
621
|
+
metadata: message.metadata
|
|
622
|
+
};
|
|
623
|
+
}
|
|
480
624
|
}
|
|
481
625
|
if (part.type === "dynamic-tool") {
|
|
482
626
|
const baseToolCall = {
|
|
@@ -551,6 +695,110 @@ const toAssistantUIMessage = (message) => {
|
|
|
551
695
|
return threadMessage;
|
|
552
696
|
};
|
|
553
697
|
|
|
698
|
+
const resolveInitialMessages = (messages) => {
|
|
699
|
+
return messages.map((message) => {
|
|
700
|
+
const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
|
|
701
|
+
if (networkPart && networkPart.type === "text") {
|
|
702
|
+
try {
|
|
703
|
+
const json = JSON.parse(networkPart.text);
|
|
704
|
+
if (json.isNetwork === true) {
|
|
705
|
+
const selectionReason = json.selectionReason || "";
|
|
706
|
+
const primitiveType = json.primitiveType || "";
|
|
707
|
+
const primitiveId = json.primitiveId || "";
|
|
708
|
+
const finalResult = json.finalResult;
|
|
709
|
+
const toolCalls = finalResult?.toolCalls || [];
|
|
710
|
+
const childMessages = [];
|
|
711
|
+
for (const toolCall of toolCalls) {
|
|
712
|
+
if (toolCall.type === "tool-call" && toolCall.payload) {
|
|
713
|
+
const toolCallId = toolCall.payload.toolCallId;
|
|
714
|
+
let toolResult;
|
|
715
|
+
for (const message2 of finalResult?.messages || []) {
|
|
716
|
+
for (const part of message2.content || []) {
|
|
717
|
+
if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
718
|
+
toolResult = part;
|
|
719
|
+
break;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
const isWorkflow = Boolean(toolResult?.result?.result?.steps);
|
|
724
|
+
childMessages.push({
|
|
725
|
+
type: "tool",
|
|
726
|
+
toolCallId: toolCall.payload.toolCallId,
|
|
727
|
+
toolName: toolCall.payload.toolName,
|
|
728
|
+
args: toolCall.payload.args,
|
|
729
|
+
toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
if (finalResult && finalResult.text) {
|
|
734
|
+
childMessages.push({
|
|
735
|
+
type: "text",
|
|
736
|
+
content: finalResult.text
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
const result = {
|
|
740
|
+
childMessages,
|
|
741
|
+
result: finalResult?.text || ""
|
|
742
|
+
};
|
|
743
|
+
console.log("json", json);
|
|
744
|
+
const nextMessage = {
|
|
745
|
+
role: "assistant",
|
|
746
|
+
parts: [
|
|
747
|
+
{
|
|
748
|
+
type: "dynamic-tool",
|
|
749
|
+
toolCallId: primitiveId,
|
|
750
|
+
toolName: primitiveId,
|
|
751
|
+
state: "output-available",
|
|
752
|
+
input: json.input,
|
|
753
|
+
output: result
|
|
754
|
+
}
|
|
755
|
+
],
|
|
756
|
+
id: message.id,
|
|
757
|
+
metadata: {
|
|
758
|
+
...message.metadata,
|
|
759
|
+
mode: "network",
|
|
760
|
+
selectionReason,
|
|
761
|
+
agentInput: json.input,
|
|
762
|
+
from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
return nextMessage;
|
|
766
|
+
}
|
|
767
|
+
} catch (error) {
|
|
768
|
+
return message;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return message;
|
|
772
|
+
});
|
|
773
|
+
};
|
|
774
|
+
const resolveToChildMessages = (messages) => {
|
|
775
|
+
const assistantMessage = messages.find((message) => message.role === "assistant");
|
|
776
|
+
if (!assistantMessage) return [];
|
|
777
|
+
const parts = assistantMessage.parts;
|
|
778
|
+
let childMessages = [];
|
|
779
|
+
for (const part of parts) {
|
|
780
|
+
const toolPart = part;
|
|
781
|
+
if (part.type.startsWith("tool-")) {
|
|
782
|
+
const toolName = part.type.substring("tool-".length);
|
|
783
|
+
const isWorkflow = toolName.startsWith("workflow-");
|
|
784
|
+
childMessages.push({
|
|
785
|
+
type: "tool",
|
|
786
|
+
toolCallId: toolPart.toolCallId,
|
|
787
|
+
toolName,
|
|
788
|
+
args: toolPart.input,
|
|
789
|
+
toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
if (part.type === "text") {
|
|
793
|
+
childMessages.push({
|
|
794
|
+
type: "text",
|
|
795
|
+
content: toolPart.text
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
return childMessages;
|
|
800
|
+
};
|
|
801
|
+
|
|
554
802
|
class AISdkNetworkTransformer {
|
|
555
803
|
transform({ chunk, conversation, metadata }) {
|
|
556
804
|
const newConversation = [...conversation];
|
|
@@ -923,87 +1171,58 @@ class AISdkNetworkTransformer {
|
|
|
923
1171
|
};
|
|
924
1172
|
}
|
|
925
1173
|
|
|
926
|
-
const
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
if (finalResult && finalResult.text) {
|
|
962
|
-
childMessages.push({
|
|
963
|
-
type: "text",
|
|
964
|
-
content: finalResult.text
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
const result = {
|
|
968
|
-
childMessages,
|
|
969
|
-
result: finalResult?.text || ""
|
|
970
|
-
};
|
|
971
|
-
console.log("json", json);
|
|
972
|
-
const nextMessage = {
|
|
973
|
-
role: "assistant",
|
|
974
|
-
parts: [
|
|
975
|
-
{
|
|
976
|
-
type: "dynamic-tool",
|
|
977
|
-
toolCallId: primitiveId,
|
|
978
|
-
toolName: primitiveId,
|
|
979
|
-
state: "output-available",
|
|
980
|
-
input: json.input,
|
|
981
|
-
output: result
|
|
982
|
-
}
|
|
983
|
-
],
|
|
984
|
-
id: message.id,
|
|
985
|
-
metadata: {
|
|
986
|
-
...message.metadata,
|
|
987
|
-
mode: "network",
|
|
988
|
-
selectionReason,
|
|
989
|
-
agentInput: json.input,
|
|
990
|
-
from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
|
|
991
|
-
}
|
|
992
|
-
};
|
|
993
|
-
return nextMessage;
|
|
994
|
-
}
|
|
995
|
-
} catch (error) {
|
|
996
|
-
return message;
|
|
1174
|
+
const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
|
|
1175
|
+
const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1176
|
+
const parts = typeof coreUserMessage.content === "string" ? [
|
|
1177
|
+
{
|
|
1178
|
+
type: "text",
|
|
1179
|
+
text: coreUserMessage.content
|
|
1180
|
+
}
|
|
1181
|
+
] : coreUserMessage.content.map((part) => {
|
|
1182
|
+
switch (part.type) {
|
|
1183
|
+
case "text": {
|
|
1184
|
+
return {
|
|
1185
|
+
type: "text",
|
|
1186
|
+
text: part.text
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
case "image": {
|
|
1190
|
+
const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
|
|
1191
|
+
return {
|
|
1192
|
+
type: "file",
|
|
1193
|
+
mediaType: part.mimeType ?? "image/*",
|
|
1194
|
+
url
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
case "file": {
|
|
1198
|
+
const url = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
|
|
1199
|
+
return {
|
|
1200
|
+
type: "file",
|
|
1201
|
+
mediaType: part.mimeType,
|
|
1202
|
+
url,
|
|
1203
|
+
...part.filename !== void 0 ? { filename: part.filename } : {}
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
default: {
|
|
1207
|
+
const exhaustiveCheck = part;
|
|
1208
|
+
throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
|
|
997
1209
|
}
|
|
998
1210
|
}
|
|
999
|
-
return message;
|
|
1000
1211
|
});
|
|
1212
|
+
return {
|
|
1213
|
+
id,
|
|
1214
|
+
role: "user",
|
|
1215
|
+
parts
|
|
1216
|
+
};
|
|
1001
1217
|
};
|
|
1002
1218
|
|
|
1003
1219
|
const useChat = ({ agentId, initializeMessages }) => {
|
|
1220
|
+
const _currentRunId = react.useRef(void 0);
|
|
1221
|
+
const _onChunk = react.useRef(void 0);
|
|
1004
1222
|
const [messages, setMessages] = react.useState(
|
|
1005
1223
|
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
1006
1224
|
);
|
|
1225
|
+
const [toolCallApprovals, setToolCallApprovals] = react.useState({});
|
|
1007
1226
|
const baseClient = useMastraClient();
|
|
1008
1227
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
1009
1228
|
const generate = async ({
|
|
@@ -1073,7 +1292,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1073
1292
|
topP,
|
|
1074
1293
|
instructions,
|
|
1075
1294
|
providerOptions,
|
|
1076
|
-
maxSteps
|
|
1295
|
+
maxSteps,
|
|
1296
|
+
requireToolApproval
|
|
1077
1297
|
} = modelSettings || {};
|
|
1078
1298
|
setIsRunning(true);
|
|
1079
1299
|
const clientWithAbort = new clientJs.MastraClient({
|
|
@@ -1081,9 +1301,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1081
1301
|
abortSignal: signal
|
|
1082
1302
|
});
|
|
1083
1303
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1304
|
+
const runId = agentId;
|
|
1084
1305
|
const response = await agent.stream({
|
|
1085
1306
|
messages: coreUserMessages,
|
|
1086
|
-
runId
|
|
1307
|
+
runId,
|
|
1087
1308
|
maxSteps,
|
|
1088
1309
|
modelSettings: {
|
|
1089
1310
|
frequencyPenalty,
|
|
@@ -1097,17 +1318,14 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1097
1318
|
instructions,
|
|
1098
1319
|
runtimeContext,
|
|
1099
1320
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1100
|
-
providerOptions
|
|
1321
|
+
providerOptions,
|
|
1322
|
+
requireToolApproval
|
|
1101
1323
|
});
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
throw new Error("[Stream] No response body");
|
|
1105
|
-
}
|
|
1324
|
+
_onChunk.current = onChunk;
|
|
1325
|
+
_currentRunId.current = runId;
|
|
1106
1326
|
await response.processDataStream({
|
|
1107
1327
|
onChunk: async (chunk) => {
|
|
1108
|
-
|
|
1109
|
-
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1110
|
-
});
|
|
1328
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1111
1329
|
onChunk?.(chunk);
|
|
1112
1330
|
}
|
|
1113
1331
|
});
|
|
@@ -1147,24 +1365,65 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1147
1365
|
const transformer = new AISdkNetworkTransformer();
|
|
1148
1366
|
await response.processDataStream({
|
|
1149
1367
|
onChunk: async (chunk) => {
|
|
1150
|
-
|
|
1151
|
-
setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
|
|
1152
|
-
});
|
|
1368
|
+
setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
|
|
1153
1369
|
onNetworkChunk?.(chunk);
|
|
1154
1370
|
}
|
|
1155
1371
|
});
|
|
1156
1372
|
setIsRunning(false);
|
|
1157
1373
|
};
|
|
1374
|
+
const handleCancelRun = () => {
|
|
1375
|
+
setIsRunning(false);
|
|
1376
|
+
_currentRunId.current = void 0;
|
|
1377
|
+
_onChunk.current = void 0;
|
|
1378
|
+
};
|
|
1379
|
+
const approveToolCall = async (toolCallId) => {
|
|
1380
|
+
const onChunk = _onChunk.current;
|
|
1381
|
+
const currentRunId = _currentRunId.current;
|
|
1382
|
+
if (!currentRunId)
|
|
1383
|
+
return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
|
|
1384
|
+
setIsRunning(true);
|
|
1385
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
|
|
1386
|
+
const agent = baseClient.getAgent(agentId);
|
|
1387
|
+
const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
|
|
1388
|
+
await response.processDataStream({
|
|
1389
|
+
onChunk: async (chunk) => {
|
|
1390
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1391
|
+
onChunk?.(chunk);
|
|
1392
|
+
}
|
|
1393
|
+
});
|
|
1394
|
+
setIsRunning(false);
|
|
1395
|
+
};
|
|
1396
|
+
const declineToolCall = async (toolCallId) => {
|
|
1397
|
+
const onChunk = _onChunk.current;
|
|
1398
|
+
const currentRunId = _currentRunId.current;
|
|
1399
|
+
if (!currentRunId)
|
|
1400
|
+
return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
|
|
1401
|
+
setIsRunning(true);
|
|
1402
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
|
|
1403
|
+
const agent = baseClient.getAgent(agentId);
|
|
1404
|
+
const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
|
|
1405
|
+
await response.processDataStream({
|
|
1406
|
+
onChunk: async (chunk) => {
|
|
1407
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1408
|
+
onChunk?.(chunk);
|
|
1409
|
+
}
|
|
1410
|
+
});
|
|
1411
|
+
setIsRunning(false);
|
|
1412
|
+
};
|
|
1158
1413
|
const sendMessage = async ({ mode = "stream", ...args }) => {
|
|
1159
1414
|
const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
|
|
1160
|
-
const
|
|
1161
|
-
|
|
1415
|
+
const coreUserMessages = [nextMessage];
|
|
1416
|
+
if (args.coreUserMessages) {
|
|
1417
|
+
coreUserMessages.push(...args.coreUserMessages);
|
|
1418
|
+
}
|
|
1419
|
+
const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
|
|
1420
|
+
setMessages((s) => [...s, ...uiMessages]);
|
|
1162
1421
|
if (mode === "generate") {
|
|
1163
|
-
await generate({ ...args, coreUserMessages
|
|
1422
|
+
await generate({ ...args, coreUserMessages });
|
|
1164
1423
|
} else if (mode === "stream") {
|
|
1165
|
-
await stream({ ...args, coreUserMessages
|
|
1424
|
+
await stream({ ...args, coreUserMessages });
|
|
1166
1425
|
} else if (mode === "network") {
|
|
1167
|
-
await network({ ...args, coreUserMessages
|
|
1426
|
+
await network({ ...args, coreUserMessages });
|
|
1168
1427
|
}
|
|
1169
1428
|
};
|
|
1170
1429
|
return {
|
|
@@ -1172,7 +1431,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1172
1431
|
sendMessage,
|
|
1173
1432
|
isRunning,
|
|
1174
1433
|
messages,
|
|
1175
|
-
|
|
1434
|
+
approveToolCall,
|
|
1435
|
+
declineToolCall,
|
|
1436
|
+
cancelRun: handleCancelRun,
|
|
1437
|
+
toolCallApprovals
|
|
1176
1438
|
};
|
|
1177
1439
|
};
|
|
1178
1440
|
|
|
@@ -1546,6 +1808,7 @@ exports.TooltipContentClass = TooltipContentClass;
|
|
|
1546
1808
|
exports.TooltipTrigger = TooltipTrigger;
|
|
1547
1809
|
exports.WorkflowIcon = WorkflowIcon;
|
|
1548
1810
|
exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
|
|
1811
|
+
exports.resolveToChildMessages = resolveToChildMessages;
|
|
1549
1812
|
exports.toAssistantUIMessage = toAssistantUIMessage;
|
|
1550
1813
|
exports.toUIMessage = toUIMessage;
|
|
1551
1814
|
exports.useChat = useChat;
|