@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/CHANGELOG.md +127 -0
- package/dist/index.cjs +137 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +137 -30
- package/dist/index.js.map +1 -1
- package/dist/react.css +1 -1
- package/dist/src/agent/hooks.d.ts +4 -1
- package/dist/src/lib/ai-sdk/types.d.ts +24 -1
- package/package.json +9 -8
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.
|
|
138
|
+
text: chunk.payload.reason
|
|
110
139
|
}
|
|
111
140
|
],
|
|
112
141
|
metadata: {
|
|
113
142
|
...metadata,
|
|
114
|
-
status: "
|
|
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
|
|
268
|
-
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
|
|
288
|
-
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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 ({
|
|
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 =
|
|
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
|
|
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({
|