@assistant-ui/react 0.1.8 → 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.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  useContentPartContext,
10
10
  useMessageContext,
11
11
  useThreadContext
12
- } from "./chunk-RITM2IUH.mjs";
12
+ } from "./chunk-7O2URLFI.mjs";
13
13
 
14
14
  // src/actions/useCopyMessage.tsx
15
15
  import { useCallback } from "react";
@@ -50,7 +50,7 @@ var getMessageText = (message) => {
50
50
 
51
51
  // src/actions/useCopyMessage.tsx
52
52
  var useCopyMessage = ({ copiedDuration = 3e3 }) => {
53
- const { useMessage, useComposer } = useMessageContext();
53
+ const { useMessage, useMessageUtils, useComposer } = useMessageContext();
54
54
  const hasCopyableContent = useCombinedStore(
55
55
  [useMessage, useComposer],
56
56
  (m, c) => {
@@ -58,13 +58,14 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
58
58
  }
59
59
  );
60
60
  const callback = useCallback(() => {
61
+ const { message } = useMessage.getState();
62
+ const { setIsCopied } = useMessageUtils.getState();
61
63
  const { isEditing, value: composerValue } = useComposer.getState();
62
- const { message, setIsCopied } = useMessage.getState();
63
64
  const valueToCopy = isEditing ? composerValue : getMessageText(message);
64
65
  navigator.clipboard.writeText(valueToCopy);
65
66
  setIsCopied(true);
66
67
  setTimeout(() => setIsCopied(false), copiedDuration);
67
- }, [useComposer, useMessage, copiedDuration]);
68
+ }, [useMessage, useMessageUtils, useComposer, copiedDuration]);
68
69
  if (!hasCopyableContent) return null;
69
70
  return callback;
70
71
  };
@@ -72,7 +73,7 @@ var useCopyMessage = ({ copiedDuration = 3e3 }) => {
72
73
  // src/actions/useReloadMessage.tsx
73
74
  import { useCallback as useCallback2 } from "react";
74
75
  var useReloadMessage = () => {
75
- const { useThread, useViewport } = useThreadContext();
76
+ const { useThread, useThreadActions, useViewport } = useThreadContext();
76
77
  const { useMessage } = useMessageContext();
77
78
  const disabled = useCombinedStore(
78
79
  [useThread, useMessage],
@@ -80,9 +81,9 @@ var useReloadMessage = () => {
80
81
  );
81
82
  const callback = useCallback2(() => {
82
83
  const { parentId } = useMessage.getState();
83
- useThread.getState().startRun(parentId);
84
+ useThreadActions.getState().startRun(parentId);
84
85
  useViewport.getState().scrollToBottom();
85
- }, [useMessage, useThread, useViewport]);
86
+ }, [useThreadActions, useMessage, useViewport]);
86
87
  if (disabled) return null;
87
88
  return callback;
88
89
  };
@@ -106,7 +107,7 @@ var useBeginMessageEdit = () => {
106
107
  // src/actions/useGoToNextBranch.tsx
107
108
  import { useCallback as useCallback4 } from "react";
108
109
  var useGoToNextBranch = () => {
109
- const { useThread } = useThreadContext();
110
+ const { useThreadActions } = useThreadContext();
110
111
  const { useMessage, useComposer } = useMessageContext();
111
112
  const disabled = useCombinedStore(
112
113
  [useMessage, useComposer],
@@ -114,8 +115,8 @@ var useGoToNextBranch = () => {
114
115
  );
115
116
  const callback = useCallback4(() => {
116
117
  const { message, branches } = useMessage.getState();
117
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
118
- }, [useMessage, useThread]);
118
+ useThreadActions.getState().switchToBranch(branches[branches.indexOf(message.id) + 1]);
119
+ }, [useThreadActions, useMessage]);
119
120
  if (disabled) return null;
120
121
  return callback;
121
122
  };
