@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.cjs CHANGED
@@ -253,6 +253,7 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
253
253
  }
254
254
  ];
255
255
  }
256
+ case "tool-error":
256
257
  case "tool-result": {
257
258
  const lastMessage = result[result.length - 1];
258
259
  if (!lastMessage || lastMessage.role !== "assistant") return result;
@@ -263,25 +264,35 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
263
264
  if (toolPartIndex !== -1) {
264
265
  const toolPart = parts[toolPartIndex];
265
266
  if (toolPart.type === "dynamic-tool") {
266
- if (chunk.payload.isError) {
267
+ if (chunk.type === "tool-result" && chunk.payload.isError || chunk.type === "tool-error") {
268
+ const error = chunk.type === "tool-error" ? chunk.payload.error : chunk.payload.result;
267
269
  parts[toolPartIndex] = {
268
270
  type: "dynamic-tool",
269
271
  toolName: toolPart.toolName,
270
272
  toolCallId: toolPart.toolCallId,
271
273
  state: "output-error",
272
274
  input: toolPart.input,
273
- errorText: String(chunk.payload.result),
275
+ errorText: String(error),
274
276
  callProviderMetadata: chunk.payload.providerMetadata
275
277
  };
276
278
  } else {
277
279
  const isWorkflow = Boolean(chunk.payload.result?.result?.steps);
280
+ const isAgent = chunk?.from === "AGENT";
281
+ let output;
282
+ if (isWorkflow) {
283
+ output = chunk.payload.result?.result;
284
+ } else if (isAgent) {
285
+ output = parts[toolPartIndex].output ?? chunk.payload.result;
286
+ } else {
287
+ output = chunk.payload.result;
288
+ }
278
289
  parts[toolPartIndex] = {
279
290
  type: "dynamic-tool",
280
291
  toolName: toolPart.toolName,
281
292
  toolCallId: toolPart.toolCallId,
282
293
  state: "output-available",
283
294
  input: toolPart.input,
284
- output: isWorkflow ? chunk.payload.result?.result : chunk.payload.result,
295
+ output,
285
296
  callProviderMetadata: chunk.payload.providerMetadata
286
297
  };
287
298
  }
@@ -315,6 +326,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
315
326
  ...toolPart,
316
327
  output: updatedWorkflowState
317
328
  };
329
+ } else if (chunk.payload.output?.from === "AGENT" || chunk.payload.output?.from === "USER" && chunk.payload.output?.payload?.output?.type?.startsWith("workflow-")) {
330
+ return toUIMessageFromAgent(chunk.payload.output, conversation);
318
331
  } else {
319
332
  const currentOutput = toolPart.output || [];
320
333
  const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
@@ -388,15 +401,37 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
388
401
  }
389
402
  ];
390
403
  }
404
+ case "tool-call-approval": {
405
+ const lastMessage = result[result.length - 1];
406
+ if (!lastMessage || lastMessage.role !== "assistant") return result;
407
+ const lastRequireApprovalMetadata = lastMessage.metadata?.mode === "stream" ? lastMessage.metadata?.requireApprovalMetadata : {};
408
+ return [
409
+ ...result.slice(0, -1),
410
+ {
411
+ ...lastMessage,
412
+ metadata: {
413
+ ...lastMessage.metadata,
414
+ mode: "stream",
415
+ requireApprovalMetadata: {
416
+ ...lastRequireApprovalMetadata,
417
+ [chunk.payload.toolCallId]: {
418
+ toolCallId: chunk.payload.toolCallId,
419
+ toolName: chunk.payload.toolName,
420
+ args: chunk.payload.args
421
+ }
422
+ }
423
+ }
424
+ }
425
+ ];
426
+ }
391
427
  case "finish": {
392
428
  const lastMessage = result[result.length - 1];
393
429
  if (!lastMessage || lastMessage.role !== "assistant") return result;
394
430
  const parts = lastMessage.parts.map((part) => {
395
- if (part.type === "text" && part.state === "streaming") {
396
- return { ...part, state: "done" };
397
- }
398
- if (part.type === "reasoning" && part.state === "streaming") {
399
- return { ...part, state: "done" };
431
+ if (typeof part === "object" && part !== null && "type" in part && "state" in part && part.state === "streaming") {
432
+ if (part.type === "text" || part.type === "reasoning") {
433
+ return { ...part, state: "done" };
434
+ }
400
435
  }
401
436
  return part;
402
437
  });
@@ -430,6 +465,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
430
465
  return result;
431
466
  }
432
467
  };
