@mastra/react 0.0.0-refactor-agent-information-for-recomposable-ui-20251112151814 → 0.0.0-safe-stringify-telemetry-20251205024938
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 +198 -24
- package/dist/index.cjs +95 -103
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +95 -103
- package/dist/index.js.map +1 -1
- package/dist/react.css +1 -1
- package/dist/src/agent/hooks.d.ts +4 -3
- package/dist/src/lib/ai-sdk/types.d.ts +10 -0
- package/package.json +12 -7
- package/dist/src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.d.ts +0 -10
- package/dist/src/lib/ai-sdk/utils/fromCoreUserMessageToUIMessage.test.d.ts +0 -1
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
|
|
268
|
-
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
|
|
288
|
-
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
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -424,10 +438,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
424
438
|
const lastMessage = result[result.length - 1];
|
|
425
439
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
426
440
|
const parts = lastMessage.parts.map((part) => {
|
|
427
|
-
if (
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
441
|
+
if (part.type === "text" && part.state === "streaming") {
|
|
442
|
+
return { ...part, state: "done" };
|
|
443
|
+
}
|
|
444
|
+
if (part.type === "reasoning" && part.state === "streaming") {
|
|
445
|
+
return { ...part, state: "done" };
|
|
431
446
|
}
|
|
432
447
|
return part;
|
|
433
448
|
});
|
|
@@ -599,23 +614,13 @@ const toAssistantUIMessage = (message) => {
|
|
|
599
614
|
};
|
|
600
615
|
}
|
|
601
616
|
if (part.type === "file") {
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
metadata: message.metadata
|
|
610
|
-
};
|
|
611
|
-
}
|
|
612
|
-
if (type === "image") {
|
|
613
|
-
return {
|
|
614
|
-
type,
|
|
615
|
-
image: part.url,
|
|
616
|
-
metadata: message.metadata
|
|
617
|
-
};
|
|
618
|
-
}
|
|
617
|
+
return {
|
|
618
|
+
type: "file",
|
|
619
|
+
mimeType: part.mediaType,
|
|
620
|
+
data: part.url,
|
|
621
|
+
// Use URL as data source
|
|
622
|
+
metadata: message.metadata
|
|
623
|
+
};
|
|
619
624
|
}
|
|
620
625
|
if (part.type === "dynamic-tool") {
|
|
621
626
|
const baseToolCall = {
|
|
@@ -651,6 +656,20 @@ const toAssistantUIMessage = (message) => {
|
|
|
651
656
|
}
|
|
652
657
|
return baseToolCall;
|
|
653
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
|
+
}
|
|
654
673
|
return {
|
|
655
674
|
type: "text",
|
|
656
675
|
text: "",
|
|
@@ -692,9 +711,7 @@ const toAssistantUIMessage = (message) => {
|
|
|
692
711
|
|
|
693
712
|
const resolveInitialMessages = (messages) => {
|
|
694
713
|
return messages.map((message) => {
|
|
695
|
-
const networkPart = message.parts.find(
|
|
696
|
-
(part) => typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" && part.text.includes('"isNetwork":true')
|
|
697
|
-
);
|
|
714
|
+
const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
|
|
698
715
|
if (networkPart && networkPart.type === "text") {
|
|
699
716
|
try {
|
|
700
717
|
const json = JSON.parse(networkPart.text);
|
|
@@ -737,7 +754,6 @@ const resolveInitialMessages = (messages) => {
|
|
|
737
754
|
childMessages,
|
|
738
755
|
result: finalResult?.text || ""
|
|
739
756
|
};
|
|
740
|
-
console.log("json", json);
|
|
741
757
|
const nextMessage = {
|
|
742
758
|
role: "assistant",
|
|
743
759
|
parts: [
|
|
@@ -765,6 +781,18 @@ const resolveInitialMessages = (messages) => {
|
|
|
765
781
|
return message;
|
|
766
782
|
}
|
|
767
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
|
+
}
|
|
768
796
|
return message;
|
|
769
797
|
});
|
|
770
798
|
};
|
|
@@ -1168,63 +1196,30 @@ class AISdkNetworkTransformer {
|
|
|
1168
1196
|
};
|
|
1169
1197
|
}
|
|
1170
1198
|
|
|
1171
|
-
const
|
|
1172
|
-
const
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
case "text": {
|
|
1181
|
-
return {
|
|
1182
|
-
type: "text",
|
|
1183
|
-
text: part.text
|
|
1184
|
-
};
|
|
1185
|
-
}
|
|
1186
|
-
case "image": {
|
|
1187
|
-
const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
|
|
1188
|
-
return {
|
|
1189
|
-
type: "file",
|
|
1190
|
-
mediaType: part.mimeType ?? "image/*",
|
|
1191
|
-
url
|
|
1192
|
-
};
|
|
1193
|
-
}
|
|
1194
|
-
case "file": {
|
|
1195
|
-
const url = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
|
|
1196
|
-
return {
|
|
1197
|
-
type: "file",
|
|
1198
|
-
mediaType: part.mimeType,
|
|
1199
|
-
url,
|
|
1200
|
-
...part.filename !== void 0 ? { filename: part.filename } : {}
|
|
1201
|
-
};
|
|
1202
|
-
}
|
|
1203
|
-
default: {
|
|
1204
|
-
const exhaustiveCheck = part;
|
|
1205
|
-
throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
|
|
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
|
+
}
|
|
1206
1208
|
}
|
|
1207
1209
|
}
|
|
1208
|
-
|
|
1209
|
-
return {
|
|
1210
|
-
id,
|
|
1211
|
-
role: "user",
|
|
1212
|
-
parts
|
|
1210
|
+
return void 0;
|
|
1213
1211
|
};
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
const
|
|
1217
|
-
const _currentRunId = useRef(void 0);
|
|
1212
|
+
const initialMessages = initializeMessages?.() || [];
|
|
1213
|
+
const initialRunId = extractRunIdFromMessages(initialMessages);
|
|
1214
|
+
const _currentRunId = useRef(initialRunId);
|
|
1218
1215
|
const _onChunk = useRef(void 0);
|
|
1219
|
-
const [messages, setMessages] = useState(
|
|
1220
|
-
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
1221
|
-
);
|
|
1216
|
+
const [messages, setMessages] = useState(() => resolveInitialMessages(initialMessages));
|
|
1222
1217
|
const [toolCallApprovals, setToolCallApprovals] = useState({});
|
|
1223
1218
|
const baseClient = useMastraClient();
|
|
1224
1219
|
const [isRunning, setIsRunning] = useState(false);
|
|
1225
1220
|
const generate = async ({
|
|
1226
1221
|
coreUserMessages,
|
|
1227
|
-
|
|
1222
|
+
runtimeContext,
|
|
1228
1223
|
threadId,
|
|
1229
1224
|
modelSettings,
|
|
1230
1225
|
signal,
|
|
@@ -1250,7 +1245,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1250
1245
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1251
1246
|
const response = await agent.generate({
|
|
1252
1247
|
messages: coreUserMessages,
|
|
1253
|
-
runId:
|
|
1248
|
+
runId: v4(),
|
|
1254
1249
|
maxSteps,
|
|
1255
1250
|
modelSettings: {
|
|
1256
1251
|
frequencyPenalty,
|
|
@@ -1262,8 +1257,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1262
1257
|
topP
|
|
1263
1258
|
},
|
|
1264
1259
|
instructions,
|
|
1265
|
-
|
|
1266
|
-
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1260
|
+
runtimeContext,
|
|
1261
|
+
...threadId ? { threadId, resourceId: resourceId || agentId } : {},
|
|
1267
1262
|
providerOptions
|
|
1268
1263
|
});
|
|
1269
1264
|
setIsRunning(false);
|
|
@@ -1278,7 +1273,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1278
1273
|
setMessages((prev) => [...prev, ...mastraUIMessages]);
|
|
1279
1274
|
}
|
|
1280
1275
|
};
|
|
1281
|
-
const stream = async ({ coreUserMessages,
|
|
1276
|
+
const stream = async ({ coreUserMessages, runtimeContext, threadId, onChunk, modelSettings, signal }) => {
|
|
1282
1277
|
const {
|
|
1283
1278
|
frequencyPenalty,
|
|
1284
1279
|
presencePenalty,
|
|
@@ -1298,7 +1293,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1298
1293
|
abortSignal: signal
|
|
1299
1294
|
});
|
|
1300
1295
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1301
|
-
const runId =
|
|
1296
|
+
const runId = v4();
|
|
1302
1297
|
const response = await agent.stream({
|
|
1303
1298
|
messages: coreUserMessages,
|
|
1304
1299
|
runId,
|
|
@@ -1313,8 +1308,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1313
1308
|
topP
|
|
1314
1309
|
},
|
|
1315
1310
|
instructions,
|
|
1316
|
-
|
|
1317
|
-
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1311
|
+
runtimeContext,
|
|
1312
|
+
...threadId ? { threadId, resourceId: resourceId || agentId } : {},
|
|
1318
1313
|
providerOptions,
|
|
1319
1314
|
requireToolApproval
|
|
1320
1315
|
});
|
|
@@ -1330,7 +1325,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1330
1325
|
};
|
|
1331
1326
|
const network = async ({
|
|
1332
1327
|
coreUserMessages,
|
|
1333
|
-
|
|
1328
|
+
runtimeContext,
|
|
1334
1329
|
threadId,
|
|
1335
1330
|
onNetworkChunk,
|
|
1336
1331
|
modelSettings,
|
|
@@ -1343,6 +1338,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1343
1338
|
abortSignal: signal
|
|
1344
1339
|
});
|
|
1345
1340
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1341
|
+
const runId = v4();
|
|
1346
1342
|
const response = await agent.network({
|
|
1347
1343
|
messages: coreUserMessages,
|
|
1348
1344
|
maxSteps,
|
|
@@ -1355,9 +1351,9 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1355
1351
|
topK,
|
|
1356
1352
|
topP
|
|
1357
1353
|
},
|
|
1358
|
-
runId
|
|
1359
|
-
|
|
1360
|
-
...threadId ? { thread: threadId, resourceId: agentId } : {}
|
|
1354
|
+
runId,
|
|
1355
|
+
runtimeContext,
|
|
1356
|
+
...threadId ? { thread: threadId, resourceId: resourceId || agentId } : {}
|
|
1361
1357
|
});
|
|
1362
1358
|
const transformer = new AISdkNetworkTransformer();
|
|
1363
1359
|
await response.processDataStream({
|
|
@@ -1409,18 +1405,14 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1409
1405
|
};
|
|
1410
1406
|
const sendMessage = async ({ mode = "stream", ...args }) => {
|
|
1411
1407
|
const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
|
|
1412
|
-
const
|
|
1413
|
-
|
|
1414
|
-
coreUserMessages.push(...args.coreUserMessages);
|
|
1415
|
-
}
|
|
1416
|
-
const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
|
|
1417
|
-
setMessages((s) => [...s, ...uiMessages]);
|
|
1408
|
+
const messages2 = args.coreUserMessages ? [nextMessage, ...args.coreUserMessages] : [nextMessage];
|
|
1409
|
+
setMessages((s) => [...s, { role: "user", parts: [{ type: "text", text: args.message }] }]);
|
|
1418
1410
|
if (mode === "generate") {
|
|
1419
|
-
await generate({ ...args, coreUserMessages });
|
|
1411
|
+
await generate({ ...args, coreUserMessages: messages2 });
|
|
1420
1412
|
} else if (mode === "stream") {
|
|
1421
|
-
await stream({ ...args, coreUserMessages });
|
|
1413
|
+
await stream({ ...args, coreUserMessages: messages2 });
|
|
1422
1414
|
} else if (mode === "network") {
|
|
1423
|
-
await network({ ...args, coreUserMessages });
|
|
1415
|
+
await network({ ...args, coreUserMessages: messages2 });
|
|
1424
1416
|
}
|
|
1425
1417
|
};
|
|
1426
1418
|
return {
|