@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/CHANGELOG.md +41 -0
- package/dist/index.cjs +92 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +92 -27
- package/dist/index.js.map +1 -1
- package/dist/src/agent/hooks.d.ts +4 -1
- package/dist/src/lib/ai-sdk/types.d.ts +10 -0
- package/package.json +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @mastra/react-hooks
|
|
2
2
|
|
|
3
|
+
## 0.1.0-beta.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Adjust the types to accept tracingOptions ([#10742](https://github.com/mastra-ai/mastra/pull/10742))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`6edf340`](https://github.com/mastra-ai/mastra/commit/6edf3402f6a46ee8def2f42a2287785251fbffd6), [`ad7e8f1`](https://github.com/mastra-ai/mastra/commit/ad7e8f16ac843cbd16687ad47b66ba96bcffe111), [`e1b7118`](https://github.com/mastra-ai/mastra/commit/e1b7118f42ca0a97247afc75e57dcd5fdf987752), [`441c7b6`](https://github.com/mastra-ai/mastra/commit/441c7b6665915cfa7fd625fded8c0f518530bf10), [`e849603`](https://github.com/mastra-ai/mastra/commit/e849603a596269069f58a438b98449ea2770493d)]:
|
|
10
|
+
- @mastra/client-js@1.0.0-beta.6
|
|
11
|
+
|
|
12
|
+
## 0.1.0-beta.5
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Configurable resourceId in react useChat ([#10461](https://github.com/mastra-ai/mastra/pull/10461))
|
|
17
|
+
|
|
18
|
+
- fix(agent): persist messages before tool suspension ([#10369](https://github.com/mastra-ai/mastra/pull/10369))
|
|
19
|
+
|
|
20
|
+
Fixes issues where thread and messages were not saved before suspension when tools require approval or call suspend() during execution. This caused conversation history to be lost if users refreshed during tool approval or suspension.
|
|
21
|
+
|
|
22
|
+
**Backend changes (@mastra/core):**
|
|
23
|
+
- Add assistant messages to messageList immediately after LLM execution
|
|
24
|
+
- Flush messages synchronously before suspension to persist state
|
|
25
|
+
- Create thread if it doesn't exist before flushing
|
|
26
|
+
- Add metadata helpers to persist and remove tool approval state
|
|
27
|
+
- Pass saveQueueManager and memory context through workflow for immediate persistence
|
|
28
|
+
|
|
29
|
+
**Frontend changes (@mastra/react):**
|
|
30
|
+
- Extract runId from pending approvals to enable resumption after refresh
|
|
31
|
+
- Convert `pendingToolApprovals` (DB format) to `requireApprovalMetadata` (runtime format)
|
|
32
|
+
- Handle both `dynamic-tool` and `tool-{NAME}` part types for approval state
|
|
33
|
+
- Change runId from hardcoded `agentId` to unique `uuid()`
|
|
34
|
+
|
|
35
|
+
**UI changes (@mastra/playground-ui):**
|
|
36
|
+
- Handle tool calls awaiting approval in message initialization
|
|
37
|
+
- Convert approval metadata format when loading initial messages
|
|
38
|
+
|
|
39
|
+
Fixes #9745, #9906
|
|
40
|
+
|
|
41
|
+
- Updated dependencies [[`898a972`](https://github.com/mastra-ai/mastra/commit/898a9727d286c2510d6b702dfd367e6aaf5c6b0f)]:
|
|
42
|
+
- @mastra/client-js@1.0.0-beta.5
|
|
43
|
+
|
|
3
44
|
## 0.1.0-beta.4
|
|
4
45
|
|
|
5
46
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
5
5
|
const jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
const react = require('react');
|
|
7
7
|
const clientJs = require('@mastra/client-js');
|
|
8
|
+
const uuid = require('@lukeed/uuid');
|
|
8
9
|
const lucideReact = require('lucide-react');
|
|
9
10
|
const tailwindMerge = require('tailwind-merge');
|
|
10
11
|
const hastUtilToJsxRuntime = require('hast-util-to-jsx-runtime');
|
|
@@ -259,17 +260,19 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
259
260
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
260
261
|
const parts = [...lastMessage.parts];
|
|
261
262
|
const toolPartIndex = parts.findIndex(
|
|
262
|
-
(part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
|
|
263
|
+
(part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
|
|
263
264
|
);
|
|
264
265
|
if (toolPartIndex !== -1) {
|
|
265
266
|
const toolPart = parts[toolPartIndex];
|
|
266
|
-
if (toolPart.type === "dynamic-tool") {
|
|
267
|
+
if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
|
|
268
|
+
const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
|
|
269
|
+
const toolCallId = toolPart.toolCallId;
|
|
267
270
|
if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
|
|
268
271
|
const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
|
|
269
272
|
parts[toolPartIndex] = {
|
|
270
273
|
type: "dynamic-tool",
|
|
271
|
-
toolName
|
|
272
|
-
toolCallId
|
|
274
|
+
toolName,
|
|
275
|
+
toolCallId,
|
|
273
276
|
state: "output-error",
|
|
274
277
|
input: toolPart.input,
|
|
275
278
|
errorText: String(error),
|
|
@@ -288,8 +291,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
288
291
|
}
|
|
289
292
|
parts[toolPartIndex] = {
|
|
290
293
|
type: "dynamic-tool",
|
|
291
|
-
toolName
|
|
292
|
-
toolCallId
|
|
294
|
+
toolName,
|
|
295
|
+
toolCallId,
|
|
293
296
|
state: "output-available",
|
|
294
297
|
input: toolPart.input,
|
|
295
298
|
output,
|
|
@@ -311,11 +314,14 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
311
314
|
if (!lastMessage || lastMessage.role !== "assistant") return result;
|
|
312
315
|
const parts = [...lastMessage.parts];
|
|
313
316
|
const toolPartIndex = parts.findIndex(
|
|
314
|
-
(part) => part.type === "dynamic-tool" && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
|
|
317
|
+
(part) => (part.type === "dynamic-tool" || typeof part.type === "string" && part.type.startsWith("tool-")) && "toolCallId" in part && part.toolCallId === chunk.payload.toolCallId
|
|
315
318
|
);
|
|
316
319
|
if (toolPartIndex !== -1) {
|
|
317
320
|
const toolPart = parts[toolPartIndex];
|
|
318
|
-
if (toolPart.type === "dynamic-tool") {
|
|
321
|
+
if (toolPart.type === "dynamic-tool" || typeof toolPart.type === "string" && toolPart.type.startsWith("tool-")) {
|
|
322
|
+
const toolName = "toolName" in toolPart && typeof toolPart.toolName === "string" ? toolPart.toolName : typeof toolPart.type === "string" && toolPart.type.startsWith("tool-") ? toolPart.type.substring(5) : "";
|
|
323
|
+
const toolCallId = toolPart.toolCallId;
|
|
324
|
+
const input = toolPart.input;
|
|
319
325
|
if (chunk.payload.output?.type?.startsWith("workflow-")) {
|
|
320
326
|
const existingWorkflowState = toolPart.output || {};
|
|
321
327
|
const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(
|
|
@@ -323,7 +329,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
323
329
|
chunk.payload.output
|
|
324
330
|
);
|
|
325
331
|
parts[toolPartIndex] = {
|
|
326
|
-
|
|
332
|
+
type: "dynamic-tool",
|
|
333
|
+
toolName,
|
|
334
|
+
toolCallId,
|
|
335
|
+
state: "input-streaming",
|
|
336
|
+
input,
|
|
327
337
|
output: updatedWorkflowState
|
|
328
338
|
};
|
|
329
339
|
} else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
|
|
@@ -332,7 +342,11 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
|
|
|
332
342
|
const currentOutput = toolPart.output || [];
|
|
333
343
|
const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
|
|
334
344
|
parts[toolPartIndex] = {
|
|
335
|
-
|
|
345
|
+
type: "dynamic-tool",
|
|
346
|
+
toolName,
|
|
347
|
+
toolCallId,
|
|
348
|
+
state: "input-streaming",
|
|
349
|
+
input,
|
|
336
350
|
output: [...existingOutput, chunk.payload.output]
|
|
337
351
|
};
|
|
338
352
|
}
|
|
@@ -655,6 +669,20 @@ const toAssistantUIMessage = (message) => {
|
|
|
655
669
|
}
|
|
656
670
|
return baseToolCall;
|
|
657
671
|
}
|
|
672
|
+
const requireApprovalMetadata = extendedMessage.metadata?.requireApprovalMetadata;
|
|
673
|
+
const partToolCallId = "toolCallId" in part && typeof part.toolCallId === "string" ? part.toolCallId : void 0;
|
|
674
|
+
const suspensionData = partToolCallId ? requireApprovalMetadata?.[partToolCallId] : void 0;
|
|
675
|
+
if (suspensionData) {
|
|
676
|
+
const toolName = "toolName" in part && typeof part.toolName === "string" ? part.toolName : part.type.startsWith("tool-") ? part.type.substring(5) : "";
|
|
677
|
+
return {
|
|
678
|
+
type: "tool-call",
|
|
679
|
+
toolCallId: partToolCallId,
|
|
680
|
+
toolName,
|
|
681
|
+
argsText: "input" in part ? JSON.stringify(part.input) : "{}",
|
|
682
|
+
args: "input" in part ? part.input : {},
|
|
683
|
+
metadata: extendedMessage.metadata
|
|
684
|
+
};
|
|
685
|
+
}
|
|
658
686
|
return {
|
|
659
687
|
type: "text",
|
|
660
688
|
text: "",
|
|
@@ -741,7 +769,6 @@ const resolveInitialMessages = (messages) => {
|
|
|
741
769
|
childMessages,
|
|
742
770
|
result: finalResult?.text || ""
|
|
743
771
|
};
|
|
744
|
-
console.log("json", json);
|
|
745
772
|
const nextMessage = {
|
|
746
773
|
role: "assistant",
|
|
747
774
|
parts: [
|
|
@@ -769,6 +796,18 @@ const resolveInitialMessages = (messages) => {
|
|
|
769
796
|
return message;
|
|
770
797
|
}
|
|
771
798
|
}
|
|
799
|
+
const extendedMessage = message;
|
|
800
|
+
const pendingToolApprovals = extendedMessage.metadata?.pendingToolApprovals;
|
|
801
|
+
if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
|
|
802
|
+
return {
|
|
803
|
+
...message,
|
|
804
|
+
metadata: {
|
|
805
|
+
...message.metadata,
|
|
806
|
+
mode: "stream",
|
|
807
|
+
requireApprovalMetadata: pendingToolApprovals
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
}
|
|
772
811
|
return message;
|
|
773
812
|
});
|
|
774
813
|
};
|
|
@@ -1217,12 +1256,24 @@ const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
|
|
|
1217
1256
|
};
|
|
1218
1257
|
};
|
|
1219
1258
|
|
|
1220
|
-
const useChat = ({ agentId, initializeMessages }) => {
|
|
1221
|
-
const
|
|
1259
|
+
const useChat = ({ agentId, resourceId, initializeMessages }) => {
|
|
1260
|
+
const extractRunIdFromMessages = (messages2) => {
|
|
1261
|
+
for (const message of messages2) {
|
|
1262
|
+
const pendingToolApprovals = message.metadata?.pendingToolApprovals;
|
|
1263
|
+
if (pendingToolApprovals && typeof pendingToolApprovals === "object") {
|
|
1264
|
+
const suspensionData = Object.values(pendingToolApprovals)[0];
|
|
1265
|
+
if (suspensionData?.runId) {
|
|
1266
|
+
return suspensionData.runId;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
return void 0;
|
|
1271
|
+
};
|
|
1272
|
+
const initialMessages = initializeMessages?.() || [];
|
|
1273
|
+
const initialRunId = extractRunIdFromMessages(initialMessages);
|
|
1274
|
+
const _currentRunId = react.useRef(initialRunId);
|
|
1222
1275
|
const _onChunk = react.useRef(void 0);
|
|
1223
|
-
const [messages, setMessages] = react.useState(
|
|
1224
|
-
() => resolveInitialMessages(initializeMessages?.() || [])
|
|
1225
|
-
);
|
|
1276
|
+
const [messages, setMessages] = react.useState(() => resolveInitialMessages(initialMessages));
|
|
1226
1277
|
const [toolCallApprovals, setToolCallApprovals] = react.useState({});
|
|
1227
1278
|
const baseClient = useMastraClient();
|
|
1228
1279
|
const [isRunning, setIsRunning] = react.useState(false);
|
|
@@ -1232,7 +1283,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1232
1283
|
threadId,
|
|
1233
1284
|
modelSettings,
|
|
1234
1285
|
signal,
|
|
1235
|
-
onFinish
|
|
1286
|
+
onFinish,
|
|
1287
|
+
tracingOptions
|
|
1236
1288
|
}) => {
|
|
1237
1289
|
const {
|
|
1238
1290
|
frequencyPenalty,
|
|
@@ -1254,7 +1306,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1254
1306
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1255
1307
|
const response = await agent.generate({
|
|
1256
1308
|
messages: coreUserMessages,
|
|
1257
|
-
runId:
|
|
1309
|
+
runId: uuid.v4(),
|
|
1258
1310
|
maxSteps,
|
|
1259
1311
|
modelSettings: {
|
|
1260
1312
|
frequencyPenalty,
|
|
@@ -1267,8 +1319,9 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1267
1319
|
},
|
|
1268
1320
|
instructions,
|
|
1269
1321
|
requestContext,
|
|
1270
|
-
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1271
|
-
providerOptions
|
|
1322
|
+
...threadId ? { threadId, resourceId: resourceId || agentId } : {},
|
|
1323
|
+
providerOptions,
|
|
1324
|
+
tracingOptions
|
|
1272
1325
|
});
|
|
1273
1326
|
setIsRunning(false);
|
|
1274
1327
|
if (response && "uiMessages" in response.response && response.response.uiMessages) {
|
|
@@ -1282,7 +1335,15 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1282
1335
|
setMessages((prev) => [...prev, ...mastraUIMessages]);
|
|
1283
1336
|
}
|
|
1284
1337
|
};
|
|
1285
|
-
const stream = async ({
|
|
1338
|
+
const stream = async ({
|
|
1339
|
+
coreUserMessages,
|
|
1340
|
+
requestContext,
|
|
1341
|
+
threadId,
|
|
1342
|
+
onChunk,
|
|
1343
|
+
modelSettings,
|
|
1344
|
+
signal,
|
|
1345
|
+
tracingOptions
|
|
1346
|
+
}) => {
|
|
1286
1347
|
const {
|
|
1287
1348
|
frequencyPenalty,
|
|
1288
1349
|
presencePenalty,
|
|
@@ -1302,7 +1363,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1302
1363
|
abortSignal: signal
|
|
1303
1364
|
});
|
|
1304
1365
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1305
|
-
const runId =
|
|
1366
|
+
const runId = uuid.v4();
|
|
1306
1367
|
const response = await agent.stream({
|
|
1307
1368
|
messages: coreUserMessages,
|
|
1308
1369
|
runId,
|
|
@@ -1318,9 +1379,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1318
1379
|
},
|
|
1319
1380
|
instructions,
|
|
1320
1381
|
requestContext,
|
|
1321
|
-
...threadId ? { threadId, resourceId: agentId } : {},
|
|
1382
|
+
...threadId ? { threadId, resourceId: resourceId || agentId } : {},
|
|
1322
1383
|
providerOptions,
|
|
1323
|
-
requireToolApproval
|
|
1384
|
+
requireToolApproval,
|
|
1385
|
+
tracingOptions
|
|
1324
1386
|
});
|
|
1325
1387
|
_onChunk.current = onChunk;
|
|
1326
1388
|
_currentRunId.current = runId;
|
|
@@ -1338,7 +1400,8 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1338
1400
|
threadId,
|
|
1339
1401
|
onNetworkChunk,
|
|
1340
1402
|
modelSettings,
|
|
1341
|
-
signal
|
|
1403
|
+
signal,
|
|
1404
|
+
tracingOptions
|
|
1342
1405
|
}) => {
|
|
1343
1406
|
const { frequencyPenalty, presencePenalty, maxRetries, maxTokens, temperature, topK, topP, maxSteps } = modelSettings || {};
|
|
1344
1407
|
setIsRunning(true);
|
|
@@ -1347,6 +1410,7 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1347
1410
|
abortSignal: signal
|
|
1348
1411
|
});
|
|
1349
1412
|
const agent = clientWithAbort.getAgent(agentId);
|
|
1413
|
+
const runId = uuid.v4();
|
|
1350
1414
|
const response = await agent.network({
|
|
1351
1415
|
messages: coreUserMessages,
|
|
1352
1416
|
maxSteps,
|
|
@@ -1359,9 +1423,10 @@ const useChat = ({ agentId, initializeMessages }) => {
|
|
|
1359
1423
|
topK,
|
|
1360
1424
|
topP
|
|
1361
1425
|
},
|
|
1362
|
-
runId
|
|
1426
|
+
runId,
|
|
1363
1427
|
requestContext,
|
|
1364
|
-
...threadId ? { thread: threadId, resourceId: agentId } : {}
|
|
1428
|
+
...threadId ? { thread: threadId, resourceId: resourceId || agentId } : {},
|
|
1429
|
+
tracingOptions
|
|
1365
1430
|
});
|
|
1366
1431
|
const transformer = new AISdkNetworkTransformer();
|
|
1367
1432
|
await response.processDataStream({
|