@mastra/react 0.0.0-error-handler-fix-20251020202607 → 0.0.0-export-agent-memory-from-local-studio-20251112153946

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,5 +1,5 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { createContext, useContext, useState, Fragment, useLayoutEffect, useRef, useEffect } from 'react';
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,25 +260,35 @@ 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(chunk.payload.result),
271
+ errorText: String(error),
270
272
  callProviderMetadata: chunk.payload.providerMetadata
271
273
  };
272
274
  } else {
273
275
  const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
276
+ const isAgent = chunk?.from === "AGENT";
277
+ let output;
278
+ if (isWorkflow) {
279
+ output = chunk.payload.result?.result;
280
+ } else if (isAgent) {
281
+ output = parts[toolPartIndex].output ?? chunk.payload.result;
282
+ } else {
283
+ output = chunk.payload.result;
284
+ }
274
285
  parts[toolPartIndex] = {
275
286
  type: "dynamic-tool",
276
287
  toolName: toolPart.toolName,
277
288
  toolCallId: toolPart.toolCallId,
278
289
  state: "output-available",
279
290
  input: toolPart.input,
280
- output: isWorkflow ? chunk.payload.result?.result : chunk.payload.result,
291
+ output,
281
292
  callProviderMetadata: chunk.payload.providerMetadata
282
293
  };
283
294
  }
@@ -311,6 +322,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
311
322
  ...toolPart,
312
323
  output: updatedWorkflowState
313
324
  };
325
+ } else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
326
+ return toUIMessageFromAgent(chunk.payload.output, conversation);
314
327
  } else {
315
328
  const currentOutput = toolPart.output || [];
316
329
  const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
@@ -384,15 +397,37 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
384
397
  }
385
398
  ];
386
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
+ }
387
423
  case "finish": {
388
424
  const lastMessage = result[result.length - 1];
389
425
  if (!lastMessage || lastMessage.role !== "assistant") return result;
390
426
  const parts = lastMessage.parts.map((part) => {
391
- if (part.type === "text" && part.state === "streaming") {
392
- return { ...part, state: "done" };
393
- }
394
- if (part.type === "reasoning" && part.state === "streaming") {
395
- return { ...part, state: "done" };
427
+ if (typeof part === "object" && part !== null && "type" in part && "state" in part && part.state === "streaming") {
428
+ if (part.type === "text" || part.type === "reasoning") {
429
+ return { ...part, state: "done" };
430
+ }
396
431
  }
397
432
  return part;
398
433
  });
@@ -426,6 +461,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
426
461
  return result;
427
462
  }
428
463
  };