@@ -123,7 +124,7 @@ var useGoToNextBranch = () => {
123
124
  // src/actions/useGoToPreviousBranch.tsx
124
125
  import { useCallback as useCallback5 } from "react";
125
126
  var useGoToPreviousBranch = () => {
126
- const { useThread } = useThreadContext();
127
+ const { useThreadActions } = useThreadContext();
127
128
  const { useMessage, useComposer } = useMessageContext();
128
129
  const disabled = useCombinedStore(
129
130
  [useMessage, useComposer],
@@ -131,8 +132,8 @@ var useGoToPreviousBranch = () => {
131
132
  );
132
133
  const callback = useCallback5(() => {
133
134
  const { message, branches } = useMessage.getState();
134
- useThread.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
135
- }, [useMessage, useThread]);
135
+ useThreadActions.getState().switchToBranch(branches[branches.indexOf(message.id) - 1]);
136
+ }, [useThreadActions, useMessage]);
136
137
  if (disabled) return null;
137
138
  return callback;
138
139
  };
@@ -278,7 +279,9 @@ var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...re
278
279
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
279
280
  } else if (newIsAtBottom !== isAtBottom) {
280
281
  isScrollingToBottomRef.current = false;
281
- useViewport.setState({ isAtBottom: newIsAtBottom });
282
+ useViewport.setState({
283
+ isAtBottom: newIsAtBottom
284
+ });
282
285
  }
283
286
  lastScrollTop.current = div.scrollTop;
284
287
  };
@@ -302,7 +305,7 @@ import { memo } from "react";
302
305
 
303
306
  // src/context/providers/MessageProvider.tsx
304
307
  import { useEffect as useEffect3, useState } from "react";
305
- import { create as create2 } from "zustand";
308
+ import { create as create3 } from "zustand";
306
309
 
307
310
  // src/context/stores/MessageComposer.ts
308
311
  import { create } from "zustand";
@@ -338,17 +341,34 @@ var makeEditComposerStore = ({
338
341
  }
339
342
  }));
340
343
 
344
+ // src/context/stores/MessageUtils.ts
345
+ import { create as create2 } from "zustand";
346
+ var makeMessageUtilsStore = () => create2((set) => ({
347
+ inProgressIndicator: null,
348
+ setInProgressIndicator: (value) => {
349
+ set({ inProgressIndicator: value });
350
+ },
351
+ isCopied: false,
352
+ setIsCopied: (value) => {
353
+ set({ isCopied: value });
354
+ },
355
+ isHovering: false,
356
+ setIsHovering: (value) => {
357
+ set({ isHovering: value });
358
+ }
359
+ }));
360
+
341
361
  // src/context/providers/MessageProvider.tsx
342
362
  import { jsx as jsx4 } from "react/jsx-runtime";
343
363
  var getIsLast = (thread, message) => {
344
364
  return thread.messages[thread.messages.length - 1]?.id === message.id;
345
365
  };
346
- var syncMessage = (thread, useMessage, messageIndex) => {
366
+ var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
347
367
  const parentId = thread.messages[messageIndex - 1]?.id ?? null;
348
368
  const message = thread.messages[messageIndex];
349
369
  if (!message) return;
350
370
  const isLast = getIsLast(thread, message);
351
- const branches = thread.getBranches(message.id);
371
+ const branches = getBranches(message.id);
352
372
  const currentState = useMessage.getState();
353
373
  if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
354
374
  return;
@@ -360,26 +380,10 @@ var syncMessage = (thread, useMessage, messageIndex) => {
360
380
  });
361
381
  };
