@mastra/react 0.0.0-monorepo-binary-20251013210052 → 0.0.0-sidebar-window-undefined-fix-20251029233656

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
@@ -5,7 +5,6 @@ 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 reactDom = require('react-dom');
9
8
  const lucideReact = require('lucide-react');
10
9
  const tailwindMerge = require('tailwind-merge');
11
10
  const hastUtilToJsxRuntime = require('hast-util-to-jsx-runtime');
@@ -254,6 +253,7 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
254
253
  }
255
254
  ];
256
255
  }
256
+ case "tool-error":
257
257
  case "tool-result": {
258
258
  const lastMessage = result[result.length - 1];
259
259
  if (!lastMessage || lastMessage.role !== "assistant") return result;
@@ -264,25 +264,35 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
264
264
  if (toolPartIndex !== -1) {
265
265
  const toolPart = parts[toolPartIndex];
266
266
  if (toolPart.type === "dynamic-tool") {
267
- 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;
268
269
  parts[toolPartIndex] = {
269
270
  type: "dynamic-tool",
270
271
  toolName: toolPart.toolName,
271
272
  toolCallId: toolPart.toolCallId,
272
273
  state: "output-error",
273
274
  input: toolPart.input,
274
- errorText: String(chunk.payload.result),
275
+ errorText: String(error),
275
276
  callProviderMetadata: chunk.payload.providerMetadata
276
277
  };
277
278
  } else {
278
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
+ }
279
289
  parts[toolPartIndex] = {
280
290
  type: "dynamic-tool",
281
291
  toolName: toolPart.toolName,
282
292
  toolCallId: toolPart.toolCallId,
283
293
  state: "output-available",
284
294
  input: toolPart.input,
285
- output: isWorkflow ? chunk.payload.result?.result : chunk.payload.result,
295
+ output,
286
296
  callProviderMetadata: chunk.payload.providerMetadata
287
297
  };
288
298
  }
@@ -316,6 +326,8 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
316
326
  ...toolPart,
317
327
  output: updatedWorkflowState
318
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);
319
331
  } else {
320
332
  const currentOutput = toolPart.output || [];
321
333
  const existingOutput = Array.isArray(currentOutput) ? currentOutput : [];
@@ -389,6 +401,29 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
389
401
  }
390
402
  ];
391
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
+ }
392
427
  case "finish": {
393
428
  const lastMessage = result[result.length - 1];
394
429
  if (!lastMessage || lastMessage.role !== "assistant") return result;
@@ -431,6 +466,105 @@ const toUIMessage = ({ chunk, conversation, metadata }) => {
431
466
  return result;
432
467
  }
433
468
  };