468
+ const toUIMessageFromAgent = (chunk, conversation, metadata) => {
469
+ const lastMessage = conversation[conversation.length - 1];
470
+ if (!lastMessage || lastMessage.role !== "assistant") return conversation;
471
+ const parts = [...lastMessage.parts];
472
+ if (chunk.type === "text-delta") {
473
+ const agentChunk = chunk.payload;
474
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
475
+ if (toolPartIndex === -1) return conversation;
476
+ const toolPart = parts[toolPartIndex];
477
+ const childMessages = toolPart?.output?.childMessages || [];
478
+ const lastChildMessage = childMessages[childMessages.length - 1];
479
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
480
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
481
+ parts[toolPartIndex] = {
482
+ ...toolPart,
483
+ output: {
484
+ childMessages: nextMessages
485
+ }
486
+ };
487
+ } else if (chunk.type === "tool-call") {
488
+ const agentChunk = chunk.payload;
489
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
490
+ if (toolPartIndex === -1) return conversation;
491
+ const toolPart = parts[toolPartIndex];
492
+ const childMessages = toolPart?.output?.childMessages || [];
493
+ parts[toolPartIndex] = {
494
+ ...toolPart,
495
+ output: {
496
+ ...toolPart?.output,
497
+ childMessages: [
498
+ ...childMessages,
499
+ {
500
+ type: "tool",
501
+ toolCallId: agentChunk.toolCallId,
502
+ toolName: agentChunk.toolName,
503
+ args: agentChunk.args
504
+ }
505
+ ]
506
+ }
507
+ };
508
+ } else if (chunk.type === "tool-output") {
509
+ const agentChunk = chunk.payload;
510
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
511
+ if (toolPartIndex === -1) return conversation;
512
+ const toolPart = parts[toolPartIndex];
513
+ if (agentChunk?.output?.type?.startsWith("workflow-")) {
514
+ const childMessages = toolPart?.output?.childMessages || [];
515
+ const lastToolIndex = childMessages.length - 1;
516
+ const currentMessage = childMessages[lastToolIndex];
517
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
518
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
519
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
520
+ parts[toolPartIndex] = {
521
+ ...toolPart,
522
+ output: {
523
+ ...toolPart?.output,
524
+ childMessages: [
525
+ ...childMessages.slice(0, -1),
526
+ {
527
+ ...currentMessage,
528
+ toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
529
+ }
530
+ ]
531
+ }
532
+ };
533
+ }
534
+ }
535
+ } else if (chunk.type === "tool-result") {
536
+ const agentChunk = chunk.payload;
537
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
538
+ if (toolPartIndex === -1) return conversation;
539
+ const toolPart = parts[toolPartIndex];
540
+ const childMessages = toolPart?.output?.childMessages || [];
541
+ const lastToolIndex = childMessages.length - 1;
542
+ const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
543
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
544
+ parts[toolPartIndex] = {
545
+ ...toolPart,
546
+ output: {
547
+ ...toolPart?.output,
548
+ childMessages: [
549
+ ...childMessages.slice(0, -1),
550
+ {
551
+ ...childMessages[lastToolIndex],
552
+ toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
553
+ }
554
+ ]
555
+ }
556
+ };
557
+ }
558
+ }
559
+ return [
560
+ ...conversation.slice(0, -1),
561
+ {
562
+ ...lastMessage,
563
+ parts
564
+ }
565
+ ];
566
+ };
433
567
 
