@mastra/react 0.0.8-alpha.0 → 0.0.8

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/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { createContext, useContext, useState, Fragment, useLayoutEffect, useRef, 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';
@@ -272,13 +271,22 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
272
271
  };
273
272
  } else {
274
273
  const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
274
+ const isAgent = chunk?.from === "AGENT";
275
+ let output;
276
+ if (isWorkflow) {
277
+ output = chunk.payload.result?.result;
278
+ } else if (isAgent) {
279
+ output = parts[toolPartIndex].output ?? chunk.payload.result;
280
+ } else {
281
+ output = chunk.payload.result;
282
+ }
275
283
  parts[toolPartIndex] = {
276
284
  type: "dynamic-tool",
277
285
  toolName: toolPart.toolName,
278
286
  toolCallId: toolPart.toolCallId,
279
287
  state: "output-available",
280
288
  input: toolPart.input,
281
- output: isWorkflow ? chunk.payload.result?.result : chunk.payload.result,
289
+ output,
282
290
  callProviderMetadata: chunk.payload.providerMetadata
283
291
  };
284
292
  }
@@ -312,6 +320,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
312
320
  ...toolPart,
313
321
  output: updatedWorkflowState
314
322
  };
323
+ } else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
324
+ return toUIMessageFromAgent(chunk.payload.output, conversation);
315
325
  } else {
316
326
  const currentOutput = toolPart.output || [];
317
327
  const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
@@ -427,6 +437,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
427
437
  return result;
428
438
  }
429
439
  };
440
+ const toUIMessageFromAgent = (chunk, conversation, metadata) => {
441
+ const lastMessage = conversation[conversation.length - 1];
442
+ if (!lastMessage || lastMessage.role !== "assistant") return conversation;
443
+ const parts = [...lastMessage.parts];
444
+ if (chunk.type === "text-delta") {
445
+ const agentChunk = chunk.payload;
446
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
447
+ if (toolPartIndex === -1) return conversation;
448
+ const toolPart = parts[toolPartIndex];
449
+ const childMessages = toolPart?.output?.childMessages || [];
450
+ const lastChildMessage = childMessages[childMessages.length - 1];
451
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
452
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
453
+ parts[toolPartIndex] = {
454
+ ...toolPart,
455
+ output: {
456
+ childMessages: nextMessages
457
+ }
458
+ };
459
+ } else if (chunk.type === "tool-call") {
460
+ const agentChunk = chunk.payload;
461
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
462
+ if (toolPartIndex === -1) return conversation;
463
+ const toolPart = parts[toolPartIndex];
464
+ const childMessages = toolPart?.output?.childMessages || [];
465
+ parts[toolPartIndex] = {
466
+ ...toolPart,
467
+ output: {
468
+ ...toolPart?.output,
469
+ childMessages: [
470
+ ...childMessages,
471
+ {
472
+ type: "tool",
473
+ toolCallId: agentChunk.toolCallId,
474
+ toolName: agentChunk.toolName,
475
+ args: agentChunk.args
476
+ }
477
+ ]
478
+ }
479
+ };
480
+ } else if (chunk.type === "tool-output") {
481
+ const agentChunk = chunk.payload;
482
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
483
+ if (toolPartIndex === -1) return conversation;
484
+ const toolPart = parts[toolPartIndex];
485
+ if (agentChunk?.output?.type?.startsWith("workflow-")) {
486
+ const childMessages = toolPart?.output?.childMessages || [];
487
+ const lastToolIndex = childMessages.length - 1;
488
+ const currentMessage = childMessages[lastToolIndex];
489
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
490
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
491
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
492
+ parts[toolPartIndex] = {
493
+ ...toolPart,
494
+ output: {
495
+ ...toolPart?.output,
496
+ childMessages: [
497
+ ...childMessages.slice(0, -1),
498
+ {
499
+ ...currentMessage,
500
+ toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
501
+ }
502
+ ]
503
+ }
504
+ };
505
+ }
506
+ }
507
+ } else if (chunk.type === "tool-result") {
508
+ const agentChunk = chunk.payload;
509
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
510
+ if (toolPartIndex === -1) return conversation;
511
+ const toolPart = parts[toolPartIndex];
512
+ const childMessages = toolPart?.output?.childMessages || [];
513
+ const lastToolIndex = childMessages.length - 1;
514
+ const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
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
+ ...childMessages[lastToolIndex],
524
+ toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
525
+ }
526
+ ]
527
+ }
528
+ };
529
+ }
530
+ }
531
+ return [
532
+ ...conversation.slice(0, -1),
533
+ {
534
+ ...lastMessage,
535
+ parts
536
+ }
537
+ ];
538
+ };
430
539
 
