@assistant-ui/react 0.1.7 → 0.1.9

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
@@ -98,7 +98,7 @@ var getMessageText = (message) => {
98
98
 
99
99
  // src/actions/useCopyMessage.tsx
100
100
  var useCopyMessage = ({ copiedDuration = 3e3 }) => {
101
- const { useMessage, useComposer } = useMessageContext();
101
+ const { useMessage, useMessageUtils, useComposer } = useMessageContext();
102
102
  const hasCopyableContent = useCombinedStore(
103
103
  [useMessage, useComposer],
104
104
  (m, c) => {
@@ -106,13 +106,14 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
106
106
  }
107
107
  );
108
108
  const callback = (0, import_react4.useCallback)(() => {
109
+ const { message } = useMessage.getState();
110
+ const { setIsCopied } = useMessageUtils.getState();
109
111
  const { isEditing, value: composerValue } = useComposer.getState();
110
- const { message, setIsCopied } = useMessage.getState();
111
112
  const valueToCopy = isEditing ? composerValue : getMessageText(message);
112
113
  navigator.clipboard.writeText(valueToCopy);
113
114
  setIsCopied(true);
114
115
  setTimeout(() => setIsCopied(false), copiedDuration);
115
- }, [useComposer, useMessage, copiedDuration]);
116
+ }, [useMessage, useMessageUtils, useComposer, copiedDuration]);
116
117
  if (!hasCopyableContent) return null;
117
118
  return callback;
118
119
  };
@@ -134,7 +135,7 @@ var useThreadContext = () => {
134
135
 
135
136
  // src/actions/useReloadMessage.tsx
136
137
  var useReloadMessage = () => {
137
- const { useThread, useViewport } = useThreadContext();
138
+ const { useThread, useThreadActions, useViewport } = useThreadContext();
138
139
  const { useMessage } = useMessageContext();
139
140
  const disabled = useCombinedStore(
140
141
  [useThread, useMessage],
@@ -142,9 +143,9 @@ var useReloadMessage = () => {
142
143
  );
143
144
  const callback = (0, import_react6.useCallback)(() => {
144
145
  const { parentId } = useMessage.getState();
145
- useThread.getState().startRun(parentId);
146
+ useThreadActions.getState().startRun(parentId);
146
147
  useViewport.getState().scrollToBottom();
147
- }, [useMessage, useThread, useViewport]);
148
+ }, [useThreadActions, useMessage, useViewport]);
148
149
  if (disabled) return null;
149
150
  return callback;
150
151
  };
@@ -168,7 +169,7 @@ var useBeginMessageEdit = () => {
168
169
  // src/actions/useGoToNextBranch.tsx
169
170
  var import_react8 = require("react");
170
171
  var useGoToNextBranch = () => {
171
- const { useThread } = useThreadContext();
172
+ const { useThreadActions } = useThreadContext();
172
173
  const { useMessage, useComposer } = useMessageContext();
173
174
  const disabled = useCombinedStore(
174
175
  [useMessage, useComposer],
@@ -176,8 +177,8 @@ var useGoToNextBranch = () => {
176
177
  );
177
178
  const callback = (0, import_react8.useCallback)(() => {
178
179
  const { message, branches } = useMessage.getState();
179
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
180
- }, [useMessage, useThread]);
180
+ useThreadActions.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
181
+ }, [useThreadActions, useMessage]);
181
182
  if (disabled) return null;
182
183
  return callback;
183
184
  };
