@mastra/react 1.0.0-beta.25 → 1.0.3-alpha.0

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.
Files changed (156) hide show
  1. package/CHANGELOG.md +2773 -3
  2. package/LICENSE.md +15 -0
  3. package/dist/agent/extractRunIdFromMessages.d.ts +10 -0
  4. package/dist/agent/extractRunIdFromMessages.d.ts.map +1 -0
  5. package/dist/agent/hooks.d.ts +91 -0
  6. package/dist/agent/hooks.d.ts.map +1 -0
  7. package/dist/agent/signal-data.d.ts +2 -0
  8. package/dist/agent/signal-data.d.ts.map +1 -0
  9. package/dist/{src/agent → agent}/types.d.ts +6 -1
  10. package/dist/agent/types.d.ts.map +1 -0
  11. package/dist/index.cjs +3743 -63
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.ts +11 -2
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +3676 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/lib/mastra-db/accumulator.d.ts +48 -0
  18. package/dist/lib/mastra-db/accumulator.d.ts.map +1 -0
  19. package/dist/lib/mastra-db/formatCompletionFeedback.d.ts +19 -0
  20. package/dist/lib/mastra-db/formatCompletionFeedback.d.ts.map +1 -0
  21. package/dist/lib/mastra-db/fromCoreUserMessage.d.ts +14 -0
  22. package/dist/lib/mastra-db/fromCoreUserMessage.d.ts.map +1 -0
  23. package/dist/lib/mastra-db/index.d.ts +6 -0
  24. package/dist/lib/mastra-db/index.d.ts.map +1 -0
  25. package/dist/lib/mastra-db/types.d.ts +171 -0
  26. package/dist/lib/mastra-db/types.d.ts.map +1 -0
  27. package/dist/lib/use-mutation.d.ts +28 -0
  28. package/dist/lib/use-mutation.d.ts.map +1 -0
  29. package/dist/mastra-client-context.d.ts +26 -0
  30. package/dist/mastra-client-context.d.ts.map +1 -0
  31. package/dist/mastra-react-provider.d.ts +5 -0
  32. package/dist/mastra-react-provider.d.ts.map +1 -0
  33. package/dist/react.css +184 -322
  34. package/dist/{src/ui → ui}/Code/Code.d.ts +2 -1
  35. package/dist/ui/Code/Code.d.ts.map +1 -0
  36. package/dist/ui/Code/highlight.d.ts +4 -0
  37. package/dist/ui/Code/highlight.d.ts.map +1 -0
  38. package/dist/ui/Code/index.d.ts +2 -0
  39. package/dist/ui/Code/index.d.ts.map +1 -0
  40. package/dist/{src/ui → ui}/Entity/Entity.d.ts +2 -1
  41. package/dist/ui/Entity/Entity.d.ts.map +1 -0
  42. package/dist/{src/ui → ui}/Entity/Entry.d.ts +2 -1
  43. package/dist/ui/Entity/Entry.d.ts.map +1 -0
  44. package/dist/{src/ui → ui}/Entity/ToolApproval.d.ts +1 -0
  45. package/dist/ui/Entity/ToolApproval.d.ts.map +1 -0
  46. package/dist/{src/ui → ui}/Entity/context.d.ts +4 -3
  47. package/dist/ui/Entity/context.d.ts.map +1 -0
  48. package/dist/ui/Entity/index.d.ts +5 -0
  49. package/dist/ui/Entity/index.d.ts.map +1 -0
  50. package/dist/{src/ui → ui}/Entity/types.d.ts +1 -0
  51. package/dist/ui/Entity/types.d.ts.map +1 -0
  52. package/dist/{src/ui → ui}/Icon/Icon.d.ts +2 -1
  53. package/dist/ui/Icon/Icon.d.ts.map +1 -0
  54. package/dist/ui/Icon/index.d.ts +2 -0
  55. package/dist/ui/Icon/index.d.ts.map +1 -0
  56. package/dist/{src/ui → ui}/IconButton/IconButton.d.ts +2 -1
  57. package/dist/ui/IconButton/IconButton.d.ts.map +1 -0
  58. package/dist/ui/IconButton/index.d.ts +2 -0
  59. package/dist/ui/IconButton/index.d.ts.map +1 -0
  60. package/dist/{src/ui → ui}/Icons/AgentIcon.d.ts +2 -1
  61. package/dist/ui/Icons/AgentIcon.d.ts.map +1 -0
  62. package/dist/{src/ui → ui}/Icons/ToolsIcon.d.ts +2 -1
  63. package/dist/ui/Icons/ToolsIcon.d.ts.map +1 -0
  64. package/dist/{src/ui → ui}/Icons/WorkflowIcon.d.ts +2 -1
  65. package/dist/ui/Icons/WorkflowIcon.d.ts.map +1 -0
  66. package/dist/ui/Icons/index.d.ts +4 -0
  67. package/dist/ui/Icons/index.d.ts.map +1 -0
  68. package/dist/{src/ui → ui}/Message/Message.d.ts +2 -1
  69. package/dist/ui/Message/Message.d.ts.map +1 -0
  70. package/dist/ui/Message/index.d.ts +2 -0
  71. package/dist/ui/Message/index.d.ts.map +1 -0
  72. package/dist/ui/MessageFactory/MessageFactory.d.ts +22 -0
  73. package/dist/ui/MessageFactory/MessageFactory.d.ts.map +1 -0
  74. package/dist/ui/MessageFactory/index.d.ts +3 -0
  75. package/dist/ui/MessageFactory/index.d.ts.map +1 -0
  76. package/dist/ui/MessageFactory/types.d.ts +181 -0
  77. package/dist/ui/MessageFactory/types.d.ts.map +1 -0
  78. package/dist/{src/ui → ui}/Tooltip/Tooltip.d.ts +2 -1
  79. package/dist/ui/Tooltip/Tooltip.d.ts.map +1 -0
  80. package/dist/ui/Tooltip/index.d.ts +2 -0
  81. package/dist/ui/Tooltip/index.d.ts.map +1 -0
  82. package/dist/ui/index.d.ts +9 -0
  83. package/dist/ui/index.d.ts.map +1 -0
  84. package/dist/voice/index.d.ts +5 -0
  85. package/dist/voice/index.d.ts.map +1 -0
  86. package/dist/voice/play-stream-with-web-audio.d.ts +2 -0
  87. package/dist/voice/play-stream-with-web-audio.d.ts.map +1 -0
  88. package/dist/voice/record-mic-to-file.d.ts +2 -0
  89. package/dist/voice/record-mic-to-file.d.ts.map +1 -0
  90. package/dist/voice/use-speech-recognition.d.ts +20 -0
  91. package/dist/voice/use-speech-recognition.d.ts.map +1 -0
  92. package/dist/workflows/WorkflowStepFactory/WorkflowStepFactory.d.ts +8 -0
  93. package/dist/workflows/WorkflowStepFactory/WorkflowStepFactory.d.ts.map +1 -0
  94. package/dist/workflows/WorkflowStepFactory/index.d.ts +3 -0
  95. package/dist/workflows/WorkflowStepFactory/index.d.ts.map +1 -0
  96. package/dist/workflows/WorkflowStepFactory/types.d.ts +72 -0
  97. package/dist/workflows/WorkflowStepFactory/types.d.ts.map +1 -0
  98. package/dist/workflows/hooks.d.ts +34 -0
  99. package/dist/workflows/hooks.d.ts.map +1 -0
  100. package/dist/workflows/index.d.ts +4 -0
  101. package/dist/workflows/index.d.ts.map +1 -0
  102. package/dist/workflows/types.d.ts +122 -0
  103. package/dist/workflows/types.d.ts.map +1 -0
  104. package/dist/workflows/use-stream-workflow.d.ts +39 -0
  105. package/dist/workflows/use-stream-workflow.d.ts.map +1 -0
  106. package/package.json +35 -31
  107. package/dist/chunk-55VPMN3N-Ax1F4Y75.js +0 -249
  108. package/dist/chunk-55VPMN3N-Ax1F4Y75.js.map +0 -1
  109. package/dist/chunk-55VPMN3N-BHqoDkCq.cjs +0 -251
  110. package/dist/chunk-55VPMN3N-BHqoDkCq.cjs.map +0 -1
  111. package/dist/index-BaK_Y6TP.cjs +0 -185
  112. package/dist/index-BaK_Y6TP.cjs.map +0 -1
  113. package/dist/index-C1OzXW5i.js +0 -180
  114. package/dist/index-C1OzXW5i.js.map +0 -1
  115. package/dist/index-ChvWx-iU.cjs +0 -20711
  116. package/dist/index-ChvWx-iU.cjs.map +0 -1
  117. package/dist/index-D3JtF_Zl.js +0 -20628
  118. package/dist/index-D3JtF_Zl.js.map +0 -1
  119. package/dist/src/agent/hooks.d.ts +0 -65
  120. package/dist/src/index.d.ts +0 -6
  121. package/dist/src/lib/ai-sdk/index.d.ts +0 -4
  122. package/dist/src/lib/ai-sdk/memory/resolveInitialMessages.d.ts +0 -12
  123. package/dist/src/lib/ai-sdk/memory/resolveInitialMessages.test.d.ts +0 -1
  124. package/dist/src/lib/ai-sdk/transformers/AISdkNetworkTransformer.d.ts +0 -10
  125. package/dist/src/lib/ai-sdk/transformers/AISdkNetworkTransformer.test.d.ts +0 -1
  126. package/dist/src/lib/ai-sdk/transformers/types.d.ts +0 -10
  127. package/dist/src/lib/ai-sdk/types.d.ts +0 -106
  128. package/dist/src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts +0 -10
  129. package/dist/src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.test.d.ts +0 -1
  130. package/dist/src/lib/ai-sdk/utils/toAssistantUIMessage.d.ts +0 -14
  131. package/dist/src/lib/ai-sdk/utils/toAssistantUIMessage.test.d.ts +0 -1
  132. package/dist/src/lib/ai-sdk/utils/toUIMessage.d.ts +0 -17
  133. package/dist/src/lib/ai-sdk/utils/toUIMessage.test.d.ts +0 -1
  134. package/dist/src/mastra-client-context.d.ts +0 -10
  135. package/dist/src/mastra-react-provider.d.ts +0 -4
  136. package/dist/src/ui/Code/highlight.d.ts +0 -3
  137. package/dist/src/ui/Code/index.d.ts +0 -1
  138. package/dist/src/ui/Entity/Entity.stories.d.ts +0 -22
  139. package/dist/src/ui/Entity/index.d.ts +0 -4
  140. package/dist/src/ui/Icon/index.d.ts +0 -1
  141. package/dist/src/ui/IconButton/IconButton.stories.d.ts +0 -12
  142. package/dist/src/ui/IconButton/index.d.ts +0 -1
  143. package/dist/src/ui/Icons/index.d.ts +0 -3
  144. package/dist/src/ui/Message/Message.stories.d.ts +0 -13
  145. package/dist/src/ui/Message/index.d.ts +0 -1
  146. package/dist/src/ui/Tooltip/Tooltip.stories.d.ts +0 -12
  147. package/dist/src/ui/Tooltip/index.d.ts +0 -1
  148. package/dist/src/ui/index.d.ts +0 -7
  149. package/dist/token-6GSAFR2W-SPYPLMBM-CWoxKwfk.cjs +0 -64
  150. package/dist/token-6GSAFR2W-SPYPLMBM-CWoxKwfk.cjs.map +0 -1
  151. package/dist/token-6GSAFR2W-SPYPLMBM-ChURikIE.js +0 -60
  152. package/dist/token-6GSAFR2W-SPYPLMBM-ChURikIE.js.map +0 -1
  153. package/dist/token-util-NEHG7TUY-JRJTGTAB-BU9ZxL1w.cjs +0 -11
  154. package/dist/token-util-NEHG7TUY-JRJTGTAB-BU9ZxL1w.cjs.map +0 -1
  155. package/dist/token-util-NEHG7TUY-JRJTGTAB-hEay2AHp.js +0 -7
  156. package/dist/token-util-NEHG7TUY-JRJTGTAB-hEay2AHp.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,70 +1,3750 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
+ var clientJs = require('@mastra/client-js');
4
+ var react = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var uuid = require('@lukeed/uuid');
7
+ var messageList = require('@mastra/core/agent/message-list');
8
+ var lucideReact = require('lucide-react');
9
+ var tailwindMerge = require('tailwind-merge');
10
+ var reactTooltip = require('@radix-ui/react-tooltip');
11
+ var hastUtilToJsxRuntime = require('hast-util-to-jsx-runtime');
12
+ var web = require('shiki/bundle/web');
4
13
 
5
- const index = require('./index-ChvWx-iU.cjs');
14
+ // src/mastra-client-context.tsx
15
+ var MastraClientContext = react.createContext({});
16
+ var MastraClientProvider = ({
17
+ children,
18
+ baseUrl,
19
+ headers,
20
+ apiPrefix,
21
+ credentials = "include",
22
+ customFetch
23
+ }) => {
24
+ const client = createMastraClient(baseUrl, headers, apiPrefix, credentials, customFetch);
25
+ return /* @__PURE__ */ jsxRuntime.jsx(MastraClientContext.Provider, { value: client, children });
26
+ };
27
+ var useMastraClient = () => react.useContext(MastraClientContext);
28
+ var IPV4_LOOPBACK_RE = /^127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
29
+ var isIPv4Loopback = (hostname) => {
30
+ const m = IPV4_LOOPBACK_RE.exec(hostname);
31
+ if (!m) return false;
32
+ return +m[1] <= 255 && +m[2] <= 255 && +m[3] <= 255;
33
+ };
34
+ var isLocalUrl = (url) => {
35
+ if (!url) return true;
36
+ try {
37
+ const { hostname } = new URL(url);
38
+ return hostname === "localhost" || hostname.endsWith(".localhost") || isIPv4Loopback(hostname) || hostname === "::1" || hostname === "[::1]";
39
+ } catch {
40
+ return false;
41
+ }
42
+ };
43
+ var createMastraClient = (baseUrl, mastraClientHeaders = {}, apiPrefix, credentials = "include", customFetch) => {
44
+ return new clientJs.MastraClient({
45
+ baseUrl: baseUrl || "",
46
+ headers: isLocalUrl(baseUrl) ? { ...mastraClientHeaders, "x-mastra-dev-playground": "true" } : mastraClientHeaders,
47
+ apiPrefix,
48
+ credentials,
49
+ fetch: customFetch
50
+ });
51
+ };
52
+ var MastraReactProvider = ({
53
+ children,
54
+ baseUrl,
55
+ headers,
56
+ apiPrefix,
57
+ credentials,
58
+ customFetch
59
+ }) => {
60
+ return /* @__PURE__ */ jsxRuntime.jsx(
61
+ MastraClientProvider,
62
+ {
63
+ baseUrl,
64
+ headers,
65
+ apiPrefix,
66
+ credentials,
67
+ customFetch,
68
+ children
69
+ }
70
+ );
71
+ };
6
72
 
73
+ // src/lib/mastra-db/formatCompletionFeedback.ts
74
+ var formatBaseCompletionFeedback = (result, maxIterationReached, formatScorerHeading, incompleteMessage) => {
75
+ const lines = [];
76
+ lines.push("#### Completion Check Results");
77
+ lines.push("");
78
+ lines.push(`Overall: ${result.complete ? "\u2705 COMPLETE" : "\u274C NOT COMPLETE"}`);
79
+ lines.push(`Duration: ${result.totalDuration}ms`);
80
+ if (result.timedOut) {
81
+ lines.push("\u26A0\uFE0F Scoring timed out");
82
+ }
83
+ lines.push("");
84
+ for (const scorer of result.scorers) {
85
+ lines.push(formatScorerHeading(scorer));
86
+ lines.push(`Score: ${scorer.score} ${scorer.passed ? "\u2705" : "\u274C"}`);
87
+ if (scorer.reason) {
88
+ lines.push(`Reason: ${scorer.reason}`);
89
+ }
90
+ lines.push("");
91
+ }
92
+ if (result.complete) {
93
+ lines.push("\u2705 The task is complete.");
94
+ } else if (maxIterationReached) {
95
+ lines.push("\u26A0\uFE0F Max iterations reached.");
96
+ } else {
97
+ lines.push(incompleteMessage);
98
+ }
99
+ return lines.join("\n");
100
+ };
101
+ var formatCompletionFeedback = (result, maxIterationReached) => {
102
+ return formatBaseCompletionFeedback(
103
+ result,
104
+ maxIterationReached,
105
+ (scorer) => `###### ${scorer.scorerName} (${scorer.scorerId})`,
106
+ "\u{1F504} Will continue working on the task."
107
+ );
108
+ };
109
+ var formatStreamCompletionFeedback = (result, maxIterationReached) => {
110
+ return formatBaseCompletionFeedback(
111
+ result,
112
+ maxIterationReached,
113
+ (scorer) => `**${scorer.scorerName}** (${scorer.scorerId})`,
114
+ "\u{1F504} The task is not yet complete. Please continue working based on the feedback above."
115
+ );
116
+ };
7
117
 
118
+ // src/lib/mastra-db/types.ts
119
+ var CLIENT_MESSAGE_ID_KEY = "clientMessageId";
8
120
 