464
+ const toUIMessageFromAgent = (chunk, conversation, metadata) => {
465
+ const lastMessage = conversation[conversation.length - 1];
466
+ if (!lastMessage || lastMessage.role !== "assistant") return conversation;
467
+ const parts = [...lastMessage.parts];
468
+ if (chunk.type === "text-delta") {
469
+ const agentChunk = chunk.payload;
470
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
471
+ if (toolPartIndex === -1) return conversation;
472
+ const toolPart = parts[toolPartIndex];
473
+ const childMessages = toolPart?.output?.childMessages || [];
474
+ const lastChildMessage = childMessages[childMessages.length - 1];
475
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
476
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
477
+ parts[toolPartIndex] = {
478
+ ...toolPart,
479
+ output: {
480
+ childMessages: nextMessages
481
+ }
482
+ };
483
+ } else if (chunk.type === "tool-call") {
484
+ const agentChunk = chunk.payload;
485
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
486
+ if (toolPartIndex === -1) return conversation;
487
+ const toolPart = parts[toolPartIndex];
488
+ const childMessages = toolPart?.output?.childMessages || [];
489
+ parts[toolPartIndex] = {
490
+ ...toolPart,
491
+ output: {
492
+ ...toolPart?.output,
493
+ childMessages: [
494
+ ...childMessages,
495
+ {
496
+ type: "tool",
497
+ toolCallId: agentChunk.toolCallId,
498
+ toolName: agentChunk.toolName,
499
+ args: agentChunk.args
500
+ }
501
+ ]
502
+ }
503
+ };
504
+ } else if (chunk.type === "tool-output") {
505
+ const agentChunk = chunk.payload;
506
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
507
+ if (toolPartIndex === -1) return conversation;
508
+ const toolPart = parts[toolPartIndex];
509
+ if (agentChunk?.output?.type?.startsWith("workflow-")) {
510
+ const childMessages = toolPart?.output?.childMessages || [];
511
+ const lastToolIndex = childMessages.length - 1;
512
+ const currentMessage = childMessages[lastToolIndex];
513
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
514
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
515
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
516
+ parts[toolPartIndex] = {
517
+ ...toolPart,
518
+ output: {
519
+ ...toolPart?.output,
520
+ childMessages: [
521
+ ...childMessages.slice(0, -1),
522
+ {
523
+ ...currentMessage,
524
+ toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
525
+ }
526
+ ]
527
+ }
528
+ };
529
+ }
530
+ }
531
+ } else if (chunk.type === "tool-result") {
532
+ const agentChunk = chunk.payload;
533
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
534
+ if (toolPartIndex === -1) return conversation;
535
+ const toolPart = parts[toolPartIndex];
536
+ const childMessages = toolPart?.output?.childMessages || [];
537
+ const lastToolIndex = childMessages.length - 1;
538
+ const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
539
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
540
+ parts[toolPartIndex] = {
541
+ ...toolPart,
542
+ output: {
543
+ ...toolPart?.output,
544
+ childMessages: [
545
+ ...childMessages.slice(0, -1),
546
+ {
547
+ ...childMessages[lastToolIndex],
548
+ toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
549
+ }
550
+ ]
551
+ }
552
+ };
553
+ }
554
+ }
555
+ return [
556
+ ...conversation.slice(0, -1),
557
+ {
558
+ ...lastMessage,
559
+ parts
560
+ }
561
+ ];
562
+ };
429
563
 
430
564
  const toAssistantUIMessage = (message) => {
431
565
  const extendedMessage = message;
@@ -465,13 +599,23 @@ const toAssistantUIMessage = (message) => {
465
599
  };
466
600
  }
467
601
  if (part.type === "file") {
468
- return {
469
- type: "file",
470
- mimeType: part.mediaType,
471
- data: part.url,
472
- // Use URL as data source
473
- metadata: message.metadata
474
- };
602
+ const type = part.mediaType.includes("image/") ? "image" : "file";
603
+ if (type === "file") {
604
+ return {
605
+ type,
606
+ mimeType: part.mediaType,
607
+ data: part.url,
608
+ // Use URL as data source
609
+ metadata: message.metadata
610
+ };
611
+ }
612
+ if (type === "image") {
613
+ return {
614
+ type,
615
+ image: part.url,
616
+ metadata: message.metadata
617
+ };
618
+ }
475
619
  }
