@mastra/react 0.0.10 → 0.0.11-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/CHANGELOG.md +9 -0
- package/dist/index.cjs +81 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +82 -11
- package/dist/index.js.map +1 -1
- package/dist/src/agent/hooks.d.ts +7 -0
- package/dist/src/agent/types.d.ts +1 -0
- package/dist/src/lib/ai-sdk/memory/resolveInitialMessages.test.d.ts +1 -0
- package/dist/src/lib/ai-sdk/transformers/AISdkNetworkTransformer.test.d.ts +1 -0
- package/dist/src/lib/ai-sdk/types.d.ts +7 -0
- package/dist/src/lib/ai-sdk/utils/toUIMessage.test.d.ts +1 -0
- package/package.json +13 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useState, Fragment, useLayoutEffect,
|
|
2
|
+
import { createContext, useContext, useRef, useState, Fragment, useLayoutEffect, useEffect } from 'react';
|
|
3
3
|
import { MastraClient } from '@mastra/client-js';
|
|
4
4
|
import { ChevronDownIcon, CheckIcon, CopyIcon } from 'lucide-react';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -249,6 +249,7 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
249
249
|
}
|
|
250
250
|
];
|
|
251
251
|
}
|
|
252
|
+
case "tool-error":
|
|
252
253
|
case "tool-result": {
|
|
253
254
|
const lastMessage = result[result.length - 1];
|
|
254
255
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
@@ -259,14 +260,15 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
259
260
|
if (toolPartIndex !== -1) {
|
|
260
261
|
const toolPart = parts[toolPartIndex];
|
|
261
262
|
if (toolPart.type === "dynamic-tool") {
|
|
262
|
-
if (chunk.payload.isError) {
|
|
263
|
+
if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
|
|
264
|
+
const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
|
|
263
265
|
parts[toolPartIndex] = {
|
|
264
266
|
type: "dynamic-tool",
|
|
265
267
|
toolName: toolPart.toolName,
|
|
266
268
|
toolCallId: toolPart.toolCallId,
|
|
267
269
|
state: "output-error",
|
|
268
270
|
input: toolPart.input,
|
|
269
|
-
errorText: String(
|
|
271
|
+
errorText: String(error),
|
|
270
272
|
callProviderMetadata: chunk.payload.providerMetadata
|
|
271
273
|
};
|
|
272
274
|
} else {
|
|
@@ -395,6 +397,29 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
395
397
|
}
|
|
396
398
|
];
|
|
397
399
|
}
|
|
400
|
+
case "tool-call-approval": {
|
|
401
|
+
const lastMessage = result[result.length - 1];
|
|
402
|
+
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
403
|
+
const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "stream" ? lastMessage.metadata?.requireApprovalMetadata : {};
|
|
404
|
+
return [
|
|
405
|
+
...result.slice(0, -1),
|
|
406
|
+
{
|
|
407
|
+
...lastMessage,
|
|
408
|
+
metadata: {
|
|
409
|
+
...lastMessage.metadata,
|
|
410
|
+
mode: "stream",
|
|
411
|
+
requireApprovalMetadata: {
|
|
412
|
+
...lastRequireApprovalMetadata,
|
|
413
|
+
[chunk.payload.toolCallId]: {
|
|
414
|
+
toolCallId: chunk.payload.toolCallId,
|
|
415
|
+
toolName: chunk.payload.toolName,
|
|
416
|
+
args: chunk.payload.args
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
];
|
|
422
|
+
}
|
|
398
423
|
case "finish": {
|
|
399
424
|
const lastMessage = result[result.length - 1];
|
|
400
425
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
@@ -1133,9 +1158,12 @@ class AISdkNetworkTransformer {
|
|
|
1133
1158
|
}
|
|
1134
1159
|
|
|
1135
1160
|
const useChat = ({ agentId, initializeMessages }) => {
|
|
1161
|
+
const _currentRunId = useRef(void 0);
|
|
1162
|
+
const _onChunk = useRef(void 0);
|
|
1136
1163
|
const [messages, setMessages] = useState(
|
|
1137
1164
|
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
1138
1165
|
);
|
|
1166
|
+
const [toolCallApprovals, setToolCallApprovals] = useState({});
|
|
1139
1167
|
const baseClient = useMastraClient();
|
|
1140
1168
|
const [isRunning, setIsRunning] = useState(false);
|
|
1141
1169
|
const generate = async ({
|
|
@@ -1205,7 +1233,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1205
1233
|
topP,
|
|
1206
1234
|
instructions,
|
|
1207
1235
|
providerOptions,
|
|
1208
|
-
maxSteps
|
|
1236
|
+
maxSteps,
|
|
1237
|
+
requireToolApproval
|
|
1209
1238
|
} = modelSettings || {};
|
|
1210
1239
|
setIsRunning(true);
|
|
1211
1240
|
const clientWithAbort = new MastraClient({
|
|
@@ -1213,9 +1242,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1213
1242
|
abortSignal: signal
|
|
1214
1243
|
});
|
|
1215
1244
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1245
|
+
const runId = agentId;
|
|
1216
1246
|
const response = await agent.stream({
|
|
1217
1247
|
messages: coreUserMessages,
|
|
1218
|
-
runId
|
|
1248
|
+
runId,
|
|
1219
1249
|
maxSteps,
|
|
1220
1250
|
modelSettings: {
|
|
1221
1251
|
frequencyPenalty,
|
|
@@ -1229,12 +1259,11 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1229
1259
|
instructions,
|
|
1230
1260
|
runtimeContext,
|
|
1231
1261
|
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1232
|
-
providerOptions
|
|
1262
|
+
providerOptions,
|
|
1263
|
+
requireToolApproval
|
|
1233
1264
|
});
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
throw new Error("[Stream] No response body");
|
|
1237
|
-
}
|
|
1265
|
+
_onChunk.current = onChunk;
|
|
1266
|
+
_currentRunId.current = runId;
|
|
1238
1267
|
await response.processDataStream({
|
|
1239
1268
|
onChunk: async (chunk) => {
|
|
1240
1269
|
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
@@ -1283,6 +1312,45 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1283
1312
|
});
|
|
1284
1313
|
setIsRunning(false);
|
|
1285
1314
|
};
|
|
1315
|
+
const handleCancelRun = () => {
|
|
1316
|
+
setIsRunning(false);
|
|
1317
|
+
_currentRunId.current = void 0;
|
|
1318
|
+
_onChunk.current = void 0;
|
|
1319
|
+
};
|
|
1320
|
+
const approveToolCall = async (toolCallId) => {
|
|
1321
|
+
const onChunk = _onChunk.current;
|
|
1322
|
+
const currentRunId = _currentRunId.current;
|
|
1323
|
+
if (!currentRunId)
|
|
1324
|
+
return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
|
|
1325
|
+
setIsRunning(true);
|
|
1326
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
|
|
1327
|
+
const agent = baseClient.getAgent(agentId);
|
|
1328
|
+
const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
|
|
1329
|
+
await response.processDataStream({
|
|
1330
|
+
onChunk: async (chunk) => {
|
|
1331
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1332
|
+
onChunk?.(chunk);
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
setIsRunning(false);
|
|
1336
|
+
};
|
|
1337
|
+
const declineToolCall = async (toolCallId) => {
|
|
1338
|
+
const onChunk = _onChunk.current;
|
|
1339
|
+
const currentRunId = _currentRunId.current;
|
|
1340
|
+
if (!currentRunId)
|
|
1341
|
+
return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
|
|
1342
|
+
setIsRunning(true);
|
|
1343
|
+
setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
|
|
1344
|
+
const agent = baseClient.getAgent(agentId);
|
|
1345
|
+
const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
|
|
1346
|
+
await response.processDataStream({
|
|
1347
|
+
onChunk: async (chunk) => {
|
|
1348
|
+
setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
|
|
1349
|
+
onChunk?.(chunk);
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
setIsRunning(false);
|
|
1353
|
+
};
|
|
1286
1354
|
const sendMessage = async ({ mode = "stream", ...args }) => {
|
|
1287
1355
|
const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
|
|
1288
1356
|
const messages2 = args.coreUserMessages ? [nextMessage, ...args.coreUserMessages] : [nextMessage];
|
|
@@ -1300,7 +1368,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1300
1368
|
sendMessage,
|
|
1301
1369
|
isRunning,
|
|
1302
1370
|
messages,
|
|
1303
|
-
|
|
1371
|
+
approveToolCall,
|
|
1372
|
+
declineToolCall,
|
|
1373
|
+
cancelRun: handleCancelRun,
|
|
1374
|
+
toolCallApprovals
|
|
1304
1375
|
};
|
|
1305
1376
|
};
|
|
1306
1377
|
|