@assistant-ui/react 0.1.7 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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)(() => {