362
382
  var useMessageContext2 = (messageIndex) => {
363
- const { useThread } = useThreadContext();
383
+ const { useThread, useThreadActions } = useThreadContext();
364
384
  const [context] = useState(() => {
365
- const useMessage = create2((set) => ({
366
- message: null,
367
- parentId: null,
368
- branches: [],
369
- isLast: false,
370
- inProgressIndicator: null,
371
- isCopied: false,
372
- isHovering: false,
373
- setInProgressIndicator: (value) => {
374
- set({ inProgressIndicator: value });
375
- },
376
- setIsCopied: (value) => {
377
- set({ isCopied: value });
378
- },
379
- setIsHovering: (value) => {
380
- set({ isHovering: value });
381
- }
382
- }));
385
+ const useMessage = create3(() => ({}));
386
+ const useMessageUtils = makeMessageUtilsStore();
383
387
  const useComposer = makeEditComposerStore({
384
388
  onEdit: () => {
385
389
  const message = useMessage.getState().message;
@@ -399,20 +403,30 @@ var useMessageContext2 = (messageIndex) => {
399
403
  const nonTextParts = message.content.filter(
400
404
  (part) => part.type !== "text" && part.type !== "ui"
401
405
  );
402
- useThread.getState().append({
406
+ useThreadActions.getState().append({
403
407
  parentId,
404
408
  content: [{ type: "text", text }, ...nonTextParts]
405
409
  });
406
410
  }
407
411
  });
408
- syncMessage(useThread.getState(), useMessage, messageIndex);
409
- return { useMessage, useComposer };
412
+ syncMessage(
413
+ useThread.getState(),
414
+ useThreadActions.getState().getBranches,
415
+ useMessage,
416
+ messageIndex
417
+ );
418
+ return { useMessage, useMessageUtils, useComposer };
410
419
  });
411
420
  useEffect3(() => {
412
421
  return useThread.subscribe((thread) => {
413
- syncMessage(thread, context.useMessage, messageIndex);
422
+ syncMessage(
423
+ thread,
424
+ useThreadActions.getState().getBranches,
425
+ context.useMessage,
426
+ messageIndex
427
+ );
414
428
  });
415
- }, [context, useThread, messageIndex]);
429
+ }, [useThread, useThreadActions, context, messageIndex]);
416
430
  return context;
417
431
  };
418
432
  var MessageProvider = ({
@@ -439,16 +453,19 @@ var ComposerIf = ({ children, ...query }) => {
439
453
 
440
454
  // src/primitives/message/MessageIf.tsx
441
455
  var useMessageIf = (props) => {
442
- const { useMessage } = useMessageContext();
443
- return useMessage(({ message, branches, isLast, isCopied, isHovering }) => {
444
- if (props.hasBranches === true && branches.length < 2) return false;
445
- if (props.user && message.role !== "user") return false;
446
- if (props.assistant && message.role !== "assistant") return false;
447
- if (props.lastOrHover === true && !isHovering && !isLast) return false;
448
- if (props.copied === true && !isCopied) return false;
449
- if (props.copied === false && isCopied) return false;
450
- return true;
451
- });
456
+ const { useMessage, useMessageUtils } = useMessageContext();
457
+ return useCombinedStore(
458
+ [useMessage, useMessageUtils],
459
+ ({ message, branches, isLast }, { isCopied, isHovering }) => {
460
+ if (props.hasBranches === true && branches.length < 2) return false;
461
+ if (props.user && message.role !== "user") return false;
462
+ if (props.assistant && message.role !== "assistant") return false;
463
+ if (props.lastOrHover === true && !isHovering && !isLast) return false;
464
+ if (props.copied === true && !isCopied) return false;
465
+ if (props.copied === false && isCopied) return false;
466
+ return true;
467
+ }
468
+ );
452
469
  };
453
470
  var MessageIf = ({ children, ...query }) => {
454
471
  const result = useMessageIf(query);
@@ -727,8 +744,8 @@ import { forwardRef as forwardRef9 } from "react";
727
744
  import { jsx as jsx12 } from "react/jsx-runtime";
728
745
  var MessageRoot = forwardRef9(
729
746
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
730
- const { useMessage } = useMessageContext();
731
- const setIsHovering = useMessage((s) => s.setIsHovering);
747
+ const { useMessageUtils } = useMessageContext();
748
+ const setIsHovering = useMessageUtils((s) => s.setIsHovering);
732
749
  const handleMouseEnter = () => {
733
750
  setIsHovering(true);
734
751
  };
@@ -753,7 +770,7 @@ import { memo as memo2 } from "react";
753
770
 
754
771
  // src/context/providers/ContentPartProvider.tsx
755
772
  import { useEffect as useEffect5, useState as useState2 } from "react";
756
- import { create as create3 } from "zustand";
773
+ import { create as create4 } from "zustand";
757
774
  import { jsx as jsx13 } from "react/jsx-runtime";
758
775
  var syncContentPart = ({ message }, useContentPart, partIndex) => {
759
776
  const part = message.content[partIndex];
@@ -762,19 +779,24 @@ var syncContentPart = ({ message }, useContentPart, partIndex) => {
762
779
  const status = partIndex === message.content.length - 1 ? messageStatus : "done";
763
780
  const currentState = useContentPart.getState();
764
781
  if (currentState.part === part && currentState.status === status) return;
765
- useContentPart.setState({ part, status });
782
+ useContentPart.setState(
783
+ Object.freeze({
784
+ part,
785
+ status
786
+ })
787
+ );
766
788
  };
767
789
  var useContentPartContext2 = (partIndex) => {
768
790
  const { useMessage } = useMessageContext();
769
791
  const [context] = useState2(() => {
770
- const useContentPart = create3(() => ({
771
- part: { type: "text", text: "" },
772
- status: "done"
773
- }));
792
+ const useContentPart = create4(
793
+ () => ({})
794
+ );
774
795
  syncContentPart(useMessage.getState(), useContentPart, partIndex);
775
796
  return { useContentPart };
776
797
  });
777
798
  useEffect5(() => {
799
+ syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
778
800
  return useMessage.subscribe((message) => {
779
801
  syncContentPart(message, context.useContentPart, partIndex);
780
802
  });
@@ -804,10 +826,10 @@ var ContentPartDisplay = () => {
804
826
 
805
827
  // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
806
828
  var ContentPartInProgressIndicator = () => {
807
- const { useMessage } = useMessageContext();
829
+ const { useMessageUtils } = useMessageContext();
808
830
  const { useContentPart } = useContentPartContext();
809
831
  const indicator = useCombinedStore(
810
- [useMessage, useContentPart],
832
+ [useMessageUtils, useContentPart],
811
833
  (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
812
834
  );
813
835
  return indicator;
@@ -856,8 +878,8 @@ var MessageContentPartComponent = ({
856
878
  tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
857
879
  } = {}
858
880
  }) => {
859
- const { useThread } = useThreadContext();
860
- const addToolResult = useThread((t) => t.addToolResult);
881
+ const { useThreadActions } = useThreadContext();
882
+ const addToolResult = useThreadActions((t) => t.addToolResult);
861
883
  const { useContentPart } = useContentPartContext();
862
884
  const { part, status } = useContentPart();
863
885
  const type = part.type;
@@ -911,10 +933,10 @@ import {
911
933
  } from "react";
912
934
  import { jsx as jsx16 } from "react/jsx-runtime";
913
935
  var MessageInProgress = forwardRef11((props, ref) => {
914
- const { useMessage } = useMessageContext();
936
+ const { useMessageUtils } = useMessageContext();
915
937
  useMemo2(() => {
916
- useMessage.getState().setInProgressIndicator(/* @__PURE__ */ jsx16(Primitive10.span, { ...props, ref }));
917
- }, [useMessage, props, ref]);
938
+ useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ jsx16(Primitive10.span, { ...props, ref }));
939
+ }, [useMessageUtils, props, ref]);
918
940
  return null;
919
941
  });
920
942
  MessageInProgress.displayName = "MessageInProgress";
@@ -998,14 +1020,14 @@ import { forwardRef as forwardRef14 } from "react";
998
1020
  import { jsx as jsx21 } from "react/jsx-runtime";
999
1021
  var ActionBarRoot = forwardRef14(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1000
1022
  const { useThread } = useThreadContext();
1001
- const { useMessage } = useMessageContext();
1023
+ const { useMessage, useMessageUtils } = useMessageContext();
1002
1024
  const hideAndfloatStatus = useCombinedStore(
1003
- [useThread, useMessage],
1004
- (t, m) => {
1025
+ [useThread, useMessage, useMessageUtils],
1026
+ (t, m, mu) => {
1005
1027
  if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
1006
1028
  const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
1007
1029
  if (!autohideEnabled) return "normal" /* Normal */;
1008
- if (!m.isHovering) return "hidden" /* Hidden */;
1030
+ if (!mu.isHovering) return "hidden" /* Hidden */;
1009
1031
  if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
1010
1032
  return "floating" /* Floating */;
1011
1033
  return "normal" /* Normal */;
@@ -1359,7 +1381,7 @@ import { memo as memo3 } from "react";
1359
1381
  import { useEffect as useEffect7, useInsertionEffect as useInsertionEffect3, useRef as useRef5, useState as useState5 } from "react";
1360
1382
 
1361
1383
  // src/context/stores/AssistantModelConfig.ts
1362
- import { create as create4 } from "zustand";
1384
+ import { create as create5 } from "zustand";
1363
1385
 
1364
1386
  // src/utils/ProxyConfigProvider.ts
1365
1387
  var ProxyConfigProvider = class {
@@ -1376,23 +1398,23 @@ var ProxyConfigProvider = class {
1376
1398
  };
1377
1399
 
1378
1400
  // src/context/stores/AssistantModelConfig.ts
1379
- var makeAssistantModelConfigStore = () => create4(() => {
1401
+ var makeAssistantModelConfigStore = () => create5(() => {
1380
1402
  const proxy = new ProxyConfigProvider();
1381
- return {
1403
+ return Object.freeze({
1382
1404
  getModelConfig: () => {
1383
1405
  return proxy.getModelConfig();
1384
1406
  },
1385
1407
  registerModelConfigProvider: (provider) => {
1386
1408
  return proxy.registerModelConfigProvider(provider);
1387
1409
  }
1388
- };
1410
+ });
1389
1411
  });
1390
1412
 
1391
1413
  // src/context/stores/AssistantToolUIs.ts
1392
- import { create as create5 } from "zustand";
1393
- var makeAssistantToolUIsStore = () => create5((set) => {
1414
+ import { create as create6 } from "zustand";
1415
+ var makeAssistantToolUIsStore = () => create6((set) => {
1394
1416
  const renderers = /* @__PURE__ */ new Map();
1395
- return {
1417
+ return Object.freeze({
1396
1418
  getToolUI: (name) => {
1397
1419
  const arr = renderers.get(name);
1398
1420
  const last = arr?.at(-1);
@@ -1412,25 +1434,27 @@ var makeAssistantToolUIsStore = () => create5((set) => {
1412
1434
  if (index !== -1) {
1413
1435
  arr.splice(index, 1);
1414
1436
  }
1415
- set({});
1437
+ if (index === arr.length) {
1438
+ set({});
1439
+ }
1416
1440
  };
1417
1441
  }
1418
- };
1442
+ });
1419
1443
  });
1420
1444
 
1421
1445
  // src/context/providers/ThreadProvider.tsx
1422
1446
  import { useEffect as useEffect6, useInsertionEffect as useInsertionEffect2, useRef as useRef4, useState as useState4 } from "react";
1423
1447
 
1424
1448
  // src/context/stores/Composer.ts
1425
- import { create as create6 } from "zustand";
1426
- var makeComposerStore = (useThread) => create6()((set, get, store) => {
1449
+ import { create as create7 } from "zustand";
1450
+ var makeComposerStore = (useThread, useThreadActions) => create7()((set, get, store) => {
1427
1451
  return {
1428
1452
  ...makeBaseComposer(set, get, store),
1429
1453
  isEditing: true,
1430
1454
  send: () => {
1431
1455
  const { setValue, value } = get();
1432
1456
  setValue("");
1433
- useThread.getState().append({
1457
+ useThreadActions.getState().append({
1434
1458
  parentId: useThread.getState().messages.at(-1)?.id ?? null,
1435
1459
  content: [{ type: "text", text: value }]
1436
1460
  });
@@ -1438,42 +1462,26 @@ var makeComposerStore = (useThread) => create6()((set, get, store) => {
1438
1462
  cancel: () => {
1439
1463
  const thread = useThread.getState();
1440
1464
  if (!thread.isRunning) return false;
1441
- useThread.getState().cancelRun();
1465
+ useThreadActions.getState().cancelRun();
1442
1466
  return true;
1443
1467
  }
1444
1468
  };
1445
1469
  });
1446
1470
 
1447
1471
  // src/context/stores/Thread.ts
1448
- import { create as create7 } from "zustand";
1472
+ import { create as create8 } from "zustand";
1449
1473
  var makeThreadStore = (runtimeRef) => {
1450
- const useThread = create7(() => ({
1474
+ return create8(() => ({
1451
1475
  messages: runtimeRef.current.messages,
1452
- isRunning: runtimeRef.current.isRunning,
1453
- getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1454
- switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1455
- startRun: (parentId) => runtimeRef.current.startRun(parentId),
1456
- append: (message) => runtimeRef.current.append(message),
1457
- cancelRun: () => runtimeRef.current.cancelRun(),
1458
- addToolResult: (toolCallId, result) => runtimeRef.current.addToolResult(toolCallId, result)
1476
+ isRunning: runtimeRef.current.isRunning
1459
1477
  }));
1460
- const onRuntimeUpdate = () => {
1461
- useThread.setState({
1462
- messages: runtimeRef.current.messages,
1463
- isRunning: runtimeRef.current.isRunning
1464
- });
1465
- };
1466
- return {
1467
- useThread,
1468
- onRuntimeUpdate
1469
- };
1470
1478
  };
1471
1479
 
1472
1480
  // src/context/stores/ThreadViewport.tsx
1473
- import { create as create8 } from "zustand";
1481
+ import { create as create9 } from "zustand";
1474
1482
  var makeThreadViewportStore = () => {
1475
1483
  const scrollToBottomListeners = /* @__PURE__ */ new Set();
1476
- return create8(() => ({
1484
+ return create9(() => ({
1477
1485
  isAtBottom: true,
1478
1486
  scrollToBottom: () => {
1479
1487
  for (const listener of scrollToBottomListeners) {
@@ -1489,6 +1497,21 @@ var makeThreadViewportStore = () => {
1489
1497
  }));
1490
1498
  };
1491
1499
 
1500
+ // src/context/stores/ThreadActions.ts
1501
+ import { create as create10 } from "zustand";
1502
+ var makeThreadActionStore = (runtimeRef) => {
1503
+ return create10(
1504
+ () => Object.freeze({
1505
+ getBranches: (messageId) => runtimeRef.current.getBranches(messageId),
1506
+ switchToBranch: (branchId) => runtimeRef.current.switchToBranch(branchId),
1507
+ startRun: (parentId) => runtimeRef.current.startRun(parentId),
1508
+ append: (message) => runtimeRef.current.append(message),
1509
+ cancelRun: () => runtimeRef.current.cancelRun(),
1510
+ addToolResult: (toolCallId, result) => runtimeRef.current.addToolResult(toolCallId, result)
1511
+ })
1512
+ );
1513
+ };
1514
+
1492
1515
  // src/context/providers/ThreadProvider.tsx
1493
1516
  import { jsx as jsx23, jsxs as jsxs4 } from "react/jsx-runtime";
1494
1517
  var ThreadProvider = ({
@@ -1499,23 +1522,31 @@ var ThreadProvider = ({
1499
1522
  useInsertionEffect2(() => {
1500
1523
  runtimeRef.current = runtime;
1501
1524
  });
1502
- const [{ context, onRuntimeUpdate }] = useState4(() => {
1503
- const { useThread, onRuntimeUpdate: onRuntimeUpdate2 } = makeThreadStore(runtimeRef);
1525
+ const [context] = useState4(() => {
1526
+ const useThread = makeThreadStore(runtimeRef);
1527
+ const useThreadActions = makeThreadActionStore(runtimeRef);
1504
1528
  const useViewport = makeThreadViewportStore();
1505
- const useComposer = makeComposerStore(useThread);
1529
+ const useComposer = makeComposerStore(useThread, useThreadActions);
1506
1530
  return {
1507
- context: {
1508
- useViewport,
1509
- useThread,
1510
- useComposer
1511
- },
1512
- onRuntimeUpdate: onRuntimeUpdate2
1531
+ useThread,
1532
+ useThreadActions,
1533
+ useComposer,
1534
+ useViewport
1513
1535
  };
1514
1536
  });
1515
1537
  useEffect6(() => {
1538
+ const onRuntimeUpdate = () => {
1539
+ context.useThread.setState(
1540
+ Object.freeze({
1541
+ messages: runtimeRef.current.messages,
1542
+ isRunning: runtimeRef.current.isRunning
1543
+ }),
1544
+ true
1545
+ );
1546
+ };
1516
1547
  onRuntimeUpdate();
1517
1548
  return runtime.subscribe(onRuntimeUpdate);
1518
- }, [onRuntimeUpdate, runtime]);
1549
+ }, [context, runtime]);
1519
1550
  const RuntimeSynchronizer = runtime.unstable_synchronizer;
1520
1551
  return /* @__PURE__ */ jsxs4(ThreadContext.Provider, { value: context, children: [
1521
1552
  RuntimeSynchronizer && /* @__PURE__ */ jsx23(RuntimeSynchronizer, {}),