@mastra/react 0.1.0-beta.1 → 0.1.0-beta.11

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';
@@ -46,7 +47,7 @@ const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
46
47
  return {
47
48
  ...prev,
48
49
  status: chunk.payload.workflowStatus,
49
- ...finalStatus === "success" && lastStep?.status === "success" ? { result: lastStep?.output } : finalStatus === "failed" && lastStep?.status === "failed" ? { error: lastStep?.error } : {}
50
+ ...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 } : {}
50
51
  };
51
52
  }
52
53
  const { stepCallId, stepName, ...newPayload } = chunk.payload ?? {};
@@ -98,6 +99,34 @@ const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
98
99
  };
99
100
  const toUIMessage = ({ chunk, conversation, metadata }) => {
100
101
  const result = [...conversation];
102
+ if (chunk.type.startsWith("data-")) {
103
+ const lastMessage = result[result.length - 1];
104
+ if (!lastMessage || lastMessage.role !== "assistant") {
105
+ const newMessage = {
106
+ id: `data-${chunk.runId}-${Date.now()}`,
107
+ role: "assistant",
108
+ parts: [
109
+ {
110
+ type: chunk.type,
111
+ data: "data" in chunk ? chunk.data : void 0
112
+ }
113
+ ],
114
+ metadata
115
+ };
116
+ return [...result, newMessage];
117
+ }
118
+ const updatedMessage = {
119
+ ...lastMessage,
120
+ parts: [
121
+ ...lastMessage.parts,
122
+ {
123
+ type: chunk.type,
124
+ data: "data" in chunk ? chunk.data : void 0
125
+ }
126
+ ]
127
+ };
128
+ return [...result.slice(0, -1), updatedMessage];
129
+ }
101
130
  switch (chunk.type) {
102
131
  case "tripwire": {
103
132
  const newMessage = {
@@ -106,12 +135,17 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
106
135
  parts: [
107
136
  {
108
137
  type: "text",
109
- text: chunk.payload.tripwireReason
138
+ text: chunk.payload.reason
110
139
  }
111
140
  ],
112
141
  metadata: {
113
142
  ...metadata,
114
- status: "warning"
143
+ status: "tripwire",
144
+ tripwire: {
145
+ retry: chunk.payload.retry,
146
+ tripwirePayload: chunk.payload.metadata,
147
+ processorId: chunk.payload.processorId
148
+ }
115
149
  }
116
150
  };
117
151
  return [...result, newMessage];
@@ -255,17 +289,19 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
255
289
  if (!lastMessage || lastMessage.role !== "assistant") return result;
256
290
  const parts = [...lastMessage.parts];
257
291
  const toolPartIndex = parts.findIndex(
258
- (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
292
+ (part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
259
293
  );
260
294
  if (toolPartIndex !== -1) {
261
295
  const toolPart = parts[toolPartIndex];
262
- if (toolPart.type === "dynamic-tool") {
296
+ if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
297
+ const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
298
+ const toolCallId = toolPart.toolCallId;
263
299
  if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
264
300
  const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
265
301
  parts[toolPartIndex] = {
266
302
  type: "dynamic-tool",
267
- toolName: toolPart.toolName,
268
- toolCallId: toolPart.toolCallId,
303
+ toolName,
304
+ toolCallId,
269
305
  state: "output-error",
270
306
  input: toolPart.input,
271
307
  errorText: String(error),
@@ -284,8 +320,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
284
320
  }
285
321
  parts[toolPartIndex] = {
286
322
  type: "dynamic-tool",
287
- toolName: toolPart.toolName,
288
- toolCallId: toolPart.toolCallId,
323
+ toolName,
324
+ toolCallId,
289
325
  state: "output-available",
290
326
  input: toolPart.input,
291
327
  output,
@@ -307,11 +343,14 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
307
343
  if (!lastMessage || lastMessage.role !== "assistant") return result;
308
344
  const parts = [...lastMessage.parts];
309
345
  const toolPartIndex = parts.findIndex(
310
- (part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
346
+ (part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
311
347
  );
312
348
  if (toolPartIndex !== -1) {
313
349
  const toolPart = parts[toolPartIndex];
314
- if (toolPart.type === "dynamic-tool") {
350
+ if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
351
+ const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : typeof toolPart.type === "string" && toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
352
+ const toolCallId = toolPart.toolCallId;
353
+ const input = toolPart.input;
315
354
  if (chunk.payload.output?.type?.startsWith("workflow-")) {
316
355
  const existingWorkflowState = toolPart.output || {};
317
356
  const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
@@ -319,7 +358,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
319
358
  chunk.payload.output
320
359
  );
321
360
  parts[toolPartIndex] = {
322
- ...toolPart,
361
+ type: "dynamic-tool",
362
+ toolName,
363
+ toolCallId,
364
+ state: "input-streaming",
365
+ input,
323
366
  output: updatedWorkflowState
324
367
  };
325
368
  } else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
@@ -328,7 +371,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
328
371
  const currentOutput = toolPart.output || [];
329
372
  const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
330
373
  parts[toolPartIndex] = {
331
- ...toolPart,
374
+ type: "dynamic-tool",
375
+ toolName,
376
+ toolCallId,
377
+ state: "input-streaming",
378
+ input,
332
379
  output: [...existingOutput, chunk.payload.output]
333
380
  };
334
381
  }
@@ -651,6 +698,29 @@ const toAssistantUIMessage = (message) => {
651
698
  }
652
699
  return baseToolCall;
653
700
  }
701
+ const requireApprovalMetadata = extendedMessage.metadata?.requireApprovalMetadata;
702
+ const partToolCallId = "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : void 0;
703
+ const suspensionData = partToolCallId ? requireApprovalMetadata?.[partToolCallId] : void 0;
704
+ if (suspensionData) {
705
+ const toolName = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.startsWith("tool-") ? part.type.substring(5) : "";
706
+ return {
707
+ type: "tool-call",
708
+ toolCallId: partToolCallId,
709
+ toolName,
710
+ argsText: "input" in part ? JSON.stringify(part.input) : "{}",
711
+ args: "input" in part ? part.input : {},
712
+ metadata: extendedMessage.metadata
713
+ };
714
+ }
715
+ if (part.type.startsWith("data-")) {
716
+ return {
717
+ type: "data",
718
+ name: part.type.substring(5),
719
+ // Extract name from 'data-{name}'
720
+ data: part.data,
721
+ metadata: message.metadata
722
+ };
723
+ }
654
724
  return {
655
725
  type: "text",
656
726
  text: "",
@@ -737,7 +807,6 @@ const resolveInitialMessages = (messages) => {
737
807
  childMessages,
738
808
  result: finalResult?.text || ""
739
809
  };
740
- console.log("json", json);
741
810
  const nextMessage = {
742
811
  role: "assistant",
743
812
  parts: [
@@ -765,6 +834,18 @@ const resolveInitialMessages = (messages) => {
765
834
  return message;
766
835
  }
767
836
  }
837
+ const extendedMessage = message;
838
+ const pendingToolApprovals = extendedMessage.metadata?.pendingToolApprovals;
839
+ if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
840
+ return {
841
+ ...message,
842
+ metadata: {
843
+ ...message.metadata,
844
+ mode: "stream",
845
+ requireApprovalMetadata: pendingToolApprovals
846
+ }
847
+ };
848
+ }
768
849
  return message;
769
850
  });
770
851
  };
@@ -1213,12 +1294,24 @@ const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1213
1294
  };
1214
1295
  };
1215
1296
 
1216
- const useChat = ({ agentId, initializeMessages }) => {
1217
- const _currentRunId = useRef(void 0);
1297
+ const useChat = ({ agentId, resourceId, initializeMessages }) => {
1298
+ const extractRunIdFromMessages = (messages2) => {
1299
+ for (const message of messages2) {
1300
+ const pendingToolApprovals = message.metadata?.pendingToolApprovals;
1301
+ if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
1302
+ const suspensionData = Object.values(pendingToolApprovals)[0];
1303
+ if (suspensionData?.runId) {
1304
+ return suspensionData.runId;
1305
+ }
1306
+ }
1307
+ }
1308
+ return void 0;
1309
+ };
1310
+ const initialMessages = initializeMessages?.() || [];
1311
+ const initialRunId = extractRunIdFromMessages(initialMessages);
1312
+ const _currentRunId = useRef(initialRunId);
1218
1313
  const _onChunk = useRef(void 0);
1219
- const [messages, setMessages] = useState(
1220
- () => resolveInitialMessages(initializeMessages?.() || [])
1221
- );
1314
+ const [messages, setMessages] = useState(() => resolveInitialMessages(initialMessages));
1222
1315
  const [toolCallApprovals, setToolCallApprovals] = useState({});
1223
1316
  const baseClient = useMastraClient();
1224
1317
  const [isRunning, setIsRunning] = useState(false);
@@ -1228,7 +1321,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1228
1321
  threadId,
1229
1322
  modelSettings,
1230
1323
  signal,
1231
- onFinish
1324
+ onFinish,
1325
+ tracingOptions
1232
1326
  }) => {
1233
1327
  const {
1234
1328
  frequencyPenalty,
@@ -1250,7 +1344,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1250
1344
  const agent = clientWithAbort.getAgent(agentId);
1251
1345
  const response = await agent.generate({
1252
1346
  messages: coreUserMessages,
1253
- runId: agentId,
1347
+ runId: v4(),
1254
1348
  maxSteps,
1255
1349
  modelSettings: {
1256
1350
  frequencyPenalty,
@@ -1263,8 +1357,9 @@ const useChat = ({ agentId, initializeMessages }) => {
1263
1357
  },
1264
1358
  instructions,
1265
1359
  requestContext,
1266
- ...threadId ? { threadId, resourceId: agentId } : {},
1267
- providerOptions
1360
+ ...threadId ? { threadId, resourceId: resourceId || agentId } : {},
1361
+ providerOptions,
1362
+ tracingOptions
1268
1363
  });
1269
1364
  setIsRunning(false);
1270
1365
  if (response && "uiMessages" in response.response && response.response.uiMessages) {
@@ -1278,7 +1373,15 @@ const useChat = ({ agentId, initializeMessages }) => {
1278
1373
  setMessages((prev) => [...prev, ...mastraUIMessages]);
1279
1374
  }
1280
1375
  };
1281
- const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
1376
+ const stream = async ({
1377
+ coreUserMessages,
1378
+ requestContext,
1379
+ threadId,
1380
+ onChunk,
1381
+ modelSettings,
1382
+ signal,
1383
+ tracingOptions
1384
+ }) => {
1282
1385
  const {
1283
1386
  frequencyPenalty,
1284
1387
  presencePenalty,
@@ -1298,7 +1401,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1298
1401
  abortSignal: signal
1299
1402
  });
1300
1403
  const agent = clientWithAbort.getAgent(agentId);
1301
- const runId = agentId;
1404
+ const runId = v4();
1302
1405
  const response = await agent.stream({
1303
1406
  messages: coreUserMessages,
1304
1407
  runId,
@@ -1314,9 +1417,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1314
1417
  },
1315
1418
  instructions,
1316
1419
  requestContext,
1317
- ...threadId ? { threadId, resourceId: agentId } : {},
1420
+ ...threadId ? { threadId, resourceId: resourceId || agentId } : {},
1318
1421
  providerOptions,
1319
- requireToolApproval
1422
+ requireToolApproval,
1423
+ tracingOptions
1320
1424
  });
1321
1425
  _onChunk.current = onChunk;
1322
1426
  _currentRunId.current = runId;
@@ -1334,7 +1438,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1334
1438
  threadId,
1335
1439
  onNetworkChunk,
1336
1440
  modelSettings,
1337
- signal
1441
+ signal,
1442
+ tracingOptions
1338
1443
  }) => {
1339
1444
  const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
1340
1445
  setIsRunning(true);
@@ -1343,6 +1448,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1343
1448
  abortSignal: signal
1344
1449
  });
1345
1450
  const agent = clientWithAbort.getAgent(agentId);
1451
+ const runId = v4();
1346
1452
  const response = await agent.network({
1347
1453
  messages: coreUserMessages,
1348
1454
  maxSteps,
@@ -1355,9 +1461,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1355
1461
  topK,
1356
1462
  topP
1357
1463
  },
1358
- runId: agentId,
1464
+ runId,
1359
1465
  requestContext,
1360
- ...threadId ? { thread: threadId, resourceId: agentId } : {}
1466
+ ...threadId ? { thread: threadId, resourceId: resourceId || agentId } : {},
1467
+ tracingOptions
1361
1468
  });
1362
1469
  const transformer = new AISdkNetworkTransformer();
1363
1470
  await response.processDataStream({