476
620
  if (part.type === "dynamic-tool") {
477
621
  const baseToolCall = {
@@ -546,6 +690,112 @@ const toAssistantUIMessage = (message) => {
546
690
  return threadMessage;
547
691
  };
548
692
 
693
+ const resolveInitialMessages = (messages) => {
694
+ 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
+ );
698
+ if (networkPart && networkPart.type === "text") {
699
+ try {
700
+ const json = JSON.parse(networkPart.text);
701
+ if (json.isNetwork === true) {
702
+ const selectionReason = json.selectionReason || "";
703
+ const primitiveType = json.primitiveType || "";
704
+ const primitiveId = json.primitiveId || "";
705
+ const finalResult = json.finalResult;
706
+ const toolCalls = finalResult?.toolCalls || [];
707
+ const childMessages = [];
708
+ for (const toolCall of toolCalls) {
709
+ if (toolCall.type === "tool-call" && toolCall.payload) {
710
+ const toolCallId = toolCall.payload.toolCallId;
711
+ let toolResult;
712
+ for (const message2 of finalResult?.messages || []) {
713
+ for (const part of message2.content || []) {
714
+ if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
715
+ toolResult = part;
716
+ break;
717
+ }
718
+ }
719
+ }
720
+ const isWorkflow = Boolean(toolResult?.result?.result?.steps);
721
+ childMessages.push({
722
+ type: "tool",
723
+ toolCallId: toolCall.payload.toolCallId,
724
+ toolName: toolCall.payload.toolName,
725
+ args: toolCall.payload.args,
726
+ toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
727
+ });
728
+ }
729
+ }
730
+ if (finalResult && finalResult.text) {
731
+ childMessages.push({
732
+ type: "text",
733
+ content: finalResult.text
734
+ });
735
+ }
736
+ const result = {
737
+ childMessages,
738
+ result: finalResult?.text || ""
739
+ };
740
+ console.log("json", json);
741
+ const nextMessage = {
742
+ role: "assistant",
743
+ parts: [
744
+ {
745
+ type: "dynamic-tool",
746
+ toolCallId: primitiveId,
747
+ toolName: primitiveId,
748
+ state: "output-available",
749
+ input: json.input,
750
+ output: result
751
+ }
752
+ ],
753
+ id: message.id,
754
+ metadata: {
755
+ ...message.metadata,
756
+ mode: "network",
757
+ selectionReason,
758
+ agentInput: json.input,
759
+ from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
760
+ }
761
+ };
762
+ return nextMessage;
763
+ }
764
+ } catch (error) {
765
+ return message;
766
+ }
767
+ }
768
+ return message;
769
+ });
770
+ };
771
+ const resolveToChildMessages = (messages) => {
772
+ const assistantMessage = messages.find((message) => message.role === "assistant");
773
+ if (!assistantMessage) return [];
774
+ const parts = assistantMessage.parts;
775
+ let childMessages = [];
776
+ for (const part of parts) {
777
+ const toolPart = part;
778
+ if (part.type.startsWith("tool-")) {
779
+ const toolName = part.type.substring("tool-".length);
780
+ const isWorkflow = toolName.startsWith("workflow-");
781
+ childMessages.push({
782
+ type: "tool",
783
+ toolCallId: toolPart.toolCallId,
784
+ toolName,
785
+ args: toolPart.input,
786
+ toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
787
+ });
788
+ }
789
+ if (part.type === "text") {
790
+ childMessages.push({
791
+ type: "text",
792
+ content: toolPart.text
793
+ });
794
+ }
795
+ }
796
+ return childMessages;
797
+ };
798
+
549
799
  class AISdkNetworkTransformer {
550
800
  transform({ chunk, conversation, metadata }) {
551
801
  const newConversation = [...conversation];
@@ -918,92 +1168,63 @@ class AISdkNetworkTransformer {
918
1168
  };
919
1169
  }
920
1170
 
921
- const resolveInitialMessages = (messages) => {
922
- return messages.map((message) => {
923
- const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
924
- if (networkPart && networkPart.type === "text") {
925
- try {
926
- const json = JSON.parse(networkPart.text);
927
- if (json.isNetwork === true) {
928
- const selectionReason = json.selectionReason || "";
929
- const primitiveType = json.primitiveType || "";
930
- const primitiveId = json.primitiveId || "";
931
- const finalResult = json.finalResult;
932
- const toolCalls = finalResult?.toolCalls || [];
933
- const childMessages = [];
934
- for (const toolCall of toolCalls) {
935
- if (toolCall.type === "tool-call" && toolCall.payload) {
936
- const toolCallId = toolCall.payload.toolCallId;
937
- let toolResult;
938
- for (const message2 of finalResult?.messages || []) {
939
- for (const part of message2.content || []) {
940
- if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
941
- toolResult = part;
942
- break;
943
- }
944
- }
945
- }
946
- const isWorkflow = Boolean(toolResult?.result?.result?.steps);
947
- childMessages.push({
948
- type: "tool",
949
- toolCallId: toolCall.payload.toolCallId,
950
- toolName: toolCall.payload.toolName,
951
- args: toolCall.payload.args,
952
- toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
953
- });
954
- }
955
- }
956
- if (finalResult && finalResult.text) {
957
- childMessages.push({
958
- type: "text",
959
- content: finalResult.text
960
- });
961
- }
962
- const result = {
963
- childMessages,
964
- result: finalResult?.text || ""
965
- };
966
- console.log("json", json);
967
- const nextMessage = {
968
- role: "assistant",
969
- parts: [
970
- {
971
- type: "dynamic-tool",
972
- toolCallId: primitiveId,
973
- toolName: primitiveId,
974
- state: "output-available",
975
- input: json.input,
976
- output: result
977
- }
978
- ],
979
- id: message.id,
980
- metadata: {
981
- ...message.metadata,
982
- mode: "network",
983
- selectionReason,
984
- agentInput: json.input,
985
- from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
986
- }
987
- };
988
- return nextMessage;
989
- }
990
- } catch (error) {
991
- return message;
1171
+ const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1172
+ const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1173
+ const parts = typeof coreUserMessage.content === "string" ? [
1174
+ {
1175
+ type: "text",
1176
+ text: coreUserMessage.content
1177
+ }
1178
+ ] : coreUserMessage.content.map((part) => {
1179
+ switch (part.type) {
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}`);
992
1206
  }
993
1207
  }
994
- return message;
995
1208
  });
1209
+ return {
1210
+ id,
1211
+ role: "user",
1212
+ parts
1213
+ };
996
1214
  };
997
1215
 
998
1216
  const useChat = ({ agentId, initializeMessages }) => {
1217
+ const _currentRunId = useRef(void 0);
1218
+ const _onChunk = useRef(void 0);
999
1219
  const [messages, setMessages] = useState(
1000
1220
  () => resolveInitialMessages(initializeMessages?.() || [])
1001
1221
  );
1222
+ const [toolCallApprovals, setToolCallApprovals] = useState({});
1002
1223
  const baseClient = useMastraClient();
1003
1224
  const [isRunning, setIsRunning] = useState(false);
1004
1225
  const generate = async ({
1005
1226
  coreUserMessages,
1006
- runtimeContext,
1227
+ requestContext,
1007
1228
  threadId,
1008
1229
  modelSettings,
1009
1230
  signal,
@@ -1041,7 +1262,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1041
1262
  topP
1042
1263
  },
1043
1264
  instructions,
1044
- runtimeContext,
1265
+ requestContext,
1045
1266
  ...threadId ? { threadId, resourceId: agentId } : {},
1046
1267
  providerOptions
1047
1268
  });
@@ -1057,7 +1278,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1057
1278
  setMessages((prev) => [...prev, ...mastraUIMessages]);
1058
1279
  }
1059
1280
  };
1060
- const stream = async ({ coreUserMessages, runtimeContext, threadId, onChunk, modelSettings, signal }) => {
1281
+ const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
1061
1282
  const {
1062
1283
  frequencyPenalty,
1063
1284
  presencePenalty,
@@ -1068,7 +1289,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1068
1289
  topP,
1069
1290
  instructions,
1070
1291
  providerOptions,
1071
- maxSteps
1292
+ maxSteps,
1293
+ requireToolApproval
1072
1294
  } = modelSettings || {};
1073
1295
  setIsRunning(true);
1074
1296
  const clientWithAbort = new MastraClient({
@@ -1076,9 +1298,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1076
1298
  abortSignal: signal
1077
1299
  });
1078
1300
  const agent = clientWithAbort.getAgent(agentId);
1301
+ const runId = agentId;
1079
1302
  const response = await agent.stream({
1080
1303
  messages: coreUserMessages,
1081
- runId: agentId,
1304
+ runId,
1082
1305
  maxSteps,
1083
1306
  modelSettings: {
1084
1307
  frequencyPenalty,
@@ -1090,14 +1313,13 @@ const useChat = ({ agentId, initializeMessages }) => {
1090
1313
  topP
1091
1314
  },
1092
1315
  instructions,
1093
- runtimeContext,
1316
+ requestContext,
1094
1317
  ...threadId ? { threadId, resourceId: agentId } : {},
1095
- providerOptions
1318
+ providerOptions,
1319
+ requireToolApproval
1096
1320
  });
1097
- if (!response.body) {
1098
- setIsRunning(false);
1099
- throw new Error("[Stream] No response body");
1100
- }
1321
+ _onChunk.current = onChunk;
1322
+ _currentRunId.current = runId;
1101
1323
  await response.processDataStream({
1102
1324
  onChunk: async (chunk) => {
1103
1325
  setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
@@ -1108,7 +1330,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1108
1330
  };
1109
1331
  const network = async ({
1110
1332
  coreUserMessages,
1111
- runtimeContext,
1333
+ requestContext,
1112
1334
  threadId,
1113
1335
  onNetworkChunk,
1114
1336
  modelSettings,
@@ -1134,7 +1356,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1134
1356
  topP
1135
1357
  },
1136
1358
  runId: agentId,
1137
- runtimeContext,
1359
+ requestContext,
1138
1360
  ...threadId ? { thread: threadId, resourceId: agentId } : {}
1139
1361
  });
1140
1362
  const transformer = new AISdkNetworkTransformer();
@@ -1146,16 +1368,59 @@ const useChat = ({ agentId, initializeMessages }) => {
1146
1368
  });
1147
1369
  setIsRunning(false);
1148
1370
  };
1371
+ const handleCancelRun = () => {
1372
+ setIsRunning(false);
1373
+ _currentRunId.current = void 0;
1374
+ _onChunk.current = void 0;
1375
+ };
1376
+ const approveToolCall = async (toolCallId) => {
1377
+ const onChunk = _onChunk.current;
1378
+ const currentRunId = _currentRunId.current;
1379
+ if (!currentRunId)
1380
+ return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
1381
+ setIsRunning(true);
1382
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
1383
+ const agent = baseClient.getAgent(agentId);
1384
+ const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
1385
+ await response.processDataStream({
1386
+ onChunk: async (chunk) => {
1387
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1388
+ onChunk?.(chunk);
1389
+ }
1390
+ });
1391
+ setIsRunning(false);
1392
+ };
1393
+ const declineToolCall = async (toolCallId) => {
1394
+ const onChunk = _onChunk.current;
1395
+ const currentRunId = _currentRunId.current;
1396
+ if (!currentRunId)
1397
+ return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
1398
+ setIsRunning(true);
1399
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
1400
+ const agent = baseClient.getAgent(agentId);
1401
+ const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
1402
+ await response.processDataStream({
1403
+ onChunk: async (chunk) => {
1404
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1405
+ onChunk?.(chunk);
1406
+ }
1407
+ });
1408
+ setIsRunning(false);
1409
+ };
1149
1410
  const sendMessage = async ({ mode = "stream", ...args }) => {
1150
1411
  const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
1151
- const messages2 = args.coreUserMessages ? [nextMessage, ...args.coreUserMessages] : [nextMessage];
1152
- setMessages((s) => [...s, { role: "user", parts: [{ type: "text", text: args.message }] }]);
1412
+ const coreUserMessages = [nextMessage];
1413
+ if (args.coreUserMessages) {
1414
+ coreUserMessages.push(...args.coreUserMessages);
1415
+ }
1416
+ const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
1417
+ setMessages((s) => [...s, ...uiMessages]);
1153
1418
  if (mode === "generate") {
1154
- await generate({ ...args, coreUserMessages: messages2 });
1419
+ await generate({ ...args, coreUserMessages });
1155
1420
  } else if (mode === "stream") {
1156
- await stream({ ...args, coreUserMessages: messages2 });
1421
+ await stream({ ...args, coreUserMessages });
1157
1422
  } else if (mode === "network") {
1158
- await network({ ...args, coreUserMessages: messages2 });
1423
+ await network({ ...args, coreUserMessages });
1159
1424
  }
1160
1425
  };
1161
1426
  return {
@@ -1163,7 +1428,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1163
1428
  sendMessage,
1164
1429
  isRunning,
1165
1430
  messages,
1166
- cancelRun: () => setIsRunning(false)
1431
+ approveToolCall,
1432
+ declineToolCall,
1433
+ cancelRun: handleCancelRun,
1434
+ toolCallApprovals
1167
1435
  };
1168
1436
  };
1169
1437
 
@@ -1482,5 +1750,5 @@ const MessageStreaming = ({ className, ...props }) => {
1482
1750
  return /* @__PURE__ */ jsx("span", { className: className || MessageStreamingClass, ...props });
1483
1751
  };
1484
1752
 
1485
- export { AgentIcon, CodeBlock, CodeBlockClass, CodeCopyButton, Entity, EntityCaret, EntityContent, EntityContentClass, EntityTrigger, EntityTriggerClass, EntityTriggerVariantClasses, Entry, EntryClass, EntryTitle, EntryTitleClass, Icon, IconButton, IconButtonClass, IconSizes, MastraReactProvider, Message, MessageActions, MessageActionsClass, MessageClass, MessageContent, MessageContentClass, MessageList, MessageListClass, MessageStreaming, MessageStreamingClass, MessageUsage, MessageUsageClass, MessageUsageEntry, MessageUsageEntryClass, MessageUsageValue, MessageUsageValueClass, MessageUsages, MessageUsagesClass, ToolApproval, ToolApprovalActions, ToolApprovalActionsClass, ToolApprovalClass, ToolApprovalContent, ToolApprovalContentClass, ToolApprovalHeader, ToolApprovalHeaderClass, ToolApprovalTitle, ToolApprovalTitleClass, ToolsIcon, Tooltip, TooltipContent, TooltipContentClass, TooltipTrigger, WorkflowIcon, mapWorkflowStreamChunkToWatchResult, toAssistantUIMessage, toUIMessage, useChat, useEntity, useMastraClient };
1753
+ export { AgentIcon, CodeBlock, CodeBlockClass, CodeCopyButton, Entity, EntityCaret, EntityContent, EntityContentClass, EntityTrigger, EntityTriggerClass, EntityTriggerVariantClasses, Entry, EntryClass, EntryTitle, EntryTitleClass, Icon, IconButton, IconButtonClass, IconSizes, MastraReactProvider, Message, MessageActions, MessageActionsClass, MessageClass, MessageContent, MessageContentClass, MessageList, MessageListClass, MessageStreaming, MessageStreamingClass, MessageUsage, MessageUsageClass, MessageUsageEntry, MessageUsageEntryClass, MessageUsageValue, MessageUsageValueClass, MessageUsages, MessageUsagesClass, ToolApproval, ToolApprovalActions, ToolApprovalActionsClass, ToolApprovalClass, ToolApprovalContent, ToolApprovalContentClass, ToolApprovalHeader, ToolApprovalHeaderClass, ToolApprovalTitle, ToolApprovalTitleClass, ToolsIcon, Tooltip, TooltipContent, TooltipContentClass, TooltipTrigger, WorkflowIcon, mapWorkflowStreamChunkToWatchResult, resolveToChildMessages, toAssistantUIMessage, toUIMessage, useChat, useEntity, useMastraClient };
1486
1754
  //# sourceMappingURL=index.js.map