469
+ const toUIMessageFromAgent = (chunk, conversation, metadata) => {
470
+ const lastMessage = conversation[conversation.length - 1];
471
+ if (!lastMessage || lastMessage.role !== "assistant") return conversation;
472
+ const parts = [...lastMessage.parts];
473
+ if (chunk.type === "text-delta") {
474
+ const agentChunk = chunk.payload;
475
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
476
+ if (toolPartIndex === -1) return conversation;
477
+ const toolPart = parts[toolPartIndex];
478
+ const childMessages = toolPart?.output?.childMessages || [];
479
+ const lastChildMessage = childMessages[childMessages.length - 1];
480
+ const textMessage = { type: "text", content: (lastChildMessage?.content || "") + agentChunk.text };
481
+ const nextMessages = lastChildMessage?.type === "text" ? [...childMessages.slice(0, -1), textMessage] : [...childMessages, textMessage];
482
+ parts[toolPartIndex] = {
483
+ ...toolPart,
484
+ output: {
485
+ childMessages: nextMessages
486
+ }
487
+ };
488
+ } else if (chunk.type === "tool-call") {
489
+ const agentChunk = chunk.payload;
490
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
491
+ if (toolPartIndex === -1) return conversation;
492
+ const toolPart = parts[toolPartIndex];
493
+ const childMessages = toolPart?.output?.childMessages || [];
494
+ parts[toolPartIndex] = {
495
+ ...toolPart,
496
+ output: {
497
+ ...toolPart?.output,
498
+ childMessages: [
499
+ ...childMessages,
500
+ {
501
+ type: "tool",
502
+ toolCallId: agentChunk.toolCallId,
503
+ toolName: agentChunk.toolName,
504
+ args: agentChunk.args
505
+ }
506
+ ]
507
+ }
508
+ };
509
+ } else if (chunk.type === "tool-output") {
510
+ const agentChunk = chunk.payload;
511
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
512
+ if (toolPartIndex === -1) return conversation;
513
+ const toolPart = parts[toolPartIndex];
514
+ if (agentChunk?.output?.type?.startsWith("workflow-")) {
515
+ const childMessages = toolPart?.output?.childMessages || [];
516
+ const lastToolIndex = childMessages.length - 1;
517
+ const currentMessage = childMessages[lastToolIndex];
518
+ const actualExistingWorkflowState = currentMessage?.toolOutput || {};
519
+ const updatedWorkflowState = mapWorkflowStreamChunkToWatchResult(actualExistingWorkflowState, agentChunk.output);
520
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
521
+ parts[toolPartIndex] = {
522
+ ...toolPart,
523
+ output: {
524
+ ...toolPart?.output,
525
+ childMessages: [
526
+ ...childMessages.slice(0, -1),
527
+ {
528
+ ...currentMessage,
529
+ toolOutput: { ...updatedWorkflowState, runId: agentChunk.output.runId }
530
+ }
531
+ ]
532
+ }
533
+ };
534
+ }
535
+ }
536
+ } else if (chunk.type === "tool-result") {
537
+ const agentChunk = chunk.payload;
538
+ const toolPartIndex = parts.findIndex((part) => part.type === "dynamic-tool");
539
+ if (toolPartIndex === -1) return conversation;
540
+ const toolPart = parts[toolPartIndex];
541
+ const childMessages = toolPart?.output?.childMessages || [];
542
+ const lastToolIndex = childMessages.length - 1;
543
+ const isWorkflow = agentChunk?.toolName?.startsWith("workflow-");
544
+ if (lastToolIndex >= 0 && childMessages[lastToolIndex]?.type === "tool") {
545
+ parts[toolPartIndex] = {
546
+ ...toolPart,
547
+ output: {
548
+ ...toolPart?.output,
549
+ childMessages: [
550
+ ...childMessages.slice(0, -1),
551
+ {
552
+ ...childMessages[lastToolIndex],
553
+ toolOutput: isWorkflow ? { ...agentChunk.result?.result, runId: agentChunk.result?.runId } : agentChunk.result
554
+ }
555
+ ]
556
+ }
557
+ };
558
+ }
559
+ }
560
+ return [
561
+ ...conversation.slice(0, -1),
562
+ {
563
+ ...lastMessage,
564
+ parts
565
+ }
566
+ ];
567
+ };
434
568
 
435
569
  const toAssistantUIMessage = (message) => {
436
570
  const extendedMessage = message;
@@ -470,13 +604,23 @@ const toAssistantUIMessage = (message) => {
470
604
  };
471
605
  }
472
606
  if (part.type === "file") {
473
- return {
474
- type: "file",
475
- mimeType: part.mediaType,
476
- data: part.url,
477
- // Use URL as data source
478
- metadata: message.metadata
479
- };
607
+ const type = part.mediaType.includes("image/") ? "image" : "file";
608
+ if (type === "file") {
609
+ return {
610
+ type,
611
+ mimeType: part.mediaType,
612
+ data: part.url,
613
+ // Use URL as data source
614
+ metadata: message.metadata
615
+ };
616
+ }
617
+ if (type === "image") {
618
+ return {
619
+ type,
620
+ image: part.url,
621
+ metadata: message.metadata
622
+ };
623
+ }
480
624
  }