9
- exports.AgentIcon = index.AgentIcon;
10
- exports.CodeBlock = index.CodeBlock;
11
- exports.CodeBlockClass = index.CodeBlockClass;
12
- exports.CodeCopyButton = index.CodeCopyButton;
13
- exports.Entity = index.Entity;
14
- exports.EntityCaret = index.EntityCaret;
15
- exports.EntityContent = index.EntityContent;
16
- exports.EntityContentClass = index.EntityContentClass;
17
- exports.EntityTrigger = index.EntityTrigger;
18
- exports.EntityTriggerClass = index.EntityTriggerClass;
19
- exports.EntityTriggerVariantClasses = index.EntityTriggerVariantClasses;
20
- exports.Entry = index.Entry;
21
- exports.EntryClass = index.EntryClass;
22
- exports.EntryTitle = index.EntryTitle;
23
- exports.EntryTitleClass = index.EntryTitleClass;
24
- exports.Icon = index.Icon;
25
- exports.IconButton = index.IconButton;
26
- exports.IconButtonClass = index.IconButtonClass;
27
- exports.IconSizes = index.IconSizes;
28
- exports.MastraReactProvider = index.MastraReactProvider;
29
- exports.Message = index.Message;
30
- exports.MessageActions = index.MessageActions;
31
- exports.MessageActionsClass = index.MessageActionsClass;
32
- exports.MessageClass = index.MessageClass;
33
- exports.MessageContent = index.MessageContent;
34
- exports.MessageContentClass = index.MessageContentClass;
35
- exports.MessageList = index.MessageList;
36
- exports.MessageListClass = index.MessageListClass;
37
- exports.MessageStreaming = index.MessageStreaming;
38
- exports.MessageStreamingClass = index.MessageStreamingClass;
39
- exports.MessageUsage = index.MessageUsage;
40
- exports.MessageUsageClass = index.MessageUsageClass;
41
- exports.MessageUsageEntry = index.MessageUsageEntry;
42
- exports.MessageUsageEntryClass = index.MessageUsageEntryClass;
43
- exports.MessageUsageValue = index.MessageUsageValue;
44
- exports.MessageUsageValueClass = index.MessageUsageValueClass;
45
- exports.MessageUsages = index.MessageUsages;
46
- exports.MessageUsagesClass = index.MessageUsagesClass;
47
- exports.ToolApproval = index.ToolApproval;
48
- exports.ToolApprovalActions = index.ToolApprovalActions;
49
- exports.ToolApprovalActionsClass = index.ToolApprovalActionsClass;
50
- exports.ToolApprovalClass = index.ToolApprovalClass;
51
- exports.ToolApprovalContent = index.ToolApprovalContent;
52
- exports.ToolApprovalContentClass = index.ToolApprovalContentClass;
53
- exports.ToolApprovalHeader = index.ToolApprovalHeader;
54
- exports.ToolApprovalHeaderClass = index.ToolApprovalHeaderClass;
55
- exports.ToolApprovalTitle = index.ToolApprovalTitle;
56
- exports.ToolApprovalTitleClass = index.ToolApprovalTitleClass;
57
- exports.ToolsIcon = index.ToolsIcon;
58
- exports.Tooltip = index.Tooltip;
59
- exports.TooltipContent = index.TooltipContent;
60
- exports.TooltipContentClass = index.TooltipContentClass;
61
- exports.TooltipTrigger = index.TooltipTrigger;
62
- exports.WorkflowIcon = index.WorkflowIcon;
63
- exports.mapWorkflowStreamChunkToWatchResult = index.mapWorkflowStreamChunkToWatchResult;
64
- exports.resolveToChildMessages = index.resolveToChildMessages;
65
- exports.toAssistantUIMessage = index.toAssistantUIMessage;
66
- exports.toUIMessage = index.toUIMessage;
67
- exports.useChat = index.useChat;
68
- exports.useEntity = index.useEntity;
69
- exports.useMastraClient = index.useMastraClient;
121
+ // src/lib/mastra-db/accumulator.ts
122
+ var cloneMetadata = (metadata) => metadata ? { ...metadata } : {};
123
+ var withParts = (message, parts) => ({
124
+ ...message,
125
+ content: {
126
+ ...message.content,
127
+ parts
128
+ }
129
+ });
130
+ var withMetadata = (message, metadata) => ({
131
+ ...message,
132
+ content: {
133
+ ...message.content,
134
+ metadata
135
+ }
136
+ });
137
+ var clearPendingStatus = (message) => {
138
+ const { status: _status, [CLIENT_MESSAGE_ID_KEY]: _clientMessageId, ...rest } = message.content.metadata ?? {};
139
+ return withMetadata(message, rest);
140
+ };
141
+ var clearPendingStatusKeepClientId = (message) => {
142
+ const { status: _status, ...rest } = message.content.metadata ?? {};
143
+ return withMetadata(message, rest);
144
+ };
145
+ var replaceLast = (conversation, message) => [
146
+ ...conversation.slice(0, -1),
147
+ message
148
+ ];
149
+ var replaceAt = (conversation, index, message) => [
150
+ ...conversation.slice(0, index),
151
+ message,
152
+ ...conversation.slice(index + 1)
153
+ ];
154
+ var newAssistantMessage = (id, parts, metadata) => ({
155
+ id,
156
+ role: "assistant",
157
+ createdAt: /* @__PURE__ */ new Date(),
158
+ content: {
159
+ format: 2,
160
+ parts,
161
+ metadata: cloneMetadata(metadata)
162
+ }
163
+ });
164
+ var appendAssistantMessage = (conversation, id, parts, metadata) => [...conversation, newAssistantMessage(id, parts, metadata)];
165
+ var isToolPart = (part) => part.type === "tool-invocation";
166
+ var partTextId = (part) => part.type === "text" ? part.textId : void 0;
167
+ var partState = (part) => part.state;
168
+ var finishStreamingAssistantMessage = (conversation) => {
169
+ const lastMessage = conversation[conversation.length - 1];
170
+ if (!lastMessage || lastMessage.role !== "assistant") return conversation;
171
+ if (lastMessage.content.parts.length === 0) return conversation.slice(0, -1);
172
+ const nextParts = lastMessage.content.parts.map((part) => {
173
+ if ((part.type === "text" || part.type === "reasoning") && partState(part) === "streaming") {
174
+ return {
175
+ ...part,
176
+ state: "done"
177
+ };
178
+ }
179
+ return part;
180
+ });
181
+ return replaceLast(conversation, withParts(lastMessage, nextParts));
182
+ };
183
+ var locateToolPart = (messages, toolCallId, allowMetadataOnlyMatch) => {
184
+ const findIndex = (parts) => parts.findIndex((part) => isToolPart(part) && part.toolInvocation.toolCallId === toolCallId);
185
+ const lastMessage = messages[messages.length - 1];
186
+ if (lastMessage && lastMessage.role === "assistant") {
187
+ const idx = findIndex(lastMessage.content.parts);
188
+ if (idx !== -1) return { messageIndex: messages.length - 1, toolPartIndex: idx };
189
+ }
190
+ let count = 0;
191
+ const maxMessagesBack = 10;
192
+ for (let i = messages.length - 1; i >= 0; i--) {
193
+ if (count > maxMessagesBack) break;
194
+ const message = messages[i];
195
+ if (message.role !== "assistant") continue;
196
+ const idx = findIndex(message.content.parts);
197
+ if (idx !== -1) return { messageIndex: i, toolPartIndex: idx };
198
+ count++;
199
+ }
200
+ if (!allowMetadataOnlyMatch) return null;
201
+ for (let i = messages.length - 1; i >= 0; i--) {
202
+ if (messages[i].role === "assistant") return { messageIndex: i, toolPartIndex: -1 };
203
+ }
204
+ return null;
205
+ };
206
+ var mergeBgTaskMetadata = (existing, mode, args, otherMetadata) => {
207
+ const base = cloneMetadata(existing);
208
+ const existingBgTasks = base.backgroundTasks ?? {};
209
+ const nextBgTasks = { ...existingBgTasks };
210
+ if (args.perTaskEntry) {
211
+ const { toolCallId, startedAt, completedAt, taskId, suspendedAt } = args.perTaskEntry;
212
+ const prev = existingBgTasks[toolCallId] ?? { taskId };
213
+ nextBgTasks[toolCallId] = {
214
+ ...prev,
215
+ taskId,
216
+ ...startedAt !== void 0 ? { startedAt } : {},
217
+ ...completedAt !== void 0 ? { completedAt } : {},
218
+ ...suspendedAt !== void 0 ? { suspendedAt } : {}
219
+ };
220
+ }
221
+ const merged = {
222
+ ...base,
223
+ ...otherMetadata ?? {},
224
+ mode,
225
+ backgroundTasks: nextBgTasks
226
+ };
227
+ if (args.resetRunningCount) merged.runningBackgroundTasksCount = void 0;
228
+ return merged;
229
+ };
230
+ var mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
231
+ if (chunk.type === "workflow-start") {
232
+ return {
233
+ input: prev?.input,
234
+ status: "running",
235
+ steps: prev?.steps || {}
236
+ };
237
+ }
238
+ if (chunk.type === "workflow-canceled") {
239
+ return { ...prev, status: "canceled" };
240
+ }
241
+ if (chunk.type === "workflow-finish") {
242
+ const finalStatus = chunk.payload.workflowStatus;
243
+ const prevSteps = prev?.steps ?? {};
244
+ const lastStep = Object.values(prevSteps).pop();
245
+ return {
246
+ ...prev,
247
+ status: chunk.payload.workflowStatus,
248
+ ...finalStatus === "success" && lastStep?.status === "success" ? { result: lastStep?.output } : finalStatus === "failed" && lastStep?.status === "failed" ? { error: lastStep?.error } : finalStatus === "tripwire" && chunk.payload.tripwire ? { tripwire: chunk.payload.tripwire } : {}
249
+ };
250
+ }
251
+ const { stepCallId: _stepCallId, stepName: _stepName, ...newPayload } = chunk.payload ?? {};
252
+ const newSteps = {
253
+ ...prev?.steps,
254
+ [chunk.payload.id]: {
255
+ ...prev?.steps?.[chunk.payload.id],
256
+ ...newPayload
257
+ }
258
+ };
259
+ if (chunk.type === "workflow-step-start") return { ...prev, steps: newSteps };
260
+ if (chunk.type === "workflow-step-suspended") {
261
+ const suspendedStepIds = Object.entries(newSteps).flatMap(
262
+ ([stepId, stepResult]) => {
263
+ if (stepResult?.status === "suspended") {
264
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
265
+ return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
266
+ }
267
+ return [];
268
+ }
269
+ );
270
+ return {
271
+ ...prev,
272
+ status: "suspended",
273
+ steps: newSteps,
274
+ suspendPayload: chunk.payload.suspendPayload,
275
+ suspended: suspendedStepIds
276
+ };
277
+ }
278
+ if (chunk.type === "workflow-step-waiting") return { ...prev, status: "waiting", steps: newSteps };
279
+ if (chunk.type === "workflow-step-progress") {
280
+ return {
281
+ ...prev,
282
+ steps: {
283
+ ...prev?.steps,
284
+ [chunk.payload.id]: {
285
+ ...prev?.steps?.[chunk.payload.id],
286
+ foreachProgress: {
287
+ completedCount: chunk.payload.completedCount,
288
+ totalCount: chunk.payload.totalCount,
289
+ currentIndex: chunk.payload.currentIndex,
290
+ iterationStatus: chunk.payload.iterationStatus,
291
+ iterationOutput: chunk.payload.iterationOutput
292
+ }
293
+ }
294
+ }
295
+ };
296
+ }
297
+ if (chunk.type === "workflow-step-result") return { ...prev, steps: newSteps };
298
+ return prev;
299
+ };
300
+ var signalContentsToUserMessages = (contents, metadata) => {
301
+ const makeUserMessage = (parts2) => ({
302
+ id: `signal-${Date.now()}`,
303
+ role: "user",
304
+ createdAt: /* @__PURE__ */ new Date(),
305
+ content: {
306
+ format: 2,
307
+ parts: parts2,
308
+ metadata: cloneMetadata(metadata)
309
+ }
310
+ });
311
+ const toMessagePart = (part) => {
312
+ if (!part || typeof part !== "object") return [];
313
+ const typedPart = part;
314
+ if (typedPart.type === "text" && typeof typedPart.text === "string") {
315
+ return [{ type: "text", text: typedPart.text }];
316
+ }
317
+ if (typedPart.type === "image") {
318
+ const image = typedPart.image;
319
+ return [
320
+ {
321
+ type: "file",
322
+ mediaType: typeof typedPart.mediaType === "string" ? typedPart.mediaType : typeof typedPart.mimeType === "string" ? typedPart.mimeType : "image/*",
323
+ url: typeof image === "string" ? image : image instanceof URL ? image.toString() : ""
324
+ }
325
+ ];
326
+ }
327
+ if (typedPart.type === "file") {
328
+ const data = typedPart.data;
329
+ return [
330
+ {
331
+ type: "file",
332
+ mediaType: typeof typedPart.mediaType === "string" ? typedPart.mediaType : typeof typedPart.mimeType === "string" ? typedPart.mimeType : "application/octet-stream",
333
+ url: typeof data === "string" ? data : data instanceof URL ? data.toString() : "",
334
+ ...typeof typedPart.filename === "string" ? { filename: typedPart.filename } : {}
335
+ }
336
+ ];
337
+ }
338
+ return [];
339
+ };
340
+ if (typeof contents === "string") {
341
+ return [makeUserMessage([{ type: "text", text: contents }])];
342
+ }
343
+ if (Array.isArray(contents)) {
344
+ const parts2 = contents.flatMap(toMessagePart);
345
+ return parts2.length ? [makeUserMessage(parts2)] : contents.flatMap((content2) => signalContentsToUserMessages(content2, metadata));
346
+ }
347
+ if (!contents || typeof contents !== "object") return [];
348
+ const message = contents;
349
+ if (message.role && message.role !== "user") return [];
350
+ const content = message.content;
351
+ if (typeof content === "string") {
352
+ return [makeUserMessage([{ type: "text", text: content }])];
353
+ }
354
+ if (!Array.isArray(content)) return [];
355
+ const parts = content.flatMap(toMessagePart);
356
+ return parts.length ? [makeUserMessage(parts)] : [];
357
+ };
358
+ var makeToolInvocationPart = (invocation) => ({
359
+ type: "tool-invocation",
360
+ toolInvocation: invocation
361
+ });
362
+ var isTemplateLiteralPassthrough = (chunk) => chunk.type.startsWith("agent-execution-event-") || chunk.type.startsWith("workflow-execution-event-");
363
+ var isDataChunk = (chunk) => chunk.type.startsWith("data-");
364
+ var accumulateChunk = ({ chunk, conversation, metadata }) => {
365
+ const result = [...conversation];
366
+ if (isTemplateLiteralPassthrough(chunk)) {
367
+ return result;
368
+ }
369
+ if (isDataChunk(chunk)) {
370
+ if (chunk.type === "data-user-message" && "data" in chunk && (chunk.data?.type === "user-message" || chunk.data?.type === "user")) {
371
+ const signalId = chunk.data.id;
372
+ const echoedClientMessageId = chunk.data?.metadata?.[CLIENT_MESSAGE_ID_KEY];
373
+ if (typeof echoedClientMessageId === "string" && result.some(
374
+ (message) => message.content.metadata?.status === "pending" && message.content.metadata[CLIENT_MESSAGE_ID_KEY] === echoedClientMessageId
375
+ )) {
376
+ return finishStreamingAssistantMessage(
377
+ result.map(
378
+ (message) => message.content.metadata?.status === "pending" && message.content.metadata[CLIENT_MESSAGE_ID_KEY] === echoedClientMessageId ? clearPendingStatusKeepClientId(typeof signalId === "string" ? { ...message, id: signalId } : message) : message
379
+ )
380
+ );
381
+ }
382
+ if (typeof signalId === "string" && result.some((message) => message.id === signalId)) {
383
+ return finishStreamingAssistantMessage(
384
+ result.map(
385
+ (message) => message.id === signalId && message.content.metadata?.status === "pending" ? clearPendingStatus(message) : message
386
+ )
387
+ );
388
+ }
389
+ const userMessages = signalContentsToUserMessages(chunk.data.contents, metadata);
390
+ if (!userMessages.length) return result;
391
+ const conversationWithFinishedAssistant = finishStreamingAssistantMessage(result);
392
+ const messageIdPrefix = typeof signalId === "string" ? signalId : `signal-${chunk.runId}-${Date.now()}`;
393
+ return [
394
+ ...conversationWithFinishedAssistant,
395
+ ...userMessages.map((message, index) => ({
396
+ ...message,
397
+ id: index === 0 ? messageIdPrefix : `${messageIdPrefix}-${index}`
398
+ }))
399
+ ];
400
+ }
401
+ const dataPart = {
402
+ type: chunk.type,
403
+ data: "data" in chunk ? chunk.data : void 0,
404
+ ..."id" in chunk && typeof chunk.id === "string" ? { id: chunk.id } : {}
405
+ };
406
+ const lastMessage = result[result.length - 1];
407
+ if (!lastMessage || lastMessage.role !== "assistant") {
408
+ return appendAssistantMessage(result, `data-${chunk.runId}-${Date.now()}`, [dataPart], metadata);
409
+ }
410
+ return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, dataPart]));
411
+ }
412
+ switch (chunk.type) {
413
+ case "tripwire": {
414
+ const newMessage = newAssistantMessage(
415
+ `tripwire-${chunk.runId + Date.now()}`,
416
+ [{ type: "text", text: chunk.payload.reason }],
417
+ {
418
+ ...metadata,
419
+ status: "tripwire",
420
+ tripwire: {
421
+ reason: chunk.payload.reason,
422
+ retry: chunk.payload.retry,
423
+ metadata: chunk.payload.metadata,
424
+ processorId: chunk.payload.processorId
425
+ }
426
+ }
427
+ );
428
+ return [...result, newMessage];
429
+ }
430
+ case "start": {
431
+ const messageId = typeof chunk.payload.messageId === "string" ? chunk.payload.messageId : void 0;
432
+ if (messageId && result.some((message) => message.id === messageId)) return result;
433
+ return [...result, newAssistantMessage(messageId ?? `start-${chunk.runId + Date.now()}`, [], metadata)];
434
+ }
435
+ case "text-start": {
436
+ const lastMessage = result[result.length - 1];
437
+ const textId = chunk.payload.id || `text-${Date.now()}`;
438
+ if (chunk.payload.id && lastMessage?.role === "assistant" && lastMessage.content.parts.some((part) => part.type === "text" && partTextId(part) === textId)) {
439
+ return result;
440
+ }
441
+ const newTextPart = {
442
+ type: "text",
443
+ text: "",
444
+ state: "streaming",
445
+ textId,
446
+ providerMetadata: chunk.payload.providerMetadata
447
+ };
448
+ if (!lastMessage || lastMessage.role !== "assistant") {
449
+ return appendAssistantMessage(
450
+ result,
451
+ `start-${chunk.runId}-${Date.now()}`,
452
+ [newTextPart],
453
+ metadata
454
+ );
455
+ }
456
+ if (lastMessage.content.metadata?.completionResult) {
457
+ return appendAssistantMessage(
458
+ result,
459
+ `start-${chunk.runId}-${Date.now()}`,
460
+ [newTextPart],
461
+ metadata
462
+ );
463
+ }
464
+ return replaceLast(
465
+ result,
466
+ withParts(lastMessage, [...lastMessage.content.parts, newTextPart])
467
+ );
468
+ }
469
+ case "background-task-progress": {
470
+ const lastMessage = result[result.length - 1];
471
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
472
+ return replaceLast(
473
+ result,
474
+ withMetadata(lastMessage, {
475
+ mode: metadata.mode,
476
+ ...lastMessage.content.metadata,
477
+ runningBackgroundTasksCount: chunk.payload.runningCount
478
+ })
479
+ );
480
+ }
481
+ case "text-delta": {
482
+ const lastMessage = result[result.length - 1];
483
+ const textId = chunk.payload.id;
484
+ if (!lastMessage || lastMessage.role !== "assistant") {
485
+ const newTextPart = {
486
+ type: "text",
487
+ text: chunk.payload.text,
488
+ state: "streaming",
489
+ textId,
490
+ providerMetadata: chunk.payload.providerMetadata
491
+ };
492
+ return appendAssistantMessage(
493
+ result,
494
+ `text-${chunk.runId}-${Date.now()}`,
495
+ [newTextPart],
496
+ metadata
497
+ );
498
+ }
499
+ const parts = [...lastMessage.content.parts];
500
+ let textPartIndex = textId ? parts.findLastIndex((part) => part.type === "text" && partTextId(part) === textId) : -1;
501
+ if (textPartIndex === -1) {
502
+ textPartIndex = parts.findLastIndex((part) => part.type === "text" && partState(part) === "streaming");
503
+ }
504
+ if (textPartIndex === -1) {
505
+ const newTextPart = {
506
+ type: "text",
507
+ text: chunk.payload.text,
508
+ state: "streaming",
509
+ textId,
510
+ providerMetadata: chunk.payload.providerMetadata
511
+ };
512
+ parts.push(newTextPart);
513
+ } else {
514
+ const textPart = parts[textPartIndex];
515
+ parts[textPartIndex] = {
516
+ ...textPart,
517
+ text: textPart.text + chunk.payload.text,
518
+ state: "streaming"
519
+ };
520
+ }
521
+ return replaceLast(result, withParts(lastMessage, parts));
522
+ }
523
+ case "text-end": {
524
+ return result;
525
+ }
526
+ case "reasoning-start": {
527
+ const lastMessage = result[result.length - 1];
528
+ const newReasoningPart = {
529
+ type: "reasoning",
530
+ reasoning: "",
531
+ state: "streaming",
532
+ providerMetadata: chunk.payload.providerMetadata
533
+ };
534
+ if (!lastMessage || lastMessage.role !== "assistant") {
535
+ return appendAssistantMessage(
536
+ result,
537
+ `reasoning-${chunk.runId + Date.now()}`,
538
+ [newReasoningPart],
539
+ metadata
540
+ );
541
+ }
542
+ return replaceLast(
543
+ result,
544
+ withParts(lastMessage, [...lastMessage.content.parts, newReasoningPart])
545
+ );
546
+ }
547
+ case "reasoning-delta": {
548
+ const lastMessage = result[result.length - 1];
549
+ if (!lastMessage || lastMessage.role !== "assistant") {
550
+ const newReasoningPart = {
551
+ type: "reasoning",
552
+ reasoning: chunk.payload.text,
553
+ state: "streaming",
554
+ providerMetadata: chunk.payload.providerMetadata
555
+ };
556
+ return appendAssistantMessage(
557
+ result,
558
+ `reasoning-${chunk.runId + Date.now()}`,
559
+ [newReasoningPart],
560
+ metadata
561
+ );
562
+ }
563
+ const parts = [...lastMessage.content.parts];
564
+ const lastIndex = parts.length - 1;
565
+ const lastPart = parts[lastIndex];
566
+ if (lastPart?.type === "reasoning") {
567
+ const reasoningPart = lastPart;
568
+ parts[lastIndex] = {
569
+ ...reasoningPart,
570
+ reasoning: reasoningPart.reasoning + chunk.payload.text,
571
+ state: "streaming"
572
+ };
573
+ } else {
574
+ const newReasoningPart = {
575
+ type: "reasoning",
576
+ reasoning: chunk.payload.text,
577
+ state: "streaming",
578
+ providerMetadata: chunk.payload.providerMetadata
579
+ };
580
+ parts.push(newReasoningPart);
581
+ }
582
+ return replaceLast(result, withParts(lastMessage, parts));
583
+ }
584
+ case "reasoning-end": {
585
+ const lastMessage = result[result.length - 1];
586
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
587
+ const parts = [...lastMessage.content.parts];
588
+ const reasoningIndex = parts.findLastIndex((part) => part.type === "reasoning" && partState(part) === "streaming");
589
+ if (reasoningIndex === -1) return result;
590
+ const reasoningPart = parts[reasoningIndex];
591
+ const existingMeta = reasoningPart.providerMetadata;
592
+ const endMeta = chunk.payload.providerMetadata;
593
+ parts[reasoningIndex] = {
594
+ ...reasoningPart,
595
+ state: "done",
596
+ ...existingMeta || endMeta ? { providerMetadata: { ...existingMeta ?? {}, ...endMeta ?? {} } } : {}
597
+ };
598
+ return replaceLast(result, withParts(lastMessage, parts));
599
+ }
600
+ case "reasoning-signature": {
601
+ const lastMessage = result[result.length - 1];
602
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
603
+ const parts = [...lastMessage.content.parts];
604
+ const reasoningIndex = parts.findLastIndex((part) => part.type === "reasoning");
605
+ if (reasoningIndex === -1) return result;
606
+ const reasoningPart = parts[reasoningIndex];
607
+ const existingMeta = reasoningPart.providerMetadata;
608
+ const sigMeta = chunk.payload.providerMetadata;
609
+ parts[reasoningIndex] = {
610
+ ...reasoningPart,
611
+ ...existingMeta || sigMeta ? { providerMetadata: { ...existingMeta ?? {}, ...sigMeta ?? {} } } : {}
612
+ };
613
+ return replaceLast(result, withParts(lastMessage, parts));
614
+ }
615
+ case "redacted-reasoning": {
616
+ const lastMessage = result[result.length - 1];
617
+ const redactedData = chunk.payload.data;
618
+ const redactedPart = {
619
+ type: "reasoning",
620
+ reasoning: typeof redactedData === "string" ? redactedData : "",
621
+ state: "done",
622
+ redacted: true,
623
+ providerMetadata: chunk.payload.providerMetadata
624
+ };
625
+ if (!lastMessage || lastMessage.role !== "assistant") {
626
+ return appendAssistantMessage(
627
+ result,
628
+ `redacted-reasoning-${chunk.runId + Date.now()}`,
629
+ [redactedPart],
630
+ metadata
631
+ );
632
+ }
633
+ return replaceLast(
634
+ result,
635
+ withParts(lastMessage, [...lastMessage.content.parts, redactedPart])
636
+ );
637
+ }
638
+ case "tool-call": {
639
+ const invocation = {
640
+ state: "call",
641
+ toolCallId: chunk.payload.toolCallId,
642
+ toolName: chunk.payload.toolName,
643
+ args: chunk.payload.args
644
+ };
645
+ const newPart = {
646
+ ...makeToolInvocationPart(invocation),
647
+ providerMetadata: chunk.payload.providerMetadata
648
+ };
649
+ const existing = locateToolPart(result, chunk.payload.toolCallId, false);
650
+ if (existing && existing.toolPartIndex >= 0) {
651
+ const { messageIndex, toolPartIndex } = existing;
652
+ const targetMessage = result[messageIndex];
653
+ if (targetMessage && targetMessage.role === "assistant") {
654
+ const parts = [...targetMessage.content.parts];
655
+ const prev = parts[toolPartIndex];
656
+ if (isToolPart(prev)) {
657
+ const { argsText: _argsText, ...rest } = prev;
658
+ parts[toolPartIndex] = {
659
+ ...rest,
660
+ toolInvocation: {
661
+ ...prev.toolInvocation,
662
+ state: "call",
663
+ toolName: chunk.payload.toolName,
664
+ toolCallId: chunk.payload.toolCallId,
665
+ args: chunk.payload.args
666
+ },
667
+ providerMetadata: chunk.payload.providerMetadata ?? prev.providerMetadata
668
+ };
669
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
670
+ }
671
+ }
672
+ }
673
+ const lastMessage = result[result.length - 1];
674
+ if (!lastMessage || lastMessage.role !== "assistant") {
675
+ return appendAssistantMessage(result, `tool-call-${chunk.runId + Date.now()}`, [newPart], metadata);
676
+ }
677
+ return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, newPart]));
678
+ }
679
+ case "tool-call-input-streaming-start": {
680
+ const lastMessage = result[result.length - 1];
681
+ const invocation = {
682
+ state: "partial-call",
683
+ toolCallId: chunk.payload.toolCallId,
684
+ toolName: chunk.payload.toolName,
685
+ args: {}
686
+ };
687
+ const newPart = {
688
+ ...makeToolInvocationPart(invocation),
689
+ argsText: ""
690
+ };
691
+ if (!lastMessage || lastMessage.role !== "assistant") {
692
+ return appendAssistantMessage(
693
+ result,
694
+ `tool-call-streaming-${chunk.runId + Date.now()}`,
695
+ [newPart],
696
+ metadata
697
+ );
698
+ }
699
+ return replaceLast(result, withParts(lastMessage, [...lastMessage.content.parts, newPart]));
700
+ }
701
+ case "tool-call-delta": {
702
+ const location = locateToolPart(result, chunk.payload.toolCallId, false);
703
+ if (!location || location.toolPartIndex < 0) return result;
704
+ const { messageIndex, toolPartIndex } = location;
705
+ const targetMessage = result[messageIndex];
706
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
707
+ const parts = [...targetMessage.content.parts];
708
+ const toolPart = parts[toolPartIndex];
709
+ if (!isToolPart(toolPart)) return result;
710
+ const nextArgsText = (toolPart.argsText ?? "") + (chunk.payload.argsTextDelta ?? "");
711
+ parts[toolPartIndex] = {
712
+ ...toolPart,
713
+ argsText: nextArgsText,
714
+ toolInvocation: {
715
+ ...toolPart.toolInvocation,
716
+ state: "partial-call"
717
+ }
718
+ };
719
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
720
+ }
721
+ case "tool-call-input-streaming-end": {
722
+ const location = locateToolPart(result, chunk.payload.toolCallId, false);
723
+ if (!location || location.toolPartIndex < 0) return result;
724
+ const { messageIndex, toolPartIndex } = location;
725
+ const targetMessage = result[messageIndex];
726
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
727
+ const parts = [...targetMessage.content.parts];
728
+ const toolPart = parts[toolPartIndex];
729
+ if (!isToolPart(toolPart)) return result;
730
+ let parsedArgs = {};
731
+ const argsText = toolPart.argsText;
732
+ if (typeof argsText === "string" && argsText.length > 0) {
733
+ try {
734
+ const maybe = JSON.parse(argsText);
735
+ if (maybe && typeof maybe === "object" && !Array.isArray(maybe)) {
736
+ parsedArgs = maybe;
737
+ }
738
+ } catch {
739
+ parsedArgs = {};
740
+ }
741
+ }
742
+ parts[toolPartIndex] = {
743
+ ...toolPart,
744
+ toolInvocation: {
745
+ ...toolPart.toolInvocation,
746
+ state: "call",
747
+ args: parsedArgs
748
+ }
749
+ };
750
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
751
+ }
752
+ case "tool-error":
753
+ case "tool-result":
754
+ case "background-task-completed":
755
+ case "background-task-failed": {
756
+ const isBgTaskEvent = chunk.type === "background-task-completed" || chunk.type === "background-task-failed";
757
+ const location = locateToolPart(result, chunk.payload.toolCallId, isBgTaskEvent);
758
+ if (!location) return result;
759
+ const { messageIndex, toolPartIndex } = location;
760
+ const targetMessage = result[messageIndex];
761
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
762
+ const parts = [...targetMessage.content.parts];
763
+ const toolPart = toolPartIndex >= 0 ? parts[toolPartIndex] : void 0;
764
+ let payloadResult;
765
+ let payloadError;
766
+ let payloadIsError = false;
767
+ let payloadProviderMetadata;
768
+ let payloadCompletedAt;
769
+ let payloadTaskId;
770
+ switch (chunk.type) {
771
+ case "tool-result":
772
+ payloadResult = chunk.payload.result;
773
+ payloadIsError = Boolean(chunk.payload.isError);
774
+ payloadProviderMetadata = chunk.payload.providerMetadata;
775
+ break;
776
+ case "tool-error":
777
+ payloadError = chunk.payload.error;
778
+ payloadProviderMetadata = chunk.payload.providerMetadata;
779
+ break;
780
+ case "background-task-completed":
781
+ payloadResult = chunk.payload.result;
782
+ payloadCompletedAt = chunk.payload.completedAt;
783
+ payloadTaskId = chunk.payload.taskId;
784
+ break;
785
+ case "background-task-failed":
786
+ payloadError = chunk.payload.error;
787
+ payloadCompletedAt = chunk.payload.completedAt;
788
+ payloadTaskId = chunk.payload.taskId;
789
+ break;
790
+ }
791
+ if (toolPart && isToolPart(toolPart)) {
792
+ const { toolName, toolCallId, args } = toolPart.toolInvocation;
793
+ const providerMeta = payloadProviderMetadata ?? toolPart.providerMetadata;
794
+ const isError = chunk.type === "tool-error" || chunk.type === "background-task-failed" || payloadIsError;
795
+ if (isError) {
796
+ const error = chunk.type === "tool-error" || chunk.type === "background-task-failed" ? payloadError : payloadResult;
797
+ const errorText = typeof error === "string" ? error : error instanceof Error ? error.message : error?.message ?? String(error);
798
+ parts[toolPartIndex] = {
799
+ ...toolPart,
800
+ providerMetadata: providerMeta,
801
+ toolInvocation: {
802
+ state: "output-error",
803
+ toolCallId,
804
+ toolName,
805
+ args,
806
+ errorText
807
+ }
808
+ };
809
+ } else {
810
+ const resultObj = payloadResult;
811
+ const existingResult = toolPart.toolInvocation.state === "partial-call" || toolPart.toolInvocation.state === "result" ? toolPart.toolInvocation.result : void 0;
812
+ const existingLooksLikeWorkflow = Boolean(
813
+ existingResult && typeof existingResult === "object" && "steps" in existingResult
814
+ );
815
+ const isWorkflow = Boolean(resultObj?.result?.steps) || toolName?.startsWith("workflow-") || existingLooksLikeWorkflow;
816
+ const isAgent = chunk.from === "AGENT";
817
+ let output;
818
+ if (isWorkflow) {
819
+ const accumulated = existingLooksLikeWorkflow && existingResult && typeof existingResult === "object" ? existingResult : void 0;
820
+ const payloadWorkflow = resultObj?.result && typeof resultObj.result === "object" ? resultObj.result : void 0;
821
+ if (accumulated || payloadWorkflow) {
822
+ output = {
823
+ ...accumulated ?? {},
824
+ ...payloadWorkflow ?? {},
825
+ // Preserve `steps` from accumulated state when the terminal
826
+ // payload doesn't carry them.
827
+ steps: payloadWorkflow?.steps ?? accumulated?.steps ?? [],
828
+ status: payloadWorkflow?.status ?? accumulated?.status ?? "success",
829
+ // Surface the terminal scalar output without losing history.
830
+ output: payloadResult
831
+ };
832
+ } else {
833
+ output = payloadResult;
834
+ }
835
+ } else if (isAgent) {
836
+ const existingOutput = toolPart.toolInvocation.state === "result" ? toolPart.toolInvocation.result : void 0;
837
+ const existingChild = existingOutput?.childMessages;
838
+ output = existingOutput ? {
839
+ ...payloadResult,
840
+ childMessages: existingChild?.length ? existingChild : resultObj?.childMessages
841
+ } : payloadResult;
842
+ } else {
843
+ output = payloadResult;
844
+ }
845
+ parts[toolPartIndex] = {
846
+ ...toolPart,
847
+ providerMetadata: providerMeta,
848
+ toolInvocation: {
849
+ state: "result",
850
+ toolCallId,
851
+ toolName,
852
+ args,
853
+ result: output
854
+ }
855
+ };
856
+ }
857
+ }
858
+ const nextMetadata = mergeBgTaskMetadata(
859
+ targetMessage.content.metadata,
860
+ metadata.mode,
861
+ {
862
+ resetRunningCount: isBgTaskEvent,
863
+ perTaskEntry: isBgTaskEvent && payloadTaskId ? {
864
+ toolCallId: chunk.payload.toolCallId,
865
+ completedAt: payloadCompletedAt,
866
+ taskId: payloadTaskId
867
+ } : void 0
868
+ }
869
+ );
870
+ const nextMessage = {
871
+ ...targetMessage,
872
+ content: {
873
+ ...targetMessage.content,
874
+ parts,
875
+ metadata: nextMetadata
876
+ }
877
+ };
878
+ return replaceAt(result, messageIndex, nextMessage);
879
+ }
880
+ case "background-task-running": {
881
+ const location = locateToolPart(result, chunk.payload.toolCallId, true);
882
+ if (!location) return result;
883
+ const { messageIndex } = location;
884
+ const targetMessage = result[messageIndex];
885
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
886
+ const nextMetadata = mergeBgTaskMetadata(
887
+ targetMessage.content.metadata,
888
+ metadata.mode,
889
+ {
890
+ perTaskEntry: {
891
+ toolCallId: chunk.payload.toolCallId,
892
+ startedAt: chunk.payload.startedAt,
893
+ taskId: chunk.payload.taskId
894
+ }
895
+ }
896
+ );
897
+ return replaceAt(result, messageIndex, withMetadata(targetMessage, nextMetadata));
898
+ }
899
+ case "tool-output":
900
+ case "background-task-output": {
901
+ const isBgTaskOutput = chunk.type === "background-task-output";
902
+ const location = locateToolPart(result, chunk.payload.toolCallId, isBgTaskOutput);
903
+ if (!location || location.toolPartIndex < 0) return result;
904
+ const { messageIndex, toolPartIndex } = location;
905
+ const targetMessage = result[messageIndex];
906
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
907
+ const parts = [...targetMessage.content.parts];
908
+ const toolPart = parts[toolPartIndex];
909
+ if (!isToolPart(toolPart)) return result;
910
+ const { toolName, toolCallId, args } = toolPart.toolInvocation;
911
+ const payloadOutput = chunk.type === "background-task-output" ? chunk.payload.payload.payload.output : chunk.payload.output;
912
+ if (payloadOutput?.type?.startsWith("workflow-")) {
913
+ const existingWorkflowState = toolPart.toolInvocation.result || {};
914
+ const updated = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, payloadOutput);
915
+ parts[toolPartIndex] = {
916
+ ...toolPart,
917
+ toolInvocation: {
918
+ state: "partial-call",
919
+ toolCallId,
920
+ toolName,
921
+ args,
922
+ result: updated
923
+ }
924
+ };
925
+ } else if (payloadOutput?.from === "AGENT" || payloadOutput?.from === "USER" && payloadOutput?.payload?.output?.type?.startsWith("workflow-")) {
926
+ return accumulateAgentChunk(payloadOutput, result, metadata, toolCallId, toolName);
927
+ } else {
928
+ const currentResult = toolPart.toolInvocation.result;
929
+ const existing = Array.isArray(currentResult) ? currentResult : [];
930
+ parts[toolPartIndex] = {
931
+ ...toolPart,
932
+ toolInvocation: {
933
+ state: "partial-call",
934
+ toolCallId,
935
+ toolName,
936
+ args,
937
+ result: [...existing, payloadOutput]
938
+ }
939
+ };
940
+ }
941
+ return replaceAt(result, messageIndex, withParts(targetMessage, parts));
942
+ }
943
+ case "is-task-complete": {
944
+ if (chunk.payload.suppressFeedback) return result;
945
+ const feedback = formatStreamCompletionFeedback(
946
+ {
947
+ complete: chunk.payload.passed,
948
+ scorers: chunk.payload.results,
949
+ totalDuration: chunk.payload.duration,
950
+ timedOut: chunk.payload.timedOut},
951
+ chunk.payload.maxIterationReached
952
+ );
953
+ const newMessage = newAssistantMessage(
954
+ `is-task-complete-${chunk.runId + Date.now()}`,
955
+ [{ type: "text", text: feedback }],
956
+ {
957
+ ...metadata,
958
+ completionResult: { passed: chunk.payload.passed }
959
+ }
960
+ );
961
+ return [...result, newMessage];
962
+ }
963
+ case "source": {
964
+ const lastMessage = result[result.length - 1];
965
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
966
+ const parts = [...lastMessage.content.parts];
967
+ if (chunk.payload.sourceType === "url") {
968
+ const sourceUrlPart = {
969
+ type: "source-url",
970
+ sourceId: chunk.payload.id,
971
+ url: chunk.payload.url || "",
972
+ title: chunk.payload.title,
973
+ providerMetadata: chunk.payload.providerMetadata
974
+ };
975
+ parts.push(sourceUrlPart);
976
+ } else if (chunk.payload.sourceType === "document") {
977
+ parts.push({
978
+ type: "source-document",
979
+ sourceId: chunk.payload.id,
980
+ mediaType: chunk.payload.mimeType || "application/octet-stream",
981
+ title: chunk.payload.title,
982
+ filename: chunk.payload.filename,
983
+ providerMetadata: chunk.payload.providerMetadata
984
+ });
985
+ }
986
+ return replaceLast(result, withParts(lastMessage, parts));
987
+ }
988
+ case "file": {
989
+ const lastMessage = result[result.length - 1];
990
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
991
+ const parts = [...lastMessage.content.parts];
992
+ let url;
993
+ if (typeof chunk.payload.data === "string") {
994
+ url = chunk.payload.base64 ? `data:${chunk.payload.mimeType};base64,${chunk.payload.data}` : `data:${chunk.payload.mimeType},${encodeURIComponent(chunk.payload.data)}`;
995
+ } else {
996
+ const base64 = btoa(String.fromCharCode(...chunk.payload.data));
997
+ url = `data:${chunk.payload.mimeType};base64,${base64}`;
998
+ }
999
+ parts.push({
1000
+ type: "file",
1001
+ mediaType: chunk.payload.mimeType,
1002
+ url,
1003
+ providerMetadata: chunk.payload.providerMetadata
1004
+ });
1005
+ return replaceLast(result, withParts(lastMessage, parts));
1006
+ }
1007
+ case "tool-call-approval": {
1008
+ const lastMessage = result[result.length - 1];
1009
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
1010
+ const existingMeta = lastMessage.content.metadata ?? {};
1011
+ const lastRequireApproval = existingMeta.mode === "stream" ? existingMeta.requireApprovalMetadata ?? {} : {};
1012
+ return replaceLast(result, {
1013
+ ...lastMessage,
1014
+ content: {
1015
+ ...lastMessage.content,
1016
+ metadata: {
1017
+ ...existingMeta,
1018
+ mode: "stream",
1019
+ requireApprovalMetadata: {
1020
+ ...lastRequireApproval,
1021
+ [chunk.payload.toolName]: {
1022
+ toolCallId: chunk.payload.toolCallId,
1023
+ toolName: chunk.payload.toolName,
1024
+ args: chunk.payload.args
1025
+ }
1026
+ }
1027
+ }
1028
+ }
1029
+ });
1030
+ }
1031
+ case "tool-call-suspended":
1032
+ case "background-task-suspended": {
1033
+ const isBgTaskEvent = chunk.type === "background-task-suspended";
1034
+ let suspToolCallId;
1035
+ let suspToolName;
1036
+ let suspArgs;
1037
+ let suspPayload;
1038
+ let suspSuspendedAt;
1039
+ let suspTaskId;
1040
+ if (chunk.type === "background-task-suspended") {
1041
+ suspToolCallId = chunk.payload.toolCallId;
1042
+ suspToolName = chunk.payload.toolName;
1043
+ suspArgs = chunk.payload.args;
1044
+ suspPayload = chunk.payload.suspendPayload;
1045
+ suspSuspendedAt = chunk.payload.suspendedAt;
1046
+ suspTaskId = chunk.payload.taskId;
1047
+ } else {
1048
+ suspToolCallId = chunk.payload.toolCallId;
1049
+ suspToolName = chunk.payload.toolName;
1050
+ suspArgs = chunk.payload.args;
1051
+ suspPayload = chunk.payload.suspendPayload;
1052
+ }
1053
+ const location = isBgTaskEvent ? locateToolPart(result, suspToolCallId, true) : { messageIndex: result.length - 1 };
1054
+ if (!location) return result;
1055
+ const { messageIndex } = location;
1056
+ const targetMessage = result[messageIndex];
1057
+ if (!targetMessage || targetMessage.role !== "assistant") return result;
1058
+ const existingMeta = targetMessage.content.metadata ?? {};
1059
+ const lastSuspendedTools = existingMeta.mode === "stream" ? existingMeta.suspendedTools ?? {} : {};
1060
+ const nextMetadata = mergeBgTaskMetadata(
1061
+ existingMeta,
1062
+ "stream",
1063
+ {
1064
+ resetRunningCount: isBgTaskEvent,
1065
+ perTaskEntry: isBgTaskEvent && suspTaskId ? {
1066
+ toolCallId: suspToolCallId,
1067
+ suspendedAt: suspSuspendedAt,
1068
+ taskId: suspTaskId
1069
+ } : void 0
1070
+ },
1071
+ {
1072
+ suspendedTools: {
1073
+ ...lastSuspendedTools,
1074
+ [suspToolName]: {
1075
+ toolCallId: suspToolCallId,
1076
+ toolName: suspToolName,
1077
+ args: suspArgs,
1078
+ suspendPayload: suspPayload,
1079
+ runId: chunk.runId
1080
+ }
1081
+ }
1082
+ }
1083
+ );
1084
+ return replaceAt(result, messageIndex, withMetadata(targetMessage, nextMetadata));
1085
+ }
1086
+ case "finish":
1087
+ case "abort": {
1088
+ return finishStreamingAssistantMessage(result);
1089
+ }
1090
+ case "error": {
1091
+ const newMessage = newAssistantMessage(
1092
+ `error-${chunk.runId + Date.now()}`,
1093
+ [
1094
+ {
1095
+ type: "text",
1096
+ text: typeof chunk.payload.error === "string" ? chunk.payload.error : JSON.stringify(chunk.payload.error)
1097
+ }
1098
+ ],
1099
+ {
1100
+ ...metadata,
1101
+ status: "error"
1102
+ }
1103
+ );
1104
+ return [...result, newMessage];
1105
+ }
1106
+ // ----- Lifecycle / step / framing chunks (not surfaced on DB messages) -----
1107
+ case "step-start":
1108
+ case "step-finish":
1109
+ case "step-output":
1110
+ case "raw":
1111
+ case "watch":
1112
+ case "response-metadata":
1113
+ return result;
1114
+ // ----- Goal evaluation signal (feedback is already injected into the
1115
+ // message history by the core goal step; the chunk is a consumer-only
1116
+ // signal and is not surfaced as its own DB message). -----
1117
+ case "goal":
1118
+ return result;
1119
+ // ----- Object chunks (object/object-result are not stored on DB messages) -----
1120
+ case "object":
1121
+ case "object-result":
1122
+ return result;
1123
+ // ----- Background-task lifecycle markers not folded into messages -----
1124
+ case "background-task-started":
1125
+ case "background-task-cancelled":
1126
+ case "background-task-resumed":
1127
+ return result;
1128
+ // ----- Workflow lifecycle passthroughs (handled by mapWorkflowStreamChunkToWatchResult inside tool-output) -----
1129
+ case "workflow-start":
1130
+ case "workflow-finish":
1131
+ case "workflow-canceled":
1132
+ case "workflow-paused":
1133
+ case "workflow-step-start":
1134
+ case "workflow-step-finish":
1135
+ case "workflow-step-suspended":
1136
+ case "workflow-step-waiting":
1137
+ case "workflow-step-output":
1138
+ case "workflow-step-progress":
1139
+ case "workflow-step-result":
1140
+ return result;
1141
+ // ----- Nested-execution / routing / network passthroughs -----
1142
+ case "agent-execution-start":
1143
+ case "agent-execution-approval":
1144
+ case "agent-execution-suspended":
1145
+ case "agent-execution-end":
1146
+ case "agent-execution-abort":
1147
+ case "tool-execution-start":
1148
+ case "tool-execution-end":
1149
+ case "tool-execution-approval":
1150
+ case "tool-execution-suspended":
1151
+ case "tool-execution-abort":
1152
+ case "routing-agent-start":
1153
+ case "routing-agent-text-delta":
1154
+ case "routing-agent-text-start":
1155
+ case "routing-agent-end":
1156
+ case "routing-agent-abort":
1157
+ case "workflow-execution-start":
1158
+ case "workflow-execution-end":
1159
+ case "workflow-execution-suspended":
1160
+ case "workflow-execution-abort":
1161
+ case "network-execution-event-step-finish":
1162
+ case "network-execution-event-finish":
1163
+ case "network-validation-start":
1164
+ case "network-validation-end":
1165
+ case "network-object":
1166
+ case "network-object-result":
1167
+ return result;
1168
+ default:
1169
+ return assertExhaustive(chunk, result);
1170
+ }
1171
+ };
1172
+ var assertExhaustive = (_chunk, fallback) => fallback;
1173
+ var accumulateAgentChunk = (chunk, conversation, _metadata, parentToolCallId, parentToolName) => {
1174
+ const lastMessage = conversation[conversation.length - 1];
1175
+ if (!lastMessage || lastMessage.role !== "assistant") return conversation;
1176
+ const parts = [...lastMessage.content.parts];
1177
+ const findToolPartIndex = () => parts.findIndex(
1178
+ (part) => isToolPart(part) && (parentToolCallId && part.toolInvocation.toolCallId === parentToolCallId || parentToolName && part.toolInvocation.toolName === parentToolName)
1179
+ );
1180
+ if (chunk.type === "text-delta") {
1181
+ const agentChunk = chunk.payload;
1182
+ const toolPartIndex = findToolPartIndex();
1183
+ if (toolPartIndex === -1) return conversation;
1184
+ const toolPart = parts[toolPartIndex];
1185
+ const existingResult = toolPart.toolInvocation.result || {};
1186
+ const childMessages = existingResult.childMessages || [];
1187
+ const lastChildMessage = childMessages[childMessages.length - 1];
1188
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
1189
+ const nextChildren = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
1190
+ parts[toolPartIndex] = {
1191
+ ...toolPart,
1192
+ toolInvocation: {
1193
+ ...toolPart.toolInvocation,
1194
+ result: { ...existingResult, childMessages: nextChildren }
1195
+ }
1196
+ };
1197
+ } else if (chunk.type === "tool-call") {
1198
+ const agentChunk = chunk.payload;
1199
+ const toolPartIndex = findToolPartIndex();
1200
+ if (toolPartIndex === -1) return conversation;
1201
+ const toolPart = parts[toolPartIndex];
1202
+ const existingResult = toolPart.toolInvocation.result || {};
1203
+ const childMessages = existingResult.childMessages || [];
1204
+ parts[toolPartIndex] = {
1205
+ ...toolPart,
1206
+ toolInvocation: {
1207
+ ...toolPart.toolInvocation,
1208
+ result: {
1209
+ ...existingResult,
1210
+ childMessages: [
1211
+ ...childMessages,
1212
+ {
1213
+ type: "tool",
1214
+ toolCallId: agentChunk.toolCallId,
1215
+ toolName: agentChunk.toolName,
1216
+ args: agentChunk.args
1217
+ }
1218
+ ]
1219
+ }
1220
+ }
1221
+ };
1222
+ } else if (chunk.type === "tool-output") {
1223
+ const agentChunk = chunk.payload;
1224
+ const toolPartIndex = findToolPartIndex();
1225
+ if (toolPartIndex === -1) return conversation;
1226
+ const toolPart = parts[toolPartIndex];
1227
+ if (agentChunk?.output?.type?.startsWith("workflow-")) {
1228
+ const existingResult = toolPart.toolInvocation.result || {};
1229
+ const childMessages = existingResult.childMessages || [];
1230
+ const lastIndex = childMessages.length - 1;
1231
+ const currentMessage = childMessages[lastIndex];
1232
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
1233
+ const updated = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
1234
+ if (lastIndex >= 0 && childMessages[lastIndex]?.type === "tool") {
1235
+ parts[toolPartIndex] = {
1236
+ ...toolPart,
1237
+ toolInvocation: {
1238
+ ...toolPart.toolInvocation,
1239
+ result: {
1240
+ ...existingResult,
1241
+ childMessages: [
1242
+ ...childMessages.slice(0, -1),
1243
+ {
1244
+ ...currentMessage,
1245
+ toolOutput: { ...updated, runId: agentChunk.output.runId }
1246
+ }
1247
+ ]
1248
+ }
1249
+ }
1250
+ };
1251
+ }
1252
+ }
1253
+ } else if (chunk.type === "tool-result") {
1254
+ const agentChunk = chunk.payload;
1255
+ const toolPartIndex = findToolPartIndex();
1256
+ if (toolPartIndex === -1) return conversation;
1257
+ const toolPart = parts[toolPartIndex];
1258
+ const existingResult = toolPart.toolInvocation.result || {};
1259
+ const childMessages = existingResult.childMessages || [];
1260
+ const lastIndex = childMessages.length - 1;
1261
+ const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
1262
+ if (lastIndex >= 0 && childMessages[lastIndex]?.type === "tool") {
1263
+ parts[toolPartIndex] = {
1264
+ ...toolPart,
1265
+ toolInvocation: {
1266
+ ...toolPart.toolInvocation,
1267
+ result: {
1268
+ ...existingResult,
1269
+ childMessages: [
1270
+ ...childMessages.slice(0, -1),
1271
+ {
1272
+ ...childMessages[lastIndex],
1273
+ toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
1274
+ }
1275
+ ]
1276
+ }
1277
+ }
1278
+ };
1279
+ }
1280
+ }
1281
+ return replaceLast(conversation, withParts(lastMessage, parts));
1282
+ };
1283
+ var networkMode = (metadata) => ({ ...metadata, mode: "network" });
1284
+ var findPartIndex = (parts, predicate) => parts.findIndex(predicate);
1285
+ var isDynamicToolPart = (part) => part.type === "dynamic-tool";
1286
+ var lastAssistant = (conversation) => {
1287
+ const last = conversation[conversation.length - 1];
1288
+ return last && last.role === "assistant" ? last : void 0;
1289
+ };
1290
+ var tryParseRoutingDecision = (buffered) => {
1291
+ const trimmed = buffered.trim();
1292
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return null;
1293
+ try {
1294
+ const parsed = JSON.parse(trimmed);
1295
+ if (parsed && typeof parsed === "object") {
1296
+ return parsed;
1297
+ }
1298
+ return null;
1299
+ } catch {
1300
+ return null;
1301
+ }
1302
+ };
1303
+ var handleRoutingAgentDelta = (chunk, conversation, metadata) => {
1304
+ const delta = chunk.payload?.text ?? "";
1305
+ if (!delta) return conversation;
1306
+ const lastMessage = lastAssistant(conversation);
1307
+ const mergeRoutingMetadata = (existing) => {
1308
+ const buffered = (existing.routingDecisionBuffer ?? "") + delta;
1309
+ const next = { ...cloneMetadata(existing), mode: "network" };
1310
+ const parsed = tryParseRoutingDecision(buffered);
1311
+ if (parsed) {
1312
+ next.routingDecision = parsed;
1313
+ delete next.routingDecisionBuffer;
1314
+ delete next.routingDecisionText;
1315
+ } else {
1316
+ next.routingDecisionBuffer = buffered;
1317
+ next.routingDecisionText = buffered;
1318
+ }
1319
+ return next;
1320
+ };
1321
+ if (!lastMessage) {
1322
+ const seed = mergeRoutingMetadata({});
1323
+ return appendAssistantMessage(
1324
+ conversation,
1325
+ `routing-agent-${chunk.payload?.runId ?? "unknown"}-${Date.now()}`,
1326
+ [],
1327
+ { ...networkMode(metadata), ...seed }
1328
+ );
1329
+ }
1330
+ return replaceLast(conversation, withMetadata(lastMessage, mergeRoutingMetadata(lastMessage.content.metadata ?? {})));
1331
+ };
1332
+ var handleAgentNetworkChunk = (chunk, conversation, metadata) => {
1333
+ if (chunk.type === "agent-execution-start") {
1334
+ const primitiveId = chunk.payload?.args?.primitiveId;
1335
+ const runId = chunk.payload.runId;
1336
+ if (!primitiveId || !runId) return conversation;
1337
+ const toolPart = {
1338
+ type: "dynamic-tool",
1339
+ toolName: primitiveId,
1340
+ toolCallId: runId,
1341
+ state: "input-available",
1342
+ input: chunk.payload.args
1343
+ };
1344
+ return appendAssistantMessage(conversation, `agent-execution-start-${runId}-${Date.now()}`, [toolPart], {
1345
+ ...networkMode(metadata),
1346
+ selectionReason: chunk.payload?.args?.selectionReason || "",
1347
+ agentInput: chunk.payload?.args?.task,
1348
+ from: "AGENT"
1349
+ });
1350
+ }
1351
+ if (chunk.type === "agent-execution-end") {
1352
+ const lastMessage = lastAssistant(conversation);
1353
+ if (!lastMessage) return conversation;
1354
+ const parts = [...lastMessage.content.parts];
1355
+ const toolPartIndex = findPartIndex(parts, (part) => isDynamicToolPart(part));
1356
+ if (toolPartIndex !== -1) {
1357
+ const toolPart = parts[toolPartIndex];
1358
+ const currentOutput = toolPart.output;
1359
+ parts[toolPartIndex] = {
1360
+ type: "dynamic-tool",
1361
+ toolName: toolPart.toolName,
1362
+ toolCallId: toolPart.toolCallId,
1363
+ state: "output-available",
1364
+ input: toolPart.input,
1365
+ output: { ...currentOutput, result: currentOutput?.result || chunk.payload?.result || "" }
1366
+ };
1367
+ }
1368
+ return replaceLast(conversation, withParts(lastMessage, parts));
1369
+ }
1370
+ if (chunk.type.startsWith("agent-execution-event-")) {
1371
+ const lastMessage = lastAssistant(conversation);
1372
+ if (!lastMessage) return conversation;
1373
+ const agentChunk = chunk.payload;
1374
+ const parts = [...lastMessage.content.parts];
1375
+ const toolPartIndex = findPartIndex(parts, (part) => isDynamicToolPart(part));
1376
+ if (toolPartIndex === -1) return conversation;
1377
+ const toolPart = parts[toolPartIndex];
1378
+ if (agentChunk.type === "text-delta") {
1379
+ const childMessages = toolPart?.output?.childMessages || [];
1380
+ const lastChildMessage = childMessages[childMessages.length - 1];
1381
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.payload.text };
1382
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
1383
+ parts[toolPartIndex] = {
1384
+ ...toolPart,
1385
+ output: { childMessages: nextMessages }
1386
+ };
1387
+ } else if (agentChunk.type === "tool-call") {
1388
+ const childMessages = toolPart?.output?.childMessages || [];
1389
+ parts[toolPartIndex] = {
1390
+ ...toolPart,
1391
+ output: {
1392
+ ...toolPart?.output,
1393
+ childMessages: [
1394
+ ...childMessages,
1395
+ {
1396
+ type: "tool",
1397
+ toolCallId: agentChunk.payload.toolCallId,
1398
+ toolName: agentChunk.payload.toolName,
1399
+ args: agentChunk.payload.args
1400
+ }
1401
+ ]
1402
+ }
1403
+ };
1404
+ } else if (agentChunk.type === "tool-output") {
1405
+ if (agentChunk.payload?.output?.type?.startsWith("workflow-")) {
1406
+ const childMessages = toolPart?.output?.childMessages || [];
1407
+ const lastToolIndex = childMessages.length - 1;
1408
+ const currentMessage = childMessages[lastToolIndex];
1409
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
1410
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
1411
+ actualExistingWorkflowState,
1412
+ agentChunk.payload.output
1413
+ );
1414
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1415
+ parts[toolPartIndex] = {
1416
+ ...toolPart,
1417
+ output: {
1418
+ ...toolPart?.output,
1419
+ childMessages: [...childMessages.slice(0, -1), { ...currentMessage, toolOutput: updatedWorkflowState }]
1420
+ }
1421
+ };
1422
+ }
1423
+ }
1424
+ } else if (agentChunk.type === "tool-result") {
1425
+ const childMessages = toolPart?.output?.childMessages || [];
1426
+ const lastToolIndex = childMessages.length - 1;
1427
+ const isWorkflow = Boolean(agentChunk.payload?.result?.result?.steps);
1428
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
1429
+ parts[toolPartIndex] = {
1430
+ ...toolPart,
1431
+ output: {
1432
+ ...toolPart?.output,
1433
+ childMessages: [
1434
+ ...childMessages.slice(0, -1),
1435
+ {
1436
+ ...childMessages[lastToolIndex],
1437
+ toolOutput: isWorkflow ? agentChunk.payload.result.result : agentChunk.payload.result
1438
+ }
1439
+ ]
1440
+ }
1441
+ };
1442
+ }
1443
+ }
1444
+ return replaceLast(conversation, withParts(lastMessage, parts));
1445
+ }
1446
+ return conversation;
1447
+ };
1448
+ var handleWorkflowNetworkChunk = (chunk, conversation, metadata) => {
1449
+ if (chunk.type === "workflow-execution-start") {
1450
+ const primitiveId = chunk.payload?.args?.primitiveId;
1451
+ const runId = chunk.payload.runId;
1452
+ if (!primitiveId || !runId) return conversation;
1453
+ let agentInput;
1454
+ try {
1455
+ agentInput = JSON.parse(chunk.payload?.args?.prompt);
1456
+ } catch {
1457
+ agentInput = chunk.payload?.args?.prompt;
1458
+ }
1459
+ const toolPart = {
1460
+ type: "dynamic-tool",
1461
+ toolName: primitiveId,
1462
+ toolCallId: runId,
1463
+ state: "input-available",
1464
+ input: chunk.payload.args
1465
+ };
1466
+ return appendAssistantMessage(conversation, `workflow-start-${runId}-${Date.now()}`, [toolPart], {
1467
+ ...networkMode(metadata),
1468
+ selectionReason: chunk.payload?.args?.selectionReason || "",
1469
+ from: "WORKFLOW",
1470
+ agentInput
1471
+ });
1472
+ }
1473
+ if (chunk.type === "workflow-execution-suspended") {
1474
+ const lastMessage = lastAssistant(conversation);
1475
+ if (!lastMessage) return conversation;
1476
+ const existing = lastMessage.content.metadata?.suspendedTools ?? {};
1477
+ return replaceLast(
1478
+ conversation,
1479
+ withMetadata(lastMessage, {
1480
+ ...cloneMetadata(lastMessage.content.metadata),
1481
+ mode: "network",
1482
+ suspendedTools: {
1483
+ ...existing,
1484
+ [chunk.payload.toolName]: {
1485
+ toolCallId: chunk.payload.toolCallId,
1486
+ toolName: chunk.payload.toolName,
1487
+ args: chunk.payload.args,
1488
+ suspendPayload: chunk.payload.suspendPayload,
1489
+ runId: chunk.payload.runId
1490
+ }
1491
+ }
1492
+ })
1493
+ );
1494
+ }
1495
+ if (chunk.type.startsWith("workflow-execution-event-")) {
1496
+ const lastMessage = lastAssistant(conversation);
1497
+ if (!lastMessage) return conversation;
1498
+ const parts = [...lastMessage.content.parts];
1499
+ const toolPartIndex = findPartIndex(parts, (part) => isDynamicToolPart(part));
1500
+ if (toolPartIndex === -1) return conversation;
1501
+ const toolPart = parts[toolPartIndex];
1502
+ const existingWorkflowState = toolPart.output || {};
1503
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(existingWorkflowState, chunk.payload);
1504
+ parts[toolPartIndex] = { ...toolPart, output: updatedWorkflowState };
1505
+ return replaceLast(conversation, withParts(lastMessage, parts));
1506
+ }
1507
+ return conversation;
1508
+ };
1509
+ var handleToolNetworkChunk = (chunk, conversation, metadata) => {
1510
+ if (chunk.type === "tool-execution-start") {
1511
+ const argsData = chunk.payload.args;
1512
+ const nestedArgs = argsData.args || {};
1513
+ const lastMessage = lastAssistant(conversation);
1514
+ const toolPart = {
1515
+ type: "dynamic-tool",
1516
+ toolName: argsData.toolName || "unknown",
1517
+ toolCallId: argsData.toolCallId || "unknown",
1518
+ state: "input-available",
1519
+ input: nestedArgs
1520
+ };
1521
+ if (!lastMessage) {
1522
+ return appendAssistantMessage(
1523
+ conversation,
1524
+ `tool-start-${chunk.payload.runId}-${Date.now()}`,
1525
+ [toolPart],
1526
+ {
1527
+ ...networkMode(metadata),
1528
+ selectionReason: metadata.mode === "network" ? metadata.selectionReason || argsData.selectionReason : "",
1529
+ agentInput: nestedArgs
1530
+ }
1531
+ );
1532
+ }
1533
+ const parts = [...lastMessage.content.parts, toolPart];
1534
+ return replaceLast(conversation, withParts(lastMessage, parts));
1535
+ }
1536
+ if (chunk.type === "tool-execution-approval") {
1537
+ const lastMessage = lastAssistant(conversation);
1538
+ if (!lastMessage) return conversation;
1539
+ const existing = lastMessage.content.metadata?.requireApprovalMetadata ?? {};
1540
+ return replaceLast(
1541
+ conversation,
1542
+ withMetadata(lastMessage, {
1543
+ ...cloneMetadata(lastMessage.content.metadata),
1544
+ mode: "network",
1545
+ requireApprovalMetadata: {
1546
+ ...existing,
1547
+ [chunk.payload.toolName]: {
1548
+ toolCallId: chunk.payload.toolCallId,
1549
+ toolName: chunk.payload.toolName,
1550
+ args: chunk.payload.args,
1551
+ runId: chunk.payload.runId
1552
+ }
1553
+ }
1554
+ })
1555
+ );
1556
+ }
1557
+ if (chunk.type === "tool-execution-suspended") {
1558
+ const lastMessage = lastAssistant(conversation);
1559
+ if (!lastMessage) return conversation;
1560
+ const existing = lastMessage.content.metadata?.suspendedTools ?? {};
1561
+ return replaceLast(
1562
+ conversation,
1563
+ withMetadata(lastMessage, {
1564
+ ...cloneMetadata(lastMessage.content.metadata),
1565
+ mode: "network",
1566
+ suspendedTools: {
1567
+ ...existing,
1568
+ [chunk.payload.toolName]: {
1569
+ toolCallId: chunk.payload.toolCallId,
1570
+ toolName: chunk.payload.toolName,
1571
+ args: chunk.payload.args,
1572
+ suspendPayload: chunk.payload.suspendPayload,
1573
+ runId: chunk.payload.runId
1574
+ }
1575
+ }
1576
+ })
1577
+ );
1578
+ }
1579
+ if (chunk.type === "tool-execution-end") {
1580
+ const lastMessage = lastAssistant(conversation);
1581
+ if (!lastMessage) return conversation;
1582
+ const parts = [...lastMessage.content.parts];
1583
+ const toolPartIndex = findPartIndex(
1584
+ parts,
1585
+ (part) => isDynamicToolPart(part) && part.toolCallId === chunk.payload.toolCallId
1586
+ );
1587
+ if (toolPartIndex !== -1) {
1588
+ const toolPart = parts[toolPartIndex];
1589
+ const currentOutput = toolPart.output;
1590
+ parts[toolPartIndex] = {
1591
+ type: "dynamic-tool",
1592
+ toolName: toolPart.toolName,
1593
+ toolCallId: toolPart.toolCallId,
1594
+ state: "output-available",
1595
+ input: toolPart.input,
1596
+ output: currentOutput?.result || chunk.payload?.result || ""
1597
+ };
1598
+ }
1599
+ return replaceLast(conversation, withParts(lastMessage, parts));
1600
+ }
1601
+ return conversation;
1602
+ };
1603
+ var accumulateNetworkChunk = ({
1604
+ chunk,
1605
+ conversation,
1606
+ metadata
1607
+ }) => {
1608
+ const newConversation = [...conversation];
1609
+ if (chunk.type === "routing-agent-text-delta") {
1610
+ return handleRoutingAgentDelta(chunk, newConversation, metadata);
1611
+ }
1612
+ if (chunk.type.startsWith("agent-execution-")) {
1613
+ return handleAgentNetworkChunk(chunk, newConversation, metadata);
1614
+ }
1615
+ if (chunk.type.startsWith("workflow-execution-")) {
1616
+ return handleWorkflowNetworkChunk(chunk, newConversation, metadata);
1617
+ }
1618
+ if (chunk.type.startsWith("tool-execution-")) {
1619
+ return handleToolNetworkChunk(chunk, newConversation, metadata);
1620
+ }
1621
+ if (chunk.type === "network-validation-end") {
1622
+ if (chunk.payload.suppressFeedback) return newConversation;
1623
+ const feedback = formatCompletionFeedback(
1624
+ {
1625
+ complete: chunk.payload.passed,
1626
+ scorers: chunk.payload.results,
1627
+ totalDuration: chunk.payload.duration,
1628
+ timedOut: chunk.payload.timedOut},
1629
+ chunk.payload.maxIterationReached
1630
+ );
1631
+ const textPart = { type: "text", text: feedback };
1632
+ return appendAssistantMessage(
1633
+ newConversation,
1634
+ `network-validation-end-${chunk.payload.runId}-${Date.now()}`,
1635
+ [textPart],
1636
+ {
1637
+ ...networkMode(metadata),
1638
+ completionResult: { passed: chunk.payload.passed }
1639
+ }
1640
+ );
1641
+ }
1642
+ if (chunk.type === "network-execution-event-step-finish") {
1643
+ const lastMessage = lastAssistant(newConversation);
1644
+ if (!lastMessage) return newConversation;
1645
+ const agentChunk = chunk.payload;
1646
+ const parts = [...lastMessage.content.parts];
1647
+ const textPartIndex = findPartIndex(parts, (part) => part.type === "text");
1648
+ if (textPartIndex === -1) {
1649
+ parts.push({ type: "text", text: agentChunk.result, state: "done" });
1650
+ return replaceLast(newConversation, withParts(lastMessage, parts));
1651
+ }
1652
+ const textPart = parts[textPartIndex];
1653
+ if (textPart.type === "text") {
1654
+ parts[textPartIndex] = {
1655
+ ...textPart,
1656
+ state: "done"
1657
+ };
1658
+ return replaceLast(newConversation, withParts(lastMessage, parts));
1659
+ }
1660
+ return newConversation;
1661
+ }
1662
+ return newConversation;
1663
+ };
1664
+
1665
+ // src/lib/mastra-db/fromCoreUserMessage.ts
1666
+ var coreUserMessageToParts = (coreUserMessage) => typeof coreUserMessage.content === "string" ? [{ type: "text", text: coreUserMessage.content }] : coreUserMessage.content.map((part) => {
1667
+ switch (part.type) {
1668
+ case "text": {
1669
+ return { type: "text", text: part.text };
1670
+ }
1671
+ case "image": {
1672
+ const data = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
1673
+ return {
1674
+ type: "file",
1675
+ mimeType: part.mimeType ?? "image/*",
1676
+ data
1677
+ };
1678
+ }
1679
+ case "file": {
1680
+ const data = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
1681
+ return {
1682
+ type: "file",
1683
+ mimeType: part.mimeType,
1684
+ data,
1685
+ ...part.filename !== void 0 ? { filename: part.filename } : {}
1686
+ };
1687
+ }
1688
+ default: {
1689
+ const exhaustiveCheck = part;
1690
+ throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
1691
+ }
1692
+ }
1693
+ });
1694
+ var newUserMessage = (parts) => ({
1695
+ id: `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
1696
+ role: "user",
1697
+ createdAt: /* @__PURE__ */ new Date(),
1698
+ content: {
1699
+ format: 2,
1700
+ parts
1701
+ }
1702
+ });
1703
+ var fromCoreUserMessageToMastraDBMessage = (coreUserMessage) => newUserMessage(coreUserMessageToParts(coreUserMessage));
1704
+ var fromCoreUserMessagesToMastraDBMessage = (coreUserMessages) => newUserMessage(coreUserMessages.flatMap(coreUserMessageToParts));
1705
+
1706
+ // src/agent/extractRunIdFromMessages.ts
1707
+ var isRecord = (value) => value !== null && typeof value === "object";
1708
+ var runIdMetadataKeys = ["pendingToolApprovals", "requireApprovalMetadata", "suspendedTools"];
1709
+ var isRunIdMetadataSource = (value) => isRecord(value) && Object.values(value).every((entry) => isRecord(entry));
1710
+ var getRunIdMetadataSources = (metadata) => {
1711
+ if (!isRecord(metadata)) return [];
1712
+ const sources = [];
1713
+ for (const key of runIdMetadataKeys) {
1714
+ const source = metadata[key];
1715
+ if (isRunIdMetadataSource(source)) {
1716
+ sources.push(source);
1717
+ }
1718
+ }
1719
+ return sources;
1720
+ };
1721
+ var extractRunIdFromMessages = (messages) => {
1722
+ for (const message of messages) {
1723
+ for (const source of getRunIdMetadataSources(message.content?.metadata)) {
1724
+ for (const entry of Object.values(source)) {
1725
+ if (isRecord(entry) && typeof entry.runId === "string" && entry.runId.length > 0) {
1726
+ return entry.runId;
1727
+ }
1728
+ }
1729
+ }
1730
+ }
1731
+ return void 0;
1732
+ };
1733
+
1734
+ // src/agent/signal-data.ts
1735
+ function convertSignalDataToBase64String(content) {
1736
+ if (typeof content === "string") {
1737
+ return content;
1738
+ }
1739
+ const bytes = content instanceof ArrayBuffer ? new Uint8Array(content) : content;
1740
+ let binary = "";
1741
+ for (const byte of bytes) {
1742
+ binary += String.fromCharCode(byte);
1743
+ }
1744
+ return btoa(binary);
1745
+ }
1746
+
1747
+ // src/agent/hooks.ts
1748
+ var extractPendingToolApprovalIdsFromMessages = (messages) => {
1749
+ const pendingToolApprovalIds = /* @__PURE__ */ new Set();
1750
+ for (const message of messages) {
1751
+ const metadata = message.content?.metadata;
1752
+ if (!metadata) continue;
1753
+ const metadataSources = [
1754
+ metadata.pendingToolApprovals,
1755
+ metadata.requireApprovalMetadata,
1756
+ metadata.suspendedTools
1757
+ ];
1758
+ for (const source of metadataSources) {
1759
+ if (!source || typeof source !== "object") continue;
1760
+ for (const suspensionData of Object.values(source)) {
1761
+ const toolCallId = suspensionData?.toolCallId;
1762
+ if (typeof toolCallId === "string" && toolCallId.length > 0) {
1763
+ pendingToolApprovalIds.add(toolCallId);
1764
+ }
1765
+ }
1766
+ }
1767
+ }
1768
+ return pendingToolApprovalIds;
1769
+ };
1770
+ var toolCallHasOutput = (parts, toolCallId) => parts.some((part) => {
1771
+ if (part.type !== "tool-invocation") return false;
1772
+ const invocation = part.toolInvocation;
1773
+ if (invocation.toolCallId !== toolCallId) return false;
1774
+ return invocation.state === "result" || invocation.result != null;
1775
+ });
1776
+ var resolveInitialMessages = (messages) => messages.filter((message) => {
1777
+ const metadata = message.content?.metadata;
1778
+ if (metadata?.completionResult?.suppressFeedback || metadata?.isTaskCompleteResult?.suppressFeedback) {
1779
+ return false;
1780
+ }
1781
+ return true;
1782
+ }).map((message) => {
1783
+ const metadata = message.content?.metadata;
1784
+ const normalizedMessage = metadata && (metadata.status === "pending" || CLIENT_MESSAGE_ID_KEY in metadata) ? (() => {
1785
+ const { [CLIENT_MESSAGE_ID_KEY]: _omitClientMessageId, ...rest } = metadata;
1786
+ const { status: _omitStatus, ...restWithoutStatus } = rest;
1787
+ return {
1788
+ ...message,
1789
+ content: {
1790
+ ...message.content,
1791
+ metadata: metadata.status === "pending" ? restWithoutStatus : rest
1792
+ }
1793
+ };
1794
+ })() : message;
1795
+ const normalizedMetadata = normalizedMessage.content?.metadata;
1796
+ const pendingToolApprovals = normalizedMetadata?.pendingToolApprovals;
1797
+ if (!pendingToolApprovals || typeof pendingToolApprovals !== "object") {
1798
+ return normalizedMessage;
1799
+ }
1800
+ const stillPending = Object.fromEntries(
1801
+ Object.entries(pendingToolApprovals).filter(
1802
+ ([, approval]) => approval && typeof approval === "object" && typeof approval.toolCallId === "string" && !toolCallHasOutput(normalizedMessage.content.parts, approval.toolCallId)
1803
+ )
1804
+ );
1805
+ const { pendingToolApprovals: _omit, ...restMetadata } = normalizedMetadata;
1806
+ const hasStillPending = Object.keys(stillPending).length > 0;
1807
+ return {
1808
+ ...normalizedMessage,
1809
+ content: {
1810
+ ...normalizedMessage.content,
1811
+ metadata: {
1812
+ ...restMetadata,
1813
+ mode: "stream",
1814
+ ...hasStillPending ? { pendingToolApprovals: stillPending, requireApprovalMetadata: stillPending } : {}
1815
+ }
1816
+ }
1817
+ };
1818
+ });
1819
+ var isObject = (value) => typeof value === "object" && value !== null;
1820
+ var getErrorName = (error) => isObject(error) && typeof error.name === "string" ? error.name : void 0;
1821
+ var isAbortError = (error) => getErrorName(error) === "AbortError";
1822
+ var isThreadSignalUnsupportedError = (error) => {
1823
+ if (!isObject(error)) return false;
1824
+ const status = error.status;
1825
+ if (status === 404 || status === 405 || status === 501) {
1826
+ return true;
1827
+ }
1828
+ return status === 400 && typeof error.message === "string" && error.message.includes("No active agent run found for signal target");
1829
+ };
1830
+ var isDataChunk2 = (chunk) => typeof chunk.type === "string" && chunk.type.startsWith("data-");
1831
+ var dbFromServerUiMessages = (uiMessages, metadata) => uiMessages.map((uiMsg) => {
1832
+ const dbMsg = messageList.AIV5Adapter.fromUIMessage(uiMsg);
1833
+ return {
1834
+ ...dbMsg,
1835
+ content: {
1836
+ ...dbMsg.content,
1837
+ metadata: {
1838
+ ...dbMsg.content.metadata ?? {},
1839
+ ...metadata
1840
+ }
1841
+ }
1842
+ };
1843
+ });
1844
+ var useChat = ({
1845
+ agentId,
1846
+ resourceId,
1847
+ threadId,
1848
+ initialMessages,
1849
+ requestContext: propsRequestContext,
1850
+ clientTools: hookClientTools,
1851
+ onSignalSent,
1852
+ onSignalEcho,
1853
+ onThreadSignalsUnsupported,
1854
+ enableThreadSignals = false
1855
+ }) => {
1856
+ const threadSignalsDisabled = enableThreadSignals === false;
1857
+ const _currentRunId = react.useRef(void 0);
1858
+ const _onChunk = react.useRef(void 0);
1859
+ const _networkRunId = react.useRef(void 0);
1860
+ const _onNetworkChunk = react.useRef(void 0);
1861
+ const _requestContext = react.useRef(propsRequestContext);
1862
+ const _streamAbortRef = react.useRef(null);
1863
+ const _threadSubscriptionAbortRef = react.useRef(null);
1864
+ const _threadSubscriptionRef = react.useRef(
1865
+ null
1866
+ );
1867
+ const _threadSubscriptionKeyRef = react.useRef(void 0);
1868
+ const _threadSubscriptionPromiseRef = react.useRef(null);
1869
+ const _threadSignalsUnsupportedRef = react.useRef(false);
1870
+ const [messages, setMessages] = react.useState([]);
1871
+ const [toolCallApprovals, setToolCallApprovals] = react.useState({});
1872
+ const [networkToolCallApprovals, setNetworkToolCallApprovals] = react.useState({});
1873
+ const pendingToolApprovalIdsRef = react.useRef(/* @__PURE__ */ new Set());
1874
+ const [isAwaitingToolApproval, setIsAwaitingToolApproval] = react.useState(false);
1875
+ const baseClient = useMastraClient();
1876
+ const [isRunning, setIsRunning] = react.useState(false);
1877
+ react.useEffect(() => {
1878
+ const formattedMessages = resolveInitialMessages(initialMessages ?? []);
1879
+ setMessages(formattedMessages);
1880
+ pendingToolApprovalIdsRef.current = extractPendingToolApprovalIdsFromMessages(formattedMessages);
1881
+ setIsAwaitingToolApproval(pendingToolApprovalIdsRef.current.size > 0);
1882
+ _currentRunId.current = extractRunIdFromMessages(formattedMessages);
1883
+ }, [initialMessages]);
1884
+ react.useEffect(() => {
1885
+ _requestContext.current = propsRequestContext;
1886
+ }, [propsRequestContext]);
1887
+ const normalizeSignalFileData = (data) => {
1888
+ if (data instanceof URL) return data.toString();
1889
+ return convertSignalDataToBase64String(data);
1890
+ };
1891
+ const getSignalContents = (coreUserMessages) => {
1892
+ const parts = coreUserMessages.reduce((allParts, message) => {
1893
+ if (typeof message.content === "string") {
1894
+ allParts.push({ type: "text", text: message.content });
1895
+ return allParts;
1896
+ }
1897
+ for (const part of message.content) {
1898
+ if (part.type === "text") {
1899
+ allParts.push({ type: "text", text: part.text });
1900
+ } else if (part.type === "file") {
1901
+ allParts.push({
1902
+ type: "file",
1903
+ data: normalizeSignalFileData(part.data),
1904
+ mediaType: part.mimeType,
1905
+ ...part.filename ? { filename: part.filename } : {}
1906
+ });
1907
+ } else if (part.type === "image") {
1908
+ allParts.push({
1909
+ type: "file",
1910
+ data: normalizeSignalFileData(part.image),
1911
+ mediaType: part.mimeType ?? "image/png"
1912
+ });
1913
+ }
1914
+ }
1915
+ return allParts;
1916
+ }, []);
1917
+ return parts.length === 1 && parts[0]?.type === "text" ? parts[0].text : parts;
1918
+ };
1919
+ const markThreadSignalsUnsupported = react.useCallback(() => {
1920
+ _threadSignalsUnsupportedRef.current = true;
1921
+ onThreadSignalsUnsupported?.();
1922
+ }, [onThreadSignalsUnsupported]);
1923
+ const getSignalPreview = (coreUserMessages) => {
1924
+ const preview = coreUserMessages.flatMap((message) => {
1925
+ if (typeof message.content === "string") {
1926
+ return [message.content];
1927
+ }
1928
+ return message.content.map((part) => {
1929
+ if (part.type === "text") return part.text;
1930
+ if (part.type === "image") return "Image";
1931
+ return part.filename ? `File: ${part.filename}` : "File";
1932
+ });
1933
+ }).join(" ").replace(/\s+/g, " ").trim();
1934
+ return preview || "Attachment";
1935
+ };
1936
+ const closeThreadSubscription = react.useCallback(() => {
1937
+ const subscription = _threadSubscriptionRef.current;
1938
+ if (subscription?.unsubscribe) {
1939
+ subscription.unsubscribe();
1940
+ } else {
1941
+ _threadSubscriptionAbortRef.current?.abort();
1942
+ }
1943
+ _threadSubscriptionRef.current = null;
1944
+ _threadSubscriptionAbortRef.current = null;
1945
+ _threadSubscriptionKeyRef.current = void 0;
1946
+ _threadSubscriptionPromiseRef.current = null;
1947
+ }, []);
1948
+ const processStreamChunk = react.useCallback(
1949
+ async (chunk, onChunk) => {
1950
+ setMessages((prev) => accumulateChunk({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1951
+ if (chunk.type === "data-user-message" && isDataChunk2(chunk) && (chunk.data?.type === "user-message" || chunk.data?.type === "user") && typeof chunk.data?.id === "string") {
1952
+ onSignalEcho?.(chunk.data.id);
1953
+ }
1954
+ if (chunk.type === "start") {
1955
+ setIsRunning(true);
1956
+ if ("runId" in chunk && typeof chunk.runId === "string") {
1957
+ _currentRunId.current = chunk.runId;
1958
+ }
1959
+ }
1960
+ if (chunk.type === "tool-call-approval" || chunk.type === "tool-call-suspended") {
1961
+ const toolCallId = chunk.payload?.toolCallId;
1962
+ if (typeof toolCallId === "string") {
1963
+ pendingToolApprovalIdsRef.current.add(toolCallId);
1964
+ setIsAwaitingToolApproval(true);
1965
+ }
1966
+ setIsRunning(false);
1967
+ }
1968
+ if (chunk.type === "finish" || chunk.type === "abort" || chunk.type === "error") {
1969
+ pendingToolApprovalIdsRef.current.clear();
1970
+ setIsAwaitingToolApproval(false);
1971
+ setIsRunning(false);
1972
+ }
1973
+ void (onChunk ?? _onChunk.current)?.(chunk);
1974
+ },
1975
+ [onSignalEcho]
1976
+ );
1977
+ const ensureThreadSubscription = react.useCallback(
1978
+ async ({ threadId: threadId2, resourceId: resourceId2 }) => {
1979
+ const subscriptionKey = `${agentId}:${resourceId2 ?? ""}:${threadId2}`;
1980
+ if (_threadSubscriptionKeyRef.current === subscriptionKey && _threadSubscriptionPromiseRef.current) {
1981
+ await _threadSubscriptionPromiseRef.current;
1982
+ return;
1983
+ }
1984
+ closeThreadSubscription();
1985
+ const subscriptionAbort = new AbortController();
1986
+ _threadSubscriptionAbortRef.current = subscriptionAbort;
1987
+ _threadSubscriptionKeyRef.current = subscriptionKey;
1988
+ const clientWithAbort = new clientJs.MastraClient({
1989
+ ...baseClient.options,
1990
+ abortSignal: subscriptionAbort.signal
1991
+ });
1992
+ const subscriptionAgent = clientWithAbort.getAgent(agentId);
1993
+ _threadSubscriptionPromiseRef.current = subscriptionAgent.subscribeToThread({ resourceId: resourceId2, threadId: threadId2 }).then((response) => {
1994
+ const subscription = response;
1995
+ if (_threadSubscriptionAbortRef.current !== subscriptionAbort) {
1996
+ subscription.unsubscribe();
1997
+ return;
1998
+ }
1999
+ _threadSubscriptionRef.current = subscription;
2000
+ void subscription.processDataStream({
2001
+ onChunk: (chunk) => processStreamChunk(chunk)
2002
+ }).catch((error) => {
2003
+ if (!isAbortError(error)) {
2004
+ console.error("[useChat] Thread subscription failed", error);
2005
+ setIsRunning(false);
2006
+ }
2007
+ }).finally(() => {
2008
+ if (_threadSubscriptionRef.current === subscription) {
2009
+ _threadSubscriptionRef.current = null;
2010
+ }
2011
+ if (_threadSubscriptionAbortRef.current === subscriptionAbort) {
2012
+ _threadSubscriptionAbortRef.current = null;
2013
+ _threadSubscriptionKeyRef.current = void 0;
2014
+ _threadSubscriptionPromiseRef.current = null;
2015
+ }
2016
+ });
2017
+ }).catch((error) => {
2018
+ if (isThreadSignalUnsupportedError(error)) {
2019
+ markThreadSignalsUnsupported();
2020
+ if (_threadSubscriptionAbortRef.current === subscriptionAbort) {
2021
+ _threadSubscriptionRef.current = null;
2022
+ _threadSubscriptionAbortRef.current = null;
2023
+ _threadSubscriptionKeyRef.current = void 0;
2024
+ _threadSubscriptionPromiseRef.current = null;
2025
+ }
2026
+ return;
2027
+ }
2028
+ if (!isAbortError(error)) {
2029
+ console.error("[useChat] Thread subscription failed", error);
2030
+ setIsRunning(false);
2031
+ }
2032
+ throw error;
2033
+ });
2034
+ await _threadSubscriptionPromiseRef.current;
2035
+ },
2036
+ [agentId, baseClient, closeThreadSubscription, markThreadSignalsUnsupported, processStreamChunk]
2037
+ );
2038
+ react.useEffect(() => {
2039
+ _threadSignalsUnsupportedRef.current = false;
2040
+ return closeThreadSubscription;
2041
+ }, [agentId, resourceId, threadId, closeThreadSubscription]);
2042
+ react.useEffect(() => {
2043
+ if (!threadId || threadSignalsDisabled) {
2044
+ closeThreadSubscription();
2045
+ return;
2046
+ }
2047
+ void ensureThreadSubscription({ threadId, resourceId: resourceId || agentId }).catch((error) => {
2048
+ if (!isAbortError(error)) {
2049
+ console.error("[useChat] Thread subscription failed", error);
2050
+ }
2051
+ });
2052
+ }, [agentId, closeThreadSubscription, ensureThreadSubscription, resourceId, threadId, threadSignalsDisabled]);
2053
+ const generate = async ({
2054
+ coreUserMessages,
2055
+ requestContext,
2056
+ threadId: threadId2,
2057
+ modelSettings,
2058
+ signal,
2059
+ onFinish,
2060
+ tracingOptions,
2061
+ clientTools
2062
+ }) => {
2063
+ const {
2064
+ frequencyPenalty,
2065
+ presencePenalty,
2066
+ maxRetries,
2067
+ maxTokens,
2068
+ temperature,
2069
+ topK,
2070
+ topP,
2071
+ instructions,
2072
+ providerOptions,
2073
+ maxSteps,
2074
+ requireToolApproval
2075
+ } = modelSettings || {};
2076
+ const resolvedRequestContext = requestContext ?? propsRequestContext;
2077
+ const resolvedClientTools = clientTools ?? hookClientTools;
2078
+ _requestContext.current = resolvedRequestContext;
2079
+ setIsRunning(true);
2080
+ const clientWithAbort = new clientJs.MastraClient({
2081
+ ...baseClient.options,
2082
+ abortSignal: signal
2083
+ });
2084
+ const agent = clientWithAbort.getAgent(agentId);
2085
+ const runId = uuid.v4();
2086
+ _currentRunId.current = runId;
2087
+ const response = await agent.generate(coreUserMessages, {
2088
+ runId,
2089
+ maxSteps,
2090
+ modelSettings: {
2091
+ frequencyPenalty,
2092
+ presencePenalty,
2093
+ maxRetries,
2094
+ maxOutputTokens: maxTokens,
2095
+ temperature,
2096
+ topK,
2097
+ topP
2098
+ },
2099
+ instructions,
2100
+ requestContext: resolvedRequestContext,
2101
+ ...threadId2 ? { memory: { thread: threadId2, resource: resourceId || agentId } } : {},
2102
+ providerOptions,
2103
+ tracingOptions,
2104
+ requireToolApproval,
2105
+ clientTools: resolvedClientTools
2106
+ });
2107
+ if (response.finishReason === "suspended" && response.suspendPayload) {
2108
+ const { toolCallId, toolName, args } = response.suspendPayload;
2109
+ if (response.response?.uiMessages) {
2110
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, {
2111
+ mode: "generate",
2112
+ requireApprovalMetadata: {
2113
+ [toolName]: { toolCallId, toolName, args }
2114
+ }
2115
+ });
2116
+ setMessages((prev) => [...prev, ...dbMessages]);
2117
+ }
2118
+ setIsRunning(false);
2119
+ return;
2120
+ }
2121
+ setIsRunning(false);
2122
+ if (response && "uiMessages" in response.response && response.response.uiMessages) {
2123
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, { mode: "generate" });
2124
+ void onFinish?.(dbMessages);
2125
+ setMessages((prev) => [...prev, ...dbMessages]);
2126
+ }
2127
+ };
2128
+ const stream = async ({
2129
+ coreUserMessages,
2130
+ requestContext,
2131
+ threadId: threadId2,
2132
+ onChunk,
2133
+ modelSettings,
2134
+ signal,
2135
+ tracingOptions,
2136
+ clientTools,
2137
+ signalId,
2138
+ clientMessageId
2139
+ }) => {
2140
+ const {
2141
+ frequencyPenalty,
2142
+ presencePenalty,
2143
+ maxRetries,
2144
+ maxTokens,
2145
+ temperature,
2146
+ topK,
2147
+ topP,
2148
+ instructions,
2149
+ providerOptions,
2150
+ maxSteps,
2151
+ requireToolApproval
2152
+ } = modelSettings || {};
2153
+ const resolvedRequestContext = requestContext ?? propsRequestContext;
2154
+ const resolvedClientTools = clientTools ?? hookClientTools;
2155
+ const signalContinuationOptions = {
2156
+ maxSteps,
2157
+ modelSettings: {
2158
+ frequencyPenalty,
2159
+ presencePenalty,
2160
+ maxRetries,
2161
+ maxOutputTokens: maxTokens,
2162
+ temperature,
2163
+ topK,
2164
+ topP
2165
+ },
2166
+ instructions,
2167
+ providerOptions,
2168
+ requireToolApproval,
2169
+ tracingOptions
2170
+ };
2171
+ _requestContext.current = resolvedRequestContext;
2172
+ setIsRunning(true);
2173
+ _streamAbortRef.current?.abort();
2174
+ const internalAbort = new AbortController();
2175
+ _streamAbortRef.current = internalAbort;
2176
+ if (signal) {
2177
+ if (signal.aborted) internalAbort.abort();
2178
+ else signal.addEventListener("abort", () => internalAbort.abort(), { once: true });
2179
+ }
2180
+ const clientWithAbort = new clientJs.MastraClient({
2181
+ ...baseClient.options,
2182
+ abortSignal: internalAbort.signal
2183
+ });
2184
+ const agent = clientWithAbort.getAgent(agentId);
2185
+ const streamWithLegacyRoute = async () => {
2186
+ const runId = uuid.v4();
2187
+ const response = await agent.stream(coreUserMessages, {
2188
+ runId,
2189
+ maxSteps,
2190
+ untilIdle: true,
2191
+ modelSettings: {
2192
+ frequencyPenalty,
2193
+ presencePenalty,
2194
+ maxRetries,
2195
+ maxOutputTokens: maxTokens,
2196
+ temperature,
2197
+ topK,
2198
+ topP
2199
+ },
2200
+ instructions,
2201
+ requestContext: resolvedRequestContext,
2202
+ ...threadId2 ? { memory: { thread: threadId2, resource: resourceId || agentId } } : {},
2203
+ providerOptions,
2204
+ requireToolApproval,
2205
+ tracingOptions,
2206
+ clientTools: resolvedClientTools
2207
+ });
2208
+ _onChunk.current = onChunk;
2209
+ _currentRunId.current = runId;
2210
+ await response.processDataStream({
2211
+ onChunk: (chunk) => processStreamChunk(chunk, onChunk)
2212
+ });
2213
+ if (_streamAbortRef.current === internalAbort) {
2214
+ _streamAbortRef.current = null;
2215
+ }
2216
+ setIsRunning(false);
2217
+ };
2218
+ if (!threadId2 || _threadSignalsUnsupportedRef.current || threadSignalsDisabled) {
2219
+ await streamWithLegacyRoute();
2220
+ return;
2221
+ }
2222
+ _onChunk.current = onChunk;
2223
+ await ensureThreadSubscription({ threadId: threadId2, resourceId: resourceId || agentId });
2224
+ if (_threadSignalsUnsupportedRef.current) {
2225
+ await streamWithLegacyRoute();
2226
+ return;
2227
+ }
2228
+ const resolvedSignalId = signalId ?? uuid.v4();
2229
+ const messageContents = getSignalContents(coreUserMessages);
2230
+ const streamOptions = {
2231
+ maxSteps,
2232
+ modelSettings: {
2233
+ frequencyPenalty,
2234
+ presencePenalty,
2235
+ maxRetries,
2236
+ maxOutputTokens: maxTokens,
2237
+ temperature,
2238
+ topK,
2239
+ topP
2240
+ },
2241
+ instructions,
2242
+ requestContext: resolvedRequestContext,
2243
+ providerOptions,
2244
+ requireToolApproval,
2245
+ tracingOptions
2246
+ };
2247
+ try {
2248
+ const result = await agent.sendMessage({
2249
+ message: clientMessageId ? { contents: messageContents, metadata: { [CLIENT_MESSAGE_ID_KEY]: clientMessageId } } : messageContents,
2250
+ resourceId: resourceId || agentId,
2251
+ threadId: threadId2,
2252
+ ifIdle: {
2253
+ streamOptions: {
2254
+ ...signalContinuationOptions,
2255
+ requestContext: resolvedRequestContext,
2256
+ clientTools: resolvedClientTools
2257
+ }
2258
+ }
2259
+ });
2260
+ const echoedSignalId = result.signal && typeof result.signal === "object" && "id" in result.signal && typeof result.signal.id === "string" ? result.signal.id : resolvedSignalId;
2261
+ onSignalSent?.(echoedSignalId, getSignalPreview(coreUserMessages));
2262
+ if (pendingToolApprovalIdsRef.current.size > 0) {
2263
+ setIsRunning(false);
2264
+ }
2265
+ } catch (error) {
2266
+ if (isThreadSignalUnsupportedError(error)) {
2267
+ onSignalSent?.(resolvedSignalId, getSignalPreview(coreUserMessages));
2268
+ try {
2269
+ await agent.sendSignal({
2270
+ signal: {
2271
+ id: resolvedSignalId,
2272
+ type: "user-message",
2273
+ contents: messageContents
2274
+ },
2275
+ resourceId: resourceId || agentId,
2276
+ threadId: threadId2,
2277
+ ifIdle: { streamOptions }
2278
+ });
2279
+ return;
2280
+ } catch (signalError) {
2281
+ onSignalEcho?.(resolvedSignalId);
2282
+ if (isThreadSignalUnsupportedError(signalError)) {
2283
+ markThreadSignalsUnsupported();
2284
+ setMessages((prev) => [...prev, fromCoreUserMessagesToMastraDBMessage(coreUserMessages)]);
2285
+ await streamWithLegacyRoute();
2286
+ return;
2287
+ }
2288
+ throw signalError;
2289
+ }
2290
+ }
2291
+ throw error;
2292
+ }
2293
+ if (_streamAbortRef.current === internalAbort) {
2294
+ _streamAbortRef.current = null;
2295
+ }
2296
+ };
2297
+ const network = async ({
2298
+ coreUserMessages,
2299
+ requestContext,
2300
+ threadId: threadId2,
2301
+ onNetworkChunk,
2302
+ modelSettings,
2303
+ signal,
2304
+ tracingOptions
2305
+ }) => {
2306
+ const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
2307
+ const resolvedRequestContext = requestContext ?? propsRequestContext;
2308
+ _requestContext.current = resolvedRequestContext;
2309
+ setIsRunning(true);
2310
+ const clientWithAbort = new clientJs.MastraClient({
2311
+ ...baseClient.options,
2312
+ abortSignal: signal
2313
+ });
2314
+ const agent = clientWithAbort.getAgent(agentId);
2315
+ const runId = uuid.v4();
2316
+ const response = await agent.network(coreUserMessages, {
2317
+ maxSteps,
2318
+ modelSettings: {
2319
+ frequencyPenalty,
2320
+ presencePenalty,
2321
+ maxRetries,
2322
+ maxOutputTokens: maxTokens,
2323
+ temperature,
2324
+ topK,
2325
+ topP
2326
+ },
2327
+ runId,
2328
+ requestContext: resolvedRequestContext,
2329
+ ...threadId2 ? { memory: { thread: threadId2, resource: resourceId || agentId } } : {},
2330
+ tracingOptions
2331
+ });
2332
+ _onNetworkChunk.current = onNetworkChunk;
2333
+ _networkRunId.current = runId;
2334
+ await response.processDataStream({
2335
+ onChunk: async (chunk) => {
2336
+ setMessages((prev) => accumulateNetworkChunk({ chunk, conversation: prev, metadata: { mode: "network" } }));
2337
+ void onNetworkChunk?.(chunk);
2338
+ }
2339
+ });
2340
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2341
+ setIsRunning(false);
2342
+ };
2343
+ const handleCancelRun = () => {
2344
+ _streamAbortRef.current?.abort();
2345
+ _streamAbortRef.current = null;
2346
+ const threadSubscription = _threadSubscriptionRef.current;
2347
+ void Promise.resolve(threadSubscription?.abort?.()).catch((error) => {
2348
+ console.error("[useChat] Failed to abort thread subscription", error);
2349
+ });
2350
+ closeThreadSubscription();
2351
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2352
+ pendingToolApprovalIdsRef.current.clear();
2353
+ setIsAwaitingToolApproval(false);
2354
+ setIsRunning(false);
2355
+ _currentRunId.current = void 0;
2356
+ _onChunk.current = void 0;
2357
+ _networkRunId.current = void 0;
2358
+ _onNetworkChunk.current = void 0;
2359
+ _requestContext.current = void 0;
2360
+ };
2361
+ const approveToolCall = async (toolCallId) => {
2362
+ const onChunk = _onChunk.current;
2363
+ const currentRunId = _currentRunId.current;
2364
+ if (!currentRunId)
2365
+ return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
2366
+ setIsRunning(true);
2367
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
2368
+ const agent = baseClient.getAgent(agentId);
2369
+ if (_threadSubscriptionKeyRef.current && threadId) {
2370
+ try {
2371
+ await agent.sendToolApproval({
2372
+ resourceId: resourceId || agentId,
2373
+ threadId,
2374
+ toolCallId,
2375
+ approved: true,
2376
+ requestContext: _requestContext.current
2377
+ });
2378
+ pendingToolApprovalIdsRef.current.delete(toolCallId);
2379
+ setIsAwaitingToolApproval(pendingToolApprovalIdsRef.current.size > 0);
2380
+ setIsRunning(false);
2381
+ } catch (error) {
2382
+ setToolCallApprovals((prev) => {
2383
+ const next = { ...prev };
2384
+ delete next[toolCallId];
2385
+ return next;
2386
+ });
2387
+ setIsRunning(false);
2388
+ throw error;
2389
+ }
2390
+ return;
2391
+ }
2392
+ const response = await agent.approveToolCall({
2393
+ runId: currentRunId,
2394
+ toolCallId,
2395
+ requestContext: _requestContext.current
2396
+ });
2397
+ await response.processDataStream({
2398
+ onChunk: async (chunk) => {
2399
+ await processStreamChunk(chunk, onChunk);
2400
+ }
2401
+ });
2402
+ setIsRunning(false);
2403
+ };
2404
+ const declineToolCall = async (toolCallId) => {
2405
+ const onChunk = _onChunk.current;
2406
+ const currentRunId = _currentRunId.current;
2407
+ if (!currentRunId)
2408
+ return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
2409
+ setIsRunning(true);
2410
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
2411
+ const agent = baseClient.getAgent(agentId);
2412
+ if (_threadSubscriptionKeyRef.current && threadId) {
2413
+ try {
2414
+ await agent.sendToolApproval({
2415
+ resourceId: resourceId || agentId,
2416
+ threadId,
2417
+ toolCallId,
2418
+ approved: false,
2419
+ requestContext: _requestContext.current
2420
+ });
2421
+ pendingToolApprovalIdsRef.current.delete(toolCallId);
2422
+ setIsAwaitingToolApproval(pendingToolApprovalIdsRef.current.size > 0);
2423
+ setIsRunning(false);
2424
+ } catch (error) {
2425
+ setToolCallApprovals((prev) => {
2426
+ const next = { ...prev };
2427
+ delete next[toolCallId];
2428
+ return next;
2429
+ });
2430
+ setIsRunning(false);
2431
+ throw error;
2432
+ }
2433
+ return;
2434
+ }
2435
+ const response = await agent.declineToolCall({
2436
+ runId: currentRunId,
2437
+ toolCallId,
2438
+ requestContext: _requestContext.current
2439
+ });
2440
+ await response.processDataStream({
2441
+ onChunk: async (chunk) => {
2442
+ await processStreamChunk(chunk, onChunk);
2443
+ }
2444
+ });
2445
+ setIsRunning(false);
2446
+ };
2447
+ const approveToolCallGenerate = async (toolCallId) => {
2448
+ const currentRunId = _currentRunId.current;
2449
+ if (!currentRunId)
2450
+ return console.info(
2451
+ "[approveToolCallGenerate] approveToolCallGenerate can only be called after a generate has started"
2452
+ );
2453
+ setIsRunning(true);
2454
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
2455
+ const agent = baseClient.getAgent(agentId);
2456
+ const response = await agent.approveToolCallGenerate({
2457
+ runId: currentRunId,
2458
+ toolCallId,
2459
+ requestContext: _requestContext.current
2460
+ });
2461
+ if (response && "uiMessages" in response.response && response.response.uiMessages) {
2462
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, { mode: "generate" });
2463
+ setMessages((prev) => [...prev, ...dbMessages]);
2464
+ }
2465
+ setIsRunning(false);
2466
+ };
2467
+ const declineToolCallGenerate = async (toolCallId) => {
2468
+ const currentRunId = _currentRunId.current;
2469
+ if (!currentRunId)
2470
+ return console.info(
2471
+ "[declineToolCallGenerate] declineToolCallGenerate can only be called after a generate has started"
2472
+ );
2473
+ setIsRunning(true);
2474
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
2475
+ const agent = baseClient.getAgent(agentId);
2476
+ const response = await agent.declineToolCallGenerate({
2477
+ runId: currentRunId,
2478
+ toolCallId,
2479
+ requestContext: _requestContext.current
2480
+ });
2481
+ if (response && "uiMessages" in response.response && response.response.uiMessages) {
2482
+ const dbMessages = dbFromServerUiMessages(response.response.uiMessages, { mode: "generate" });
2483
+ setMessages((prev) => [...prev, ...dbMessages]);
2484
+ }
2485
+ setIsRunning(false);
2486
+ };
2487
+ const approveNetworkToolCall = async (toolName, runId) => {
2488
+ const onNetworkChunk = _onNetworkChunk.current;
2489
+ const networkRunId = runId || _networkRunId.current;
2490
+ if (!networkRunId)
2491
+ return console.info(
2492
+ "[approveNetworkToolCall] approveNetworkToolCall can only be called after a network stream has started"
2493
+ );
2494
+ setIsRunning(true);
2495
+ setNetworkToolCallApprovals((prev) => ({
2496
+ ...prev,
2497
+ [runId ? `${runId}-${toolName}` : toolName]: { status: "approved" }
2498
+ }));
2499
+ const agent = baseClient.getAgent(agentId);
2500
+ const response = await agent.approveNetworkToolCall({
2501
+ runId: networkRunId,
2502
+ requestContext: _requestContext.current
2503
+ });
2504
+ await response.processDataStream({
2505
+ onChunk: async (chunk) => {
2506
+ setMessages((prev) => accumulateNetworkChunk({ chunk, conversation: prev, metadata: { mode: "network" } }));
2507
+ void onNetworkChunk?.(chunk);
2508
+ }
2509
+ });
2510
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2511
+ setIsRunning(false);
2512
+ };
2513
+ const declineNetworkToolCall = async (toolName, runId) => {
2514
+ const onNetworkChunk = _onNetworkChunk.current;
2515
+ const networkRunId = runId || _networkRunId.current;
2516
+ if (!networkRunId)
2517
+ return console.info(
2518
+ "[declineNetworkToolCall] declineNetworkToolCall can only be called after a network stream has started"
2519
+ );
2520
+ setIsRunning(true);
2521
+ setNetworkToolCallApprovals((prev) => ({
2522
+ ...prev,
2523
+ [runId ? `${runId}-${toolName}` : toolName]: { status: "declined" }
2524
+ }));
2525
+ const agent = baseClient.getAgent(agentId);
2526
+ const response = await agent.declineNetworkToolCall({
2527
+ runId: networkRunId,
2528
+ requestContext: _requestContext.current
2529
+ });
2530
+ await response.processDataStream({
2531
+ onChunk: async (chunk) => {
2532
+ setMessages((prev) => accumulateNetworkChunk({ chunk, conversation: prev, metadata: { mode: "network" } }));
2533
+ void onNetworkChunk?.(chunk);
2534
+ }
2535
+ });
2536
+ setMessages((prev) => finishStreamingAssistantMessage(prev));
2537
+ setIsRunning(false);
2538
+ };
2539
+ const sendMessage = async ({ mode = "stream", ...args }) => {
2540
+ const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
2541
+ const coreUserMessages = [nextMessage];
2542
+ if (args.coreUserMessages) {
2543
+ coreUserMessages.push(...args.coreUserMessages);
2544
+ }
2545
+ const dbUserMessage = fromCoreUserMessagesToMastraDBMessage(coreUserMessages);
2546
+ const clientSetId = mode === "stream" && args.threadId && !_threadSignalsUnsupportedRef.current && !threadSignalsDisabled ? `client-set-${uuid.v4()}` : void 0;
2547
+ const signalId = clientSetId;
2548
+ const clientMessageId = clientSetId;
2549
+ if (signalId) {
2550
+ const metadata = {
2551
+ ...dbUserMessage.content.metadata,
2552
+ mode: "stream",
2553
+ status: "pending",
2554
+ [CLIENT_MESSAGE_ID_KEY]: clientMessageId
2555
+ };
2556
+ const pendingMessage = { ...dbUserMessage, id: clientSetId, content: { ...dbUserMessage.content, metadata } };
2557
+ setMessages((s) => [...s, pendingMessage]);
2558
+ } else {
2559
+ setMessages((s) => [...s, dbUserMessage]);
2560
+ }
2561
+ if (mode === "generate") {
2562
+ await generate({ ...args, coreUserMessages });
2563
+ } else if (mode === "stream") {
2564
+ await stream({ ...args, coreUserMessages, signalId, clientMessageId });
2565
+ } else if (mode === "network") {
2566
+ await network({ ...args, coreUserMessages });
2567
+ }
2568
+ };
2569
+ return {
2570
+ setMessages,
2571
+ sendMessage,
2572
+ isRunning,
2573
+ isAwaitingToolApproval,
2574
+ messages,
2575
+ approveToolCall,
2576
+ declineToolCall,
2577
+ approveToolCallGenerate,
2578
+ declineToolCallGenerate,
2579
+ cancelRun: handleCancelRun,
2580
+ toolCallApprovals,
2581
+ approveNetworkToolCall,
2582
+ declineNetworkToolCall,
2583
+ networkToolCallApprovals
2584
+ };
2585
+ };
2586
+ var IconSizes = {
2587
+ sm: "mastra:[&>svg]:size-3",
2588
+ md: "mastra:[&>svg]:size-4",
2589
+ lg: "mastra:[&>svg]:size-5"
2590
+ };
2591
+ var Icon = ({ children, className, size = "md", ...props }) => {
2592
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || IconSizes[size], ...props, children });
2593
+ };
2594
+ var EntityContext = react.createContext({
2595
+ expanded: false,
2596
+ setExpanded: () => {
2597
+ },
2598
+ variant: "initial",
2599
+ disabled: false
2600
+ });
2601
+ var EntityProvider = EntityContext.Provider;
2602
+ var useEntity = () => react.useContext(EntityContext);
2603
+ var Entity = ({
2604
+ className,
2605
+ variant = "initial",
2606
+ initialExpanded = false,
2607
+ disabled = false,
2608
+ ...props
2609
+ }) => {
2610
+ const [expanded, setExpanded] = react.useState(initialExpanded);
2611
+ return /* @__PURE__ */ jsxRuntime.jsx(EntityProvider, { value: { expanded, setExpanded, variant, disabled }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...props }) });
2612
+ };
2613
+ var EntityTriggerClass = tailwindMerge.twMerge(
2614
+ "mastra:aria-disabled:cursor-not-allowed mastra:aria-disabled:bg-surface5 mastra:aria-disabled:text-text3",
2615
+ "mastra:aria-expanded:rounded-b-none mastra:aria-expanded:border-b-0",
2616
+ "mastra:bg-surface3 mastra:text-text6 mastra:hover:bg-surface4 mastra:active:bg-surface5",
2617
+ "mastra:rounded-lg mastra:py-2 mastra:px-4 mastra:border mastra:border-border1",
2618
+ "mastra:cursor-pointer mastra:inline-flex mastra:items-center mastra:gap-1 mastra:font-mono"
2619
+ );
2620
+ var EntityTriggerVariantClasses = {
2621
+ agent: "mastra:[&_svg.mastra-icon]:text-accent1",
2622
+ workflow: "mastra:[&_svg.mastra-icon]:text-accent3",
2623
+ tool: "mastra:[&_svg.mastra-icon]:text-accent6",
2624
+ memory: "mastra:[&_svg.mastra-icon]:text-accent2",
2625
+ initial: "mastra:[&_svg.mastra-icon]:text-text3"
2626
+ };
2627
+ var EntityTrigger = ({ className, children, ...props }) => {
2628
+ const { expanded, setExpanded, variant, disabled } = useEntity();
2629
+ const handleClick = (e) => {
2630
+ if (disabled) return;
2631
+ setExpanded(!expanded);
2632
+ props?.onClick?.(e);
2633
+ };
2634
+ return /* @__PURE__ */ jsxRuntime.jsx(
2635
+ "button",
2636
+ {
2637
+ className: className || tailwindMerge.twMerge(EntityTriggerClass, !disabled && EntityTriggerVariantClasses[variant]),
2638
+ ...props,
2639
+ onClick: handleClick,
2640
+ "aria-expanded": expanded,
2641
+ "aria-disabled": disabled,
2642
+ children
2643
+ }
2644
+ );
2645
+ };
2646
+ var EntityContentClass = tailwindMerge.twMerge(
2647
+ "mastra:space-y-4",
2648
+ "mastra:rounded-lg mastra:rounded-tl-none mastra:p-4 mastra:border mastra:border-border1 mastra:-mt-[0.5px]",
2649
+ "mastra:bg-surface3 mastra:text-text6"
2650
+ );
2651
+ var EntityContent = ({ className, ...props }) => {
2652
+ const { expanded } = useEntity();
2653
+ if (!expanded) return null;
2654
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || EntityContentClass, ...props });
2655
+ };
2656
+ var EntityCaret = ({ className, ...props }) => {
2657
+ const { expanded } = useEntity();
2658
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(
2659
+ lucideReact.ChevronDownIcon,
2660
+ {
2661
+ className: tailwindMerge.twMerge(
2662
+ `mastra:text-text3 mastra:transition-transform mastra:duration-200 mastra:ease-in-out`,
2663
+ expanded ? "mastra:rotate-0" : "mastra:-rotate-90",
2664
+ className
2665
+ ),
2666
+ ...props
2667
+ }
2668
+ ) });
2669
+ };
2670
+ var ToolApprovalClass = tailwindMerge.twMerge(
2671
+ "mastra:rounded-lg mastra:border mastra:border-border1 mastra:max-w-1/2 mastra:mt-2",
2672
+ "mastra:bg-surface3 mastra:text-text6"
2673
+ );
2674
+ var ToolApproval = ({ className, ...props }) => {
2675
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || ToolApprovalClass, ...props });
2676
+ };
2677
+ var ToolApprovalTitleClass = tailwindMerge.twMerge("mastra:text-text6 mastra:inline-flex mastra:items-center mastra:gap-1");
2678
+ var ToolApprovalTitle = ({ className, ...props }) => {
2679
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || ToolApprovalTitleClass, ...props });
2680
+ };
2681
+ var ToolApprovalHeaderClass = tailwindMerge.twMerge(
2682
+ "mastra:flex mastra:justify-between mastra:items-center mastra:gap-2",
2683
+ "mastra:border-b mastra:border-border1 mastra:px-4 mastra:py-2"
2684
+ );
2685
+ var ToolApprovalHeader = ({ className, ...props }) => {
2686
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || ToolApprovalHeaderClass, ...props });
2687
+ };
2688
+ var ToolApprovalContentClass = tailwindMerge.twMerge("mastra:text-text6 mastra:p-4");
2689
+ var ToolApprovalContent = ({ className, ...props }) => {
2690
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || ToolApprovalContentClass, ...props });
2691
+ };
2692
+ var ToolApprovalActionsClass = tailwindMerge.twMerge("mastra:flex mastra:gap-2 mastra:items-center");
2693
+ var ToolApprovalActions = ({ className, ...props }) => {
2694
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || ToolApprovalActionsClass, ...props });
2695
+ };
2696
+ var EntryClass = "mastra:space-y-2";
2697
+ var Entry = ({ className, ...props }) => {
2698
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || EntryClass, ...props });
2699
+ };
2700
+ var EntryTitleClass = "mastra:font-mono mastra:text-sm mastra:text-text3";
2701
+ var EntryTitle = ({ className, as: Root = "h3", ...props }) => {
2702
+ return /* @__PURE__ */ jsxRuntime.jsx(Root, { className: className || EntryTitleClass, ...props });
2703
+ };
2704
+ var Tooltip = ({ children }) => {
2705
+ return /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.Root, { children }) });
2706
+ };
2707
+ var TooltipContentClass = "mastra:bg-surface4 mastra:text-text6 mastra mastra:rounded-lg mastra:py-1 mastra:px-2 mastra:text-xs mastra:border mastra:border-border1 mastra-tooltip-enter";
2708
+ var TooltipContent = ({ children, className, ...props }) => {
2709
+ return /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.TooltipPortal, { children: /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.TooltipContent, { className: className || TooltipContentClass, ...props, children }) });
2710
+ };
2711
+ var TooltipTrigger = (props) => {
2712
+ return /* @__PURE__ */ jsxRuntime.jsx(reactTooltip.TooltipTrigger, { ...props, asChild: true });
2713
+ };
2714
+ var IconButtonClass = "mastra:text-text3 mastra:hover:text-text6 mastra:active:text-text6 mastra:hover:bg-surface4 mastra:active:bg-surface5 mastra:rounded-md mastra:cursor-pointer";
2715
+ var IconButton = ({ children, tooltip, size = "md", className, ...props }) => {
2716
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
2717
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(
2718
+ "button",
2719
+ {
2720
+ ...props,
2721
+ className: className || tailwindMerge.twMerge(IconButtonClass, size === "md" && "mastra:p-0.5", size === "lg" && "mastra:p-1"),
2722
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size, children })
2723
+ }
2724
+ ) }),
2725
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: tooltip })
2726
+ ] });
2727
+ };
2728
+ async function highlight(code, lang) {
2729
+ const out = await web.codeToHast(code, {
2730
+ lang,
2731
+ theme: "dracula-soft"
2732
+ });
2733
+ return hastUtilToJsxRuntime.toJsxRuntime(out, {
2734
+ Fragment: react.Fragment,
2735
+ jsx: jsxRuntime.jsx,
2736
+ jsxs: jsxRuntime.jsxs
2737
+ });
2738
+ }
2739
+ var CodeBlockClass = "mastra:rounded-lg mastra:[&>pre]:p-4 mastra:overflow-hidden mastra:[&>pre]:!bg-surface4 mastra:[&>pre>code]:leading-5 mastra:relative";
2740
+ var CodeBlock = ({ code, language, className, cta }) => {
2741
+ const [nodes, setNodes] = react.useState(null);
2742
+ react.useLayoutEffect(() => {
2743
+ void highlight(code, language).then(setNodes);
2744
+ }, [language]);
2745
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: className || CodeBlockClass, children: [
2746
+ nodes ?? null,
2747
+ cta
2748
+ ] });
2749
+ };
2750
+ var CodeCopyButton = ({ code }) => {
2751
+ const [isCopied, setIsCopied] = react.useState(false);
2752
+ const handleCopy = () => {
2753
+ void navigator.clipboard.writeText(code);
2754
+ setIsCopied(true);
2755
+ setTimeout(() => setIsCopied(false), 2e3);
2756
+ };
2757
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mastra:absolute mastra:top-2 mastra:right-2", children: /* @__PURE__ */ jsxRuntime.jsx(IconButton, { tooltip: "Copy", onClick: handleCopy, children: isCopied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) }) });
2758
+ };
2759
+ var AgentIcon = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsxs(
2760
+ "svg",
2761
+ {
2762
+ width: "17",
2763
+ height: "16",
2764
+ viewBox: "0 0 17 16",
2765
+ fill: "none",
2766
+ xmlns: "http://www.w3.org/2000/svg",
2767
+ ...props,
2768
+ className: tailwindMerge.twMerge("mastra-icon", className),
2769
+ children: [
2770
+ /* @__PURE__ */ jsxRuntime.jsx(
2771
+ "path",
2772
+ {
2773
+ fillRule: "evenodd",
2774
+ clipRule: "evenodd",
2775
+ d: "M8.5 15C10.3565 15 12.137 14.2625 13.4497 12.9497C14.7625 11.637 15.5 9.85652 15.5 8C15.5 6.14348 14.7625 4.36301 13.4497 3.05025C12.137 1.7375 10.3565 1 8.5 1C6.64348 1 4.86301 1.7375 3.55025 3.05025C2.2375 4.36301 1.5 6.14348 1.5 8C1.5 9.85652 2.2375 11.637 3.55025 12.9497C4.86301 14.2625 6.64348 15 8.5 15ZM5.621 10.879L4.611 11.889C3.84179 11.1198 3.31794 10.1398 3.1057 9.07291C2.89346 8.00601 3.00236 6.90013 3.41864 5.89512C3.83491 4.89012 4.53986 4.03112 5.44434 3.42676C6.34881 2.8224 7.41219 2.49983 8.5 2.49983C9.58781 2.49983 10.6512 2.8224 11.5557 3.42676C12.4601 4.03112 13.1651 4.89012 13.5814 5.89512C13.9976 6.90013 14.1065 8.00601 13.8943 9.07291C13.6821 10.1398 13.1582 11.1198 12.389 11.889L11.379 10.879C11.1004 10.6003 10.7696 10.3792 10.4055 10.2284C10.0414 10.0776 9.6511 9.99995 9.257 10H7.743C7.3489 9.99995 6.95865 10.0776 6.59455 10.2284C6.23045 10.3792 5.89963 10.6003 5.621 10.879Z",
2776
+ fill: "currentColor"
2777
+ }
2778
+ ),
2779
+ /* @__PURE__ */ jsxRuntime.jsx(
2780
+ "path",
2781
+ {
2782
+ d: "M8.5 4C7.96957 4 7.46086 4.21071 7.08579 4.58579C6.71071 4.96086 6.5 5.46957 6.5 6V6.5C6.5 7.03043 6.71071 7.53914 7.08579 7.91421C7.46086 8.28929 7.96957 8.5 8.5 8.5C9.03043 8.5 9.53914 8.28929 9.91421 7.91421C10.2893 7.53914 10.5 7.03043 10.5 6.5V6C10.5 5.46957 10.2893 4.96086 9.91421 4.58579C9.53914 4.21071 9.03043 4 8.5 4Z",
2783
+ fill: "currentColor"
2784
+ }
2785
+ )
2786
+ ]
2787
+ }
2788
+ );
2789
+ var ToolsIcon = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2790
+ "svg",
2791
+ {
2792
+ width: "17",
2793
+ height: "16",
2794
+ viewBox: "0 0 17 16",
2795
+ fill: "none",
2796
+ xmlns: "http://www.w3.org/2000/svg",
2797
+ ...props,
2798
+ className: tailwindMerge.twMerge("mastra-icon", className),
2799
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2800
+ "path",
2801
+ {
2802
+ fillRule: "evenodd",
2803
+ clipRule: "evenodd",
2804
+ d: "M7.5605 1.42351C8.0791 0.904904 8.92215 0.906157 9.4395 1.42351L10.6922 2.67617C11.2108 3.19477 11.2095 4.03782 10.6922 4.55517L9.4395 5.80783C8.9209 6.32643 8.07785 6.32518 7.5605 5.80783L6.30784 4.55517C5.78923 4.03656 5.79049 3.19352 6.30784 2.67617L7.5605 1.42351ZM3.17618 5.80783C3.69478 5.28923 4.53782 5.29048 5.05517 5.80783L6.30784 7.0605C6.82644 7.5791 6.82519 8.42214 6.30784 8.93949L5.05517 10.1922C4.53657 10.7108 3.69353 10.7095 3.17618 10.1922L1.92351 8.93949C1.40491 8.42089 1.40616 7.57785 1.92351 7.0605L3.17618 5.80783ZM11.9448 5.80783C12.4634 5.28923 13.3065 5.29048 13.8238 5.80783L15.0765 7.0605C15.5951 7.5791 15.5938 8.42214 15.0765 8.93949L13.8238 10.1922C13.3052 10.7108 12.4622 10.7095 11.9448 10.1922L10.6922 8.93949C10.1736 8.42089 10.1748 7.57785 10.6922 7.0605L11.9448 5.80783ZM7.5605 10.1922C8.0791 9.67355 8.92215 9.67481 9.4395 10.1922L10.6922 11.4448C11.2108 11.9634 11.2095 12.8065 10.6922 13.3238L9.4395 14.5765C8.9209 15.0951 8.07785 15.0938 7.5605 14.5765L6.30784 13.3238C5.78923 12.8052 5.79049 11.9622 6.30784 11.4448L7.5605 10.1922Z",
2805
+ fill: "currentColor"
2806
+ }
2807
+ )
2808
+ }
2809
+ );
2810
+ var WorkflowIcon = ({ className, ...props }) => /* @__PURE__ */ jsxRuntime.jsx(
2811
+ "svg",
2812
+ {
2813
+ width: "17",
2814
+ height: "16",
2815
+ viewBox: "0 0 17 16",
2816
+ fill: "none",
2817
+ xmlns: "http://www.w3.org/2000/svg",
2818
+ ...props,
2819
+ className: tailwindMerge.twMerge("mastra-icon", className),
2820
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2821
+ "path",
2822
+ {
2823
+ fillRule: "evenodd",
2824
+ clipRule: "evenodd",
2825
+ d: "M6.24388 2.4018C6.24388 2.0394 6.53767 1.74561 6.90008 1.74561H10.0991C10.4614 1.74561 10.7553 2.0394 10.7553 2.4018V4.57546C10.7553 4.93787 10.4614 5.23166 10.0991 5.23166H9.31982V7.35469L10.0033 9.22664C9.90442 9.20146 9.80035 9.1761 9.6915 9.14986L9.62652 9.13422C9.30473 9.05687 8.92256 8.96501 8.61993 8.84491C8.5819 8.82981 8.54147 8.81292 8.49957 8.79391C8.45767 8.81292 8.41724 8.82981 8.3792 8.84491C8.07657 8.96501 7.6944 9.05687 7.37261 9.13422L7.30763 9.14986C7.19879 9.1761 7.09471 9.20146 6.99577 9.22664L7.67932 7.35469V5.23166H6.90008C6.53767 5.23166 6.24388 4.93787 6.24388 4.57546V2.4018ZM6.99577 9.22664C6.99577 9.22664 6.99578 9.22664 6.99577 9.22664L6.43283 10.7683H6.81806C7.18047 10.7683 7.47426 11.0622 7.47426 11.4245V13.5982C7.47426 13.9606 7.18047 14.2544 6.81806 14.2544H3.61909C3.25668 14.2544 2.96289 13.9606 2.96289 13.5982V11.4245C2.96289 11.0622 3.25668 10.7683 3.61909 10.7683H4.26617C4.2921 10.4663 4.32783 10.1494 4.37744 9.85171C4.43762 9.49063 4.52982 9.08135 4.68998 8.76102C4.93975 8.2615 5.44743 8.01751 5.7771 7.88788C6.14684 7.74249 6.57537 7.63889 6.92317 7.55505C7.24707 7.47696 7.49576 7.41679 7.67932 7.35469L6.99577 9.22664ZM6.43283 10.7683L6.99577 9.22664C6.75846 9.28705 6.55067 9.34646 6.37745 9.41458C6.22784 9.47341 6.1623 9.51712 6.14023 9.53254C6.09752 9.63631 6.04409 9.83055 5.99562 10.1214C5.96201 10.3231 5.93498 10.5439 5.91341 10.7683H6.43283ZM10.0033 9.22664L9.31982 7.35469C9.50338 7.41679 9.75206 7.47696 10.076 7.55505C10.4238 7.63889 10.8523 7.74249 11.2221 7.88788C11.5517 8.01751 12.0594 8.2615 12.3091 8.76102C12.4693 9.08135 12.5615 9.49063 12.6217 9.85171C12.6713 10.1494 12.707 10.4663 12.733 10.7683H13.38C13.7424 10.7683 14.0362 11.0622 14.0362 11.4245V13.5982C14.0362 13.9606 13.7424 14.2544 13.38 14.2544H10.1811C9.81867 14.2544 9.52488 13.9606 9.52488 13.5982V11.4245C9.52488 11.0622 9.81867 10.7683 10.1811 10.7683H10.5663L10.0033 9.22664ZM10.0033 9.22664L10.5663 10.7683H11.0857C11.0642 10.5439 11.0372 10.3231 11.0035 10.1214C10.9551 9.83055 10.9016 9.63631 10.8589 9.53254C10.8369 9.51712 10.7713 9.47341 10.6217 9.41458C10.4485 9.34646 10.2407 9.28705 10.0033 9.22664Z",
2826
+ fill: "currentColor"
2827
+ }
2828
+ )
2829
+ }
2830
+ );
2831
+ var MessageClass = "mastra:flex mastra:flex-col mastra:w-full mastra:py-4 mastra:gap-2 mastra:group";
2832
+ var Message = ({ position, className, children, ...props }) => {
2833
+ return /* @__PURE__ */ jsxRuntime.jsx(
2834
+ "div",
2835
+ {
2836
+ className: className || tailwindMerge.twMerge(
2837
+ MessageClass,
2838
+ position === "left" ? "" : "mastra:items-end mastra:[&_.mastra-message-content]:bg-surface4 mastra:[&_.mastra-message-content]:px-4"
2839
+ ),
2840
+ ...props,
2841
+ children
2842
+ }
2843
+ );
2844
+ };
2845
+ var MessageContentClass = "mastra:max-w-4/5 mastra:py-2 mastra:text-text6 mastra:rounded-lg mastra-message-content mastra:text-md";
2846
+ var MessageContent = ({ children, className, isStreaming, ...props }) => {
2847
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: className || MessageContentClass, ...props, children: [
2848
+ children,
2849
+ isStreaming && /* @__PURE__ */ jsxRuntime.jsx(MessageStreaming, {})
2850
+ ] });
2851
+ };
2852
+ var MessageActionsClass = "mastra:gap-2 mastra:flex mastra:opacity-0 mastra:group-hover:opacity-100 mastra:group-focus-within:opacity-100 mastra:items-center";
2853
+ var MessageActions = ({ children, className, ...props }) => {
2854
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || MessageActionsClass, ...props, children });
2855
+ };
2856
+ var MessageUsagesClass = "mastra:flex mastra:gap-2 mastra:items-center";
2857
+ var MessageUsages = ({ children, className, ...props }) => {
2858
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || MessageUsagesClass, ...props, children });
2859
+ };
2860
+ var MessageUsageClass = "mastra:flex mastra:gap-2 mastra:items-center mastra:font-mono mastra:text-xs mastra:bg-surface3 mastra:rounded-lg mastra:px-2 mastra:py-1";
2861
+ var MessageUsage = ({ children, className, ...props }) => {
2862
+ return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: className || MessageUsageClass, ...props, children });
2863
+ };
2864
+ var MessageUsageEntryClass = "mastra:text-text3 mastra:text-xs mastra:flex mastra:gap-1 mastra:items-center";
2865
+ var MessageUsageEntry = ({ children, className, ...props }) => {
2866
+ return /* @__PURE__ */ jsxRuntime.jsx("dt", { className: className || MessageUsageEntryClass, ...props, children });
2867
+ };
2868
+ var MessageUsageValueClass = "mastra:text-text6 mastra:text-xs";
2869
+ var MessageUsageValue = ({ children, className, ...props }) => {
2870
+ return /* @__PURE__ */ jsxRuntime.jsx("dd", { className: className || MessageUsageValueClass, ...props, children });
2871
+ };
2872
+ var MessageListClass = "mastra:overflow-y-auto mastra:h-full mastra-list";
2873
+ var MessageList = ({ children, className, ...props }) => {
2874
+ const listRef = react.useRef(null);
2875
+ react.useEffect(() => {
2876
+ const scrollToBottom = () => {
2877
+ if (!listRef.current) return;
2878
+ listRef.current.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" });
2879
+ };
2880
+ requestAnimationFrame(scrollToBottom);
2881
+ });
2882
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: className || MessageListClass, ...props, ref: listRef, children });
2883
+ };
2884
+ var MessageStreamingClass = "mastra:inline-block mastra:w-[2px] mastra:h-[1em] mastra:bg-text5 mastra:ml-0.5 mastra:align-text-bottom mastra:animate-pulse";
2885
+ var MessageStreaming = ({ className, ...props }) => {
2886
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: className || MessageStreamingClass, ...props });
2887
+ };
2888
+ var isDynamicToolPart2 = (part) => (
2889
+ // `tool-invocation` is the v4 typed discriminant and must NOT be treated as a
2890
+ // v5 `tool-${string}` streaming part, even though it shares the `tool-` prefix.
2891
+ part.type === "dynamic-tool" || part.type.startsWith("tool-") && part.type !== "tool-invocation"
2892
+ );
2893
+ var isDataPart = (part) => part.type.startsWith("data-");
2894
+ var sourceToSourceUrl = (part) => ({
2895
+ type: "source-url",
2896
+ sourceId: part.source.id,
2897
+ url: part.source.url,
2898
+ title: part.source.title,
2899
+ providerMetadata: part.providerMetadata
2900
+ });
2901
+ var getPartKey = (part, index) => {
2902
+ if (isDynamicToolPart2(part)) {
2903
+ return part.toolCallId ?? `${part.type}-${index}`;
2904
+ }
2905
+ switch (part.type) {
2906
+ case "text":
2907
+ return part.textId ?? `text-${index}`;
2908
+ case "reasoning":
2909
+ return part.reasoningId ?? `reasoning-${index}`;
2910
+ case "tool-invocation":
2911
+ return part.toolInvocation.toolCallId ?? `tool-invocation-${index}`;
2912
+ case "source-url":
2913
+ return part.sourceId || `source-url-${index}`;
2914
+ case "source":
2915
+ return part.source.id ?? `source-${index}`;
2916
+ }
2917
+ const id = part.id;
2918
+ return id ?? `${part.type}-${index}`;
2919
+ };
2920
+ var renderPart = (part, renderers, fallback) => {
2921
+ if (isDynamicToolPart2(part)) {
2922
+ return renderers.DynamicTool?.(part) ?? fallback?.(part) ?? null;
2923
+ }
2924
+ if (isDataPart(part)) {
2925
+ return renderers.Data?.(part) ?? fallback?.(part) ?? null;
2926
+ }
2927
+ switch (part.type) {
2928
+ case "text":
2929
+ return renderers.Text?.(part) ?? fallback?.(part) ?? null;
2930
+ case "reasoning":
2931
+ return renderers.Reasoning?.(part) ?? fallback?.(part) ?? null;
2932
+ case "file":
2933
+ return renderers.File?.(part) ?? fallback?.(part) ?? null;
2934
+ case "step-start":
2935
+ return renderers.StepStart?.(part) ?? fallback?.(part) ?? null;
2936
+ case "tool-invocation":
2937
+ return renderers.ToolInvocation?.(part) ?? fallback?.(part) ?? null;
2938
+ case "source":
2939
+ return renderers.SourceUrl?.(sourceToSourceUrl(part)) ?? fallback?.(part) ?? null;
2940
+ case "source-url":
2941
+ return renderers.SourceUrl?.(part) ?? fallback?.(part) ?? null;
2942
+ case "source-document":
2943
+ return renderers.SourceDocument?.(part) ?? fallback?.(part) ?? null;
2944
+ default: {
2945
+ return fallback?.(part) ?? null;
2946
+ }
2947
+ }
2948
+ };
2949
+ var PartRenderer = react.memo(({ part, renderers, fallback }) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderPart(part, renderers, fallback) }));
2950
+ PartRenderer.displayName = "PartRenderer";
2951
+ var joinText = (parts) => parts.filter((part) => part.type === "text").map((part) => part.text).join("");
2952
+ var resolveTaskVerdict = (metadata) => {
2953
+ const verdict = metadata?.completionResult ?? metadata?.isTaskCompleteResult;
2954
+ if (!verdict) return void 0;
2955
+ return { passed: !!verdict.passed, suppressFeedback: verdict.suppressFeedback };
2956
+ };
2957
+ var roleRendererFor = (role, roles) => {
2958
+ switch (role) {
2959
+ case "user":
2960
+ return roles?.User;
2961
+ case "assistant":
2962
+ return roles?.Assistant;
2963
+ case "system":
2964
+ return roles?.System;
2965
+ case "signal":
2966
+ return roles?.Signal;
2967
+ default:
2968
+ return void 0;
2969
+ }
2970
+ };
2971
+ var MessageFactoryComponent = ({ message, roles, status, fallback, ...renderers }) => {
2972
+ const parts = message.content.parts ?? [];
2973
+ const metadata = message.content.metadata;
2974
+ let content;
2975
+ if (metadata?.status === "tripwire" && status?.Tripwire) {
2976
+ content = status.Tripwire({ text: joinText(parts), tripwire: metadata.tripwire, message });
2977
+ } else if (metadata?.status === "warning" && status?.Warning) {
2978
+ content = status.Warning({ text: joinText(parts), message });
2979
+ } else if (metadata?.status === "error" && status?.Error) {
2980
+ content = status.Error({ text: joinText(parts), message });
2981
+ } else {
2982
+ content = /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: parts.map((part, index) => /* @__PURE__ */ jsxRuntime.jsx(PartRenderer, { part, renderers, fallback }, getPartKey(part, index))) });
2983
+ if (metadata?.status === "pending" && status?.Pending) {
2984
+ content = status.Pending({ children: content, text: joinText(parts), message });
2985
+ }
2986
+ const verdict = resolveTaskVerdict(metadata);
2987
+ if (verdict && status?.Task) {
2988
+ content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2989
+ content,
2990
+ status.Task({ ...verdict, text: joinText(parts), message })
2991
+ ] });
2992
+ }
2993
+ }
2994
+ const RoleWrapper = roleRendererFor(message.role, roles);
2995
+ if (RoleWrapper) {
2996
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: RoleWrapper({ message, children: content }) });
2997
+ }
2998
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
2999
+ };
3000
+ var MessageFactory = react.memo(MessageFactoryComponent);
3001
+ MessageFactory.displayName = "MessageFactory";
3002
+ function useMutation(mutationFn) {
3003
+ const [isPending, setIsPending] = react.useState(false);
3004
+ const [isSuccess, setIsSuccess] = react.useState(false);
3005
+ const [isError, setIsError] = react.useState(false);
3006
+ const [error, setError] = react.useState(null);
3007
+ const [data, setData] = react.useState(void 0);
3008
+ const mutationFnRef = react.useRef(mutationFn);
3009
+ mutationFnRef.current = mutationFn;
3010
+ const reset = react.useCallback(() => {
3011
+ setIsPending(false);
3012
+ setIsSuccess(false);
3013
+ setIsError(false);
3014
+ setError(null);
3015
+ setData(void 0);
3016
+ }, []);
3017
+ const mutateAsync = react.useCallback(async (variables) => {
3018
+ setIsPending(true);
3019
+ setIsSuccess(false);
3020
+ setIsError(false);
3021
+ setError(null);
3022
+ try {
3023
+ const result = await mutationFnRef.current(variables);
3024
+ setData(result);
3025
+ setIsSuccess(true);
3026
+ return result;
3027
+ } catch (err) {
3028
+ const typedError = err;
3029
+ setError(typedError);
3030
+ setIsError(true);
3031
+ throw err;
3032
+ } finally {
3033
+ setIsPending(false);
3034
+ }
3035
+ }, []);
3036
+ const mutate = react.useCallback(
3037
+ (variables) => {
3038
+ mutateAsync(variables).catch(() => {
3039
+ });
3040
+ },
3041
+ [mutateAsync]
3042
+ );
3043
+ return {
3044
+ mutate,
3045
+ mutateAsync,
3046
+ isPending,
3047
+ isSuccess,
3048
+ isError,
3049
+ error,
3050
+ data,
3051
+ reset
3052
+ };
3053
+ }
3054
+ function useStreamWorkflow({ debugMode, tracingOptions, onError }) {
3055
+ const client = useMastraClient();
3056
+ const [streamResult, setStreamResult] = react.useState({});
3057
+ const [isStreaming, setIsStreaming] = react.useState(false);
3058
+ const readerRef = react.useRef(null);
3059
+ const observerRef = react.useRef(null);
3060
+ const resumeStreamRef = react.useRef(null);
3061
+ const timeTravelStreamRef = react.useRef(null);
3062
+ const isMountedRef = react.useRef(true);
3063
+ react.useEffect(() => {
3064
+ isMountedRef.current = true;
3065
+ return () => {
3066
+ isMountedRef.current = false;
3067
+ if (readerRef.current) {
3068
+ try {
3069
+ readerRef.current.releaseLock();
3070
+ } catch {
3071
+ }
3072
+ readerRef.current = null;
3073
+ }
3074
+ if (observerRef.current) {
3075
+ try {
3076
+ observerRef.current.releaseLock();
3077
+ } catch {
3078
+ }
3079
+ observerRef.current = null;
3080
+ }
3081
+ if (resumeStreamRef.current) {
3082
+ try {
3083
+ resumeStreamRef.current.releaseLock();
3084
+ } catch {
3085
+ }
3086
+ resumeStreamRef.current = null;
3087
+ }
3088
+ if (timeTravelStreamRef.current) {
3089
+ try {
3090
+ timeTravelStreamRef.current.releaseLock();
3091
+ } catch {
3092
+ }
3093
+ timeTravelStreamRef.current = null;
3094
+ }
3095
+ };
3096
+ }, []);
3097
+ const handleStreamError = react.useCallback(
3098
+ (err, defaultMessage, setStreamingState) => {
3099
+ if (err instanceof TypeError) {
3100
+ return;
3101
+ }
3102
+ const error = err instanceof Error ? err : new Error(defaultMessage);
3103
+ onError?.(error, defaultMessage);
3104
+ setStreamingState?.(false);
3105
+ },
3106
+ [onError]
3107
+ );
3108
+ const handleWorkflowFinish = react.useCallback((value) => {
3109
+ if (value.type === "workflow-finish") {
3110
+ const streamStatus = value.payload?.workflowStatus;
3111
+ const metadata = value.payload?.metadata;
3112
+ setStreamResult((prev) => ({
3113
+ ...prev,
3114
+ status: streamStatus
3115
+ }));
3116
+ if (streamStatus === "failed") {
3117
+ throw new Error(metadata?.errorMessage || "Workflow execution failed");
3118
+ }
3119
+ }
3120
+ }, []);
3121
+ const streamWorkflow = useMutation(
3122
+ async ({ workflowId, runId, inputData, initialState, requestContext: playgroundRequestContext, perStep }) => {
3123
+ if (readerRef.current) {
3124
+ readerRef.current.releaseLock();
3125
+ }
3126
+ if (!isMountedRef.current) return;
3127
+ setIsStreaming(true);
3128
+ setStreamResult({ input: inputData });
3129
+ const workflow = client.getWorkflow(workflowId);
3130
+ const run = await workflow.createRun({ runId });
3131
+ const stream = await run.stream({
3132
+ inputData,
3133
+ initialState,
3134
+ requestContext: playgroundRequestContext,
3135
+ closeOnSuspend: true,
3136
+ tracingOptions,
3137
+ perStep: perStep ?? debugMode
3138
+ });
3139
+ if (!stream) {
3140
+ return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
3141
+ }
3142
+ const reader = stream.getReader();
3143
+ readerRef.current = reader;
3144
+ try {
3145
+ while (true) {
3146
+ if (!isMountedRef.current) break;
3147
+ const { done, value } = await reader.read();
3148
+ if (done) break;
3149
+ if (isMountedRef.current) {
3150
+ setStreamResult((prev) => {
3151
+ const newResult = mapWorkflowStreamChunkToWatchResult(prev, value);
3152
+ return newResult;
3153
+ });
3154
+ if (value.type === "workflow-step-start") {
3155
+ setIsStreaming(true);
3156
+ }
3157
+ if (value.type === "workflow-step-suspended") {
3158
+ setIsStreaming(false);
3159
+ }
3160
+ if (value.type === "workflow-finish") {
3161
+ handleWorkflowFinish(value);
3162
+ }
3163
+ }
3164
+ }
3165
+ } catch (err) {
3166
+ handleStreamError(err, "Error streaming workflow");
3167
+ } finally {
3168
+ if (isMountedRef.current) {
3169
+ setIsStreaming(false);
3170
+ }
3171
+ if (readerRef.current) {
3172
+ readerRef.current.releaseLock();
3173
+ readerRef.current = null;
3174
+ }
3175
+ }
3176
+ }
3177
+ );
3178
+ const observeWorkflowStream = useMutation(
3179
+ async ({ workflowId, runId, storeRunResult }) => {
3180
+ if (observerRef.current) {
3181
+ observerRef.current.releaseLock();
3182
+ }
3183
+ if (!isMountedRef.current) return;
3184
+ setIsStreaming(true);
3185
+ setStreamResult(storeRunResult || {});
3186
+ if (storeRunResult?.status === "suspended") {
3187
+ setIsStreaming(false);
3188
+ return;
3189
+ }
3190
+ const workflow = client.getWorkflow(workflowId);
3191
+ const run = await workflow.createRun({ runId });
3192
+ const stream = await run.observeStream();
3193
+ if (!stream) {
3194
+ return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
3195
+ }
3196
+ const reader = stream.getReader();
3197
+ observerRef.current = reader;
3198
+ try {
3199
+ while (true) {
3200
+ if (!isMountedRef.current) break;
3201
+ const { done, value } = await reader.read();
3202
+ if (done) break;
3203
+ if (isMountedRef.current) {
3204
+ setStreamResult((prev) => {
3205
+ const newResult = mapWorkflowStreamChunkToWatchResult(prev, value);
3206
+ return newResult;
3207
+ });
3208
+ if (value.type === "workflow-step-start") {
3209
+ setIsStreaming(true);
3210
+ }
3211
+ if (value.type === "workflow-step-suspended") {
3212
+ setIsStreaming(false);
3213
+ }
3214
+ if (value.type === "workflow-finish") {
3215
+ handleWorkflowFinish(value);
3216
+ }
3217
+ }
3218
+ }
3219
+ } catch (err) {
3220
+ handleStreamError(err, "Error observing workflow");
3221
+ } finally {
3222
+ if (isMountedRef.current) {
3223
+ setIsStreaming(false);
3224
+ }
3225
+ if (observerRef.current) {
3226
+ observerRef.current.releaseLock();
3227
+ observerRef.current = null;
3228
+ }
3229
+ }
3230
+ }
3231
+ );
3232
+ const resumeWorkflowStream = useMutation(
3233
+ async ({ workflowId, runId, step, resumeData, requestContext: playgroundRequestContext, perStep }) => {
3234
+ if (resumeStreamRef.current) {
3235
+ resumeStreamRef.current.releaseLock();
3236
+ }
3237
+ if (!isMountedRef.current) return;
3238
+ setIsStreaming(true);
3239
+ const workflow = client.getWorkflow(workflowId);
3240
+ const run = await workflow.createRun({ runId });
3241
+ const stream = await run.resumeStream({
3242
+ step,
3243
+ resumeData,
3244
+ requestContext: playgroundRequestContext,
3245
+ tracingOptions,
3246
+ perStep: perStep ?? debugMode
3247
+ });
3248
+ if (!stream) {
3249
+ return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
3250
+ }
3251
+ const reader = stream.getReader();
3252
+ resumeStreamRef.current = reader;
3253
+ try {
3254
+ while (true) {
3255
+ if (!isMountedRef.current) break;
3256
+ const { done, value } = await reader.read();
3257
+ if (done) break;
3258
+ if (isMountedRef.current) {
3259
+ setStreamResult((prev) => {
3260
+ const newResult = mapWorkflowStreamChunkToWatchResult(prev, value);
3261
+ return newResult;
3262
+ });
3263
+ if (value.type === "workflow-step-start") {
3264
+ setIsStreaming(true);
3265
+ }
3266
+ if (value.type === "workflow-step-suspended") {
3267
+ setIsStreaming(false);
3268
+ }
3269
+ if (value.type === "workflow-finish") {
3270
+ handleWorkflowFinish(value);
3271
+ }
3272
+ }
3273
+ }
3274
+ } catch (err) {
3275
+ handleStreamError(err, "Error resuming workflow stream");
3276
+ } finally {
3277
+ if (isMountedRef.current) {
3278
+ setIsStreaming(false);
3279
+ }
3280
+ if (resumeStreamRef.current) {
3281
+ resumeStreamRef.current.releaseLock();
3282
+ resumeStreamRef.current = null;
3283
+ }
3284
+ }
3285
+ }
3286
+ );
3287
+ const timeTravelWorkflowStream = useMutation(
3288
+ async ({ workflowId, requestContext: playgroundRequestContext, runId, perStep, ...params }) => {
3289
+ if (timeTravelStreamRef.current) {
3290
+ timeTravelStreamRef.current.releaseLock();
3291
+ }
3292
+ if (!isMountedRef.current) return;
3293
+ setIsStreaming(true);
3294
+ const workflow = client.getWorkflow(workflowId);
3295
+ const run = await workflow.createRun({ runId });
3296
+ const stream = await run.timeTravelStream({
3297
+ ...params,
3298
+ perStep: perStep ?? debugMode,
3299
+ requestContext: playgroundRequestContext,
3300
+ tracingOptions
3301
+ });
3302
+ if (!stream) {
3303
+ return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
3304
+ }
3305
+ const reader = stream.getReader();
3306
+ timeTravelStreamRef.current = reader;
3307
+ try {
3308
+ while (true) {
3309
+ if (!isMountedRef.current) break;
3310
+ const { done, value } = await reader.read();
3311
+ if (done) break;
3312
+ if (isMountedRef.current) {
3313
+ setStreamResult((prev) => {
3314
+ const newResult = mapWorkflowStreamChunkToWatchResult(prev, value);
3315
+ return newResult;
3316
+ });
3317
+ if (value.type === "workflow-step-start") {
3318
+ setIsStreaming(true);
3319
+ }
3320
+ if (value.type === "workflow-step-suspended") {
3321
+ setIsStreaming(false);
3322
+ }
3323
+ if (value.type === "workflow-finish") {
3324
+ handleWorkflowFinish(value);
3325
+ }
3326
+ }
3327
+ }
3328
+ } catch (err) {
3329
+ handleStreamError(err, "Error time traveling workflow stream");
3330
+ } finally {
3331
+ if (isMountedRef.current) {
3332
+ setIsStreaming(false);
3333
+ }
3334
+ if (timeTravelStreamRef.current) {
3335
+ timeTravelStreamRef.current.releaseLock();
3336
+ timeTravelStreamRef.current = null;
3337
+ }
3338
+ }
3339
+ }
3340
+ );
3341
+ const closeStreamsAndReset = react.useCallback(() => {
3342
+ setIsStreaming(false);
3343
+ setStreamResult({});
3344
+ if (readerRef.current) {
3345
+ try {
3346
+ readerRef.current.releaseLock();
3347
+ } catch {
3348
+ }
3349
+ readerRef.current = null;
3350
+ }
3351
+ if (observerRef.current) {
3352
+ try {
3353
+ observerRef.current.releaseLock();
3354
+ } catch {
3355
+ }
3356
+ observerRef.current = null;
3357
+ }
3358
+ if (resumeStreamRef.current) {
3359
+ try {
3360
+ resumeStreamRef.current.releaseLock();
3361
+ } catch {
3362
+ }
3363
+ resumeStreamRef.current = null;
3364
+ }
3365
+ if (timeTravelStreamRef.current) {
3366
+ try {
3367
+ timeTravelStreamRef.current.releaseLock();
3368
+ } catch {
3369
+ }
3370
+ timeTravelStreamRef.current = null;
3371
+ }
3372
+ }, []);
3373
+ return {
3374
+ streamWorkflow,
3375
+ streamResult,
3376
+ isStreaming,
3377
+ observeWorkflowStream,
3378
+ closeStreamsAndReset,
3379
+ resumeWorkflowStream,
3380
+ timeTravelWorkflowStream
3381
+ };
3382
+ }
3383
+
3384
+ // src/workflows/hooks.ts
3385
+ function useCreateWorkflowRun() {
3386
+ const client = useMastraClient();
3387
+ return useMutation(async ({ workflowId, prevRunId }) => {
3388
+ try {
3389
+ const workflow = client.getWorkflow(workflowId);
3390
+ const { runId: newRunId } = await workflow.createRun({ runId: prevRunId });
3391
+ return { runId: newRunId };
3392
+ } catch (error) {
3393
+ console.error("Error creating workflow run:", error);
3394
+ throw error;
3395
+ }
3396
+ });
3397
+ }
3398
+ function useCancelWorkflowRun() {
3399
+ const client = useMastraClient();
3400
+ return useMutation(async ({ workflowId, runId }) => {
3401
+ try {
3402
+ const workflow = client.getWorkflow(workflowId);
3403
+ const run = await workflow.createRun({ runId });
3404
+ return run.cancelRun();
3405
+ } catch (error) {
3406
+ console.error("Error canceling workflow run:", error);
3407
+ throw error;
3408
+ }
3409
+ });
3410
+ }
3411
+ var renderUnknown = (step, UnknownStep) => UnknownStep?.(step) ?? null;
3412
+ var WorkflowStepFactoryComponent = ({
3413
+ step,
3414
+ Step,
3415
+ MapStep,
3416
+ ForEachStep,
3417
+ ParallelStep,
3418
+ Conditional,
3419
+ LoopStep,
3420
+ SleepStep,
3421
+ SleepUntilStep,
3422
+ NestedWorkflowStep,
3423
+ UnknownStep
3424
+ }) => {
3425
+ switch (step.kind) {
3426
+ case "step":
3427
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Step?.(step) ?? renderUnknown(step, UnknownStep) });
3428
+ case "map-step":
3429
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: MapStep?.(step) ?? renderUnknown(step, UnknownStep) });
3430
+ case "foreach-step":
3431
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: ForEachStep?.(step) ?? renderUnknown(step, UnknownStep) });
3432
+ case "parallel-step":
3433
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: ParallelStep?.(step) ?? renderUnknown(step, UnknownStep) });
3434
+ case "conditional":
3435
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: Conditional?.(step) ?? renderUnknown(step, UnknownStep) });
3436
+ case "loop-step":
3437
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: LoopStep?.(step) ?? renderUnknown(step, UnknownStep) });
3438
+ case "sleep-step":
3439
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: SleepStep?.(step) ?? renderUnknown(step, UnknownStep) });
3440
+ case "sleep-until-step":
3441
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: SleepUntilStep?.(step) ?? renderUnknown(step, UnknownStep) });
3442
+ case "nested-workflow-step":
3443
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: NestedWorkflowStep?.(step) ?? renderUnknown(step, UnknownStep) });
3444
+ default:
3445
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderUnknown(step, UnknownStep) });
3446
+ }
3447
+ };
3448
+ var WorkflowStepFactory = react.memo(WorkflowStepFactoryComponent);
3449
+
3450
+ // src/voice/record-mic-to-file.ts
3451
+ async function recordMicrophoneToFile(onFinish) {
3452
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
3453
+ const mediaRecorder = new MediaRecorder(stream);
3454
+ let chunks = [];
3455
+ mediaRecorder.ondataavailable = (e) => {
3456
+ chunks.push(e.data);
3457
+ };
3458
+ mediaRecorder.onstop = () => {
3459
+ const blob = new Blob(chunks, { type: "audio/webm" });
3460
+ const file = new File([blob], `recording-${Date.now()}.webm`, {
3461
+ type: "audio/webm",
3462
+ lastModified: Date.now()
3463
+ });
3464
+ stream.getTracks().forEach((track) => track.stop());
3465
+ onFinish(file);
3466
+ };
3467
+ return mediaRecorder;
3468
+ }
3469
+
3470
+ // src/voice/play-stream-with-web-audio.ts
3471
+ async function playStreamWithWebAudio(stream, onEnded) {
3472
+ const audioContext = new window.AudioContext();
3473
+ const reader = stream.getReader();
3474
+ const chunks = [];
3475
+ try {
3476
+ while (true) {
3477
+ const { done, value } = await reader.read();
3478
+ if (done) break;
3479
+ chunks.push(value);
3480
+ }
3481
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
3482
+ const combinedBuffer = new Uint8Array(totalLength);
3483
+ let offset = 0;
3484
+ for (const chunk of chunks) {
3485
+ combinedBuffer.set(chunk, offset);
3486
+ offset += chunk.length;
3487
+ }
3488
+ const audioBuffer = await audioContext.decodeAudioData(combinedBuffer.buffer);
3489
+ const source = audioContext.createBufferSource();
3490
+ source.buffer = audioBuffer;
3491
+ source.onended = onEnded ?? null;
3492
+ source.connect(audioContext.destination);
3493
+ source.start();
3494
+ return () => {
3495
+ source.onended = null;
3496
+ source.stop();
3497
+ void audioContext.close();
3498
+ };
3499
+ } catch (error) {
3500
+ await reader.cancel().catch(() => void 0);
3501
+ await audioContext.close().catch(() => void 0);
3502
+ throw error;
3503
+ } finally {
3504
+ reader.releaseLock();
3505
+ }
3506
+ }
3507
+ var useSpeechRecognition = ({
3508
+ language = "en-US",
3509
+ agentId,
3510
+ requestContext
3511
+ }) => {
3512
+ const client = useMastraClient();
3513
+ const [agent, setAgent] = react.useState(null);
3514
+ react.useEffect(() => {
3515
+ let cancelled = false;
3516
+ if (!agentId) {
3517
+ setAgent(null);
3518
+ return () => {
3519
+ cancelled = true;
3520
+ };
3521
+ }
3522
+ const agent2 = client.getAgent(agentId);
3523
+ const check = async () => {
3524
+ try {
3525
+ const speakers = await agent2.voice.getSpeakers(requestContext);
3526
+ if (!cancelled) {
3527
+ setAgent(speakers.length > 0 ? agent2 : null);
3528
+ }
3529
+ } catch {
3530
+ if (!cancelled) {
3531
+ setAgent(null);
3532
+ }
3533
+ }
3534
+ };
3535
+ void check();
3536
+ return () => {
3537
+ cancelled = true;
3538
+ };
3539
+ }, [agentId, client, requestContext]);
3540
+ const browserSpeechRecognition = useBrowserSpeechRecognition({ language });
3541
+ const mastraSpeechRecognition = useMastraSpeechToText({ agent, language });
3542
+ if (!agent) {
3543
+ return browserSpeechRecognition;
3544
+ }
3545
+ return mastraSpeechRecognition;
3546
+ };
3547
+ var useBrowserSpeechRecognition = ({ language = "en-US" }) => {
3548
+ const speechRecognitionRef = react.useRef(null);
3549
+ const [state, setState] = react.useState({
3550
+ isListening: false,
3551
+ transcript: "",
3552
+ error: null
3553
+ });
3554
+ const start = () => {
3555
+ if (!speechRecognitionRef.current) return;
3556
+ speechRecognitionRef.current.start();
3557
+ };
3558
+ const stop = () => {
3559
+ if (!speechRecognitionRef.current) return;
3560
+ speechRecognitionRef.current.stop();
3561
+ };
3562
+ react.useEffect(() => {
3563
+ if (!("webkitSpeechRecognition" in window) && !("SpeechRecognition" in window)) {
3564
+ setState((prev) => ({ ...prev, error: "Speech Recognition not supported in this browser" }));
3565
+ return;
3566
+ }
3567
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
3568
+ const recognition = new SpeechRecognition();
3569
+ speechRecognitionRef.current = recognition;
3570
+ recognition.continuous = true;
3571
+ recognition.lang = language;
3572
+ recognition.onstart = () => {
3573
+ setState((prev) => ({ ...prev, isListening: true, error: null }));
3574
+ };
3575
+ recognition.onresult = (event) => {
3576
+ let finalTranscript = "";
3577
+ for (let i = event.resultIndex; i < event.results.length; i++) {
3578
+ const transcript = event.results[i][0].transcript;
3579
+ if (event.results[i].isFinal) {
3580
+ finalTranscript += transcript + " ";
3581
+ }
3582
+ }
3583
+ setState((prev) => ({ ...prev, transcript: finalTranscript }));
3584
+ };
3585
+ recognition.onerror = (event) => {
3586
+ setState((prev) => ({ ...prev, error: `Error: ${event.error}` }));
3587
+ };
3588
+ recognition.onend = () => setState((prev) => ({ ...prev, isListening: false }));
3589
+ return () => {
3590
+ try {
3591
+ recognition.stop();
3592
+ } catch {
3593
+ }
3594
+ recognition.onstart = null;
3595
+ recognition.onresult = null;
3596
+ recognition.onerror = null;
3597
+ recognition.onend = null;
3598
+ speechRecognitionRef.current = null;
3599
+ };
3600
+ }, [language]);
3601
+ return {
3602
+ ...state,
3603
+ start,
3604
+ stop
3605
+ };
3606
+ };
3607
+ var useMastraSpeechToText = ({
3608
+ agent,
3609
+ language
3610
+ }) => {
3611
+ const [state, setState] = react.useState({
3612
+ isListening: false,
3613
+ transcript: "",
3614
+ error: null
3615
+ });
3616
+ const recorderRef = react.useRef(null);
3617
+ const sessionRef = react.useRef(0);
3618
+ const startInFlightRef = react.useRef(false);
3619
+ react.useEffect(() => {
3620
+ return () => {
3621
+ sessionRef.current += 1;
3622
+ startInFlightRef.current = false;
3623
+ recorderRef.current?.stop();
3624
+ recorderRef.current = null;
3625
+ };
3626
+ }, [agent]);
3627
+ const handleFinish = (session) => (file) => {
3628
+ if (!agent || session !== sessionRef.current) return;
3629
+ recorderRef.current = null;
3630
+ setState((prev) => ({ ...prev, isListening: false }));
3631
+ void agent.voice.listen(file, { language }).then((res) => {
3632
+ if (session !== sessionRef.current) return;
3633
+ setState((prev) => ({ ...prev, transcript: res.text, error: null }));
3634
+ }).catch((error) => {
3635
+ if (session !== sessionRef.current) return;
3636
+ const message = error instanceof Error ? error.message : "Failed to transcribe speech";
3637
+ setState((prev) => ({ ...prev, error: message }));
3638
+ });
3639
+ };
3640
+ const start = () => {
3641
+ if (!agent || startInFlightRef.current || recorderRef.current) return;
3642
+ startInFlightRef.current = true;
3643
+ const session = sessionRef.current;
3644
+ void recordMicrophoneToFile(handleFinish(session)).then((recorder) => {
3645
+ startInFlightRef.current = false;
3646
+ if (session !== sessionRef.current) {
3647
+ try {
3648
+ recorder.stop();
3649
+ } catch {
3650
+ }
3651
+ return;
3652
+ }
3653
+ recorderRef.current = recorder;
3654
+ setState((prev) => ({ ...prev, isListening: true, error: null }));
3655
+ recorder.start();
3656
+ }).catch((error) => {
3657
+ startInFlightRef.current = false;
3658
+ if (session !== sessionRef.current) return;
3659
+ const message = error instanceof Error ? error.message : "Failed to start speech recording";
3660
+ setState((prev) => ({ ...prev, isListening: false, error: message }));
3661
+ });
3662
+ };
3663
+ const stop = () => {
3664
+ sessionRef.current += 1;
3665
+ startInFlightRef.current = false;
3666
+ recorderRef.current?.stop();
3667
+ recorderRef.current = null;
3668
+ setState((prev) => ({ ...prev, isListening: false }));
3669
+ };
3670
+ return {
3671
+ ...state,
3672
+ start,
3673
+ stop
3674
+ };
3675
+ };
3676
+
3677
+ exports.AgentIcon = AgentIcon;
3678
+ exports.CLIENT_MESSAGE_ID_KEY = CLIENT_MESSAGE_ID_KEY;
3679
+ exports.CodeBlock = CodeBlock;
3680
+ exports.CodeBlockClass = CodeBlockClass;
3681
+ exports.CodeCopyButton = CodeCopyButton;
3682
+ exports.Entity = Entity;
3683
+ exports.EntityCaret = EntityCaret;
3684
+ exports.EntityContent = EntityContent;
3685
+ exports.EntityContentClass = EntityContentClass;
3686
+ exports.EntityTrigger = EntityTrigger;
3687
+ exports.EntityTriggerClass = EntityTriggerClass;
3688
+ exports.EntityTriggerVariantClasses = EntityTriggerVariantClasses;
3689
+ exports.Entry = Entry;
3690
+ exports.EntryClass = EntryClass;
3691
+ exports.EntryTitle = EntryTitle;
3692
+ exports.EntryTitleClass = EntryTitleClass;
3693
+ exports.Icon = Icon;
3694
+ exports.IconButton = IconButton;
3695
+ exports.IconButtonClass = IconButtonClass;
3696
+ exports.IconSizes = IconSizes;
3697
+ exports.MastraReactProvider = MastraReactProvider;
3698
+ exports.Message = Message;
3699
+ exports.MessageActions = MessageActions;
3700
+ exports.MessageActionsClass = MessageActionsClass;
3701
+ exports.MessageClass = MessageClass;
3702
+ exports.MessageContent = MessageContent;
3703
+ exports.MessageContentClass = MessageContentClass;
3704
+ exports.MessageFactory = MessageFactory;
3705
+ exports.MessageList = MessageList;
3706
+ exports.MessageListClass = MessageListClass;
3707
+ exports.MessageStreaming = MessageStreaming;
3708
+ exports.MessageStreamingClass = MessageStreamingClass;
3709
+ exports.MessageUsage = MessageUsage;
3710
+ exports.MessageUsageClass = MessageUsageClass;
3711
+ exports.MessageUsageEntry = MessageUsageEntry;
3712
+ exports.MessageUsageEntryClass = MessageUsageEntryClass;
3713
+ exports.MessageUsageValue = MessageUsageValue;
3714
+ exports.MessageUsageValueClass = MessageUsageValueClass;
3715
+ exports.MessageUsages = MessageUsages;
3716
+ exports.MessageUsagesClass = MessageUsagesClass;
3717
+ exports.ToolApproval = ToolApproval;
3718
+ exports.ToolApprovalActions = ToolApprovalActions;
3719
+ exports.ToolApprovalActionsClass = ToolApprovalActionsClass;
3720
+ exports.ToolApprovalClass = ToolApprovalClass;
3721
+ exports.ToolApprovalContent = ToolApprovalContent;
3722
+ exports.ToolApprovalContentClass = ToolApprovalContentClass;
3723
+ exports.ToolApprovalHeader = ToolApprovalHeader;
3724
+ exports.ToolApprovalHeaderClass = ToolApprovalHeaderClass;
3725
+ exports.ToolApprovalTitle = ToolApprovalTitle;
3726
+ exports.ToolApprovalTitleClass = ToolApprovalTitleClass;
3727
+ exports.ToolsIcon = ToolsIcon;
3728
+ exports.Tooltip = Tooltip;
3729
+ exports.TooltipContent = TooltipContent;
3730
+ exports.TooltipContentClass = TooltipContentClass;
3731
+ exports.TooltipTrigger = TooltipTrigger;
3732
+ exports.WorkflowIcon = WorkflowIcon;
3733
+ exports.WorkflowStepFactory = WorkflowStepFactory;
3734
+ exports.accumulateChunk = accumulateChunk;
3735
+ exports.accumulateNetworkChunk = accumulateNetworkChunk;
3736
+ exports.finishStreamingAssistantMessage = finishStreamingAssistantMessage;
3737
+ exports.fromCoreUserMessageToMastraDBMessage = fromCoreUserMessageToMastraDBMessage;
3738
+ exports.fromCoreUserMessagesToMastraDBMessage = fromCoreUserMessagesToMastraDBMessage;
3739
+ exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
3740
+ exports.playStreamWithWebAudio = playStreamWithWebAudio;
3741
+ exports.recordMicrophoneToFile = recordMicrophoneToFile;
3742
+ exports.useCancelWorkflowRun = useCancelWorkflowRun;
3743
+ exports.useChat = useChat;
3744
+ exports.useCreateWorkflowRun = useCreateWorkflowRun;
3745
+ exports.useEntity = useEntity;
3746
+ exports.useMastraClient = useMastraClient;
3747
+ exports.useSpeechRecognition = useSpeechRecognition;
3748
+ exports.useStreamWorkflow = useStreamWorkflow;
70
3749
  //# sourceMappingURL=index.cjs.map
3750
+ //# sourceMappingURL=index.cjs.map