@mastra/react 0.0.0-usechat-duplicate-20251016110554 → 0.0.0-vnext-20251119160359
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 +126 -2
- package/dist/index.cjs +377 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +378 -115
- 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 +15 -11
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,15 +401,37 @@ 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;
|
|
395
430
|
const parts = lastMessage.parts.map((part) => {
|
|
396
|
-
if (part
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
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
|
+
}
|
|
401
435
|
}
|
|
402
436
|
return part;
|
|
403
437
|
});
|
|
@@ -431,6 +465,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
431
465
|
return result;
|
|
432
466
|
}
|
|
433
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
|
+
};
|
|
434
567
|
|
|
435
568
|
const toAssistantUIMessage = (message) => {
|
|
436
569
|
const extendedMessage = message;
|
|
@@ -470,13 +603,23 @@ const toAssistantUIMessage = (message) => {
|
|
|
470
603
|
};
|
|
471
604
|
}
|
|
472
605
|
if (part.type === "file") {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
+
}
|
|
480
623
|
}
|
|
481
624
|
if (part.type === "dynamic-tool") {
|
|
482
625
|
const baseToolCall = {
|
|
@@ -551,6 +694,112 @@ const toAssistantUIMessage = (message) => {
|
|
|
551
694
|
return threadMessage;
|
|
552
695
|
};
|
|
553
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
|
+
|
|
554
803
|
class AISdkNetworkTransformer {
|
|
555
804
|
transform({ chunk, conversation, metadata }) {
|
|
556
805
|
const newConversation = [...conversation];
|
|
@@ -923,92 +1172,63 @@ class AISdkNetworkTransformer {
|
|
|
923
1172
|
};
|
|
924
1173
|
}
|
|
925
1174
|
|
|
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;
|
|
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}`);
|
|
997
1210
|
}
|
|
998
1211
|
}
|
|
999
|
-
return message;
|
|
1000
1212
|
});
|
|
1213
|
+
return {
|
|
1214
|
+
id,
|
|
1215
|
+
role: "user",
|
|
1216
|
+
parts
|
|
1217
|
+
};
|
|
1001
1218
|
};
|
|
1002
1219
|
|
|
1003
1220
|
const useChat = ({ agentId, initializeMessages }) => {
|
|
1221
|
+
const _currentRunId = react.useRef(void 0);
|
|
1222
|
+
const _onChunk = react.useRef(void 0);
|
|
1004
1223
|
const [messages, setMessages] = react.useState(
|
|
1005
1224
|
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
1006
1225
|
);
|
|
1226
|
+
const [toolCallApprovals, setToolCallApprovals] = react.useState({});
|
|
1007
1227
|
const baseClient = useMastraClient();
|
|
1008
1228
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
1009
1229
|
const generate = async ({
|
|
1010
1230
|
coreUserMessages,
|
|
1011
|
-
|
|
1231
|
+
requestContext,
|
|
1012
1232
|
threadId,
|
|
1013
1233
|
modelSettings,
|
|
1014
1234
|
signal,
|
|
@@ -1046,7 +1266,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1046
1266
|
topP
|
|
1047
1267
|
},
|
|
1048
1268
|
instructions,
|
|
1049
|
-
|
|
1269
|
+
requestContext,
|
|
1050
1270
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1051
1271
|
providerOptions
|
|
1052
1272
|
});
|
|
@@ -1062,7 +1282,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1062
1282
|
setMessages((prev) => [...prev, ...mastraUIMessages]);
|
|
1063
1283
|
}
|
|
1064
1284
|
};
|
|
1065
|
-
const stream = async ({ coreUserMessages,
|
|
1285
|
+
const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
|
|
1066
1286
|
const {
|
|
1067
1287
|
frequencyPenalty,
|
|
1068
1288
|
presencePenalty,
|
|
@@ -1073,7 +1293,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1073
1293
|
topP,
|
|
1074
1294
|
instructions,
|
|
1075
1295
|
providerOptions,
|
|
1076
|
-
maxSteps
|
|
1296
|
+
maxSteps,
|
|
1297
|
+
requireToolApproval
|
|
1077
1298
|
} = modelSettings || {};
|
|
1078
1299
|
setIsRunning(true);
|
|
1079
1300
|
const clientWithAbort = new clientJs.MastraClient({
|
|
@@ -1081,9 +1302,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1081
1302
|
abortSignal: signal
|
|
1082
1303
|
});
|
|
1083
1304
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1305
|
+
const runId = agentId;
|
|
1084
1306
|
const response = await agent.stream({
|
|
1085
1307
|
messages: coreUserMessages,
|
|
1086
|
-
runId
|
|
1308
|
+
runId,
|
|
1087
1309
|
maxSteps,
|
|
1088
1310
|
modelSettings: {
|
|
1089
1311
|
frequencyPenalty,
|
|
@@ -1095,19 +1317,16 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1095
1317
|
topP
|
|
1096
1318
|
},
|
|
1097
1319
|
instructions,
|
|
1098
|
-
|
|
1320
|
+
requestContext,
|
|
1099
1321
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1100
|
-
providerOptions
|
|
1322
|
+
providerOptions,
|
|
1323
|
+
requireToolApproval
|
|
1101
1324
|
});
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
throw new Error("[Stream] No response body");
|
|
1105
|
-
}
|
|
1325
|
+
_onChunk.current = onChunk;
|
|
1326
|
+
_currentRunId.current = runId;
|
|
1106
1327
|
await response.processDataStream({
|
|
1107
1328
|
onChunk: async (chunk) => {
|
|
1108
|
-
|
|
1109
|
-
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1110
|
-
});
|
|
1329
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1111
1330
|
onChunk?.(chunk);
|
|
1112
1331
|
}
|
|
1113
1332
|
});
|
|
@@ -1115,7 +1334,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1115
1334
|
};
|
|
1116
1335
|
const network = async ({
|
|
1117
1336
|
coreUserMessages,
|
|
1118
|
-
|
|
1337
|
+
requestContext,
|
|
1119
1338
|
threadId,
|
|
1120
1339
|
onNetworkChunk,
|
|
1121
1340
|
modelSettings,
|
|
@@ -1141,30 +1360,71 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1141
1360
|
topP
|
|
1142
1361
|
},
|
|
1143
1362
|
runId: agentId,
|
|
1144
|
-
|
|
1363
|
+
requestContext,
|
|
1145
1364
|
...threadId ? { thread: threadId, resourceId: agentId } : {}
|
|
1146
1365
|
});
|
|
1147
1366
|
const transformer = new AISdkNetworkTransformer();
|
|
1148
1367
|
await response.processDataStream({
|
|
1149
1368
|
onChunk: async (chunk) => {
|
|
1150
|
-
|
|
1151
|
-
setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
|
|
1152
|
-
});
|
|
1369
|
+
setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
|
|
1153
1370
|
onNetworkChunk?.(chunk);
|
|
1154
1371
|
}
|
|
1155
1372
|
});
|
|
1156
1373
|
setIsRunning(false);
|
|
1157
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
|
+
};
|
|
1158
1414
|
const sendMessage = async ({ mode = "stream", ...args }) => {
|
|
1159
1415
|
const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
|
|
1160
|
-
const
|
|
1161
|
-
|
|
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]);
|
|
1162
1422
|
if (mode === "generate") {
|
|
1163
|
-
await generate({ ...args, coreUserMessages
|
|
1423
|
+
await generate({ ...args, coreUserMessages });
|
|
1164
1424
|
} else if (mode === "stream") {
|
|
1165
|
-
await stream({ ...args, coreUserMessages
|
|
1425
|
+
await stream({ ...args, coreUserMessages });
|
|
1166
1426
|
} else if (mode === "network") {
|
|
1167
|
-
await network({ ...args, coreUserMessages
|
|
1427
|
+
await network({ ...args, coreUserMessages });
|
|
1168
1428
|
}
|
|
1169
1429
|
};
|
|
1170
1430
|
return {
|
|
@@ -1172,7 +1432,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1172
1432
|
sendMessage,
|
|
1173
1433
|
isRunning,
|
|
1174
1434
|
messages,
|
|
1175
|
-
|
|
1435
|
+
approveToolCall,
|
|
1436
|
+
declineToolCall,
|
|
1437
|
+
cancelRun: handleCancelRun,
|
|
1438
|
+
toolCallApprovals
|
|
1176
1439
|
};
|
|
1177
1440
|
};
|
|
1178
1441
|
|
|
@@ -1546,6 +1809,7 @@ exports.TooltipContentClass = TooltipContentClass;
|
|
|
1546
1809
|
exports.TooltipTrigger = TooltipTrigger;
|
|
1547
1810
|
exports.WorkflowIcon = WorkflowIcon;
|
|
1548
1811
|
exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
|
|
1812
|
+
exports.resolveToChildMessages = resolveToChildMessages;
|
|
1549
1813
|
exports.toAssistantUIMessage = toAssistantUIMessage;
|
|
1550
1814
|
exports.toUIMessage = toUIMessage;
|
|
1551
1815
|
exports.useChat = useChat;
|