@@ -185,7 +186,7 @@ var useGoToNextBranch = () => {
185
186
  // src/actions/useGoToPreviousBranch.tsx
186
187
  var import_react9 = require("react");
187
188
  var useGoToPreviousBranch = () => {
188
- const { useThread } = useThreadContext();
189
+ const { useThreadActions } = useThreadContext();
189
190
  const { useMessage, useComposer } = useMessageContext();
190
191
  const disabled = useCombinedStore(
191
192
  [useMessage, useComposer],
@@ -193,8 +194,8 @@ var useGoToPreviousBranch = () => {
193
194
  );
194
195
  const callback = (0, import_react9.useCallback)(() => {
195
196
  const { message, branches } = useMessage.getState();
196
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
197
- }, [useMessage, useThread]);
197
+ useThreadActions.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
198
+ }, [useThreadActions, useMessage]);
198
199
  if (disabled) return null;
199
200
  return callback;
200
201
  };
@@ -337,7 +338,9 @@ var ThreadViewport = (0, import_react13.forwardRef)(({ autoScroll = true, onScro
337
338
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
338
339
  } else if (newIsAtBottom !== isAtBottom) {
339
340
  isScrollingToBottomRef.current = false;
340
- useViewport.setState({ isAtBottom: newIsAtBottom });
341
+ useViewport.setState({
342
+ isAtBottom: newIsAtBottom
343
+ });
341
344
  }
342
345
  lastScrollTop.current = div.scrollTop;
343
346
  };
@@ -361,7 +364,7 @@ var import_react16 = require("react");
361
364
 
362
365
  // src/context/providers/MessageProvider.tsx
363
366
  var import_react14 = require("react");
364
- var import_zustand2 = require("zustand");
367
+ var import_zustand3 = require("zustand");
365
368
 
366
369
  // src/context/stores/MessageComposer.ts
367
370
  var import_zustand = require("zustand");
@@ -397,17 +400,34 @@ var makeEditComposerStore = ({
397
400
  }
398
401
  }));
399
402
 
403
+ // src/context/stores/MessageUtils.ts
404
+ var import_zustand2 = require("zustand");
405
+ var makeMessageUtilsStore = () => (0, import_zustand2.create)((set) => ({
406
+ inProgressIndicator: null,
407
+ setInProgressIndicator: (value) => {
408
+ set({ inProgressIndicator: value });
409
+ },
410
+ isCopied: false,
411
+ setIsCopied: (value) => {
412
+ set({ isCopied: value });
413
+ },
414
+ isHovering: false,
415
+ setIsHovering: (value) => {
416
+ set({ isHovering: value });
417
+ }
418
+ }));
419
+
400
420
  // src/context/providers/MessageProvider.tsx
401
421
  var import_jsx_runtime4 = require("react/jsx-runtime");
402
422
  var getIsLast = (thread, message) => {
403
423
  return thread.messages[thread.messages.length - 1]?.id === message.id;
404
424
  };
405
- var syncMessage = (thread, useMessage, messageIndex) => {
425
+ var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
406
426
  const parentId = thread.messages[messageIndex - 1]?.id ?? null;
407
427
  const message = thread.messages[messageIndex];
408
428
  if (!message) return;
409
429
  const isLast = getIsLast(thread, message);
410
- const branches = thread.getBranches(message.id);
430
+ const branches = getBranches(message.id);
411
431
  const currentState = useMessage.getState();
412
432
  if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
413
433
  return;
@@ -419,26 +439,10 @@ var syncMessage = (thread, useMessage, messageIndex) => {
419
439
  });
420
440
  };
