@mastra/react 0.0.0-monorepo-binary-20251013210052 → 0.0.0-playground-studio-again-20251114100107
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 +173 -2
- package/dist/index.cjs +449 -124
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +450 -126
- 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.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 +21 -13
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useState, Fragment, useLayoutEffect,
|
|
2
|
+
import { createContext, useContext, useRef, useState, Fragment, useLayoutEffect, useEffect } from 'react';
|
|
3
3
|
import { MastraClient } from '@mastra/client-js';
|
|
4
|
-
import { flushSync } from 'react-dom';
|
|
5
4
|
import { ChevronDownIcon, CheckIcon, CopyIcon } from 'lucide-react';
|
|
6
5
|
import { twMerge } from 'tailwind-merge';
|
|
7
6
|
import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
|
@@ -250,6 +249,7 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
250
249
|
}
|
|
251
250
|
];
|
|
252
251
|
}
|
|
252
|
+
case "tool-error":
|
|
253
253
|
case "tool-result": {
|
|
254
254
|
const lastMessage = result[result.length - 1];
|
|
255
255
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
@@ -260,25 +260,35 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
260
260
|
if (toolPartIndex !== -1) {
|
|
261
261
|
const toolPart = parts[toolPartIndex];
|
|
262
262
|
if (toolPart.type === "dynamic-tool") {
|
|
263
|
-
if (chunk.payload.isError) {
|
|
263
|
+
if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
|
|
264
|
+
const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
|
|
264
265
|
parts[toolPartIndex] = {
|
|
265
266
|
type: "dynamic-tool",
|
|
266
267
|
toolName: toolPart.toolName,
|
|
267
268
|
toolCallId: toolPart.toolCallId,
|
|
268
269
|
state: "output-error",
|
|
269
270
|
input: toolPart.input,
|
|
270
|
-
errorText: String(
|
|
271
|
+
errorText: String(error),
|
|
271
272
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
272
273
|
};
|
|
273
274
|
} else {
|
|
274
275
|
const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
|
|
276
|
+
const isAgent = chunk?.from === "AGENT";
|
|
277
|
+
let output;
|
|
278
|
+
if (isWorkflow) {
|
|
279
|
+
output = chunk.payload.result?.result;
|
|
280
|
+
} else if (isAgent) {
|
|
281
|
+
output = parts[toolPartIndex].output ?? chunk.payload.result;
|
|
282
|
+
} else {
|
|
283
|
+
output = chunk.payload.result;
|
|
284
|
+
}
|
|
275
285
|
parts[toolPartIndex] = {
|
|
276
286
|
type: "dynamic-tool",
|
|
277
287
|
toolName: toolPart.toolName,
|
|
278
288
|
toolCallId: toolPart.toolCallId,
|
|
279
289
|
state: "output-available",
|
|
280
290
|
input: toolPart.input,
|
|
281
|
-
output
|
|
291
|
+
output,
|
|
282
292
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
283
293
|
};
|
|
284
294
|
}
|
|
@@ -312,6 +322,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
312
322
|
...toolPart,
|
|
313
323
|
output: updatedWorkflowState
|
|
314
324
|
};
|
|
325
|
+
} else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
|
|
326
|
+
return toUIMessageFromAgent(chunk.payload.output, conversation);
|
|
315
327
|
} else {
|
|
316
328
|
const currentOutput = toolPart.output || [];
|
|
317
329
|
const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
|
|
@@ -385,15 +397,37 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
385
397
|
}
|
|
386
398
|
];
|
|
387
399
|
}
|
|
400
|
+
case "tool-call-approval": {
|
|
401
|
+
const lastMessage = result[result.length - 1];
|
|
402
|
+
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
403
|
+
const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "stream" ? lastMessage.metadata?.requireApprovalMetadata : {};
|
|
404
|
+
return [
|
|
405
|
+
...result.slice(0, -1),
|
|
406
|
+
{
|
|
407
|
+
...lastMessage,
|
|
408
|
+
metadata: {
|
|
409
|
+
...lastMessage.metadata,
|
|
410
|
+
mode: "stream",
|
|
411
|
+
requireApprovalMetadata: {
|
|
412
|
+
...lastRequireApprovalMetadata,
|
|
413
|
+
[chunk.payload.toolCallId]: {
|
|
414
|
+
toolCallId: chunk.payload.toolCallId,
|
|
415
|
+
toolName: chunk.payload.toolName,
|
|
416
|
+
args: chunk.payload.args
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
];
|
|
422
|
+
}
|
|
388
423
|
case "finish": {
|
|
389
424
|
const lastMessage = result[result.length - 1];
|
|
390
425
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
391
426
|
const parts = lastMessage.parts.map((part) => {
|
|
392
|
-
if (part
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
return { ...part, state: "done" };
|
|
427
|
+
if (typeof part === "object" && part !== null && "type" in part && "state" in part && part.state === "streaming") {
|
|
428
|
+
if (part.type === "text" || part.type === "reasoning") {
|
|
429
|
+
return { ...part, state: "done" };
|
|
430
|
+
}
|
|
397
431
|
}
|
|
398
432
|
return part;
|
|
399
433
|
});
|
|
@@ -427,6 +461,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
427
461
|
return result;
|
|
428
462
|
}
|
|
429
463
|
};
|
|
464
|
+
const toUIMessageFromAgent = (chunk, conversation, metadata) => {
|
|
465
|
+
const lastMessage = conversation[conversation.length - 1];
|
|
466
|
+
if (!lastMessage || lastMessage.role !== "assistant") return conversation;
|
|
467
|
+
const parts = [...lastMessage.parts];
|
|
468
|
+
if (chunk.type === "text-delta") {
|
|
469
|
+
const agentChunk = chunk.payload;
|
|
470
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
471
|
+
if (toolPartIndex === -1) return conversation;
|
|
472
|
+
const toolPart = parts[toolPartIndex];
|
|
473
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
474
|
+
const lastChildMessage = childMessages[childMessages.length - 1];
|
|
475
|
+
const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
|
|
476
|
+
const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
|
|
477
|
+
parts[toolPartIndex] = {
|
|
478
|
+
...toolPart,
|
|
479
|
+
output: {
|
|
480
|
+
childMessages: nextMessages
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
} else if (chunk.type === "tool-call") {
|
|
484
|
+
const agentChunk = chunk.payload;
|
|
485
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
486
|
+
if (toolPartIndex === -1) return conversation;
|
|
487
|
+
const toolPart = parts[toolPartIndex];
|
|
488
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
489
|
+
parts[toolPartIndex] = {
|
|
490
|
+
...toolPart,
|
|
491
|
+
output: {
|
|
492
|
+
...toolPart?.output,
|
|
493
|
+
childMessages: [
|
|
494
|
+
...childMessages,
|
|
495
|
+
{
|
|
496
|
+
type: "tool",
|
|
497
|
+
toolCallId: agentChunk.toolCallId,
|
|
498
|
+
toolName: agentChunk.toolName,
|
|
499
|
+
args: agentChunk.args
|
|
500
|
+
}
|
|
501
|
+
]
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
} else if (chunk.type === "tool-output") {
|
|
505
|
+
const agentChunk = chunk.payload;
|
|
506
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
507
|
+
if (toolPartIndex === -1) return conversation;
|
|
508
|
+
const toolPart = parts[toolPartIndex];
|
|
509
|
+
if (agentChunk?.output?.type?.startsWith("workflow-")) {
|
|
510
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
511
|
+
const lastToolIndex = childMessages.length - 1;
|
|
512
|
+
const currentMessage = childMessages[lastToolIndex];
|
|
513
|
+
const actualExistingWorkflowState = currentMessage?.toolOutput || {};
|
|
514
|
+
const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
|
|
515
|
+
if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
|
|
516
|
+
parts[toolPartIndex] = {
|
|
517
|
+
...toolPart,
|
|
518
|
+
output: {
|
|
519
|
+
...toolPart?.output,
|
|
520
|
+
childMessages: [
|
|
521
|
+
...childMessages.slice(0, -1),
|
|
522
|
+
{
|
|
523
|
+
...currentMessage,
|
|
524
|
+
toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
|
|
525
|
+
}
|
|
526
|
+
]
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
} else if (chunk.type === "tool-result") {
|
|
532
|
+
const agentChunk = chunk.payload;
|
|
533
|
+
const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
|
|
534
|
+
if (toolPartIndex === -1) return conversation;
|
|
535
|
+
const toolPart = parts[toolPartIndex];
|
|
536
|
+
const childMessages = toolPart?.output?.childMessages || [];
|
|
537
|
+
const lastToolIndex = childMessages.length - 1;
|
|
538
|
+
const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
|
|
539
|
+
if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
|
|
540
|
+
parts[toolPartIndex] = {
|
|
541
|
+
...toolPart,
|
|
542
|
+
output: {
|
|
543
|
+
...toolPart?.output,
|
|
544
|
+
childMessages: [
|
|
545
|
+
...childMessages.slice(0, -1),
|
|
546
|
+
{
|
|
547
|
+
...childMessages[lastToolIndex],
|
|
548
|
+
toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
|
|
549
|
+
}
|
|
550
|
+
]
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return [
|
|
556
|
+
...conversation.slice(0, -1),
|
|
557
|
+
{
|
|
558
|
+
...lastMessage,
|
|
559
|
+
parts
|
|
560
|
+
}
|
|
561
|
+
];
|
|
562
|
+
};
|
|
430
563
|
|
|
431
564
|
const toAssistantUIMessage = (message) => {
|
|
432
565
|
const extendedMessage = message;
|
|
@@ -466,13 +599,23 @@ const toAssistantUIMessage = (message) => {
|
|
|
466
599
|
};
|
|
467
600
|
}
|
|
468
601
|
if (part.type === "file") {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
602
|
+
const type = part.mediaType.includes("image/") ? "image" : "file";
|
|
603
|
+
if (type === "file") {
|
|
604
|
+
return {
|
|
605
|
+
type,
|
|
606
|
+
mimeType: part.mediaType,
|
|
607
|
+
data: part.url,
|
|
608
|
+
// Use URL as data source
|
|
609
|
+
metadata: message.metadata
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
if (type === "image") {
|
|
613
|
+
return {
|
|
614
|
+
type,
|
|
615
|
+
image: part.url,
|
|
616
|
+
metadata: message.metadata
|
|
617
|
+
};
|
|
618
|
+
}
|
|
476
619
|
}
|
|
477
620
|
if (part.type === "dynamic-tool") {
|
|
478
621
|
const baseToolCall = {
|
|
@@ -547,9 +690,118 @@ const toAssistantUIMessage = (message) => {
|
|
|
547
690
|
return threadMessage;
|
|
548
691
|
};
|
|
549
692
|
|
|
693
|
+
const resolveInitialMessages = (messages) => {
|
|
694
|
+
return messages.map((message) => {
|
|
695
|
+
const networkPart = message.parts.find(
|
|
696
|
+
(part) => typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" && part.text.includes('"isNetwork":true')
|
|
697
|
+
);
|
|
698
|
+
if (networkPart && networkPart.type === "text") {
|
|
699
|
+
try {
|
|
700
|
+
const json = JSON.parse(networkPart.text);
|
|
701
|
+
if (json.isNetwork === true) {
|
|
702
|
+
const selectionReason = json.selectionReason || "";
|
|
703
|
+
const primitiveType = json.primitiveType || "";
|
|
704
|
+
const primitiveId = json.primitiveId || "";
|
|
705
|
+
const finalResult = json.finalResult;
|
|
706
|
+
const toolCalls = finalResult?.toolCalls || [];
|
|
707
|
+
const childMessages = [];
|
|
708
|
+
for (const toolCall of toolCalls) {
|
|
709
|
+
if (toolCall.type === "tool-call" && toolCall.payload) {
|
|
710
|
+
const toolCallId = toolCall.payload.toolCallId;
|
|
711
|
+
let toolResult;
|
|
712
|
+
for (const message2 of finalResult?.messages || []) {
|
|
713
|
+
for (const part of message2.content || []) {
|
|
714
|
+
if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
|
|
715
|
+
toolResult = part;
|
|
716
|
+
break;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
const isWorkflow = Boolean(toolResult?.result?.result?.steps);
|
|
721
|
+
childMessages.push({
|
|
722
|
+
type: "tool",
|
|
723
|
+
toolCallId: toolCall.payload.toolCallId,
|
|
724
|
+
toolName: toolCall.payload.toolName,
|
|
725
|
+
args: toolCall.payload.args,
|
|
726
|
+
toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (finalResult && finalResult.text) {
|
|
731
|
+
childMessages.push({
|
|
732
|
+
type: "text",
|
|
733
|
+
content: finalResult.text
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
const result = {
|
|
737
|
+
childMessages,
|
|
738
|
+
result: finalResult?.text || ""
|
|
739
|
+
};
|
|
740
|
+
console.log("json", json);
|
|
741
|
+
const nextMessage = {
|
|
742
|
+
role: "assistant",
|
|
743
|
+
parts: [
|
|
744
|
+
{
|
|
745
|
+
type: "dynamic-tool",
|
|
746
|
+
toolCallId: primitiveId,
|
|
747
|
+
toolName: primitiveId,
|
|
748
|
+
state: "output-available",
|
|
749
|
+
input: json.input,
|
|
750
|
+
output: result
|
|
751
|
+
}
|
|
752
|
+
],
|
|
753
|
+
id: message.id,
|
|
754
|
+
metadata: {
|
|
755
|
+
...message.metadata,
|
|
756
|
+
mode: "network",
|
|
757
|
+
selectionReason,
|
|
758
|
+
agentInput: json.input,
|
|
759
|
+
from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
return nextMessage;
|
|
763
|
+
}
|
|
764
|
+
} catch (error) {
|
|
765
|
+
return message;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return message;
|
|
769
|
+
});
|
|
770
|
+
};
|
|
771
|
+
const resolveToChildMessages = (messages) => {
|
|
772
|
+
const assistantMessage = messages.find((message) => message.role === "assistant");
|
|
773
|
+
if (!assistantMessage) return [];
|
|
774
|
+
const parts = assistantMessage.parts;
|
|
775
|
+
let childMessages = [];
|
|
776
|
+
for (const part of parts) {
|
|
777
|
+
const toolPart = part;
|
|
778
|
+
if (part.type.startsWith("tool-")) {
|
|
779
|
+
const toolName = part.type.substring("tool-".length);
|
|
780
|
+
const isWorkflow = toolName.startsWith("workflow-");
|
|
781
|
+
childMessages.push({
|
|
782
|
+
type: "tool",
|
|
783
|
+
toolCallId: toolPart.toolCallId,
|
|
784
|
+
toolName,
|
|
785
|
+
args: toolPart.input,
|
|
786
|
+
toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
if (part.type === "text") {
|
|
790
|
+
childMessages.push({
|
|
791
|
+
type: "text",
|
|
792
|
+
content: toolPart.text
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return childMessages;
|
|
797
|
+
};
|
|
798
|
+
|
|
550
799
|
class AISdkNetworkTransformer {
|
|
551
800
|
transform({ chunk, conversation, metadata }) {
|
|
552
801
|
const newConversation = [...conversation];
|
|
802
|
+
if (chunk.type === "routing-agent-text-delta") {
|
|
803
|
+
return this.handleRoutingAgentConversation(chunk, newConversation);
|
|
804
|
+
}
|
|
553
805
|
if (chunk.type.startsWith("agent-execution-")) {
|
|
554
806
|
return this.handleAgentConversation(chunk, newConversation, metadata);
|
|
555
807
|
}
|
|
@@ -560,22 +812,80 @@ class AISdkNetworkTransformer {
|
|
|
560
812
|
return this.handleToolConversation(chunk, newConversation, metadata);
|
|
561
813
|
}
|
|
562
814
|
if (chunk.type === "network-execution-event-step-finish") {
|
|
563
|
-
const
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
815
|
+
const lastMessage = newConversation[newConversation.length - 1];
|
|
816
|
+
if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
|
|
817
|
+
const agentChunk = chunk.payload;
|
|
818
|
+
const parts = [...lastMessage.parts];
|
|
819
|
+
const textPartIndex = parts.findIndex((part) => part.type === "text");
|
|
820
|
+
if (textPartIndex === -1) {
|
|
821
|
+
parts.push({
|
|
822
|
+
type: "text",
|
|
823
|
+
text: agentChunk.result,
|
|
824
|
+
state: "done"
|
|
825
|
+
});
|
|
826
|
+
return [
|
|
827
|
+
...newConversation.slice(0, -1),
|
|
567
828
|
{
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
state: "done"
|
|
829
|
+
...lastMessage,
|
|
830
|
+
parts
|
|
571
831
|
}
|
|
572
|
-
]
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
832
|
+
];
|
|
833
|
+
}
|
|
834
|
+
const textPart = parts[textPartIndex];
|
|
835
|
+
if (textPart.type === "text") {
|
|
836
|
+
parts[textPartIndex] = {
|
|
837
|
+
...textPart,
|
|
838
|
+
state: "done"
|
|
839
|
+
};
|
|
840
|
+
return [
|
|
841
|
+
...newConversation.slice(0, -1),
|
|
842
|
+
{
|
|
843
|
+
...lastMessage,
|
|
844
|
+
parts
|
|
845
|
+
}
|
|
846
|
+
];
|
|
847
|
+
}
|
|
848
|
+
return newConversation;
|
|
576
849
|
}
|
|
577
850
|
return newConversation;
|
|
578
851
|
}
|
|
852
|
+
handleRoutingAgentConversation = (chunk, newConversation) => {
|
|
853
|
+
const lastMessage = newConversation[newConversation.length - 1];
|
|
854
|
+
if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
|
|
855
|
+
const agentChunk = chunk.payload;
|
|
856
|
+
const parts = [...lastMessage.parts];
|
|
857
|
+
const textPartIndex = parts.findIndex((part) => part.type === "text");
|
|
858
|
+
if (textPartIndex === -1) {
|
|
859
|
+
parts.push({
|
|
860
|
+
type: "text",
|
|
861
|
+
text: agentChunk.text,
|
|
862
|
+
state: "streaming"
|
|
863
|
+
});
|
|
864
|
+
return [
|
|
865
|
+
...newConversation.slice(0, -1),
|
|
866
|
+
{
|
|
867
|
+
...lastMessage,
|
|
868
|
+
parts
|
|
869
|
+
}
|
|
870
|
+
];
|
|
871
|
+
}
|
|
872
|
+
const textPart = parts[textPartIndex];
|
|
873
|
+
if (textPart.type === "text") {
|
|
874
|
+
parts[textPartIndex] = {
|
|
875
|
+
...textPart,
|
|
876
|
+
text: textPart.text + agentChunk.text,
|
|
877
|
+
state: "streaming"
|
|
878
|
+
};
|
|
879
|
+
return [
|
|
880
|
+
...newConversation.slice(0, -1),
|
|
881
|
+
{
|
|
882
|
+
...lastMessage,
|
|
883
|
+
parts
|
|
884
|
+
}
|
|
885
|
+
];
|
|
886
|
+
}
|
|
887
|
+
return newConversation;
|
|
888
|
+
};
|
|
579
889
|
handleAgentConversation = (chunk, newConversation, metadata) => {
|
|
580
890
|
if (chunk.type === "agent-execution-start") {
|
|
581
891
|
const primitiveId = chunk.payload?.args?.primitiveId;
|
|
@@ -858,92 +1168,63 @@ class AISdkNetworkTransformer {
|
|
|
858
1168
|
};
|
|
859
1169
|
}
|
|
860
1170
|
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
if (finalResult && finalResult.text) {
|
|
897
|
-
childMessages.push({
|
|
898
|
-
type: "text",
|
|
899
|
-
content: finalResult.text
|
|
900
|
-
});
|
|
901
|
-
}
|
|
902
|
-
const result = {
|
|
903
|
-
childMessages,
|
|
904
|
-
result: finalResult?.text || ""
|
|
905
|
-
};
|
|
906
|
-
console.log("json", json);
|
|
907
|
-
const nextMessage = {
|
|
908
|
-
role: "assistant",
|
|
909
|
-
parts: [
|
|
910
|
-
{
|
|
911
|
-
type: "dynamic-tool",
|
|
912
|
-
toolCallId: primitiveId,
|
|
913
|
-
toolName: primitiveId,
|
|
914
|
-
state: "output-available",
|
|
915
|
-
input: json.input,
|
|
916
|
-
output: result
|
|
917
|
-
}
|
|
918
|
-
],
|
|
919
|
-
id: message.id,
|
|
920
|
-
metadata: {
|
|
921
|
-
...message.metadata,
|
|
922
|
-
mode: "network",
|
|
923
|
-
selectionReason,
|
|
924
|
-
agentInput: json.input,
|
|
925
|
-
from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
|
|
926
|
-
}
|
|
927
|
-
};
|
|
928
|
-
return nextMessage;
|
|
929
|
-
}
|
|
930
|
-
} catch (error) {
|
|
931
|
-
return message;
|
|
1171
|
+
const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
|
|
1172
|
+
const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1173
|
+
const parts = typeof coreUserMessage.content === "string" ? [
|
|
1174
|
+
{
|
|
1175
|
+
type: "text",
|
|
1176
|
+
text: coreUserMessage.content
|
|
1177
|
+
}
|
|
1178
|
+
] : coreUserMessage.content.map((part) => {
|
|
1179
|
+
switch (part.type) {
|
|
1180
|
+
case "text": {
|
|
1181
|
+
return {
|
|
1182
|
+
type: "text",
|
|
1183
|
+
text: part.text
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
case "image": {
|
|
1187
|
+
const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
|
|
1188
|
+
return {
|
|
1189
|
+
type: "file",
|
|
1190
|
+
mediaType: part.mimeType ?? "image/*",
|
|
1191
|
+
url
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
case "file": {
|
|
1195
|
+
const url = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
|
|
1196
|
+
return {
|
|
1197
|
+
type: "file",
|
|
1198
|
+
mediaType: part.mimeType,
|
|
1199
|
+
url,
|
|
1200
|
+
...part.filename !== void 0 ? { filename: part.filename } : {}
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
default: {
|
|
1204
|
+
const exhaustiveCheck = part;
|
|
1205
|
+
throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
|
|
932
1206
|
}
|
|
933
1207
|
}
|
|
934
|
-
return message;
|
|
935
1208
|
});
|
|
1209
|
+
return {
|
|
1210
|
+
id,
|
|
1211
|
+
role: "user",
|
|
1212
|
+
parts
|
|
1213
|
+
};
|
|
936
1214
|
};
|
|
937
1215
|
|
|
938
1216
|
const useChat = ({ agentId, initializeMessages }) => {
|
|
1217
|
+
const _currentRunId = useRef(void 0);
|
|
1218
|
+
const _onChunk = useRef(void 0);
|
|
939
1219
|
const [messages, setMessages] = useState(
|
|
940
1220
|
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
941
1221
|
);
|
|
1222
|
+
const [toolCallApprovals, setToolCallApprovals] = useState({});
|
|
942
1223
|
const baseClient = useMastraClient();
|
|
943
1224
|
const [isRunning, setIsRunning] = useState(false);
|
|
944
1225
|
const generate = async ({
|
|
945
1226
|
coreUserMessages,
|
|
946
|
-
|
|
1227
|
+
requestContext,
|
|
947
1228
|
threadId,
|
|
948
1229
|
modelSettings,
|
|
949
1230
|
signal,
|
|
@@ -981,7 +1262,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
981
1262
|
topP
|
|
982
1263
|
},
|
|
983
1264
|
instructions,
|
|
984
|
-
|
|
1265
|
+
requestContext,
|
|
985
1266
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
986
1267
|
providerOptions
|
|
987
1268
|
});
|
|
@@ -997,7 +1278,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
997
1278
|
setMessages((prev) => [...prev, ...mastraUIMessages]);
|
|
998
1279
|
}
|
|
999
1280
|
};
|
|
1000
|
-
const stream = async ({ coreUserMessages,
|
|
1281
|
+
const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
|
|
1001
1282
|
const {
|
|
1002
1283
|
frequencyPenalty,
|
|
1003
1284
|
presencePenalty,
|
|
@@ -1008,7 +1289,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1008
1289
|
topP,
|
|
1009
1290
|
instructions,
|
|
1010
1291
|
providerOptions,
|
|
1011
|
-
maxSteps
|
|
1292
|
+
maxSteps,
|
|
1293
|
+
requireToolApproval
|
|
1012
1294
|
} = modelSettings || {};
|
|
1013
1295
|
setIsRunning(true);
|
|
1014
1296
|
const clientWithAbort = new MastraClient({
|
|
@@ -1016,9 +1298,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1016
1298
|
abortSignal: signal
|
|
1017
1299
|
});
|
|
1018
1300
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1301
|
+
const runId = agentId;
|
|
1019
1302
|
const response = await agent.stream({
|
|
1020
1303
|
messages: coreUserMessages,
|
|
1021
|
-
runId
|
|
1304
|
+
runId,
|
|
1022
1305
|
maxSteps,
|
|
1023
1306
|
modelSettings: {
|
|
1024
1307
|
frequencyPenalty,
|
|
@@ -1030,19 +1313,16 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1030
1313
|
topP
|
|
1031
1314
|
},
|
|
1032
1315
|
instructions,
|
|
1033
|
-
|
|
1316
|
+
requestContext,
|
|
1034
1317
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1035
|
-
providerOptions
|
|
1318
|
+
providerOptions,
|
|
1319
|
+
requireToolApproval
|
|
1036
1320
|
});
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
throw new Error("[Stream] No response body");
|
|
1040
|
-
}
|
|
1321
|
+
_onChunk.current = onChunk;
|
|
1322
|
+
_currentRunId.current = runId;
|
|
1041
1323
|
await response.processDataStream({
|
|
1042
1324
|
onChunk: async (chunk) => {
|
|
1043
|
-
|
|
1044
|
-
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1045
|
-
});
|
|
1325
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1046
1326
|
onChunk?.(chunk);
|
|
1047
1327
|
}
|
|
1048
1328
|
});
|
|
@@ -1050,7 +1330,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1050
1330
|
};
|
|
1051
1331
|
const network = async ({
|
|
1052
1332
|
coreUserMessages,
|
|
1053
|
-
|
|
1333
|
+
requestContext,
|
|
1054
1334
|
threadId,
|
|
1055
1335
|
onNetworkChunk,
|
|
1056
1336
|
modelSettings,
|
|
@@ -1076,30 +1356,71 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1076
1356
|
topP
|
|
1077
1357
|
},
|
|
1078
1358
|
runId: agentId,
|
|
1079
|
-
|
|
1359
|
+
requestContext,
|
|
1080
1360
|
...threadId ? { thread: threadId, resourceId: agentId } : {}
|
|
1081
1361
|
});
|
|
1082
1362
|
const transformer = new AISdkNetworkTransformer();
|
|
1083
1363
|
await response.processDataStream({
|
|
1084
1364
|
onChunk: async (chunk) => {
|
|
1085
|
-
|
|
1086
|
-
setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
|
|
1087
|
-
});
|
|
1365
|
+
setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
|
|
1088
1366
|
onNetworkChunk?.(chunk);
|
|
1089
1367
|
}
|
|
1090
1368
|
});
|
|
1091
1369
|
setIsRunning(false);
|
|
1092
1370
|
};
|
|
1371
|
+
const handleCancelRun = () => {
|
|
1372
|
+
setIsRunning(false);
|
|
1373
|
+
_currentRunId.current = void 0;
|
|
1374
|
+
_onChunk.current = void 0;
|
|
1375
|
+
};
|
|
1376
|
+
const approveToolCall = async (toolCallId) => {
|
|
1377
|
+
const onChunk = _onChunk.current;
|
|
1378
|
+
const currentRunId = _currentRunId.current;
|
|
1379
|
+
if (!currentRunId)
|
|
1380
|
+
return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
|
|
1381
|
+
setIsRunning(true);
|
|
1382
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
|
|
1383
|
+
const agent = baseClient.getAgent(agentId);
|
|
1384
|
+
const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
|
|
1385
|
+
await response.processDataStream({
|
|
1386
|
+
onChunk: async (chunk) => {
|
|
1387
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1388
|
+
onChunk?.(chunk);
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
setIsRunning(false);
|
|
1392
|
+
};
|
|
1393
|
+
const declineToolCall = async (toolCallId) => {
|
|
1394
|
+
const onChunk = _onChunk.current;
|
|
1395
|
+
const currentRunId = _currentRunId.current;
|
|
1396
|
+
if (!currentRunId)
|
|
1397
|
+
return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
|
|
1398
|
+
setIsRunning(true);
|
|
1399
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
|
|
1400
|
+
const agent = baseClient.getAgent(agentId);
|
|
1401
|
+
const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
|
|
1402
|
+
await response.processDataStream({
|
|
1403
|
+
onChunk: async (chunk) => {
|
|
1404
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1405
|
+
onChunk?.(chunk);
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
setIsRunning(false);
|
|
1409
|
+
};
|
|
1093
1410
|
const sendMessage = async ({ mode = "stream", ...args }) => {
|
|
1094
1411
|
const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
|
|
1095
|
-
const
|
|
1096
|
-
|
|
1412
|
+
const coreUserMessages = [nextMessage];
|
|
1413
|
+
if (args.coreUserMessages) {
|
|
1414
|
+
coreUserMessages.push(...args.coreUserMessages);
|
|
1415
|
+
}
|
|
1416
|
+
const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
|
|
1417
|
+
setMessages((s) => [...s, ...uiMessages]);
|
|
1097
1418
|
if (mode === "generate") {
|
|
1098
|
-
await generate({ ...args, coreUserMessages
|
|
1419
|
+
await generate({ ...args, coreUserMessages });
|
|
1099
1420
|
} else if (mode === "stream") {
|
|
1100
|
-
await stream({ ...args, coreUserMessages
|
|
1421
|
+
await stream({ ...args, coreUserMessages });
|
|
1101
1422
|
} else if (mode === "network") {
|
|
1102
|
-
await network({ ...args, coreUserMessages
|
|
1423
|
+
await network({ ...args, coreUserMessages });
|
|
1103
1424
|
}
|
|
1104
1425
|
};
|
|
1105
1426
|
return {
|
|
@@ -1107,7 +1428,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1107
1428
|
sendMessage,
|
|
1108
1429
|
isRunning,
|
|
1109
1430
|
messages,
|
|
1110
|
-
|
|
1431
|
+
approveToolCall,
|
|
1432
|
+
declineToolCall,
|
|
1433
|
+
cancelRun: handleCancelRun,
|
|
1434
|
+
toolCallApprovals
|
|
1111
1435
|
};
|
|
1112
1436
|
};
|
|
1113
1437
|
|
|
@@ -1426,5 +1750,5 @@ const MessageStreaming = ({ className, ...props }) => {
|
|
|
1426
1750
|
return /* @__PURE__ */ jsx("span", { className: className || MessageStreamingClass, ...props });
|
|
1427
1751
|
};
|
|
1428
1752
|
|
|
1429
|
-
export { AgentIcon, CodeBlock, CodeBlockClass, CodeCopyButton, Entity, EntityCaret, EntityContent, EntityContentClass, EntityTrigger, EntityTriggerClass, EntityTriggerVariantClasses, Entry, EntryClass, EntryTitle, EntryTitleClass, Icon, IconButton, IconButtonClass, IconSizes, MastraReactProvider, Message, MessageActions, MessageActionsClass, MessageClass, MessageContent, MessageContentClass, MessageList, MessageListClass, MessageStreaming, MessageStreamingClass, MessageUsage, MessageUsageClass, MessageUsageEntry, MessageUsageEntryClass, MessageUsageValue, MessageUsageValueClass, MessageUsages, MessageUsagesClass, ToolApproval, ToolApprovalActions, ToolApprovalActionsClass, ToolApprovalClass, ToolApprovalContent, ToolApprovalContentClass, ToolApprovalHeader, ToolApprovalHeaderClass, ToolApprovalTitle, ToolApprovalTitleClass, ToolsIcon, Tooltip, TooltipContent, TooltipContentClass, TooltipTrigger, WorkflowIcon, mapWorkflowStreamChunkToWatchResult, toAssistantUIMessage, toUIMessage, useChat, useEntity, useMastraClient };
|
|
1753
|
+
export { AgentIcon, CodeBlock, CodeBlockClass, CodeCopyButton, Entity, EntityCaret, EntityContent, EntityContentClass, EntityTrigger, EntityTriggerClass, EntityTriggerVariantClasses, Entry, EntryClass, EntryTitle, EntryTitleClass, Icon, IconButton, IconButtonClass, IconSizes, MastraReactProvider, Message, MessageActions, MessageActionsClass, MessageClass, MessageContent, MessageContentClass, MessageList, MessageListClass, MessageStreaming, MessageStreamingClass, MessageUsage, MessageUsageClass, MessageUsageEntry, MessageUsageEntryClass, MessageUsageValue, MessageUsageValueClass, MessageUsages, MessageUsagesClass, ToolApproval, ToolApprovalActions, ToolApprovalActionsClass, ToolApprovalClass, ToolApprovalContent, ToolApprovalContentClass, ToolApprovalHeader, ToolApprovalHeaderClass, ToolApprovalTitle, ToolApprovalTitleClass, ToolsIcon, Tooltip, TooltipContent, TooltipContentClass, TooltipTrigger, WorkflowIcon, mapWorkflowStreamChunkToWatchResult, resolveToChildMessages, toAssistantUIMessage, toUIMessage, useChat, useEntity, useMastraClient };
|
|
1430
1754
|
//# sourceMappingURL=index.js.map
|