@mastra/react 0.0.20 → 0.0.21-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.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { createContext, useContext, useRef, useState, Fragment, useLayoutEffect, useEffect } from 'react';
3
3
  import { MastraClient } from '@mastra/client-js';
4
+ import { v4 } from '@lukeed/uuid';
4
5
  import { ChevronDownIcon, CheckIcon, CopyIcon } from 'lucide-react';
5
6
  import { twMerge } from 'tailwind-merge';
6
7
  import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
@@ -255,17 +256,19 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
255
256
  if (!lastMessage || lastMessage.role !== "assistant") return result;
256
257
  const parts = [...lastMessage.parts];
257
258
  const toolPartIndex = parts.findIndex(
258
- (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
259
+ (part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
259
260
  );
260
261
  if (toolPartIndex !== -1) {
261
262
  const toolPart = parts[toolPartIndex];
262
- if (toolPart.type === "dynamic-tool") {
263
+ if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
264
+ const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
265
+ const toolCallId = toolPart.toolCallId;
263
266
  if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
264
267
  const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
265
268
  parts[toolPartIndex] = {
266
269
  type: "dynamic-tool",
267
- toolName: toolPart.toolName,
268
- toolCallId: toolPart.toolCallId,
270
+ toolName,
271
+ toolCallId,
269
272
  state: "output-error",
270
273
  input: toolPart.input,
271
274
  errorText: String(error),
@@ -284,8 +287,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
284
287
  }
285
288
  parts[toolPartIndex] = {
286
289
  type: "dynamic-tool",
287
- toolName: toolPart.toolName,
288
- toolCallId: toolPart.toolCallId,
290
+ toolName,
291
+ toolCallId,
289
292
  state: "output-available",
290
293
  input: toolPart.input,
291
294
  output,
@@ -307,11 +310,14 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
307
310
  if (!lastMessage || lastMessage.role !== "assistant") return result;
308
311
  const parts = [...lastMessage.parts];
309
312
  const toolPartIndex = parts.findIndex(
310
- (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
313
+ (part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
311
314
  );
312
315
  if (toolPartIndex !== -1) {
313
316
  const toolPart = parts[toolPartIndex];
314
- if (toolPart.type === "dynamic-tool") {
317
+ if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
318
+ const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : typeof toolPart.type === "string" && toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
319
+ const toolCallId = toolPart.toolCallId;
320
+ const input = toolPart.input;
315
321
  if (chunk.payload.output?.type?.startsWith("workflow-")) {
316
322
  const existingWorkflowState = toolPart.output || {};
317
323
  const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
@@ -319,7 +325,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
319
325
  chunk.payload.output
320
326
  );
321
327
  parts[toolPartIndex] = {
322
- ...toolPart,
328
+ type: "dynamic-tool",
329
+ toolName,
330
+ toolCallId,
331
+ state: "input-streaming",
332
+ input,
323
333
  output: updatedWorkflowState
324
334
  };
325
335
  } else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
@@ -328,7 +338,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
328
338
  const currentOutput = toolPart.output || [];
329
339
  const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
330
340
  parts[toolPartIndex] = {
331
- ...toolPart,
341
+ type: "dynamic-tool",
342
+ toolName,
343
+ toolCallId,
344
+ state: "input-streaming",
345
+ input,
332
346
  output: [...existingOutput, chunk.payload.output]
333
347
  };
334
348
  }
@@ -642,6 +656,20 @@ const toAssistantUIMessage = (message) => {
642
656
  }
643
657
  return baseToolCall;
644
658
  }
659
+ const requireApprovalMetadata = extendedMessage.metadata?.requireApprovalMetadata;
660
+ const partToolCallId = "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : void 0;
661
+ const suspensionData = partToolCallId ? requireApprovalMetadata?.[partToolCallId] : void 0;
662
+ if (suspensionData) {
663
+ const toolName = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.startsWith("tool-") ? part.type.substring(5) : "";
664
+ return {
665
+ type: "tool-call",
666
+ toolCallId: partToolCallId,
667
+ toolName,
668
+ argsText: "input" in part ? JSON.stringify(part.input) : "{}",
669
+ args: "input" in part ? part.input : {},
670
+ metadata: extendedMessage.metadata
671
+ };
672
+ }
645
673
  return {
646
674
  type: "text",
647
675
  text: "",
@@ -726,7 +754,6 @@ const resolveInitialMessages = (messages) => {
726
754
  childMessages,
727
755
  result: finalResult?.text || ""
728
756
  };
729
- console.log("json", json);
730
757
  const nextMessage = {
731
758
  role: "assistant",
732
759
  parts: [
@@ -754,6 +781,18 @@ const resolveInitialMessages = (messages) => {
754
781
  return message;
755
782
  }
756
783
  }
784
+ const extendedMessage = message;
785
+ const pendingToolApprovals = extendedMessage.metadata?.pendingToolApprovals;
786
+ if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
787
+ return {
788
+ ...message,
789
+ metadata: {
790
+ ...message.metadata,
791
+ mode: "stream",
792
+ requireApprovalMetadata: pendingToolApprovals
793
+ }
794
+ };
795
+ }
757
796
  return message;
758
797
  });
759
798
  };
@@ -1157,12 +1196,24 @@ class AISdkNetworkTransformer {
1157
1196
  };
1158
1197
  }
1159
1198
 
1160
- const useChat = ({ agentId, initializeMessages }) => {
1161
- const _currentRunId = useRef(void 0);
1199
+ const useChat = ({ agentId, resourceId, initializeMessages }) => {
1200
+ const extractRunIdFromMessages = (messages2) => {
1201
+ for (const message of messages2) {
1202
+ const pendingToolApprovals = message.metadata?.pendingToolApprovals;
1203
+ if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
1204
+ const suspensionData = Object.values(pendingToolApprovals)[0];
1205
+ if (suspensionData?.runId) {
1206
+ return suspensionData.runId;
1207
+ }
1208
+ }
1209
+ }
1210
+ return void 0;
1211
+ };
1212
+ const initialMessages = initializeMessages?.() || [];
1213
+ const initialRunId = extractRunIdFromMessages(initialMessages);
1214
+ const _currentRunId = useRef(initialRunId);
1162
1215
  const _onChunk = useRef(void 0);
1163
- const [messages, setMessages] = useState(
1164
- () => resolveInitialMessages(initializeMessages?.() || [])
1165
- );
1216
+ const [messages, setMessages] = useState(() => resolveInitialMessages(initialMessages));
1166
1217
  const [toolCallApprovals, setToolCallApprovals] = useState({});
1167
1218
  const baseClient = useMastraClient();
1168
1219
  const [isRunning, setIsRunning] = useState(false);
@@ -1194,7 +1245,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1194
1245
  const agent = clientWithAbort.getAgent(agentId);
1195
1246
  const response = await agent.generate({
1196
1247
  messages: coreUserMessages,
1197
- runId: agentId,
1248
+ runId: v4(),
1198
1249
  maxSteps,
1199
1250
  modelSettings: {
1200
1251
  frequencyPenalty,
@@ -1207,7 +1258,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1207
1258
  },
1208
1259
  instructions,
1209
1260
  runtimeContext,
1210
- ...threadId ? { threadId, resourceId: agentId } : {},
1261
+ ...threadId ? { threadId, resourceId: resourceId || agentId } : {},
1211
1262
  providerOptions
1212
1263
  });
1213
1264
  setIsRunning(false);
@@ -1242,7 +1293,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1242
1293
  abortSignal: signal
1243
1294
  });
1244
1295
  const agent = clientWithAbort.getAgent(agentId);
1245
- const runId = agentId;
1296
+ const runId = v4();
1246
1297
  const response = await agent.stream({
1247
1298
  messages: coreUserMessages,
1248
1299
  runId,
@@ -1258,7 +1309,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1258
1309
  },
1259
1310
  instructions,
1260
1311
  runtimeContext,
1261
- ...threadId ? { threadId, resourceId: agentId } : {},
1312
+ ...threadId ? { threadId, resourceId: resourceId || agentId } : {},
1262
1313
  providerOptions,
1263
1314
  requireToolApproval
1264
1315
  });
@@ -1287,6 +1338,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1287
1338
  abortSignal: signal
1288
1339
  });
1289
1340
  const agent = clientWithAbort.getAgent(agentId);
1341
+ const runId = v4();
1290
1342
  const response = await agent.network({
1291
1343
  messages: coreUserMessages,
1292
1344
  maxSteps,
@@ -1299,9 +1351,9 @@ const useChat = ({ agentId, initializeMessages }) => {
1299
1351
  topK,
1300
1352
  topP
1301
1353
  },
1302
- runId: agentId,
1354
+ runId,
1303
1355
  runtimeContext,
1304
- ...threadId ? { thread: threadId, resourceId: agentId } : {}
1356
+ ...threadId ? { thread: threadId, resourceId: resourceId || agentId } : {}
1305
1357
  });
1306
1358
  const transformer = new AISdkNetworkTransformer();
1307
1359
  await response.processDataStream({