@mastra/react 0.0.0-error-handler-fix-20251020202607 → 0.0.0-export-agent-memory-from-local-studio-20251112153946
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 +101 -2
- package/dist/index.cjs +375 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +376 -108
- package/dist/index.js.map +1 -1
- package/dist/react.css +1 -1
- package/dist/src/agent/hooks.d.ts +9 -2
- 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 +11 -7
package/dist/index.cjs
CHANGED
|
@@ -253,6 +253,7 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
253
253
|
}
|
|
254
254
|
];
|
|
255
255
|
}
|
|
256
|
+
case "tool-error":
|
|
256
257
|
case "tool-result": {
|
|
257
258
|
const lastMessage = result[result.length - 1];
|
|
258
259
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
@@ -263,25 +264,35 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
263
264
|
if (toolPartIndex !== -1) {
|
|
264
265
|
const toolPart = parts[toolPartIndex];
|
|
265
266
|
if (toolPart.type === "dynamic-tool") {
|
|
266
|
-
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;
|
|
267
269
|
parts[toolPartIndex] = {
|
|
268
270
|
type: "dynamic-tool",
|
|
269
271
|
toolName: toolPart.toolName,
|
|
270
272
|
toolCallId: toolPart.toolCallId,
|
|
271
273
|
state: "output-error",
|
|
272
274
|
input: toolPart.input,
|
|
273
|
-
errorText: String(
|
|
275
|
+
errorText: String(error),
|
|
274
276
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
275
277
|
};
|
|
276
278
|
} else {
|
|
277
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
|
+
}
|
|
278
289
|
parts[toolPartIndex] = {
|
|
279
290
|
type: "dynamic-tool",
|
|
280
291
|
toolName: toolPart.toolName,
|
|
281
292
|
toolCallId: toolPart.toolCallId,
|
|
282
293
|
state: "output-available",
|
|
283
294
|
input: toolPart.input,
|
|
284
|
-
output
|
|
295
|
+
output,
|
|
285
296
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
286
297
|
};
|
|
287
298
|
}
|
|
@@ -315,6 +326,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
315
326
|
...toolPart,
|
|
316
327
|
output: updatedWorkflowState
|
|
317
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);
|
|
318
331
|
} else {
|
|
319
332
|
const currentOutput = toolPart.output || [];
|
|
320
333
|
const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
|
|
@@ -388,15 +401,37 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
388
401
|
}
|
|
389
402
|
];
|
|
390
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
|
+
}
|
|
391
427
|
case "finish": {
|
|
392
428
|
const lastMessage = result[result.length - 1];
|
|
393
429
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
394
430
|
const parts = lastMessage.parts.map((part) => {
|
|
395
|
-
if (part
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
return { ...part, state: "done" };
|
|
431
|
+
if (typeof part === "object" && part !== null && "type" in part && "state" in part && part.state === "streaming") {
|
|
432
|
+
if (part.type === "text" || part.type === "reasoning") {
|
|
433
|
+
return { ...part, state: "done" };
|
|
434
|
+
}
|
|
400
435
|
}
|
|
401
436
|
return part;
|
|
402
437
|
});
|
|
@@ -430,6 +465,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
430
465
|
return result;
|
|
431
466
|
}
|
|
432
467
|
};
|
|
468
|
+
const toUIMessageFromAgent = (chunk, conversation, metadata) => {
|
|
469
|
+
const lastMessage = conversation[conversation.length - 1];
|
|
470
|
+
if (!lastMessage || lastMessage.role !== "assistant") return conversation;
|
|
471
|
+
const parts = [...lastMessage.parts];
|
|
472
|
+
if (chunk.type === "text-delta") {
|
|
473
|
+
const agentChunk = chunk.payload;
|
|
474
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
475
|
+
if (toolPartIndex === -1) return conversation;
|
|
476
|
+
const toolPart = parts[toolPartIndex];
|
|
477
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
478
|
+
const lastChildMessage = childMessages[childMessages.length - 1];
|
|
479
|
+
const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
|
|
480
|
+
const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
|
|
481
|
+
parts[toolPartIndex] = {
|
|
482
|
+
...toolPart,
|
|
483
|
+
output: {
|
|
484
|
+
childMessages: nextMessages
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
} else if (chunk.type === "tool-call") {
|
|
488
|
+
const agentChunk = chunk.payload;
|
|
489
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
490
|
+
if (toolPartIndex === -1) return conversation;
|
|
491
|
+
const toolPart = parts[toolPartIndex];
|
|
492
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
493
|
+
parts[toolPartIndex] = {
|
|
494
|
+
...toolPart,
|
|
495
|
+
output: {
|
|
496
|
+
...toolPart?.output,
|
|
497
|
+
childMessages: [
|
|
498
|
+
...childMessages,
|
|
499
|
+
{
|
|
500
|
+
type: "tool",
|
|
501
|
+
toolCallId: agentChunk.toolCallId,
|
|
502
|
+
toolName: agentChunk.toolName,
|
|
503
|
+
args: agentChunk.args
|
|
504
|
+
}
|
|
505
|
+
]
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
} else if (chunk.type === "tool-output") {
|
|
509
|
+
const agentChunk = chunk.payload;
|
|
510
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
511
|
+
if (toolPartIndex === -1) return conversation;
|
|
512
|
+
const toolPart = parts[toolPartIndex];
|
|
513
|
+
if (agentChunk?.output?.type?.startsWith("workflow-")) {
|
|
514
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
515
|
+
const lastToolIndex = childMessages.length - 1;
|
|
516
|
+
const currentMessage = childMessages[lastToolIndex];
|
|
517
|
+
const actualExistingWorkflowState = currentMessage?.toolOutput || {};
|
|
518
|
+
const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
|
|
519
|
+
if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
|
|
520
|
+
parts[toolPartIndex] = {
|
|
521
|
+
...toolPart,
|
|
522
|
+
output: {
|
|
523
|
+
...toolPart?.output,
|
|
524
|
+
childMessages: [
|
|
525
|
+
...childMessages.slice(0, -1),
|
|
526
|
+
{
|
|
527
|
+
...currentMessage,
|
|
528
|
+
toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
|
|
529
|
+
}
|
|
530
|
+
]
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
} else if (chunk.type === "tool-result") {
|
|
536
|
+
const agentChunk = chunk.payload;
|
|
537
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
538
|
+
if (toolPartIndex === -1) return conversation;
|
|
539
|
+
const toolPart = parts[toolPartIndex];
|
|
540
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
541
|
+
const lastToolIndex = childMessages.length - 1;
|
|
542
|
+
const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
|
|
543
|
+
if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
|
|
544
|
+
parts[toolPartIndex] = {
|
|
545
|
+
...toolPart,
|
|
546
|
+
output: {
|
|
547
|
+
...toolPart?.output,
|
|
548
|
+
childMessages: [
|
|
549
|
+
...childMessages.slice(0, -1),
|
|
550
|
+
{
|
|
551
|
+
...childMessages[lastToolIndex],
|
|
552
|
+
toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
|
|
553
|
+
}
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return [
|
|
560
|
+
...conversation.slice(0, -1),
|
|
561
|
+
{
|
|
562
|
+
...lastMessage,
|
|
563
|
+
parts
|
|
564
|
+
}
|
|
565
|
+
];
|
|
566
|
+
};
|
|
433
567
|
|
|
434
568
|
const toAssistantUIMessage = (message) => {
|
|
435
569
|
const extendedMessage = message;
|
|
@@ -469,13 +603,23 @@ const toAssistantUIMessage = (message) => {
|
|
|
469
603
|
};
|
|
470
604
|
}
|
|
471
605
|
if (part.type === "file") {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
606
|
+
const type = part.mediaType.includes("image/") ? "image" : "file";
|
|
607
|
+
if (type === "file") {
|
|
608
|
+
return {
|
|
609
|
+
type,
|
|
610
|
+
mimeType: part.mediaType,
|
|
611
|
+
data: part.url,
|
|
612
|
+
// Use URL as data source
|
|
613
|
+
metadata: message.metadata
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (type === "image") {
|
|
617
|
+
return {
|
|
618
|
+
type,
|
|
619
|
+
image: part.url,
|
|
620
|
+
metadata: message.metadata
|
|
621
|
+
};
|
|
622
|
+
}
|
|
479
623
|
}
|
|
480
624
|
if (part.type === "dynamic-tool") {
|
|
481
625
|
const baseToolCall = {
|
|
@@ -550,6 +694,112 @@ const toAssistantUIMessage = (message) => {
|
|
|
550
694
|
return threadMessage;
|
|
551
695
|
};
|
|
552
696
|
|
|
697
|
+
const resolveInitialMessages = (messages) => {
|
|
698
|
+
return messages.map((message) => {
|
|
699
|
+
const networkPart = message.parts.find(
|
|
700
|
+
(part) => typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" && part.text.includes('"isNetwork":true')
|
|
701
|
+
);
|
|
702
|
+
if (networkPart && networkPart.type === "text") {
|
|
703
|
+
try {
|
|
704
|
+
const json = JSON.parse(networkPart.text);
|
|
705
|
+
if (json.isNetwork === true) {
|
|
706
|
+
const selectionReason = json.selectionReason || "";
|
|
707
|
+
const primitiveType = json.primitiveType || "";
|
|
708
|
+
const primitiveId = json.primitiveId || "";
|
|
709
|
+
const finalResult = json.finalResult;
|
|
710
|
+
const toolCalls = finalResult?.toolCalls || [];
|
|
711
|
+
const childMessages = [];
|
|
712
|
+
for (const toolCall of toolCalls) {
|
|
713
|
+
if (toolCall.type === "tool-call" && toolCall.payload) {
|
|
714
|
+
const toolCallId = toolCall.payload.toolCallId;
|
|
715
|
+
let toolResult;
|
|
716
|
+
for (const message2 of finalResult?.messages || []) {
|
|
717
|
+
for (const part of message2.content || []) {
|
|
718
|
+
if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
719
|
+
toolResult = part;
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
const isWorkflow = Boolean(toolResult?.result?.result?.steps);
|
|
725
|
+
childMessages.push({
|
|
726
|
+
type: "tool",
|
|
727
|
+
toolCallId: toolCall.payload.toolCallId,
|
|
728
|
+
toolName: toolCall.payload.toolName,
|
|
729
|
+
args: toolCall.payload.args,
|
|
730
|
+
toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
if (finalResult && finalResult.text) {
|
|
735
|
+
childMessages.push({
|
|
736
|
+
type: "text",
|
|
737
|
+
content: finalResult.text
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
const result = {
|
|
741
|
+
childMessages,
|
|
742
|
+
result: finalResult?.text || ""
|
|
743
|
+
};
|
|
744
|
+
console.log("json", json);
|
|
745
|
+
const nextMessage = {
|
|
746
|
+
role: "assistant",
|
|
747
|
+
parts: [
|
|
748
|
+
{
|
|
749
|
+
type: "dynamic-tool",
|
|
750
|
+
toolCallId: primitiveId,
|
|
751
|
+
toolName: primitiveId,
|
|
752
|
+
state: "output-available",
|
|
753
|
+
input: json.input,
|
|
754
|
+
output: result
|
|
755
|
+
}
|
|
756
|
+
],
|
|
757
|
+
id: message.id,
|
|
758
|
+
metadata: {
|
|
759
|
+
...message.metadata,
|
|
760
|
+
mode: "network",
|
|
761
|
+
selectionReason,
|
|
762
|
+
agentInput: json.input,
|
|
763
|
+
from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
return nextMessage;
|
|
767
|
+
}
|
|
768
|
+
} catch (error) {
|
|
769
|
+
return message;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return message;
|
|
773
|
+
});
|
|
774
|
+
};
|
|
775
|
+
const resolveToChildMessages = (messages) => {
|
|
776
|
+
const assistantMessage = messages.find((message) => message.role === "assistant");
|
|
777
|
+
if (!assistantMessage) return [];
|
|
778
|
+
const parts = assistantMessage.parts;
|
|
779
|
+
let childMessages = [];
|
|
780
|
+
for (const part of parts) {
|
|
781
|
+
const toolPart = part;
|
|
782
|
+
if (part.type.startsWith("tool-")) {
|
|
783
|
+
const toolName = part.type.substring("tool-".length);
|
|
784
|
+
const isWorkflow = toolName.startsWith("workflow-");
|
|
785
|
+
childMessages.push({
|
|
786
|
+
type: "tool",
|
|
787
|
+
toolCallId: toolPart.toolCallId,
|
|
788
|
+
toolName,
|
|
789
|
+
args: toolPart.input,
|
|
790
|
+
toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
if (part.type === "text") {
|
|
794
|
+
childMessages.push({
|
|
795
|
+
type: "text",
|
|
796
|
+
content: toolPart.text
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return childMessages;
|
|
801
|
+
};
|
|
802
|
+
|
|
553
803
|
class AISdkNetworkTransformer {
|
|
554
804
|
transform({ chunk, conversation, metadata }) {
|
|
555
805
|
const newConversation = [...conversation];
|
|
@@ -922,92 +1172,63 @@ class AISdkNetworkTransformer {
|
|
|
922
1172
|
};
|
|
923
1173
|
}
|
|
924
1174
|
|
|
925
|
-
const
|
|
926
|
-
|
|
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
|
-
if (finalResult && finalResult.text) {
|
|
961
|
-
childMessages.push({
|
|
962
|
-
type: "text",
|
|
963
|
-
content: finalResult.text
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
|
-
const result = {
|
|
967
|
-
childMessages,
|
|
968
|
-
result: finalResult?.text || ""
|
|
969
|
-
};
|
|
970
|
-
console.log("json", json);
|
|
971
|
-
const nextMessage = {
|
|
972
|
-
role: "assistant",
|
|
973
|
-
parts: [
|
|
974
|
-
{
|
|
975
|
-
type: "dynamic-tool",
|
|
976
|
-
toolCallId: primitiveId,
|
|
977
|
-
toolName: primitiveId,
|
|
978
|
-
state: "output-available",
|
|
979
|
-
input: json.input,
|
|
980
|
-
output: result
|
|
981
|
-
}
|
|
982
|
-
],
|
|
983
|
-
id: message.id,
|
|
984
|
-
metadata: {
|
|
985
|
-
...message.metadata,
|
|
986
|
-
mode: "network",
|
|
987
|
-
selectionReason,
|
|
988
|
-
agentInput: json.input,
|
|
989
|
-
from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
|
|
990
|
-
}
|
|
991
|
-
};
|
|
992
|
-
return nextMessage;
|
|
993
|
-
}
|
|
994
|
-
} catch (error) {
|
|
995
|
-
return message;
|
|
1175
|
+
const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
|
|
1176
|
+
const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1177
|
+
const parts = typeof coreUserMessage.content === "string" ? [
|
|
1178
|
+
{
|
|
1179
|
+
type: "text",
|
|
1180
|
+
text: coreUserMessage.content
|
|
1181
|
+
}
|
|
1182
|
+
] : coreUserMessage.content.map((part) => {
|
|
1183
|
+
switch (part.type) {
|
|
1184
|
+
case "text": {
|
|
1185
|
+
return {
|
|
1186
|
+
type: "text",
|
|
1187
|
+
text: part.text
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
case "image": {
|
|
1191
|
+
const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
|
|
1192
|
+
return {
|
|
1193
|
+
type: "file",
|
|
1194
|
+
mediaType: part.mimeType ?? "image/*",
|
|
1195
|
+
url
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
case "file": {
|
|
1199
|
+
const url = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
|
|
1200
|
+
return {
|
|
1201
|
+
type: "file",
|
|
1202
|
+
mediaType: part.mimeType,
|
|
1203
|
+
url,
|
|
1204
|
+
...part.filename !== void 0 ? { filename: part.filename } : {}
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
default: {
|
|
1208
|
+
const exhaustiveCheck = part;
|
|
1209
|
+
throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
|
|
996
1210
|
}
|
|
997
1211
|
}
|
|
998
|
-
return message;
|
|
999
1212
|
});
|
|
1213
|
+
return {
|
|
1214
|
+
id,
|
|
1215
|
+
role: "user",
|
|
1216
|
+
parts
|
|
1217
|
+
};
|
|
1000
1218
|
};
|
|
1001
1219
|
|
|
1002
1220
|
const useChat = ({ agentId, initializeMessages }) => {
|
|
1221
|
+
const _currentRunId = react.useRef(void 0);
|
|
1222
|
+
const _onChunk = react.useRef(void 0);
|
|
1003
1223
|
const [messages, setMessages] = react.useState(
|
|
1004
1224
|
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
1005
1225
|
);
|
|
1226
|
+
const [toolCallApprovals, setToolCallApprovals] = react.useState({});
|
|
1006
1227
|
const baseClient = useMastraClient();
|
|
1007
1228
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
1008
1229
|
const generate = async ({
|
|
1009
1230
|
coreUserMessages,
|
|
1010
|
-
|
|
1231
|
+
requestContext,
|
|
1011
1232
|
threadId,
|
|
1012
1233
|
modelSettings,
|
|
1013
1234
|
signal,
|
|
@@ -1045,7 +1266,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1045
1266
|
topP
|
|
1046
1267
|
},
|
|
1047
1268
|
instructions,
|
|
1048
|
-
|
|
1269
|
+
requestContext,
|
|
1049
1270
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1050
1271
|
providerOptions
|
|
1051
1272
|
});
|
|
@@ -1061,7 +1282,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1061
1282
|
setMessages((prev) => [...prev, ...mastraUIMessages]);
|
|
1062
1283
|
}
|
|
1063
1284
|
};
|
|
1064
|
-
const stream = async ({ coreUserMessages,
|
|
1285
|
+
const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
|
|
1065
1286
|
const {
|
|
1066
1287
|
frequencyPenalty,
|
|
1067
1288
|
presencePenalty,
|
|
@@ -1072,7 +1293,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1072
1293
|
topP,
|
|
1073
1294
|
instructions,
|
|
1074
1295
|
providerOptions,
|
|
1075
|
-
maxSteps
|
|
1296
|
+
maxSteps,
|
|
1297
|
+
requireToolApproval
|
|
1076
1298
|
} = modelSettings || {};
|
|
1077
1299
|
setIsRunning(true);
|
|
1078
1300
|
const clientWithAbort = new clientJs.MastraClient({
|
|
@@ -1080,9 +1302,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1080
1302
|
abortSignal: signal
|
|
1081
1303
|
});
|
|
1082
1304
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1305
|
+
const runId = agentId;
|
|
1083
1306
|
const response = await agent.stream({
|
|
1084
1307
|
messages: coreUserMessages,
|
|
1085
|
-
runId
|
|
1308
|
+
runId,
|
|
1086
1309
|
maxSteps,
|
|
1087
1310
|
modelSettings: {
|
|
1088
1311
|
frequencyPenalty,
|
|
@@ -1094,14 +1317,13 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1094
1317
|
topP
|
|
1095
1318
|
},
|
|
1096
1319
|
instructions,
|
|
1097
|
-
|
|
1320
|
+
requestContext,
|
|
1098
1321
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1099
|
-
providerOptions
|
|
1322
|
+
providerOptions,
|
|
1323
|
+
requireToolApproval
|
|
1100
1324
|
});
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
throw new Error("[Stream] No response body");
|
|
1104
|
-
}
|
|
1325
|
+
_onChunk.current = onChunk;
|
|
1326
|
+
_currentRunId.current = runId;
|
|
1105
1327
|
await response.processDataStream({
|
|
1106
1328
|
onChunk: async (chunk) => {
|
|
1107
1329
|
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
@@ -1112,7 +1334,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1112
1334
|
};
|
|
1113
1335
|
const network = async ({
|
|
1114
1336
|
coreUserMessages,
|
|
1115
|
-
|
|
1337
|
+
requestContext,
|
|
1116
1338
|
threadId,
|
|
1117
1339
|
onNetworkChunk,
|
|
1118
1340
|
modelSettings,
|
|
@@ -1138,7 +1360,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1138
1360
|
topP
|
|
1139
1361
|
},
|
|
1140
1362
|
runId: agentId,
|
|
1141
|
-
|
|
1363
|
+
requestContext,
|
|
1142
1364
|
...threadId ? { thread: threadId, resourceId: agentId } : {}
|
|
1143
1365
|
});
|
|
1144
1366
|
const transformer = new AISdkNetworkTransformer();
|
|
@@ -1150,16 +1372,59 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1150
1372
|
});
|
|
1151
1373
|
setIsRunning(false);
|
|
1152
1374
|
};
|
|
1375
|
+
const handleCancelRun = () => {
|
|
1376
|
+
setIsRunning(false);
|
|
1377
|
+
_currentRunId.current = void 0;
|
|
1378
|
+
_onChunk.current = void 0;
|
|
1379
|
+
};
|
|
1380
|
+
const approveToolCall = async (toolCallId) => {
|
|
1381
|
+
const onChunk = _onChunk.current;
|
|
1382
|
+
const currentRunId = _currentRunId.current;
|
|
1383
|
+
if (!currentRunId)
|
|
1384
|
+
return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
|
|
1385
|
+
setIsRunning(true);
|
|
1386
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
|
|
1387
|
+
const agent = baseClient.getAgent(agentId);
|
|
1388
|
+
const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
|
|
1389
|
+
await response.processDataStream({
|
|
1390
|
+
onChunk: async (chunk) => {
|
|
1391
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1392
|
+
onChunk?.(chunk);
|
|
1393
|
+
}
|
|
1394
|
+
});
|
|
1395
|
+
setIsRunning(false);
|
|
1396
|
+
};
|
|
1397
|
+
const declineToolCall = async (toolCallId) => {
|
|
1398
|
+
const onChunk = _onChunk.current;
|
|
1399
|
+
const currentRunId = _currentRunId.current;
|
|
1400
|
+
if (!currentRunId)
|
|
1401
|
+
return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
|
|
1402
|
+
setIsRunning(true);
|
|
1403
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
|
|
1404
|
+
const agent = baseClient.getAgent(agentId);
|
|
1405
|
+
const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
|
|
1406
|
+
await response.processDataStream({
|
|
1407
|
+
onChunk: async (chunk) => {
|
|
1408
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1409
|
+
onChunk?.(chunk);
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
setIsRunning(false);
|
|
1413
|
+
};
|
|
1153
1414
|
const sendMessage = async ({ mode = "stream", ...args }) => {
|
|
1154
1415
|
const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1416
|
+
const coreUserMessages = [nextMessage];
|
|
1417
|
+
if (args.coreUserMessages) {
|
|
1418
|
+
coreUserMessages.push(...args.coreUserMessages);
|
|
1419
|
+
}
|
|
1420
|
+
const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
|
|
1421
|
+
setMessages((s) => [...s, ...uiMessages]);
|
|
1157
1422
|
if (mode === "generate") {
|
|
1158
|
-
await generate({ ...args, coreUserMessages
|
|
1423
|
+
await generate({ ...args, coreUserMessages });
|
|
1159
1424
|
} else if (mode === "stream") {
|
|
1160
|
-
await stream({ ...args, coreUserMessages
|
|
1425
|
+
await stream({ ...args, coreUserMessages });
|
|
1161
1426
|
} else if (mode === "network") {
|
|
1162
|
-
await network({ ...args, coreUserMessages
|
|
1427
|
+
await network({ ...args, coreUserMessages });
|
|
1163
1428
|
}
|
|
1164
1429
|
};
|
|
1165
1430
|
return {
|
|
@@ -1167,7 +1432,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1167
1432
|
sendMessage,
|
|
1168
1433
|
isRunning,
|
|
1169
1434
|
messages,
|
|
1170
|
-
|
|
1435
|
+
approveToolCall,
|
|
1436
|
+
declineToolCall,
|
|
1437
|
+
cancelRun: handleCancelRun,
|
|
1438
|
+
toolCallApprovals
|
|
1171
1439
|
};
|
|
1172
1440
|
};
|
|
1173
1441
|
|
|
@@ -1541,6 +1809,7 @@ exports.TooltipContentClass = TooltipContentClass;
|
|
|
1541
1809
|
exports.TooltipTrigger = TooltipTrigger;
|
|
1542
1810
|
exports.WorkflowIcon = WorkflowIcon;
|
|
1543
1811
|
exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
|
|
1812
|
+
exports.resolveToChildMessages = resolveToChildMessages;
|
|
1544
1813
|
exports.toAssistantUIMessage = toAssistantUIMessage;
|
|
1545
1814
|
exports.toUIMessage = toUIMessage;
|
|
1546
1815
|
exports.useChat = useChat;
|