@mastra/react 0.1.0-beta.4 → 0.1.0-beta.6

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
  }
@@ -651,6 +665,20 @@ const toAssistantUIMessage = (message) => {
651
665
  }
652
666
  return baseToolCall;
653
667
  }
668
+ const requireApprovalMetadata = extendedMessage.metadata?.requireApprovalMetadata;
669
+ const partToolCallId = "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : void 0;
670
+ const suspensionData = partToolCallId ? requireApprovalMetadata?.[partToolCallId] : void 0;
671
+ if (suspensionData) {
672
+ const toolName = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.startsWith("tool-") ? part.type.substring(5) : "";
673
+ return {
674
+ type: "tool-call",
675
+ toolCallId: partToolCallId,
676
+ toolName,
677
+ argsText: "input" in part ? JSON.stringify(part.input) : "{}",
678
+ args: "input" in part ? part.input : {},
679
+ metadata: extendedMessage.metadata
680
+ };
681
+ }
654
682
  return {
655
683
  type: "text",
656
684
  text: "",
@@ -737,7 +765,6 @@ const resolveInitialMessages = (messages) => {
737
765
  childMessages,
738
766
  result: finalResult?.text || ""
739
767
  };
740
- console.log("json", json);
741
768
  const nextMessage = {
742
769
  role: "assistant",
743
770
  parts: [
@@ -765,6 +792,18 @@ const resolveInitialMessages = (messages) => {
765
792
  return message;
766
793
  }
767
794
  }
795
+ const extendedMessage = message;
796
+ const pendingToolApprovals = extendedMessage.metadata?.pendingToolApprovals;
797
+ if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
798
+ return {
799
+ ...message,
800
+ metadata: {
801
+ ...message.metadata,
802
+ mode: "stream",
803
+ requireApprovalMetadata: pendingToolApprovals
804
+ }
805
+ };
806
+ }
768
807
  return message;
769
808
  });
770
809
  };
@@ -1213,12 +1252,24 @@ const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1213
1252
  };
1214
1253
  };
1215
1254
 
1216
- const useChat = ({ agentId, initializeMessages }) => {
1217
- const _currentRunId = useRef(void 0);
1255
+ const useChat = ({ agentId, resourceId, initializeMessages }) => {
1256
+ const extractRunIdFromMessages = (messages2) => {
1257
+ for (const message of messages2) {
1258
+ const pendingToolApprovals = message.metadata?.pendingToolApprovals;
1259
+ if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
1260
+ const suspensionData = Object.values(pendingToolApprovals)[0];
1261
+ if (suspensionData?.runId) {
1262
+ return suspensionData.runId;
1263
+ }
1264
+ }
1265
+ }
1266
+ return void 0;
1267
+ };
1268
+ const initialMessages = initializeMessages?.() || [];
1269
+ const initialRunId = extractRunIdFromMessages(initialMessages);
1270
+ const _currentRunId = useRef(initialRunId);
1218
1271
  const _onChunk = useRef(void 0);
1219
- const [messages, setMessages] = useState(
1220
- () => resolveInitialMessages(initializeMessages?.() || [])
1221
- );
1272
+ const [messages, setMessages] = useState(() => resolveInitialMessages(initialMessages));
1222
1273
  const [toolCallApprovals, setToolCallApprovals] = useState({});
1223
1274
  const baseClient = useMastraClient();
1224
1275
  const [isRunning, setIsRunning] = useState(false);
@@ -1228,7 +1279,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1228
1279
  threadId,
1229
1280
  modelSettings,
1230
1281
  signal,
1231
- onFinish
1282
+ onFinish,
1283
+ tracingOptions
1232
1284
  }) => {
1233
1285
  const {
1234
1286
  frequencyPenalty,
@@ -1250,7 +1302,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1250
1302
  const agent = clientWithAbort.getAgent(agentId);
1251
1303
  const response = await agent.generate({
1252
1304
  messages: coreUserMessages,
1253
- runId: agentId,
1305
+ runId: v4(),
1254
1306
  maxSteps,
1255
1307
  modelSettings: {
1256
1308
  frequencyPenalty,
@@ -1263,8 +1315,9 @@ const useChat = ({ agentId, initializeMessages }) => {
1263
1315
  },
1264
1316
  instructions,
1265
1317
  requestContext,
1266
- ...threadId ? { threadId, resourceId: agentId } : {},
1267
- providerOptions
1318
+ ...threadId ? { threadId, resourceId: resourceId || agentId } : {},
1319
+ providerOptions,
1320
+ tracingOptions
1268
1321
  });
1269
1322
  setIsRunning(false);
1270
1323
  if (response && "uiMessages" in response.response && response.response.uiMessages) {
@@ -1278,7 +1331,15 @@ const useChat = ({ agentId, initializeMessages }) => {
1278
1331
  setMessages((prev) => [...prev, ...mastraUIMessages]);
1279
1332
  }
1280
1333
  };
1281
- const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
1334
+ const stream = async ({
1335
+ coreUserMessages,
1336
+ requestContext,
1337
+ threadId,
1338
+ onChunk,
1339
+ modelSettings,
1340
+ signal,
1341
+ tracingOptions
1342
+ }) => {
1282
1343
  const {
1283
1344
  frequencyPenalty,
1284
1345
  presencePenalty,
@@ -1298,7 +1359,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1298
1359
  abortSignal: signal
1299
1360
  });
1300
1361
  const agent = clientWithAbort.getAgent(agentId);
1301
- const runId = agentId;
1362
+ const runId = v4();
1302
1363
  const response = await agent.stream({
1303
1364
  messages: coreUserMessages,
1304
1365
  runId,
@@ -1314,9 +1375,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1314
1375
  },
1315
1376
  instructions,
1316
1377
  requestContext,
1317
- ...threadId ? { threadId, resourceId: agentId } : {},
1378
+ ...threadId ? { threadId, resourceId: resourceId || agentId } : {},
1318
1379
  providerOptions,
1319
- requireToolApproval
1380
+ requireToolApproval,
1381
+ tracingOptions
1320
1382
  });
1321
1383
  _onChunk.current = onChunk;
1322
1384
  _currentRunId.current = runId;
@@ -1334,7 +1396,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1334
1396
  threadId,
1335
1397
  onNetworkChunk,
1336
1398
  modelSettings,
1337
- signal
1399
+ signal,
1400
+ tracingOptions
1338
1401
  }) => {
1339
1402
  const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
1340
1403
  setIsRunning(true);
@@ -1343,6 +1406,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1343
1406
  abortSignal: signal
1344
1407
  });
1345
1408
  const agent = clientWithAbort.getAgent(agentId);
1409
+ const runId = v4();
1346
1410
  const response = await agent.network({
1347
1411
  messages: coreUserMessages,
1348
1412
  maxSteps,
@@ -1355,9 +1419,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1355
1419
  topK,
1356
1420
  topP
1357
1421
  },
1358
- runId: agentId,
1422
+ runId,
1359
1423
  requestContext,
1360
- ...threadId ? { thread: threadId, resourceId: agentId } : {}
1424
+ ...threadId ? { thread: threadId, resourceId: resourceId || agentId } : {},
1425
+ tracingOptions
1361
1426
  });
1362
1427
  const transformer = new AISdkNetworkTransformer();
1363
1428
  await response.processDataStream({