431
540
  const toAssistantUIMessage = (message) => {
432
541
  const extendedMessage = message;
@@ -547,6 +656,110 @@ const toAssistantUIMessage = (message) => {
547
656
  return threadMessage;
548
657
  };
549
658
 
659
+ const resolveInitialMessages = (messages) => {
660
+ return messages.map((message) => {
661
+ const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
662
+ if (networkPart && networkPart.type === "text") {
663
+ try {
664
+ const json = JSON.parse(networkPart.text);
665
+ if (json.isNetwork === true) {
666
+ const selectionReason = json.selectionReason || "";
667
+ const primitiveType = json.primitiveType || "";
668
+ const primitiveId = json.primitiveId || "";
669
+ const finalResult = json.finalResult;
670
+ const toolCalls = finalResult?.toolCalls || [];
671
+ const childMessages = [];
672
+ for (const toolCall of toolCalls) {
673
+ if (toolCall.type === "tool-call" && toolCall.payload) {
674
+ const toolCallId = toolCall.payload.toolCallId;
675
+ let toolResult;
676
+ for (const message2 of finalResult?.messages || []) {
677
+ for (const part of message2.content || []) {
678
+ if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
679
+ toolResult = part;
680
+ break;
681
+ }
682
+ }
683
+ }
684
+ const isWorkflow = Boolean(toolResult?.result?.result?.steps);
685
+ childMessages.push({
686
+ type: "tool",
687
+ toolCallId: toolCall.payload.toolCallId,
688
+ toolName: toolCall.payload.toolName,
689
+ args: toolCall.payload.args,
690
+ toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
691
+ });
692
+ }
693
+ }
694
+ if (finalResult && finalResult.text) {
695
+ childMessages.push({
696
+ type: "text",
697
+ content: finalResult.text
698
+ });
699
+ }
700
+ const result = {
701
+ childMessages,
702
+ result: finalResult?.text || ""
703
+ };
704
+ console.log("json", json);
705
+ const nextMessage = {
706
+ role: "assistant",
707
+ parts: [
708
+ {
709
+ type: "dynamic-tool",
710
+ toolCallId: primitiveId,
711
+ toolName: primitiveId,
712
+ state: "output-available",
713
+ input: json.input,
714
+ output: result
715
+ }
716
+ ],
717
+ id: message.id,
718
+ metadata: {
719
+ ...message.metadata,
720
+ mode: "network",
721
+ selectionReason,
722
+ agentInput: json.input,
723
+ from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
724
+ }
725
+ };
726
+ return nextMessage;
727
+ }
728
+ } catch (error) {
729
+ return message;
730
+ }
731
+ }
732
+ return message;
733
+ });
734
+ };
735
+ const resolveToChildMessages = (messages) => {
736
+ const assistantMessage = messages.find((message) => message.role === "assistant");
737
+ if (!assistantMessage) return [];
738
+ const parts = assistantMessage.parts;
739
+ let childMessages = [];
740
+ for (const part of parts) {
741
+ const toolPart = part;
742
+ if (part.type.startsWith("tool-")) {
743
+ const toolName = part.type.substring("tool-".length);
744
+ const isWorkflow = toolName.startsWith("workflow-");
745
+ childMessages.push({
746
+ type: "tool",
747
+ toolCallId: toolPart.toolCallId,
748
+ toolName,
749
+ args: toolPart.input,
750
+ toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
751
+ });
752
+ }
753
+ if (part.type === "text") {
754
+ childMessages.push({
755
+ type: "text",
756
+ content: toolPart.text
757
+ });
758
+ }
759
+ }
760
+ return childMessages;
761
+ };
762
+
550
763
  class AISdkNetworkTransformer {
551
764
  transform({ chunk, conversation, metadata }) {
552
765
  const newConversation = [...conversation];
@@ -919,83 +1132,6 @@ class AISdkNetworkTransformer {
919
1132
  };
920
1133
  }
921
1134
 
922
- const resolveInitialMessages = (messages) => {
923
- return messages.map((message) => {
924
- const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
925
- if (networkPart && networkPart.type === "text") {
926
- try {
927
- const json = JSON.parse(networkPart.text);
928
- if (json.isNetwork === true) {
929
- const selectionReason = json.selectionReason || "";
930
- const primitiveType = json.primitiveType || "";
931
- const primitiveId = json.primitiveId || "";
932
- const finalResult = json.finalResult;
933
- const toolCalls = finalResult?.toolCalls || [];
934
- const childMessages = [];
935
- for (const toolCall of toolCalls) {
936
- if (toolCall.type === "tool-call" && toolCall.payload) {
937
- const toolCallId = toolCall.payload.toolCallId;
938
- let toolResult;
939
- for (const message2 of finalResult?.messages || []) {
940
- for (const part of message2.content || []) {
941
- if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
942
- toolResult = part;
943
- break;
944
- }
945
- }
946
- }
947
- const isWorkflow = Boolean(toolResult?.result?.result?.steps);
948
- childMessages.push({
949
- type: "tool",
950
- toolCallId: toolCall.payload.toolCallId,
951
- toolName: toolCall.payload.toolName,
952
- args: toolCall.payload.args,
953
- toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
954
- });
955
- }
956
- }
957
- if (finalResult && finalResult.text) {
958
- childMessages.push({
959
- type: "text",
960
- content: finalResult.text
961
- });
962
- }
963
- const result = {
964
- childMessages,
965
- result: finalResult?.text || ""
966
- };
967
- console.log("json", json);
968
- const nextMessage = {
969
- role: "assistant",
970
- parts: [
971
- {
972
- type: "dynamic-tool",
973
- toolCallId: primitiveId,
974
- toolName: primitiveId,
975
- state: "output-available",
976
- input: json.input,
977
- output: result
978
- }
979
- ],
980
- id: message.id,
981
- metadata: {
982
- ...message.metadata,
983
- mode: "network",
984
- selectionReason,
985
- agentInput: json.input,
986
- from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
987
- }
988
- };
989
- return nextMessage;
990
- }
991
- } catch (error) {
992
- return message;
993
- }
994
- }
995
- return message;
996
- });
997
- };
998
-
999
1135
  const useChat = ({ agentId, initializeMessages }) => {
1000
1136
  const [messages, setMessages] = useState(
1001
1137
  () => resolveInitialMessages(initializeMessages?.() || [])
@@ -1101,9 +1237,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1101
1237
  }
1102
1238
  await response.processDataStream({
1103
1239
  onChunk: async (chunk) => {
1104
- flushSync(() => {
1105
- setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1106
- });
1240
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1107
1241
  onChunk?.(chunk);
1108
1242
  }
1109
1243
  });
@@ -1143,9 +1277,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1143
1277
  const transformer = new AISdkNetworkTransformer();
1144
1278
  await response.processDataStream({
1145
1279
  onChunk: async (chunk) => {
1146
- flushSync(() => {
1147
- setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
1148
- });
1280
+ setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
1149
1281
  onNetworkChunk?.(chunk);
1150
1282
  }
1151
1283
  });
@@ -1487,5 +1619,5 @@ const MessageStreaming = ({ className, ...props }) => {
1487
1619
  return /* @__PURE__ */ jsx("span", { className: className || MessageStreamingClass, ...props });
1488
1620
  };
1489
1621
 
1490
- 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 };
1622
+ 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 };
1491
1623
  //# sourceMappingURL=index.js.map