421
441
  var useMessageContext2 = (messageIndex) => {
422
- const { useThread } = useThreadContext();
442
+ const { useThread, useThreadActions } = useThreadContext();
423
443
  const [context] = (0, import_react14.useState)(() => {
424
- const useMessage = (0, import_zustand2.create)((set) => ({
425
- message: null,
426
- parentId: null,
427
- branches: [],
428
- isLast: false,
429
- inProgressIndicator: null,
430
- isCopied: false,
431
- isHovering: false,
432
- setInProgressIndicator: (value) => {
433
- set({ inProgressIndicator: value });
434
- },
435
- setIsCopied: (value) => {
436
- set({ isCopied: value });
437
- },
438
- setIsHovering: (value) => {
439
- set({ isHovering: value });
440
- }
441
- }));
444
+ const useMessage = (0, import_zustand3.create)(() => ({}));
445
+ const useMessageUtils = makeMessageUtilsStore();
442
446
  const useComposer = makeEditComposerStore({
443
447
  onEdit: () => {
444
448
  const message = useMessage.getState().message;
@@ -458,20 +462,30 @@ var useMessageContext2 = (messageIndex) => {
458
462
  const nonTextParts = message.content.filter(
459
463
  (part) => part.type !== "text" && part.type !== "ui"
460
464
  );
461
- useThread.getState().append({
465
+ useThreadActions.getState().append({
462
466
  parentId,
463
467
  content: [{ type: "text", text }, ...nonTextParts]
464
468
  });
465
469
  }
466
470
  });
467
- syncMessage(useThread.getState(), useMessage, messageIndex);
468
- return { useMessage, useComposer };
471
+ syncMessage(
472
+ useThread.getState(),
473
+ useThreadActions.getState().getBranches,
474
+ useMessage,
475
+ messageIndex
476
+ );
477
+ return { useMessage, useMessageUtils, useComposer };
469
478
  });
470
479
  (0, import_react14.useEffect)(() => {
471
480
  return useThread.subscribe((thread) => {
472
- syncMessage(thread, context.useMessage, messageIndex);
481
+ syncMessage(
482
+ thread,
483
+ useThreadActions.getState().getBranches,
484
+ context.useMessage,
485
+ messageIndex
486
+ );
473
487
  });
474
- }, [context, useThread, messageIndex]);
488
+ }, [useThread, useThreadActions, context, messageIndex]);
475
489
  return context;
476
490
  };
477
491
  var MessageProvider = ({
@@ -512,16 +526,19 @@ var ComposerIf = ({ children, ...query }) => {
512
526
 
513
527
  // src/primitives/message/MessageIf.tsx
514
528
  var useMessageIf = (props) => {
515
- const { useMessage } = useMessageContext();
516
- return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
517
- if (props.hasBranches === true && branches.length < 2) return false;
518
- if (props.user && message.role !== "user") return false;
519
- if (props.assistant && message.role !== "assistant") return false;
520
- if (props.lastOrHover === true && !isHovering && !isLast) return false;
521
- if (props.copied === true && !isCopied) return false;
522
- if (props.copied === false && isCopied) return false;
523
- return true;
524
- });
529
+ const { useMessage, useMessageUtils } = useMessageContext();
530
+ return useCombinedStore(
531
+ [useMessage, useMessageUtils],
532
+ ({ message, branches, isLast }, { isCopied, isHovering }) => {
533
+ if (props.hasBranches === true && branches.length < 2) return false;
534
+ if (props.user && message.role !== "user") return false;
535
+ if (props.assistant && message.role !== "assistant") return false;
536
+ if (props.lastOrHover === true && !isHovering && !isLast) return false;
537
+ if (props.copied === true && !isCopied) return false;
538
+ if (props.copied === false && isCopied) return false;
539
+ return true;
540
+ }
541
+ );
525
542
  };
526
543
  var MessageIf = ({ children, ...query }) => {
527
544
  const result = useMessageIf(query);
@@ -792,8 +809,8 @@ var import_react23 = require("react");
792
809
  var import_jsx_runtime12 = require("react/jsx-runtime");
793
810
  var MessageRoot = (0, import_react23.forwardRef)(
794
811
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
795
- const { useMessage } = useMessageContext();
796
- const setIsHovering = useMessage((s) => s.setIsHovering);
812
+ const { useMessageUtils } = useMessageContext();
813
+ const setIsHovering = useMessageUtils((s) => s.setIsHovering);
797
814
  const handleMouseEnter = () => {
798
815
  setIsHovering(true);
799
816
  };
@@ -846,7 +863,7 @@ var useContentPartContext = () => {
846
863
 
847
864
  // src/context/providers/ContentPartProvider.tsx
848
865
  var import_react26 = require("react");
849
- var import_zustand3 = require("zustand");
866
+ var import_zustand4 = require("zustand");
850
867
  var import_jsx_runtime13 = require("react/jsx-runtime");
851
868
  var syncContentPart = ({ message }, useContentPart, partIndex) => {
852
869
  const part = message.content[partIndex];
@@ -855,19 +872,24 @@ var syncContentPart = ({ message }, useContentPart, partIndex) => {
855
872
  const status = partIndex === message.content.length - 1 ? messageStatus : "done";
856
873
  const currentState = useContentPart.getState();
857
874
  if (currentState.part === part && currentState.status === status) return;
858
- useContentPart.setState({ part, status });
875
+ useContentPart.setState(
876
+ Object.freeze({
877
+ part,
878
+ status
879
+ })
880
+ );
859
881
  };
860
882
  var useContentPartContext2 = (partIndex) => {
861
883
  const { useMessage } = useMessageContext();
862
884
  const [context] = (0, import_react26.useState)(() => {
863
- const useContentPart = (0, import_zustand3.create)(() => ({
864
- part: { type: "text", text: "" },
865
- status: "done"
866
- }));
885
+ const useContentPart = (0, import_zustand4.create)(
886
+ () => ({})
887
+ );
867
888
  syncContentPart(useMessage.getState(), useContentPart, partIndex);
868
889
  return { useContentPart };
869
890
  });
870
891
  (0, import_react26.useEffect)(() => {
892
+ syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
871
893
  return useMessage.subscribe((message) => {
872
894
  syncContentPart(message, context.useContentPart, partIndex);
873
895
  });
@@ -897,10 +919,10 @@ var ContentPartDisplay = () => {
897
919
 
898
920
  // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
899
921
  var ContentPartInProgressIndicator = () => {
900
- const { useMessage } = useMessageContext();
922
+ const { useMessageUtils } = useMessageContext();
901
923
  const { useContentPart } = useContentPartContext();
902
924
  const indicator = useCombinedStore(
903
- [useMessage, useContentPart],
925
+ [useMessageUtils, useContentPart],
904
926
  (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
905
927
  );
906
928
  return indicator;
@@ -934,10 +956,8 @@ var defaultComponents = {
934
956
  UI: () => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ContentPartDisplay, {}),
935
957
  tools: {
936
958
  Fallback: (props) => {
937
- const { useToolRenderers } = useAssistantContext();
938
- const Render = useToolRenderers(
939
- (s) => s.getToolRenderer(props.part.toolName)
940
- );
959
+ const { useToolUIs } = useAssistantContext();
960
+ const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
941
961
  if (!Render) return null;
942
962
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Render, { ...props });
943
963
  }
@@ -951,6 +971,8 @@ var MessageContentPartComponent = ({
951
971
  tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
952
972
  } = {}
953
973
  }) => {
974
+ const { useThreadActions } = useThreadContext();
975
+ const addToolResult = useThreadActions((t) => t.addToolResult);
954
976
  const { useContentPart } = useContentPartContext();
955
977
  const { part, status } = useContentPart();
956
978
  const type = part.type;
@@ -963,7 +985,8 @@ var MessageContentPartComponent = ({
963
985
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(UI, { part, status });
964
986
  case "tool-call": {
965
987
  const Tool = by_name[part.toolName] || Fallback;
966
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Tool, { part, status });
988
+ const addResult = (result) => addToolResult(part.toolCallId, result);
989
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Tool, { part, status, addResult });
967
990
  }
968
991
  default:
969
992
  throw new Error(`Unknown content part type: ${type}`);
@@ -1000,10 +1023,10 @@ var import_react_primitive10 = require("@radix-ui/react-primitive");
1000
1023
  var import_react29 = require("react");
1001
1024
  var import_jsx_runtime16 = require("react/jsx-runtime");
1002
1025
  var MessageInProgress = (0, import_react29.forwardRef)((props, ref) => {
1003
- const { useMessage } = useMessageContext();
1026
+ const { useMessageUtils } = useMessageContext();
1004
1027
  (0, import_react29.useMemo)(() => {
1005
- useMessage.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive10.Primitive.span, { ...props, ref }));
1006
- }, [useMessage, props, ref]);
1028
+ useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive10.Primitive.span, { ...props, ref }));
1029
+ }, [useMessageUtils, props, ref]);
1007
1030
  return null;
1008
1031
  });
1009
1032
  MessageInProgress.displayName = "MessageInProgress";
@@ -1087,14 +1110,14 @@ var import_react32 = require("react");
1087
1110
  var import_jsx_runtime21 = require("react/jsx-runtime");
1088
1111
  var ActionBarRoot = (0, import_react32.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1089
1112
  const { useThread } = useThreadContext();
1090
- const { useMessage } = useMessageContext();
1113
+ const { useMessage, useMessageUtils } = useMessageContext();
1091
1114
  const hideAndfloatStatus = useCombinedStore(
1092
- [useThread, useMessage],
1093
- (t, m) => {
1115
+ [useThread, useMessage, useMessageUtils],
1116
+ (t, m, mu) => {
1094
1117
  if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
1095
1118
  const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
1096
1119
  if (!autohideEnabled) return "normal" /* Normal */;
1097
- if (!m.isHovering) return "hidden" /* Hidden */;
1120
+ if (!mu.isHovering) return "hidden" /* Hidden */;
1098
1121
  if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
1099
1122
  return "floating" /* Floating */;
1100
1123
  return "normal" /* Normal */;
@@ -1427,6 +1450,9 @@ var LocalRuntime = class {
1427
1450
  this._configProviders.add(provider);
1428
1451
  return () => this._configProviders.delete(provider);
1429
1452
  }
1453
+ addToolResult() {
1454
+ throw new Error("LocalRuntime does not yet support tool results");
1455
+ }
1430
1456
  };
1431
1457
 
1432
1458
  // src/runtime/local/useLocalRuntime.tsx
@@ -1445,7 +1471,7 @@ var import_react37 = require("react");
1445
1471
  var import_react36 = require("react");
1446
1472
 
1447
1473
  // src/context/stores/AssistantModelConfig.ts
1448
- var import_zustand4 = require("zustand");
1474
+ var import_zustand5 = require("zustand");
1449
1475
 
1450
1476
  // src/utils/ProxyConfigProvider.ts
1451
1477
  var ProxyConfigProvider = class {
@@ -1462,30 +1488,30 @@ var ProxyConfigProvider = class {
1462
1488
  };
1463
1489
 
1464
1490
  // src/context/stores/AssistantModelConfig.ts
1465
- var makeAssistantModelConfigStore = () => (0, import_zustand4.create)(() => {
1491
+ var makeAssistantModelConfigStore = () => (0, import_zustand5.create)(() => {
1466
1492
  const proxy = new ProxyConfigProvider();
1467
- return {
1493
+ return Object.freeze({
1468
1494
  getModelConfig: () => {
1469
1495
  return proxy.getModelConfig();
1470
1496
  },
1471
1497
  registerModelConfigProvider: (provider) => {
1472
1498
  return proxy.registerModelConfigProvider(provider);
1473
1499
  }
1474
- };
1500
+ });
1475
1501
  });
1476
1502
 
1477
- // src/context/stores/AssistantToolRenderers.ts
1478
- var import_zustand5 = require("zustand");
1479
- var makeAssistantToolRenderersStore = () => (0, import_zustand5.create)((set) => {
1503
+ // src/context/stores/AssistantToolUIs.ts
1504
+ var import_zustand6 = require("zustand");
1505
+ var makeAssistantToolUIsStore = () => (0, import_zustand6.create)((set) => {
1480
1506
  const renderers = /* @__PURE__ */ new Map();
1481
- return {
1482
- getToolRenderer: (name) => {
1507
+ return Object.freeze({
1508
+ getToolUI: (name) => {
1483
1509
  const arr = renderers.get(name);
1484
1510
  const last = arr?.at(-1);
1485
1511
  if (last) return last;
1486
1512
  return null;
1487
1513
  },
1488
- setToolRenderer: (name, render) => {
1514
+ setToolUI: (name, render) => {
1489
1515
  let arr = renderers.get(name);
1490
1516
  if (!arr) {
1491
1517
  arr = [];
@@ -1498,25 +1524,27 @@ var makeAssistantToolRenderersStore = () => (0, import_zustand5.create)((set) =>
1498
1524
  if (index !== -1) {
1499
1525
  arr.splice(index, 1);
1500
1526
  }
1501
- set({});
1527
+ if (index === arr.length) {
1528
+ set({});
1529
+ }
1502
1530
  };
1503
1531
  }
1504
- };
1532
+ });
1505
1533
  });
1506
1534
 
1507
1535
  // src/context/providers/ThreadProvider.tsx
1508
1536
  var import_react35 = require("react");
1509
1537
 
1510
1538
  // src/context/stores/Composer.ts
1511
- var import_zustand6 = require("zustand");
1512
- var makeComposerStore = (useThread) => (0, import_zustand6.create)()((set, get, store) => {
1539
+ var import_zustand7 = require("zustand");
1540
+ var makeComposerStore = (useThread, useThreadActions) => (0, import_zustand7.create)()((set, get, store) => {
1513
1541
  return {
1514
1542
  ...makeBaseComposer(set, get, store),
1515
1543
  isEditing: true,
1516
1544
  send: () => {
1517
1545
  const { setValue, value } = get();
1518
1546
  setValue("");
1519
- useThread.getState().append({
1547
+ useThreadActions.getState().append({
1520
1548
  parentId: useThread.getState().messages.at(-1)?.id ?? null,
1521
1549
  content: [{ type: "text", text: value }]
1522
1550
  });
@@ -1524,41 +1552,26 @@ var makeComposerStore = (useThread) => (0, import_zustand6.create)()((set, get,
1524
1552
  cancel: () => {
1525
1553
  const thread = useThread.getState();
1526
1554
  if (!thread.isRunning) return false;
1527
- useThread.getState().cancelRun();
1555
+ useThreadActions.getState().cancelRun();
1528
1556
  return true;
1529
1557
  }
1530
1558
  };
1531
1559
  });
1532
1560
 
1533
1561
  // src/context/stores/Thread.ts
1534
- var import_zustand7 = require("zustand");
1562
+ var import_zustand8 = require("zustand");
1535
1563
  var makeThreadStore = (runtimeRef) => {
1536
- const useThread = (0, import_zustand7.create)(() => ({
1564
+ return (0, import_zustand8.create)(() => ({
1537
1565
  messages: runtimeRef.current.messages,
1538
- isRunning: runtimeRef.current.isRunning,
1539
- getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1540
- switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1541
- startRun: (parentId) => runtimeRef.current.startRun(parentId),
1542
- append: (message) => runtimeRef.current.append(message),
1543
- cancelRun: () => runtimeRef.current.cancelRun()
1566
+ isRunning: runtimeRef.current.isRunning
1544
1567
  }));
1545
- const onRuntimeUpdate = () => {
1546
- useThread.setState({
1547
- messages: runtimeRef.current.messages,
1548
- isRunning: runtimeRef.current.isRunning
1549
- });
1550
- };
1551
- return {
1552
- useThread,
1553
- onRuntimeUpdate
1554
- };
1555
1568
  };
1556
1569
 
1557
1570
  // src/context/stores/ThreadViewport.tsx
1558
- var import_zustand8 = require("zustand");
1571
+ var import_zustand9 = require("zustand");
1559
1572
  var makeThreadViewportStore = () => {
1560
1573
  const scrollToBottomListeners = /* @__PURE__ */ new Set();
1561
- return (0, import_zustand8.create)(() => ({
1574
+ return (0, import_zustand9.create)(() => ({
1562
1575
  isAtBottom: true,
1563
1576
  scrollToBottom: () => {
1564
1577
  for (const listener of scrollToBottomListeners) {
@@ -1574,6 +1587,21 @@ var makeThreadViewportStore = () => {
1574
1587
  }));
1575
1588
  };
1576
1589
 
1590
+ // src/context/stores/ThreadActions.ts
1591
+ var import_zustand10 = require("zustand");
1592
+ var makeThreadActionStore = (runtimeRef) => {
1593
+ return (0, import_zustand10.create)(
1594
+ () => Object.freeze({
1595
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1596
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1597
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
1598
+ append: (message) => runtimeRef.current.append(message),
1599
+ cancelRun: () => runtimeRef.current.cancelRun(),
1600
+ addToolResult: (toolCallId, result) => runtimeRef.current.addToolResult(toolCallId, result)
1601
+ })
1602
+ );
1603
+ };
1604
+
1577
1605
  // src/context/providers/ThreadProvider.tsx
1578
1606
  var import_jsx_runtime23 = require("react/jsx-runtime");
1579
1607
  var ThreadProvider = ({
@@ -1584,23 +1612,31 @@ var ThreadProvider = ({
1584
1612
  (0, import_react35.useInsertionEffect)(() => {
1585
1613
  runtimeRef.current = runtime;
1586
1614
  });
1587
- const [{ context, onRuntimeUpdate }] = (0, import_react35.useState)(() => {
1588
- const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1615
+ const [context] = (0, import_react35.useState)(() => {
1616
+ const useThread = makeThreadStore(runtimeRef);
1617
+ const useThreadActions = makeThreadActionStore(runtimeRef);
1589
1618
  const useViewport = makeThreadViewportStore();
1590
- const useComposer = makeComposerStore(useThread);
1619
+ const useComposer = makeComposerStore(useThread, useThreadActions);
1591
1620
  return {
1592
- context: {
1593
- useViewport,
1594
- useThread,
1595
- useComposer
1596
- },
1597
- onRuntimeUpdate: onRuntimeUpdate2
1621
+ useThread,
1622
+ useThreadActions,
1623
+ useComposer,
1624
+ useViewport
1598
1625
  };
1599
1626
  });
1600
1627
  (0, import_react35.useEffect)(() => {
1628
+ const onRuntimeUpdate = () => {
1629
+ context.useThread.setState(
1630
+ Object.freeze({
1631
+ messages: runtimeRef.current.messages,
1632
+ isRunning: runtimeRef.current.isRunning
1633
+ }),
1634
+ true
1635
+ );
1636
+ };
1601
1637
  onRuntimeUpdate();
1602
1638
  return runtime.subscribe(onRuntimeUpdate);
1603
- }, [onRuntimeUpdate, runtime]);
1639
+ }, [context, runtime]);
1604
1640
  const RuntimeSynchronizer = runtime.unstable_synchronizer;
1605
1641
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(ThreadContext.Provider, { value: context, children: [
1606
1642
  RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(RuntimeSynchronizer, {}),
@@ -1617,8 +1653,8 @@ var AssistantProvider = ({ children, runtime }) => {
1617
1653
  });
1618
1654
  const [context] = (0, import_react36.useState)(() => {
1619
1655
  const useModelConfig = makeAssistantModelConfigStore();
1620
- const useToolRenderers = makeAssistantToolRenderersStore();
1621
- return { useModelConfig, useToolRenderers };
1656
+ const useToolUIs = makeAssistantToolUIsStore();
1657
+ return { useModelConfig, useToolUIs };
1622
1658
  });
1623
1659
  const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
1624
1660
  (0, import_react36.useEffect)(() => {