434
568
  const toAssistantUIMessage = (message) => {
435
569
  const extendedMessage = message;
@@ -469,13 +603,23 @@ const toAssistantUIMessage = (message) => {
469
603
  };
470
604
  }
471
605
  if (part.type === "file") {
472
- return {
473
- type: "file",
474
- mimeType: part.mediaType,
475
- data: part.url,
476
- // Use URL as data source
477
- metadata: message.metadata
478
- };
606
+ const type = part.mediaType.includes("image/") ? "image" : "file";
607
+ if (type === "file") {
608
+ return {
609
+ type,
610
+ mimeType: part.mediaType,
611
+ data: part.url,
612
+ // Use URL as data source
613
+ metadata: message.metadata
614
+ };
615
+ }
616
+ if (type === "image") {
617
+ return {
618
+ type,
619
+ image: part.url,
620
+ metadata: message.metadata
621
+ };
622
+ }
479
623
  }
480
624
  if (part.type === "dynamic-tool") {
481
625
  const baseToolCall = {
@@ -550,6 +694,112 @@ const toAssistantUIMessage = (message) => {
550
694
  return threadMessage;
551
695
  };
552
696
 
697
+ const resolveInitialMessages = (messages) => {
698
+ return messages.map((message) => {
699
+ const networkPart = message.parts.find(
700
+ (part) => typeof part === "object" && part !== null && "type" in part && part.type === "text" && "text" in part && typeof part.text === "string" && part.text.includes('"isNetwork":true')
701
+ );
702
+ if (networkPart && networkPart.type === "text") {
703
+ try {
704
+ const json = JSON.parse(networkPart.text);
705
+ if (json.isNetwork === true) {
706
+ const selectionReason = json.selectionReason || "";
707
+ const primitiveType = json.primitiveType || "";
708
+ const primitiveId = json.primitiveId || "";
709
+ const finalResult = json.finalResult;
710
+ const toolCalls = finalResult?.toolCalls || [];
711
+ const childMessages = [];
712
+ for (const toolCall of toolCalls) {
713
+ if (toolCall.type === "tool-call" && toolCall.payload) {
714
+ const toolCallId = toolCall.payload.toolCallId;
715
+ let toolResult;
716
+ for (const message2 of finalResult?.messages || []) {
717
+ for (const part of message2.content || []) {
718
+ if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
719
+ toolResult = part;
720
+ break;
721
+ }
722
+ }
723
+ }
724
+ const isWorkflow = Boolean(toolResult?.result?.result?.steps);
725
+ childMessages.push({
726
+ type: "tool",
727
+ toolCallId: toolCall.payload.toolCallId,
728
+ toolName: toolCall.payload.toolName,
729
+ args: toolCall.payload.args,
730
+ toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
731
+ });
732
+ }
733
+ }
734
+ if (finalResult && finalResult.text) {
735
+ childMessages.push({
736
+ type: "text",
737
+ content: finalResult.text
738
+ });
739
+ }
740
+ const result = {
741
+ childMessages,
742
+ result: finalResult?.text || ""
743
+ };
744
+ console.log("json", json);
745
+ const nextMessage = {
746
+ role: "assistant",
747
+ parts: [
748
+ {
749
+ type: "dynamic-tool",
750
+ toolCallId: primitiveId,
751
+ toolName: primitiveId,
752
+ state: "output-available",
753
+ input: json.input,
754
+ output: result
755
+ }
756
+ ],
757
+ id: message.id,
758
+ metadata: {
759
+ ...message.metadata,
760
+ mode: "network",
761
+ selectionReason,
762
+ agentInput: json.input,
763
+ from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
764
+ }
765
+ };
766
+ return nextMessage;
767
+ }
768
+ } catch (error) {
769
+ return message;
770
+ }
771
+ }
772
+ return message;
773
+ });
774
+ };
775
+ const resolveToChildMessages = (messages) => {
776
+ const assistantMessage = messages.find((message) => message.role === "assistant");
777
+ if (!assistantMessage) return [];
778
+ const parts = assistantMessage.parts;
779
+ let childMessages = [];
780
+ for (const part of parts) {
781
+ const toolPart = part;
782
+ if (part.type.startsWith("tool-")) {
783
+ const toolName = part.type.substring("tool-".length);
784
+ const isWorkflow = toolName.startsWith("workflow-");
785
+ childMessages.push({
786
+ type: "tool",
787
+ toolCallId: toolPart.toolCallId,
788
+ toolName,
789
+ args: toolPart.input,
790
+ toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
791
+ });
792
+ }
793
+ if (part.type === "text") {
794
+ childMessages.push({
795
+ type: "text",
796
+ content: toolPart.text
797
+ });
798
+ }
799
+ }
800
+ return childMessages;
801
+ };
802
+
553
803
  class AISdkNetworkTransformer {
554
804
  transform({ chunk, conversation, metadata }) {
555
805
  const newConversation = [...conversation];
@@ -922,92 +1172,63 @@ class AISdkNetworkTransformer {
922
1172
  };
923
1173
  }
924
1174
 
925
- const resolveInitialMessages = (messages) => {
926
- return messages.map((message) => {
927
- const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
928
- if (networkPart && networkPart.type === "text") {
929
- try {
930
- const json = JSON.parse(networkPart.text);
931
- if (json.isNetwork === true) {
932
- const selectionReason = json.selectionReason || "";
933
- const primitiveType = json.primitiveType || "";
934
- const primitiveId = json.primitiveId || "";
935
- const finalResult = json.finalResult;
936
- const toolCalls = finalResult?.toolCalls || [];
937
- const childMessages = [];
938
- for (const toolCall of toolCalls) {
939
- if (toolCall.type === "tool-call" && toolCall.payload) {
940
- const toolCallId = toolCall.payload.toolCallId;
941
- let toolResult;
942
- for (const message2 of finalResult?.messages || []) {
943
- for (const part of message2.content || []) {
944
- if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
945
- toolResult = part;
946
- break;
947
- }
948
- }
949
- }
950
- const isWorkflow = Boolean(toolResult?.result?.result?.steps);
951
- childMessages.push({
952
- type: "tool",
953
- toolCallId: toolCall.payload.toolCallId,
954
- toolName: toolCall.payload.toolName,
955
- args: toolCall.payload.args,
956
- toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
957
- });
958
- }
959
- }
960
- if (finalResult && finalResult.text) {
961
- childMessages.push({
962
- type: "text",
963
- content: finalResult.text
964
- });
965
- }
966
- const result = {
967
- childMessages,
968
- result: finalResult?.text || ""
969
- };
970
- console.log("json", json);
971
- const nextMessage = {
972
- role: "assistant",
973
- parts: [
974
- {
975
- type: "dynamic-tool",
976
- toolCallId: primitiveId,
977
- toolName: primitiveId,
978
- state: "output-available",
979
- input: json.input,
980
- output: result
981
- }
982
- ],
983
- id: message.id,
984
- metadata: {
985
- ...message.metadata,
986
- mode: "network",
987
- selectionReason,
988
- agentInput: json.input,
989
- from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
990
- }
991
- };
992
- return nextMessage;
993
- }
994
- } catch (error) {
995
- return message;
1175
+ const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1176
+ const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1177
+ const parts = typeof coreUserMessage.content === "string" ? [
1178
+ {
1179
+ type: "text",
1180
+ text: coreUserMessage.content
1181
+ }
1182
+ ] : coreUserMessage.content.map((part) => {
1183
+ switch (part.type) {
1184
+ case "text": {
1185
+ return {
1186
+ type: "text",
1187
+ text: part.text
1188
+ };
1189
+ }
1190
+ case "image": {
1191
+ const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
1192
+ return {
1193
+ type: "file",
1194
+ mediaType: part.mimeType ?? "image/*",
1195
+ url
1196
+ };
1197
+ }
1198
+ case "file": {
1199
+ const url = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
1200
+ return {
1201
+ type: "file",
1202
+ mediaType: part.mimeType,
1203
+ url,
1204
+ ...part.filename !== void 0 ? { filename: part.filename } : {}
1205
+ };
1206
+ }
1207
+ default: {
1208
+ const exhaustiveCheck = part;
1209
+ throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
996
1210
  }
997
1211
  }
998
- return message;
999
1212
  });
1213
+ return {
1214
+ id,
1215
+ role: "user",
1216
+ parts
1217
+ };
1000
1218
  };
1001
1219
 
1002
1220
  const useChat = ({ agentId, initializeMessages }) => {
1221
+ const _currentRunId = react.useRef(void 0);
1222
+ const _onChunk = react.useRef(void 0);
1003
1223
  const [messages, setMessages] = react.useState(
1004
1224
  () => resolveInitialMessages(initializeMessages?.() || [])
1005
1225
  );
1226
+ const [toolCallApprovals, setToolCallApprovals] = react.useState({});
1006
1227
  const baseClient = useMastraClient();
1007
1228
  const [isRunning, setIsRunning] = react.useState(false);
1008
1229
  const generate = async ({
1009
1230
  coreUserMessages,
1010
- runtimeContext,
1231
+ requestContext,
1011
1232
  threadId,
1012
1233
  modelSettings,
1013
1234
  signal,
@@ -1045,7 +1266,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1045
1266
  topP
1046
1267
  },
1047
1268
  instructions,
1048
- runtimeContext,
1269
+ requestContext,
1049
1270
  ...threadId ? { threadId, resourceId: agentId } : {},
1050
1271
  providerOptions
1051
1272
  });
@@ -1061,7 +1282,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1061
1282
  setMessages((prev) => [...prev, ...mastraUIMessages]);
1062
1283
  }
1063
1284
  };
1064
- const stream = async ({ coreUserMessages, runtimeContext, threadId, onChunk, modelSettings, signal }) => {
1285
+ const stream = async ({ coreUserMessages, requestContext, threadId, onChunk, modelSettings, signal }) => {
1065
1286
  const {
1066
1287
  frequencyPenalty,
1067
1288
  presencePenalty,
@@ -1072,7 +1293,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1072
1293
  topP,
1073
1294
  instructions,
1074
1295
  providerOptions,
1075
- maxSteps
1296
+ maxSteps,
1297
+ requireToolApproval
1076
1298
  } = modelSettings || {};
1077
1299
  setIsRunning(true);
1078
1300
  const clientWithAbort = new clientJs.MastraClient({
@@ -1080,9 +1302,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1080
1302
  abortSignal: signal
1081
1303
  });
1082
1304
  const agent = clientWithAbort.getAgent(agentId);
1305
+ const runId = agentId;
1083
1306
  const response = await agent.stream({
1084
1307
  messages: coreUserMessages,
1085
- runId: agentId,
1308
+ runId,
1086
1309
  maxSteps,
1087
1310
  modelSettings: {
1088
1311
  frequencyPenalty,
@@ -1094,14 +1317,13 @@ const useChat = ({ agentId, initializeMessages }) => {
1094
1317
  topP
1095
1318
  },
1096
1319
  instructions,
1097
- runtimeContext,
1320
+ requestContext,
1098
1321
  ...threadId ? { threadId, resourceId: agentId } : {},
1099
- providerOptions
1322
+ providerOptions,
1323
+ requireToolApproval
1100
1324
  });
1101
- if (!response.body) {
1102
- setIsRunning(false);
1103
- throw new Error("[Stream] No response body");
1104
- }
1325
+ _onChunk.current = onChunk;
1326
+ _currentRunId.current = runId;
1105
1327
  await response.processDataStream({
1106
1328
  onChunk: async (chunk) => {
1107
1329
  setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
@@ -1112,7 +1334,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1112
1334
  };
1113
1335
  const network = async ({
1114
1336
  coreUserMessages,
1115
- runtimeContext,
1337
+ requestContext,
1116
1338
  threadId,
1117
1339
  onNetworkChunk,
1118
1340
  modelSettings,
@@ -1138,7 +1360,7 @@ const useChat = ({ agentId, initializeMessages }) => {
1138
1360
  topP
1139
1361
  },
1140
1362
  runId: agentId,
1141
- runtimeContext,
1363
+ requestContext,
1142
1364
  ...threadId ? { thread: threadId, resourceId: agentId } : {}
1143
1365
  });
1144
1366
  const transformer = new AISdkNetworkTransformer();
@@ -1150,16 +1372,59 @@ const useChat = ({ agentId, initializeMessages }) => {
1150
1372
  });
1151
1373
  setIsRunning(false);
1152
1374
  };
1375
+ const handleCancelRun = () => {
1376
+ setIsRunning(false);
1377
+ _currentRunId.current = void 0;
1378
+ _onChunk.current = void 0;
1379
+ };
1380
+ const approveToolCall = async (toolCallId) => {
1381
+ const onChunk = _onChunk.current;
1382
+ const currentRunId = _currentRunId.current;
1383
+ if (!currentRunId)
1384
+ return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
1385
+ setIsRunning(true);
1386
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
1387
+ const agent = baseClient.getAgent(agentId);
1388
+ const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
1389
+ await response.processDataStream({
1390
+ onChunk: async (chunk) => {
1391
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1392
+ onChunk?.(chunk);
1393
+ }
1394
+ });
1395
+ setIsRunning(false);
1396
+ };
1397
+ const declineToolCall = async (toolCallId) => {
1398
+ const onChunk = _onChunk.current;
1399
+ const currentRunId = _currentRunId.current;
1400
+ if (!currentRunId)
1401
+ return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
1402
+ setIsRunning(true);
1403
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
1404
+ const agent = baseClient.getAgent(agentId);
1405
+ const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
1406
+ await response.processDataStream({
1407
+ onChunk: async (chunk) => {
1408
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1409
+ onChunk?.(chunk);
1410
+ }
1411
+ });
1412
+ setIsRunning(false);
1413
+ };
1153
1414
  const sendMessage = async ({ mode = "stream", ...args }) => {
1154
1415
  const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
1155
- const messages2 = args.coreUserMessages ? [nextMessage, ...args.coreUserMessages] : [nextMessage];
1156
- setMessages((s) => [...s, { role: "user", parts: [{ type: "text", text: args.message }] }]);
1416
+ const coreUserMessages = [nextMessage];
1417
+ if (args.coreUserMessages) {
1418
+ coreUserMessages.push(...args.coreUserMessages);
1419
+ }
1420
+ const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
1421
+ setMessages((s) => [...s, ...uiMessages]);
1157
1422
  if (mode === "generate") {
1158
- await generate({ ...args, coreUserMessages: messages2 });
1423
+ await generate({ ...args, coreUserMessages });
1159
1424
  } else if (mode === "stream") {
1160
- await stream({ ...args, coreUserMessages: messages2 });
1425
+ await stream({ ...args, coreUserMessages });
1161
1426
  } else if (mode === "network") {
1162
- await network({ ...args, coreUserMessages: messages2 });
1427
+ await network({ ...args, coreUserMessages });
1163
1428
  }
1164
1429
  };
1165
1430
  return {
@@ -1167,7 +1432,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1167
1432
  sendMessage,
1168
1433
  isRunning,
1169
1434
  messages,
1170
- cancelRun: () => setIsRunning(false)
1435
+ approveToolCall,
1436
+ declineToolCall,
1437
+ cancelRun: handleCancelRun,
1438
+ toolCallApprovals
1171
1439
  };
1172
1440
  };
1173
1441
 
@@ -1541,6 +1809,7 @@ exports.TooltipContentClass = TooltipContentClass;
1541
1809
  exports.TooltipTrigger = TooltipTrigger;
1542
1810
  exports.WorkflowIcon = WorkflowIcon;
1543
1811
  exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
1812
+ exports.resolveToChildMessages = resolveToChildMessages;
1544
1813
  exports.toAssistantUIMessage = toAssistantUIMessage;
1545
1814
  exports.toUIMessage = toUIMessage;
1546
1815
  exports.useChat = useChat;