481
625
  if (part.type === "dynamic-tool") {
482
626
  const baseToolCall = {
@@ -551,9 +695,116 @@ const toAssistantUIMessage = (message) => {
551
695
  return threadMessage;
552
696
  };
553
697
 
698
+ const resolveInitialMessages = (messages) => {
699
+ return messages.map((message) => {
700
+ const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
701
+ if (networkPart && networkPart.type === "text") {
702
+ try {
703
+ const json = JSON.parse(networkPart.text);
704
+ if (json.isNetwork === true) {
705
+ const selectionReason = json.selectionReason || "";
706
+ const primitiveType = json.primitiveType || "";
707
+ const primitiveId = json.primitiveId || "";
708
+ const finalResult = json.finalResult;
709
+ const toolCalls = finalResult?.toolCalls || [];
710
+ const childMessages = [];
711
+ for (const toolCall of toolCalls) {
712
+ if (toolCall.type === "tool-call" && toolCall.payload) {
713
+ const toolCallId = toolCall.payload.toolCallId;
714
+ let toolResult;
715
+ for (const message2 of finalResult?.messages || []) {
716
+ for (const part of message2.content || []) {
717
+ if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
718
+ toolResult = part;
719
+ break;
720
+ }
721
+ }
722
+ }
723
+ const isWorkflow = Boolean(toolResult?.result?.result?.steps);
724
+ childMessages.push({
725
+ type: "tool",
726
+ toolCallId: toolCall.payload.toolCallId,
727
+ toolName: toolCall.payload.toolName,
728
+ args: toolCall.payload.args,
729
+ toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
730
+ });
731
+ }
732
+ }
733
+ if (finalResult && finalResult.text) {
734
+ childMessages.push({
735
+ type: "text",
736
+ content: finalResult.text
737
+ });
738
+ }
739
+ const result = {
740
+ childMessages,
741
+ result: finalResult?.text || ""
742
+ };
743
+ console.log("json", json);
744
+ const nextMessage = {
745
+ role: "assistant",
746
+ parts: [
747
+ {
748
+ type: "dynamic-tool",
749
+ toolCallId: primitiveId,
750
+ toolName: primitiveId,
751
+ state: "output-available",
752
+ input: json.input,
753
+ output: result
754
+ }
755
+ ],
756
+ id: message.id,
757
+ metadata: {
758
+ ...message.metadata,
759
+ mode: "network",
760
+ selectionReason,
761
+ agentInput: json.input,
762
+ from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
763
+ }
764
+ };
765
+ return nextMessage;
766
+ }
767
+ } catch (error) {
768
+ return message;
769
+ }
770
+ }
771
+ return message;
772
+ });
773
+ };
774
+ const resolveToChildMessages = (messages) => {
775
+ const assistantMessage = messages.find((message) => message.role === "assistant");
776
+ if (!assistantMessage) return [];
777
+ const parts = assistantMessage.parts;
778
+ let childMessages = [];
779
+ for (const part of parts) {
780
+ const toolPart = part;
781
+ if (part.type.startsWith("tool-")) {
782
+ const toolName = part.type.substring("tool-".length);
783
+ const isWorkflow = toolName.startsWith("workflow-");
784
+ childMessages.push({
785
+ type: "tool",
786
+ toolCallId: toolPart.toolCallId,
787
+ toolName,
788
+ args: toolPart.input,
789
+ toolOutput: isWorkflow ? { ...toolPart.output?.result, runId: toolPart.output?.runId } : toolPart.output
790
+ });
791
+ }
792
+ if (part.type === "text") {
793
+ childMessages.push({
794
+ type: "text",
795
+ content: toolPart.text
796
+ });
797
+ }
798
+ }
799
+ return childMessages;
800
+ };
801
+
554
802
  class AISdkNetworkTransformer {
555
803
  transform({ chunk, conversation, metadata }) {
556
804
  const newConversation = [...conversation];
805
+ if (chunk.type === "routing-agent-text-delta") {
806
+ return this.handleRoutingAgentConversation(chunk, newConversation);
807
+ }
557
808
  if (chunk.type.startsWith("agent-execution-")) {
558
809
  return this.handleAgentConversation(chunk, newConversation, metadata);
559
810
  }
@@ -564,22 +815,80 @@ class AISdkNetworkTransformer {
564
815
  return this.handleToolConversation(chunk, newConversation, metadata);
565
816
  }
566
817
  if (chunk.type === "network-execution-event-step-finish") {
567
- const newMessage = {
568
- id: `network-execution-event-step-finish-${chunk.runId}-${Date.now()}`,
569
- role: "assistant",
570
- parts: [
818
+ const lastMessage = newConversation[newConversation.length - 1];
819
+ if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
820
+ const agentChunk = chunk.payload;
821
+ const parts = [...lastMessage.parts];
822
+ const textPartIndex = parts.findIndex((part) => part.type === "text");
823
+ if (textPartIndex === -1) {
824
+ parts.push({
825
+ type: "text",
826
+ text: agentChunk.result,
827
+ state: "done"
828
+ });
829
+ return [
830
+ ...newConversation.slice(0, -1),
571
831
  {
572
- type: "text",
573
- text: chunk.payload?.result || "",
574
- state: "done"
832
+ ...lastMessage,
833
+ parts
575
834
  }
576
- ],
577
- metadata
578
- };
579
- return [...newConversation, newMessage];
835
+ ];
836
+ }
837
+ const textPart = parts[textPartIndex];
838
+ if (textPart.type === "text") {
839
+ parts[textPartIndex] = {
840
+ ...textPart,
841
+ state: "done"
842
+ };
843
+ return [
844
+ ...newConversation.slice(0, -1),
845
+ {
846
+ ...lastMessage,
847
+ parts
848
+ }
849
+ ];
850
+ }
851
+ return newConversation;
580
852
  }
581
853
  return newConversation;
582
854
  }
855
+ handleRoutingAgentConversation = (chunk, newConversation) => {
856
+ const lastMessage = newConversation[newConversation.length - 1];
857
+ if (!lastMessage || lastMessage.role !== "assistant") return newConversation;
858
+ const agentChunk = chunk.payload;
859
+ const parts = [...lastMessage.parts];
860
+ const textPartIndex = parts.findIndex((part) => part.type === "text");
861
+ if (textPartIndex === -1) {
862
+ parts.push({
863
+ type: "text",
864
+ text: agentChunk.text,
865
+ state: "streaming"
866
+ });
867
+ return [
868
+ ...newConversation.slice(0, -1),
869
+ {
870
+ ...lastMessage,
871
+ parts
872
+ }
873
+ ];
874
+ }
875
+ const textPart = parts[textPartIndex];
876
+ if (textPart.type === "text") {
877
+ parts[textPartIndex] = {
878
+ ...textPart,
879
+ text: textPart.text + agentChunk.text,
880
+ state: "streaming"
881
+ };
882
+ return [
883
+ ...newConversation.slice(0, -1),
884
+ {
885
+ ...lastMessage,
886
+ parts
887
+ }
888
+ ];
889
+ }
890
+ return newConversation;
891
+ };
583
892
  handleAgentConversation = (chunk, newConversation, metadata) => {
584
893
  if (chunk.type === "agent-execution-start") {
585
894
  const primitiveId = chunk.payload?.args?.primitiveId;
@@ -862,87 +1171,58 @@ class AISdkNetworkTransformer {
862
1171
  };
863
1172
  }
864
1173
 
865
- const resolveInitialMessages = (messages) => {
866
- return messages.map((message) => {
867
- const networkPart = message.parts.find((part) => part.type === "text" && part.text.includes('"isNetwork":true'));
868
- if (networkPart && networkPart.type === "text") {
869
- try {
870
- const json = JSON.parse(networkPart.text);
871
- if (json.isNetwork === true) {
872
- const selectionReason = json.selectionReason || "";
873
- const primitiveType = json.primitiveType || "";
874
- const primitiveId = json.primitiveId || "";
875
- const finalResult = json.finalResult;
876
- const toolCalls = finalResult?.toolCalls || [];
877
- const childMessages = [];
878
- for (const toolCall of toolCalls) {
879
- if (toolCall.type === "tool-call" && toolCall.payload) {
880
- const toolCallId = toolCall.payload.toolCallId;
881
- let toolResult;
882
- for (const message2 of finalResult?.messages || []) {
883
- for (const part of message2.content || []) {
884
- if (typeof part === "object" && part.type === "tool-result" && part.toolCallId === toolCallId) {
885
- toolResult = part;
886
- break;
887
- }
888
- }
889
- }
890
- const isWorkflow = Boolean(toolResult?.result?.result?.steps);
891
- childMessages.push({
892
- type: "tool",
893
- toolCallId: toolCall.payload.toolCallId,
894
- toolName: toolCall.payload.toolName,
895
- args: toolCall.payload.args,
896
- toolOutput: isWorkflow ? toolResult?.result?.result : toolResult?.result
897
- });
898
- }
899
- }
900
- if (finalResult && finalResult.text) {
901
- childMessages.push({
902
- type: "text",
903
- content: finalResult.text
904
- });
905
- }
906
- const result = {
907
- childMessages,
908
- result: finalResult?.text || ""
909
- };
910
- console.log("json", json);
911
- const nextMessage = {
912
- role: "assistant",
913
- parts: [
914
- {
915
- type: "dynamic-tool",
916
- toolCallId: primitiveId,
917
- toolName: primitiveId,
918
- state: "output-available",
919
- input: json.input,
920
- output: result
921
- }
922
- ],
923
- id: message.id,
924
- metadata: {
925
- ...message.metadata,
926
- mode: "network",
927
- selectionReason,
928
- agentInput: json.input,
929
- from: primitiveType === "agent" ? "AGENT" : "WORKFLOW"
930
- }
931
- };
932
- return nextMessage;
933
- }
934
- } catch (error) {
935
- return message;
1174
+ const fromCoreUserMessageToUIMessage = (coreUserMessage) => {
1175
+ const id = `user-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
1176
+ const parts = typeof coreUserMessage.content === "string" ? [
1177
+ {
1178
+ type: "text",
1179
+ text: coreUserMessage.content
1180
+ }
1181
+ ] : coreUserMessage.content.map((part) => {
1182
+ switch (part.type) {
1183
+ case "text": {
1184
+ return {
1185
+ type: "text",
1186
+ text: part.text
1187
+ };
1188
+ }
1189
+ case "image": {
1190
+ const url = typeof part.image === "string" ? part.image : part.image instanceof URL ? part.image.toString() : "";
1191
+ return {
1192
+ type: "file",
1193
+ mediaType: part.mimeType ?? "image/*",
1194
+ url
1195
+ };
1196
+ }
1197
+ case "file": {
1198
+ const url = typeof part.data === "string" ? part.data : part.data instanceof URL ? part.data.toString() : "";
1199
+ return {
1200
+ type: "file",
1201
+ mediaType: part.mimeType,
1202
+ url,
1203
+ ...part.filename !== void 0 ? { filename: part.filename } : {}
1204
+ };
1205
+ }
1206
+ default: {
1207
+ const exhaustiveCheck = part;
1208
+ throw new Error(`Unhandled content part type: ${exhaustiveCheck.type}`);
936
1209
  }
937
1210
  }
938
- return message;
939
1211
  });
1212
+ return {
1213
+ id,
1214
+ role: "user",
1215
+ parts
1216
+ };
940
1217
  };
941
1218
 
942
1219
  const useChat = ({ agentId, initializeMessages }) => {
1220
+ const _currentRunId = react.useRef(void 0);
1221
+ const _onChunk = react.useRef(void 0);
943
1222
  const [messages, setMessages] = react.useState(
944
1223
  () => resolveInitialMessages(initializeMessages?.() || [])
945
1224
  );
1225
+ const [toolCallApprovals, setToolCallApprovals] = react.useState({});
946
1226
  const baseClient = useMastraClient();
947
1227
  const [isRunning, setIsRunning] = react.useState(false);
948
1228
  const generate = async ({
@@ -1012,7 +1292,8 @@ const useChat = ({ agentId, initializeMessages }) => {
1012
1292
  topP,
1013
1293
  instructions,
1014
1294
  providerOptions,
1015
- maxSteps
1295
+ maxSteps,
1296
+ requireToolApproval
1016
1297
  } = modelSettings || {};
1017
1298
  setIsRunning(true);
1018
1299
  const clientWithAbort = new clientJs.MastraClient({
@@ -1020,9 +1301,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1020
1301
  abortSignal: signal
1021
1302
  });
1022
1303
  const agent = clientWithAbort.getAgent(agentId);
1304
+ const runId = agentId;
1023
1305
  const response = await agent.stream({
1024
1306
  messages: coreUserMessages,
1025
- runId: agentId,
1307
+ runId,
1026
1308
  maxSteps,
1027
1309
  modelSettings: {
1028
1310
  frequencyPenalty,
@@ -1036,17 +1318,14 @@ const useChat = ({ agentId, initializeMessages }) => {
1036
1318
  instructions,
1037
1319
  runtimeContext,
1038
1320
  ...threadId ? { threadId, resourceId: agentId } : {},
1039
- providerOptions
1321
+ providerOptions,
1322
+ requireToolApproval
1040
1323
  });
1041
- if (!response.body) {
1042
- setIsRunning(false);
1043
- throw new Error("[Stream] No response body");
1044
- }
1324
+ _onChunk.current = onChunk;
1325
+ _currentRunId.current = runId;
1045
1326
  await response.processDataStream({
1046
1327
  onChunk: async (chunk) => {
1047
- reactDom.flushSync(() => {
1048
- setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1049
- });
1328
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1050
1329
  onChunk?.(chunk);
1051
1330
  }
1052
1331
  });
@@ -1086,24 +1365,65 @@ const useChat = ({ agentId, initializeMessages }) => {
1086
1365
  const transformer = new AISdkNetworkTransformer();
1087
1366
  await response.processDataStream({
1088
1367
  onChunk: async (chunk) => {
1089
- reactDom.flushSync(() => {
1090
- setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
1091
- });
1368
+ setMessages((prev) => transformer.transform({ chunk, conversation: prev, metadata: { mode: "network" } }));
1092
1369
  onNetworkChunk?.(chunk);
1093
1370
  }
1094
1371
  });
1095
1372
  setIsRunning(false);
1096
1373
  };
1374
+ const handleCancelRun = () => {
1375
+ setIsRunning(false);
1376
+ _currentRunId.current = void 0;
1377
+ _onChunk.current = void 0;
1378
+ };
1379
+ const approveToolCall = async (toolCallId) => {
1380
+ const onChunk = _onChunk.current;
1381
+ const currentRunId = _currentRunId.current;
1382
+ if (!currentRunId)
1383
+ return console.info("[approveToolCall] approveToolCall can only be called after a stream has started");
1384
+ setIsRunning(true);
1385
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "approved" } }));
1386
+ const agent = baseClient.getAgent(agentId);
1387
+ const response = await agent.approveToolCall({ runId: currentRunId, toolCallId });
1388
+ await response.processDataStream({
1389
+ onChunk: async (chunk) => {
1390
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1391
+ onChunk?.(chunk);
1392
+ }
1393
+ });
1394
+ setIsRunning(false);
1395
+ };
1396
+ const declineToolCall = async (toolCallId) => {
1397
+ const onChunk = _onChunk.current;
1398
+ const currentRunId = _currentRunId.current;
1399
+ if (!currentRunId)
1400
+ return console.info("[declineToolCall] declineToolCall can only be called after a stream has started");
1401
+ setIsRunning(true);
1402
+ setToolCallApprovals((prev) => ({ ...prev, [toolCallId]: { status: "declined" } }));
1403
+ const agent = baseClient.getAgent(agentId);
1404
+ const response = await agent.declineToolCall({ runId: currentRunId, toolCallId });
1405
+ await response.processDataStream({
1406
+ onChunk: async (chunk) => {
1407
+ setMessages((prev) => toUIMessage({ chunk, conversation: prev, metadata: { mode: "stream" } }));
1408
+ onChunk?.(chunk);
1409
+ }
1410
+ });
1411
+ setIsRunning(false);
1412
+ };
1097
1413
  const sendMessage = async ({ mode = "stream", ...args }) => {
1098
1414
  const nextMessage = { role: "user", content: [{ type: "text", text: args.message }] };
1099
- const messages2 = args.coreUserMessages ? [nextMessage, ...args.coreUserMessages] : [nextMessage];
1100
- setMessages((s) => [...s, { role: "user", parts: [{ type: "text", text: args.message }] }]);
1415
+ const coreUserMessages = [nextMessage];
1416
+ if (args.coreUserMessages) {
1417
+ coreUserMessages.push(...args.coreUserMessages);
1418
+ }
1419
+ const uiMessages = coreUserMessages.map(fromCoreUserMessageToUIMessage);
1420
+ setMessages((s) => [...s, ...uiMessages]);
1101
1421
  if (mode === "generate") {
1102
- await generate({ ...args, coreUserMessages: messages2 });
1422
+ await generate({ ...args, coreUserMessages });
1103
1423
  } else if (mode === "stream") {
1104
- await stream({ ...args, coreUserMessages: messages2 });
1424
+ await stream({ ...args, coreUserMessages });
1105
1425
  } else if (mode === "network") {
1106
- await network({ ...args, coreUserMessages: messages2 });
1426
+ await network({ ...args, coreUserMessages });
1107
1427
  }
1108
1428
  };
1109
1429
  return {
@@ -1111,7 +1431,10 @@ const useChat = ({ agentId, initializeMessages }) => {
1111
1431
  sendMessage,
1112
1432
  isRunning,
1113
1433
  messages,
1114
- cancelRun: () => setIsRunning(false)
1434
+ approveToolCall,
1435
+ declineToolCall,
1436
+ cancelRun: handleCancelRun,
1437
+ toolCallApprovals
1115
1438
  };
1116
1439
  };
1117
1440
 
@@ -1485,6 +1808,7 @@ exports.TooltipContentClass = TooltipContentClass;
1485
1808
  exports.TooltipTrigger = TooltipTrigger;
1486
1809
  exports.WorkflowIcon = WorkflowIcon;
1487
1810
  exports.mapWorkflowStreamChunkToWatchResult = mapWorkflowStreamChunkToWatchResult;
1811
+ exports.resolveToChildMessages = resolveToChildMessages;
1488
1812
  exports.toAssistantUIMessage = toAssistantUIMessage;
1489
1813
  exports.toUIMessage = toUIMessage;
1490
1814
  exports.useChat = useChat;