@assistant-ui/react 0.5.81 → 0.5.83

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
@@ -10,13 +10,13 @@ import {
10
10
  toLanguageModelMessages,
11
11
  toLanguageModelTools,
12
12
  toolResultStream
13
- } from "./chunk-RHM73CQE.mjs";
13
+ } from "./chunk-TWIMAOZR.mjs";
14
14
  import {
15
15
  __export
16
16
  } from "./chunk-BJPOCE4O.mjs";
17
17
 
18
18
  // src/context/providers/AssistantRuntimeProvider.tsx
19
- import { memo, useEffect as useEffect2, useMemo as useMemo2, useState as useState2 } from "react";
19
+ import { memo, useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
20
20
 
21
21
  // src/context/react/AssistantContext.ts
22
22
  import { createContext } from "react";
@@ -86,6 +86,10 @@ var { useToolUIs, useToolUIsStore } = createContextStoreHook(
86
86
  useAssistantContext,
87
87
  "useToolUIs"
88
88
  );
89
+ var { useThreadManager } = createContextStoreHook(
90
+ useAssistantContext,
91
+ "useThreadManager"
92
+ );
89
93
 
90
94
  // src/context/stores/AssistantToolUIs.ts
91
95
  import { create } from "zustand";
@@ -120,10 +124,10 @@ var makeAssistantToolUIsStore = () => create((set) => {
120
124
  });
121
125
 
122
126
  // src/context/providers/ThreadRuntimeProvider.tsx
123
- import { useEffect, useMemo, useState } from "react";
127
+ import { useEffect as useEffect2, useMemo, useState as useState2 } from "react";
124
128
 
125
129
  // src/context/react/ThreadContext.ts
126
- import { createContext as createContext2 } from "react";
130
+ import { createContext as createContext2, useEffect, useState } from "react";
127
131
  var ThreadContext = createContext2(null);
128
132
  var useThreadContext = createContextHook(
129
133
  ThreadContext,
@@ -156,6 +160,15 @@ var {
156
160
  useViewport: useThreadViewport,
157
161
  useViewportStore: useThreadViewportStore
158
162
  } = createContextStoreHook(useThreadContext, "useViewport");
163
+ function useThreadModelConfig(options) {
164
+ const [, rerender] = useState({});
165
+ const runtime = useThreadRuntime(options);
166
+ useEffect(() => {
167
+ return runtime?.unstable_on("model-config-update", () => rerender({}));
168
+ }, [runtime]);
169
+ if (!runtime) return null;
170
+ return runtime?.getModelConfig();
171
+ }
159
172
 
160
173
  // src/context/stores/ThreadViewport.tsx
161
174
  import { create as create2 } from "zustand";
@@ -186,15 +199,15 @@ var writableStore = (store) => {
186
199
  import { create as create3 } from "zustand";
187
200
  import { jsx } from "react/jsx-runtime";
188
201
  var useThreadRuntimeStore2 = (runtime) => {
189
- const [store] = useState(() => create3(() => runtime));
190
- useEffect(() => {
202
+ const [store] = useState2(() => create3(() => runtime));
203
+ useEffect2(() => {
191
204
  writableStore(store).setState(runtime, true);
192
205
  }, [runtime, store]);
193
206
  return store;
194
207
  };
195
208
  var useThreadStore2 = (runtime) => {
196
- const [store] = useState(() => create3(() => runtime.getState()));
197
- useEffect(() => {
209
+ const [store] = useState2(() => create3(() => runtime.getState()));
210
+ useEffect2(() => {
198
211
  const updateState = () => writableStore(store).setState(runtime.getState(), true);
199
212
  updateState();
200
213
  return runtime.subscribe(updateState);
@@ -202,8 +215,8 @@ var useThreadStore2 = (runtime) => {
202
215
  return store;
203
216
  };
204
217
  var useThreadMessagesStore2 = (runtime) => {
205
- const [store] = useState(() => create3(() => runtime.messages));
206
- useEffect(() => {
218
+ const [store] = useState2(() => create3(() => runtime.messages));
219
+ useEffect2(() => {
207
220
  const updateState = () => writableStore(store).setState(runtime.messages, true);
208
221
  updateState();
209
222
  return runtime.subscribe(updateState);
@@ -211,8 +224,8 @@ var useThreadMessagesStore2 = (runtime) => {
211
224
  return store;
212
225
  };
213
226
  var useThreadComposerStore2 = (runtime) => {
214
- const [store] = useState(() => create3(() => runtime.getState()));
215
- useEffect(() => {
227
+ const [store] = useState2(() => create3(() => runtime.getState()));
228
+ useEffect2(() => {
216
229
  const updateState = () => writableStore(store).setState(runtime.getState(), true);
217
230
  updateState();
218
231
  return runtime.subscribe(updateState);
@@ -242,8 +255,8 @@ var ThreadRuntimeProvider = ({ children, runtime }) => {
242
255
  import { create as create4 } from "zustand";
243
256
  import { jsx as jsx2 } from "react/jsx-runtime";
244
257
  var useAssistantRuntimeStore2 = (runtime) => {
245
- const [store] = useState2(() => create4(() => runtime));
246
- useEffect2(() => {
258
+ const [store] = useState3(() => create4(() => runtime));
259
+ useEffect3(() => {
247
260
  writableStore(store).setState(runtime, true);
248
261
  }, [runtime, store]);
249
262
  return store;
@@ -251,22 +264,35 @@ var useAssistantRuntimeStore2 = (runtime) => {
251
264
  var useAssistantToolUIsStore = () => {
252
265
  return useMemo2(() => makeAssistantToolUIsStore(), []);
253
266
  };
267
+ var useThreadManagerStore = (runtime) => {
268
+ const [store] = useState3(
269
+ () => create4(() => runtime.threadManager.getState())
270
+ );
271
+ useEffect3(() => {
272
+ const updateState = () => writableStore(store).setState(runtime.threadManager.getState(), true);
273
+ updateState();
274
+ return runtime.threadManager.subscribe(updateState);
275
+ }, [runtime, store]);
276
+ return store;
277
+ };
254
278
  var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
255
279
  const useAssistantRuntime2 = useAssistantRuntimeStore2(runtime);
256
280
  const useToolUIs2 = useAssistantToolUIsStore();
281
+ const useThreadManager2 = useThreadManagerStore(runtime);
257
282
  const context = useMemo2(() => {
258
283
  return {
259
284
  useToolUIs: useToolUIs2,
260
285
  useAssistantRuntime: useAssistantRuntime2,
261
- useAssistantActions: useAssistantRuntime2
286
+ useAssistantActions: useAssistantRuntime2,
287
+ useThreadManager: useThreadManager2
262
288
  };
263
- }, [useAssistantRuntime2, useToolUIs2]);
289
+ }, [useAssistantRuntime2, useToolUIs2, useThreadManager2]);
264
290
  return /* @__PURE__ */ jsx2(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx2(ThreadRuntimeProvider, { runtime: runtime.thread, children }) });
265
291
  };
266
292
  var AssistantRuntimeProvider = memo(AssistantRuntimeProviderImpl);
267
293
 
268
294
  // src/context/providers/TextContentPartProvider.tsx
269
- import { useEffect as useEffect3, useState as useState3 } from "react";
295
+ import { useEffect as useEffect4, useState as useState4 } from "react";
270
296
  import { create as create5 } from "zustand";
271
297
 
272
298
  // src/context/react/ContentPartContext.ts
@@ -295,6 +321,9 @@ var ContentPartRuntimeImpl = class {
295
321
  this.messageApi = messageApi;
296
322
  this.threadApi = threadApi;
297
323
  }
324
+ get path() {
325
+ return this.contentBinding.path;
326
+ }
298
327
  getState() {
299
328
  return this.contentBinding.getState();
300
329
  }
@@ -328,7 +357,7 @@ var RUNNING_STATUS = {
328
357
  type: "running"
329
358
  };
330
359
  var TextContentPartProvider = ({ children, text, isRunning }) => {
331
- const [context] = useState3(() => {
360
+ const [context] = useState4(() => {
332
361
  const useContentPartRuntime2 = create5(
333
362
  // TODO
334
363
  () => new ContentPartRuntimeImpl(null, null, null)
@@ -341,7 +370,7 @@ var TextContentPartProvider = ({ children, text, isRunning }) => {
341
370
  }));
342
371
  return { useContentPartRuntime: useContentPartRuntime2, useContentPart: useContentPart2 };
343
372
  });
344
- useEffect3(() => {
373
+ useEffect4(() => {
345
374
  const state = context.useContentPart.getState();
346
375
  const textUpdated = state.text !== text;
347
376
  const targetStatus = isRunning ? RUNNING_STATUS : COMPLETE_STATUS;
@@ -432,11 +461,11 @@ var useSwitchToNewThread = () => {
432
461
  };
433
462
 
434
463
  // src/model-config/useAssistantTool.tsx
435
- import { useEffect as useEffect4 } from "react";
464
+ import { useEffect as useEffect5 } from "react";
436
465
  var useAssistantTool = (tool) => {
437
466
  const assistantRuntime = useAssistantRuntime();
438
467
  const toolUIsStore = useToolUIsStore();
439
- useEffect4(() => {
468
+ useEffect5(() => {
440
469
  const { toolName, render, ...rest } = tool;
441
470
  const config = {
442
471
  tools: {
@@ -465,10 +494,10 @@ var makeAssistantTool = (tool) => {
465
494
  };
466
495
 
467
496
  // src/model-config/useAssistantToolUI.tsx
468
- import { useEffect as useEffect5 } from "react";
497
+ import { useEffect as useEffect6 } from "react";
469
498
  var useAssistantToolUI = (tool) => {
470
499
  const toolUIsStore = useToolUIsStore();
471
- useEffect5(() => {
500
+ useEffect6(() => {
472
501
  if (!tool) return;
473
502
  const { toolName, render } = tool;
474
503
  return toolUIsStore.getState().setToolUI(toolName, render);
@@ -486,10 +515,10 @@ var makeAssistantToolUI = (tool) => {
486
515
  };
487
516
 
488
517
  // src/model-config/useAssistantInstructions.tsx
489
- import { useEffect as useEffect6 } from "react";
518
+ import { useEffect as useEffect7 } from "react";
490
519
  var useAssistantInstructions = (instruction) => {
491
520
  const assistantRuntime = useAssistantRuntime();
492
- useEffect6(() => {
521
+ useEffect7(() => {
493
522
  const config = {
494
523
  system: instruction
495
524
  };
@@ -501,64 +530,23 @@ var useAssistantInstructions = (instruction) => {
501
530
 
502
531
  // src/primitive-hooks/actionBar/useActionBarCopy.tsx
503
532
  import { useCallback as useCallback3 } from "react";
504
-
505
- // src/utils/combined/useCombinedStore.ts
506
- import { useMemo as useMemo4 } from "react";
507
-
508
- // src/utils/combined/createCombinedStore.ts
509
- import { useSyncExternalStore } from "react";
510
- var createCombinedStore = (stores) => {
511
- const subscribe = (callback) => {
512
- const unsubscribes = stores.map((store) => store.subscribe(callback));
513
- return () => {
514
- for (const unsub of unsubscribes) {
515
- unsub();
516
- }
517
- };
518
- };
519
- return (selector) => {
520
- const getSnapshot = () => selector(...stores.map((store) => store.getState()));
521
- return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
522
- };
523
- };
524
-
525
- // src/utils/combined/useCombinedStore.ts
526
- var useCombinedStore = (stores, selector) => {
527
- const useCombined = useMemo4(() => createCombinedStore(stores), stores);
528
- return useCombined(selector);
529
- };
530
-
531
- // src/utils/getThreadMessageText.tsx
532
- var getThreadMessageText = (message) => {
533
- const textParts = message.content.filter(
534
- (part) => part.type === "text"
535
- );
536
- return textParts.map((part) => part.text).join("\n\n");
537
- };
538
-
539
- // src/primitive-hooks/actionBar/useActionBarCopy.tsx
540
533
  var useActionBarCopy = ({
541
534
  copiedDuration = 3e3
542
535
  } = {}) => {
543
536
  const messageRuntime = useMessageRuntime();
544
537
  const composerRuntime = useComposerRuntime();
545
- const messageUtilsStore = useMessageUtilsStore();
546
- const hasCopyableContent = useCombinedStore(
547
- [messageRuntime, composerRuntime],
548
- (message, c) => {
549
- return !c.isEditing && (message.role !== "assistant" || message.status.type !== "running") && message.content.some((c2) => c2.type === "text" && c2.text.length > 0);
550
- }
551
- );
538
+ const setIsCopied = useMessageUtils((s) => s.setIsCopied);
539
+ const hasCopyableContent = useMessage((message) => {
540
+ return (message.role !== "assistant" || message.status.type !== "running") && message.content.some((c) => c.type === "text" && c.text.length > 0);
541
+ });
552
542
  const callback = useCallback3(() => {
553
- const message = messageRuntime.getState();
554
- const { setIsCopied } = messageUtilsStore.getState();
555
543
  const { isEditing, text: composerValue } = composerRuntime.getState();
556
- const valueToCopy = isEditing ? composerValue : getThreadMessageText(message);
544
+ const valueToCopy = isEditing ? composerValue : messageRuntime.unstable_getCopyText();
557
545
  navigator.clipboard.writeText(valueToCopy).then(() => {
558
546
  setIsCopied(true);
559
547
  setTimeout(() => setIsCopied(false), copiedDuration);
560
548
  });
561
- }, [messageRuntime, messageUtilsStore, composerRuntime, copiedDuration]);
549
+ }, [messageRuntime, setIsCopied, composerRuntime, copiedDuration]);
562
550
  if (!hasCopyableContent) return null;
563
551
  return callback;
564
552
  };
@@ -577,6 +565,34 @@ var useActionBarEdit = () => {
577
565
 
578
566
  // src/primitive-hooks/actionBar/useActionBarReload.tsx
579
567
  import { useCallback as useCallback5 } from "react";
568
+
569
+ // src/utils/combined/useCombinedStore.ts
570
+ import { useMemo as useMemo4 } from "react";
571
+
572
+ // src/utils/combined/createCombinedStore.ts
573
+ import { useSyncExternalStore } from "react";
574
+ var createCombinedStore = (stores) => {
575
+ const subscribe = (callback) => {
576
+ const unsubscribes = stores.map((store) => store.subscribe(callback));
577
+ return () => {
578
+ for (const unsub of unsubscribes) {
579
+ unsub();
580
+ }
581
+ };
582
+ };
583
+ return (selector) => {
584
+ const getSnapshot = () => selector(...stores.map((store) => store.getState()));
585
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
586
+ };
587
+ };
588
+
589
+ // src/utils/combined/useCombinedStore.ts
590
+ var useCombinedStore = (stores, selector) => {
591
+ const useCombined = useMemo4(() => createCombinedStore(stores), stores);
592
+ return useCombined(selector);
593
+ };
594
+
595
+ // src/primitive-hooks/actionBar/useActionBarReload.tsx
580
596
  var useActionBarReload = () => {
581
597
  const messageRuntime = useMessageRuntime();
582
598
  const threadRuntime = useThreadRuntime();
@@ -1084,7 +1100,7 @@ __export(assistantModal_exports, {
1084
1100
  });
1085
1101
 
1086
1102
  // src/primitives/assistantModal/AssistantModalRoot.tsx
1087
- import { useEffect as useEffect7, useState as useState4 } from "react";
1103
+ import { useEffect as useEffect8, useState as useState5 } from "react";
1088
1104
  import * as PopoverPrimitive2 from "@radix-ui/react-popover";
1089
1105
  import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
1090
1106
 
@@ -1098,10 +1114,10 @@ var useAssistantModalOpenState = ({
1098
1114
  defaultOpen = false,
1099
1115
  unstable_openOnRunStart = true
1100
1116
  }) => {
1101
- const state = useState4(defaultOpen);
1117
+ const state = useState5(defaultOpen);
1102
1118
  const [, setOpen] = state;
1103
1119
  const threadRuntime = useThreadRuntime();
1104
- useEffect7(() => {
1120
+ useEffect8(() => {
1105
1121
  if (!unstable_openOnRunStart) return void 0;
1106
1122
  return threadRuntime.unstable_on("run-start", () => {
1107
1123
  setOpen(true);
@@ -1434,19 +1450,19 @@ MessagePrimitiveIf.displayName = "MessagePrimitive.If";
1434
1450
  import { memo as memo2, useMemo as useMemo6 } from "react";
1435
1451
 
1436
1452
  // src/context/providers/ContentPartRuntimeProvider.tsx
1437
- import { useEffect as useEffect8, useState as useState5 } from "react";
1453
+ import { useEffect as useEffect9, useState as useState6 } from "react";
1438
1454
  import { create as create6 } from "zustand";
1439
1455
  import { jsx as jsx19 } from "react/jsx-runtime";
1440
1456
  var useContentPartRuntimeStore = (runtime) => {
1441
- const [store] = useState5(() => create6(() => runtime));
1442
- useEffect8(() => {
1457
+ const [store] = useState6(() => create6(() => runtime));
1458
+ useEffect9(() => {
1443
1459
  writableStore(store).setState(runtime, true);
1444
1460
  }, [runtime, store]);
1445
1461
  return store;
1446
1462
  };
1447
1463
  var useContentPartStore2 = (runtime) => {
1448
- const [store] = useState5(() => create6(() => runtime.getState()));
1449
- useEffect8(() => {
1464
+ const [store] = useState6(() => create6(() => runtime.getState()));
1465
+ useEffect9(() => {
1450
1466
  const updateState = () => writableStore(store).setState(runtime.getState(), true);
1451
1467
  updateState();
1452
1468
  return runtime.subscribe(updateState);
@@ -1459,7 +1475,7 @@ var ContentPartRuntimeProvider = ({
1459
1475
  }) => {
1460
1476
  const useContentPartRuntime2 = useContentPartRuntimeStore(runtime);
1461
1477
  const useContentPart2 = useContentPartStore2(runtime);
1462
- const [context] = useState5(() => {
1478
+ const [context] = useState6(() => {
1463
1479
  return { useContentPartRuntime: useContentPartRuntime2, useContentPart: useContentPart2 };
1464
1480
  });
1465
1481
  return /* @__PURE__ */ jsx19(ContentPartContext.Provider, { value: context, children });
@@ -1471,7 +1487,7 @@ import {
1471
1487
  } from "react";
1472
1488
 
1473
1489
  // src/utils/smooth/useSmooth.tsx
1474
- import { useEffect as useEffect9, useMemo as useMemo5, useRef as useRef2, useState as useState7 } from "react";
1490
+ import { useEffect as useEffect10, useMemo as useMemo5, useRef as useRef2, useState as useState8 } from "react";
1475
1491
  import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
1476
1492
 
1477
1493
  // src/utils/smooth/SmoothContext.tsx
@@ -1479,7 +1495,7 @@ import {
1479
1495
  createContext as createContext6,
1480
1496
  forwardRef as forwardRef13,
1481
1497
  useContext as useContext3,
1482
- useState as useState6
1498
+ useState as useState7
1483
1499
  } from "react";
1484
1500
  import { create as create7 } from "zustand";
1485
1501
  import { jsx as jsx20 } from "react/jsx-runtime";
@@ -1491,7 +1507,7 @@ var makeSmoothContext = (initialState) => {
1491
1507
  var SmoothContextProvider = ({ children }) => {
1492
1508
  const outer = useSmoothContext({ optional: true });
1493
1509
  const contentPartStore = useContentPartStore();
1494
- const [context] = useState6(
1510
+ const [context] = useState7(
1495
1511
  () => makeSmoothContext(contentPartStore.getState().status)
1496
1512
  );
1497
1513
  if (outer) return children;
@@ -1572,7 +1588,7 @@ var useSmooth = (state, smooth = false) => {
1572
1588
  selector: (m) => m.id
1573
1589
  });
1574
1590
  const idRef = useRef2(id);
1575
- const [displayedText, setDisplayedText] = useState7(text);
1591
+ const [displayedText, setDisplayedText] = useState8(text);
1576
1592
  const smoothStatusStore = useSmoothStatusStore({ optional: true });
1577
1593
  const setText = useCallbackRef((text2) => {
1578
1594
  setDisplayedText(text2);
@@ -1582,17 +1598,17 @@ var useSmooth = (state, smooth = false) => {
1582
1598
  );
1583
1599
  }
1584
1600
  });
1585
- useEffect9(() => {
1601
+ useEffect10(() => {
1586
1602
  if (smoothStatusStore) {
1587
1603
  writableStore(smoothStatusStore).setState(
1588
1604
  text !== state.text ? SMOOTH_STATUS : state.status
1589
1605
  );
1590
1606
  }
1591
1607
  }, [smoothStatusStore, text, displayedText, state.status, state.text]);
1592
- const [animatorRef] = useState7(
1608
+ const [animatorRef] = useState8(
1593
1609
  new TextStreamAnimator(text, setText)
1594
1610
  );
1595
- useEffect9(() => {
1611
+ useEffect10(() => {
1596
1612
  if (!smooth) {
1597
1613
  animatorRef.stop();
1598
1614
  return;
@@ -1608,7 +1624,7 @@ var useSmooth = (state, smooth = false) => {
1608
1624
  animatorRef.targetText = text;
1609
1625
  animatorRef.start();
1610
1626
  }, [setText, animatorRef, id, smooth, text]);
1611
- useEffect9(() => {
1627
+ useEffect10(() => {
1612
1628
  return () => {
1613
1629
  animatorRef.stop();
1614
1630
  };
@@ -1656,11 +1672,22 @@ var ContentPartPrimitiveInProgress = ({ children }) => {
1656
1672
  };
1657
1673
  ContentPartPrimitiveInProgress.displayName = "ContentPartPrimitive.InProgress";
1658
1674
 
1675
+ // src/utils/getThreadMessageText.tsx
1676
+ var getThreadMessageText = (message) => {
1677
+ const textParts = message.content.filter(
1678
+ (part) => part.type === "text"
1679
+ );
1680
+ return textParts.map((part) => part.text).join("\n\n");
1681
+ };
1682
+
1659
1683
  // src/api/AttachmentRuntime.ts
1660
1684
  var AttachmentRuntimeImpl = class {
1661
1685
  constructor(_core) {
1662
1686
  this._core = _core;
1663
1687
  }
1688
+ get path() {
1689
+ return this._core.path;
1690
+ }
1664
1691
  getState() {
1665
1692
  return this._core.getState();
1666
1693
  }
@@ -1739,6 +1766,9 @@ var LazyMemoizeSubject = class extends BaseSubject {
1739
1766
  super();
1740
1767
  this.binding = binding;
1741
1768
  }
1769
+ get path() {
1770
+ return this.binding.path;
1771
+ }
1742
1772
  _previousStateDirty = true;
1743
1773
  _previousState;
1744
1774
  getState = () => {
@@ -1785,6 +1815,9 @@ var ShallowMemoizeSubject = class extends BaseSubject {
1785
1815
  throw new Error("Entry not available in the store");
1786
1816
  this._previousState = state;
1787
1817
  }
1818
+ get path() {
1819
+ return this.binding.path;
1820
+ }
1788
1821
  _previousState;
1789
1822
  getState = () => {
1790
1823
  if (!this.isConnected) this._syncState();
@@ -1851,6 +1884,9 @@ var ComposerRuntimeImpl = class {
1851
1884
  constructor(_core) {
1852
1885
  this._core = _core;
1853
1886
  }
1887
+ get path() {
1888
+ return this._core.path;
1889
+ }
1854
1890
  /**
1855
1891
  * @deprecated Use `getState().isEditing` instead. This will be removed in 0.6.0.
1856
1892
  */
@@ -1936,16 +1972,21 @@ var ComposerRuntimeImpl = class {
1936
1972
  }
1937
1973
  };
1938
1974
  var ThreadComposerRuntimeImpl = class extends ComposerRuntimeImpl {
1975
+ get path() {
1976
+ return this._core.path;
1977
+ }
1939
1978
  get type() {
1940
1979
  return "thread";
1941
1980
  }
1942
1981
  _getState;
1943
1982
  constructor(core) {
1944
1983
  const stateBinding = new LazyMemoizeSubject({
1984
+ path: core.path,
1945
1985
  getState: () => getThreadComposerState(core.getState()),
1946
1986
  subscribe: (callback) => core.subscribe(callback)
1947
1987
  });
1948
1988
  super({
1989
+ path: core.path,
1949
1990
  getState: () => core.getState(),
1950
1991
  subscribe: (callback) => stateBinding.subscribe(callback)
1951
1992
  });
@@ -1960,6 +2001,12 @@ var ThreadComposerRuntimeImpl = class extends ComposerRuntimeImpl {
1960
2001
  getAttachmentByIndex(idx) {
1961
2002
  return new ThreadComposerAttachmentRuntimeImpl(
1962
2003
  new ShallowMemoizeSubject({
2004
+ path: {
2005
+ ...this.path,
2006
+ attachmentSource: "thread-composer",
2007
+ attachmentSelector: { type: "index", index: idx },
2008
+ ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`
2009
+ },
1963
2010
  getState: () => {
1964
2011
  const attachments = this.getState().attachments;
1965
2012
  const attachment = attachments[idx];
@@ -1979,16 +2026,21 @@ var ThreadComposerRuntimeImpl = class extends ComposerRuntimeImpl {
1979
2026
  var EditComposerRuntimeImpl = class extends ComposerRuntimeImpl {
1980
2027
  constructor(core, _beginEdit) {
1981
2028
  const stateBinding = new LazyMemoizeSubject({
2029
+ path: core.path,
1982
2030
  getState: () => getEditComposerState(core.getState(), this._beginEdit),
1983
2031
  subscribe: (callback) => core.subscribe(callback)
1984
2032
  });
1985
2033
  super({
2034
+ path: core.path,
1986
2035
  getState: () => core.getState(),
1987
2036
  subscribe: (callback) => stateBinding.subscribe(callback)
1988
2037
  });
1989
2038
  this._beginEdit = _beginEdit;
1990
2039
  this._getState = stateBinding.getState.bind(stateBinding);
1991
2040
  }
2041
+ get path() {
2042
+ return this._core.path;
2043
+ }
1992
2044
  get type() {
1993
2045
  return "edit";
1994
2046
  }
@@ -2008,6 +2060,12 @@ var EditComposerRuntimeImpl = class extends ComposerRuntimeImpl {
2008
2060
  getAttachmentByIndex(idx) {
2009
2061
  return new EditComposerAttachmentRuntimeImpl(
2010
2062
  new ShallowMemoizeSubject({
2063
+ path: {
2064
+ ...this.path,
2065
+ attachmentSource: "edit-composer",
2066
+ attachmentSelector: { type: "index", index: idx },
2067
+ ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`
2068
+ },
2011
2069
  getState: () => {
2012
2070
  const attachments = this.getState().attachments;
2013
2071
  const attachment = attachments[idx];
@@ -2031,6 +2089,9 @@ var NestedSubscriptionSubject = class extends BaseSubject {
2031
2089
  super();
2032
2090
  this.binding = binding;
2033
2091
  }
2092
+ get path() {
2093
+ return this.binding.path;
2094
+ }
2034
2095
  getState() {
2035
2096
  return this.binding.getState();
2036
2097
  }
@@ -2097,14 +2158,23 @@ var MessageRuntimeImpl = class {
2097
2158
  constructor(_core, _threadBinding) {
2098
2159
  this._core = _core;
2099
2160
  this._threadBinding = _threadBinding;
2161
+ this.composer = new EditComposerRuntimeImpl(
2162
+ new NestedSubscriptionSubject({
2163
+ path: {
2164
+ ...this.path,
2165
+ ref: this.path.ref + `${this.path.ref}.composer`,
2166
+ composerSource: "edit"
2167
+ },
2168
+ getState: () => this._threadBinding.getState().getEditComposer(this._core.getState().id),
2169
+ subscribe: (callback) => this._threadBinding.subscribe(callback)
2170
+ }),
2171
+ () => this._threadBinding.getState().beginEdit(this._core.getState().id)
2172
+ );
2100
2173
  }
2101
- composer = new EditComposerRuntimeImpl(
2102
- new NestedSubscriptionSubject({
2103
- getState: () => this._threadBinding.getState().getEditComposer(this._core.getState().id),
2104
- subscribe: (callback) => this._threadBinding.subscribe(callback)
2105
- }),
2106
- () => this._threadBinding.getState().beginEdit(this._core.getState().id)
2107
- );
2174
+ get path() {
2175
+ return this._core.path;
2176
+ }
2177
+ composer;
2108
2178
  getState() {
2109
2179
  return this._core.getState();
2110
2180
  }
@@ -2160,13 +2230,21 @@ var MessageRuntimeImpl = class {
2160
2230
  if (!targetBranch) throw new Error("Branch not found");
2161
2231
  this._threadBinding.getState().switchToBranch(targetBranch);
2162
2232
  }
2233
+ unstable_getCopyText() {
2234
+ return getThreadMessageText(this.getState());
2235
+ }
2163
2236
  subscribe(callback) {
2164
2237
  return this._core.subscribe(callback);
2165
2238
  }
2166
2239
  getContentPartByIndex(idx) {
2167
- if (idx < 0) throw new Error("Message index must be >= 0");
2240
+ if (idx < 0) throw new Error("Content part index must be >= 0");
2168
2241
  return new ContentPartRuntimeImpl(
2169
2242
  new ShallowMemoizeSubject({
2243
+ path: {
2244
+ ...this.path,
2245
+ ref: this.path.ref + `${this.path.ref}.content[${idx}]`,
2246
+ contentPartSelector: { type: "index", index: idx }
2247
+ },
2170
2248
  getState: () => {
2171
2249
  return getContentPartState(this.getState(), idx);
2172
2250
  },
@@ -2176,9 +2254,37 @@ var MessageRuntimeImpl = class {
2176
2254
  this._threadBinding
2177
2255
  );
2178
2256
  }
2257
+ getContentPartByToolCallId(toolCallId) {
2258
+ return new ContentPartRuntimeImpl(
2259
+ new ShallowMemoizeSubject({
2260
+ path: {
2261
+ ...this.path,
2262
+ ref: this.path.ref + `${this.path.ref}.content[toolCallId=${JSON.stringify(toolCallId)}]`,
2263
+ contentPartSelector: { type: "toolCallId", toolCallId }
2264
+ },
2265
+ getState: () => {
2266
+ const state = this._core.getState();
2267
+ const idx = state.content.findIndex(
2268
+ (part) => part.type === "tool-call" && part.toolCallId === toolCallId
2269
+ );
2270
+ if (idx === -1) return SKIP_UPDATE;
2271
+ return getContentPartState(state, idx);
2272
+ },
2273
+ subscribe: (callback) => this._core.subscribe(callback)
2274
+ }),
2275
+ this._core,
2276
+ this._threadBinding
2277
+ );
2278
+ }
2179
2279
  getAttachmentByIndex(idx) {
2180
2280
  return new MessageAttachmentRuntimeImpl(
2181
2281
  new ShallowMemoizeSubject({
2282
+ path: {
2283
+ ...this.path,
2284
+ ref: this.path.ref + `${this.path.ref}.attachments[${idx}]`,
2285
+ attachmentSource: "message",
2286
+ attachmentSelector: { type: "index", index: idx }
2287
+ },
2182
2288
  getState: () => {
2183
2289
  const attachments = this.getState().attachments;
2184
2290
  const attachment = attachments?.[idx];
@@ -2285,22 +2391,22 @@ import { memo as memo3, useMemo as useMemo8 } from "react";
2285
2391
 
2286
2392
  // src/context/providers/AttachmentRuntimeProvider.tsx
2287
2393
  import {
2288
- useEffect as useEffect10,
2394
+ useEffect as useEffect11,
2289
2395
  useMemo as useMemo7,
2290
- useState as useState8
2396
+ useState as useState9
2291
2397
  } from "react";
2292
2398
  import { create as create8 } from "zustand";
2293
2399
  import { jsx as jsx24 } from "react/jsx-runtime";
2294
2400
  var useAttachmentRuntimeStore = (runtime) => {
2295
- const [store] = useState8(() => create8(() => runtime));
2296
- useEffect10(() => {
2401
+ const [store] = useState9(() => create8(() => runtime));
2402
+ useEffect11(() => {
2297
2403
  writableStore(store).setState(runtime, true);
2298
2404
  }, [runtime, store]);
2299
2405
  return store;
2300
2406
  };
2301
2407
  var useAttachmentStore = (runtime) => {
2302
- const [store] = useState8(() => create8(() => runtime.getState()));
2303
- useEffect10(() => {
2408
+ const [store] = useState9(() => create8(() => runtime.getState()));
2409
+ useEffect11(() => {
2304
2410
  const updateState = () => writableStore(store).setState(runtime.getState(), true);
2305
2411
  updateState();
2306
2412
  return runtime.subscribe(updateState);
@@ -2426,7 +2532,7 @@ import { Slot } from "@radix-ui/react-slot";
2426
2532
  import {
2427
2533
  forwardRef as forwardRef18,
2428
2534
  useCallback as useCallback20,
2429
- useEffect as useEffect12,
2535
+ useEffect as useEffect13,
2430
2536
  useRef as useRef3
2431
2537
  } from "react";
2432
2538
  import TextareaAutosize from "react-textarea-autosize";
@@ -2434,11 +2540,11 @@ import { useEscapeKeydown as useEscapeKeydown2 } from "@radix-ui/react-use-escap
2434
2540
 
2435
2541
  // src/utils/hooks/useOnScrollToBottom.tsx
2436
2542
  import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
2437
- import { useEffect as useEffect11 } from "react";
2543
+ import { useEffect as useEffect12 } from "react";
2438
2544
  var useOnScrollToBottom = (callback) => {
2439
2545
  const callbackRef = useCallbackRef2(callback);
2440
2546
  const onScrollToBottom = useThreadViewport((vp) => vp.onScrollToBottom);
2441
- useEffect11(() => {
2547
+ useEffect12(() => {
2442
2548
  return onScrollToBottom(callbackRef);
2443
2549
  }, [onScrollToBottom, callbackRef]);
2444
2550
  };
@@ -2497,18 +2603,18 @@ var ComposerPrimitiveInput = forwardRef18(
2497
2603
  textareaRef.current.value.length
2498
2604
  );
2499
2605
  }, [autoFocusEnabled]);
2500
- useEffect12(() => focus2(), [focus2]);
2606
+ useEffect13(() => focus2(), [focus2]);
2501
2607
  useOnScrollToBottom(() => {
2502
2608
  if (composerRuntime.type === "thread" && unstable_focusOnScrollToBottom) {
2503
2609
  focus2();
2504
2610
  }
2505
2611
  });
2506
- useEffect12(() => {
2612
+ useEffect13(() => {
2507
2613
  if (composerRuntime.type !== "thread" || !unstable_focusOnRunStart)
2508
2614
  return void 0;
2509
2615
  return threadRuntime.unstable_on("run-start", focus2);
2510
2616
  }, [unstable_focusOnRunStart]);
2511
- useEffect12(() => {
2617
+ useEffect13(() => {
2512
2618
  if (composerRuntime.type !== "thread" || !unstable_focusOnThreadSwitched)
2513
2619
  return void 0;
2514
2620
  return threadRuntime.unstable_on("switched-to", focus2);
@@ -2665,7 +2771,7 @@ import { forwardRef as forwardRef20 } from "react";
2665
2771
 
2666
2772
  // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
2667
2773
  import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
2668
- import { useEffect as useEffect13, useRef as useRef4 } from "react";
2774
+ import { useEffect as useEffect14, useRef as useRef4 } from "react";
2669
2775
 
2670
2776
  // src/utils/hooks/useOnResizeContent.tsx
2671
2777
  import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
@@ -2757,7 +2863,7 @@ var useThreadViewportAutoScroll = ({
2757
2863
  scrollToBottom("auto");
2758
2864
  });
2759
2865
  const threadRuntime = useThreadRuntime();
2760
- useEffect13(() => {
2866
+ useEffect14(() => {
2761
2867
  if (!unstable_scrollToBottomOnRunStart) return void 0;
2762
2868
  return threadRuntime.unstable_on("run-start", focus);
2763
2869
  }, [unstable_scrollToBottomOnRunStart]);
@@ -2779,7 +2885,7 @@ ThreadPrimitiveViewport.displayName = "ThreadPrimitive.Viewport";
2779
2885
  import { memo as memo5, useMemo as useMemo10 } from "react";
2780
2886
 
2781
2887
  // src/context/providers/MessageRuntimeProvider.tsx
2782
- import { useEffect as useEffect14, useState as useState9 } from "react";
2888
+ import { useEffect as useEffect15, useState as useState10 } from "react";
2783
2889
  import { create as create10 } from "zustand";
2784
2890
 
2785
2891
  // src/context/stores/MessageUtils.ts
@@ -2800,15 +2906,15 @@ var makeMessageUtilsStore = () => create9((set) => {
2800
2906
  // src/context/providers/MessageRuntimeProvider.tsx
2801
2907
  import { jsx as jsx32 } from "react/jsx-runtime";
2802
2908
  var useMessageRuntimeStore = (runtime) => {
2803
- const [store] = useState9(() => create10(() => runtime));
2804
- useEffect14(() => {
2909
+ const [store] = useState10(() => create10(() => runtime));
2910
+ useEffect15(() => {
2805
2911
  writableStore(store).setState(runtime, true);
2806
2912
  }, [runtime, store]);
2807
2913
  return store;
2808
2914
  };
2809
2915
  var useMessageStore2 = (runtime) => {
2810
- const [store] = useState9(() => create10(() => runtime.getState()));
2811
- useEffect14(() => {
2916
+ const [store] = useState10(() => create10(() => runtime.getState()));
2917
+ useEffect15(() => {
2812
2918
  const updateState = () => writableStore(store).setState(runtime.getState(), true);
2813
2919
  updateState();
2814
2920
  return runtime.subscribe(updateState);
@@ -2816,13 +2922,13 @@ var useMessageStore2 = (runtime) => {
2816
2922
  return store;
2817
2923
  };
2818
2924
  var useMessageUtilsStore2 = () => {
2819
- const [store] = useState9(() => makeMessageUtilsStore());
2925
+ const [store] = useState10(() => makeMessageUtilsStore());
2820
2926
  return store;
2821
2927
  };
2822
2928
  var useEditComposerStore2 = (useMessageRuntime2) => {
2823
2929
  const runtime = useMessageRuntime2.getState().composer;
2824
- const [store] = useState9(() => create10(() => runtime.getState()));
2825
- useEffect14(() => {
2930
+ const [store] = useState10(() => create10(() => runtime.getState()));
2931
+ useEffect15(() => {
2826
2932
  const updateState = () => writableStore(store).setState(runtime.getState());
2827
2933
  updateState();
2828
2934
  return runtime.subscribe(updateState);
@@ -2837,7 +2943,7 @@ var MessageRuntimeProvider = ({
2837
2943
  const useMessage2 = useMessageStore2(runtime);
2838
2944
  const useMessageUtils2 = useMessageUtilsStore2();
2839
2945
  const useEditComposer2 = useEditComposerStore2(useMessageRuntime2);
2840
- const [context] = useState9(() => {
2946
+ const [context] = useState10(() => {
2841
2947
  return { useMessageRuntime: useMessageRuntime2, useMessage: useMessage2, useMessageUtils: useMessageUtils2, useEditComposer: useEditComposer2 };
2842
2948
  });
2843
2949
  return /* @__PURE__ */ jsx32(MessageContext.Provider, { value: context, children });
@@ -2929,13 +3035,13 @@ var subscribeToMainThread = (runtime, callback) => {
2929
3035
  let cleanup;
2930
3036
  const inner = () => {
2931
3037
  cleanup?.();
2932
- cleanup = runtime.thread.subscribe(callback);
3038
+ cleanup = runtime.threadManager.mainThread.subscribe(callback);
2933
3039
  if (!first) {
2934
3040
  callback();
2935
3041
  }
2936
3042
  first = false;
2937
3043
  };
2938
- const unsubscribe = runtime.subscribe(inner);
3044
+ const unsubscribe = runtime.threadManager.mainThread.subscribe(inner);
2939
3045
  inner();
2940
3046
  return () => {
2941
3047
  unsubscribe();
@@ -2944,29 +3050,44 @@ var subscribeToMainThread = (runtime, callback) => {
2944
3050
  };
2945
3051
 
2946
3052
  // src/runtimes/local/useLocalRuntime.tsx
2947
- import { useInsertionEffect, useMemo as useMemo11, useState as useState11 } from "react";
3053
+ import { useEffect as useEffect16, useMemo as useMemo11, useState as useState12 } from "react";
2948
3054
 
2949
- // src/runtimes/core/BaseAssistantRuntimeCore.tsx
2950
- var BaseAssistantRuntimeCore = class {
2951
- constructor(_thread) {
2952
- this._thread = _thread;
2953
- this._thread = _thread;
3055
+ // src/utils/ProxyConfigProvider.ts
3056
+ var ProxyConfigProvider = class {
3057
+ _providers = /* @__PURE__ */ new Set();
3058
+ getModelConfig() {
3059
+ return mergeModelConfigs(this._providers);
2954
3060
  }
2955
- get thread() {
2956
- return this._thread;
3061
+ registerModelConfigProvider(provider) {
3062
+ this._providers.add(provider);
3063
+ const unsubscribe = provider.subscribe?.(() => {
3064
+ this.notifySubscribers();
3065
+ });
3066
+ this.notifySubscribers();
3067
+ return () => {
3068
+ this._providers.delete(provider);
3069
+ unsubscribe?.();
3070
+ this.notifySubscribers();
3071
+ };
2957
3072
  }
2958
- set thread(thread) {
2959
- this._thread = thread;
2960
- this.subscriptionHandler();
3073
+ _subscribers = /* @__PURE__ */ new Set();
3074
+ notifySubscribers() {
3075
+ for (const callback of this._subscribers) callback();
2961
3076
  }
2962
- _subscriptions = /* @__PURE__ */ new Set();
2963
3077
  subscribe(callback) {
2964
- this._subscriptions.add(callback);
2965
- return () => this._subscriptions.delete(callback);
3078
+ this._subscribers.add(callback);
3079
+ return () => this._subscribers.delete(callback);
3080
+ }
3081
+ };
3082
+
3083
+ // src/runtimes/core/BaseAssistantRuntimeCore.tsx
3084
+ var BaseAssistantRuntimeCore = class {
3085
+ _proxyConfigProvider = new ProxyConfigProvider();
3086
+ constructor() {
3087
+ }
3088
+ registerModelConfigProvider(provider) {
3089
+ return this._proxyConfigProvider.registerModelConfigProvider(provider);
2966
3090
  }
2967
- subscriptionHandler = () => {
2968
- for (const callback of this._subscriptions) callback();
2969
- };
2970
3091
  };
2971
3092
 
2972
3093
  // src/internal.ts
@@ -3102,20 +3223,6 @@ var DefaultThreadComposerRuntimeCore = class extends BaseComposerRuntimeCore {
3102
3223
  }
3103
3224
  };
3104
3225
 
3105
- // src/utils/ProxyConfigProvider.ts
3106
- var ProxyConfigProvider = class {
3107
- _providers = /* @__PURE__ */ new Set();
3108
- getModelConfig() {
3109
- return mergeModelConfigs(this._providers);
3110
- }
3111
- registerModelConfigProvider(provider) {
3112
- this._providers.add(provider);
3113
- return () => {
3114
- this._providers.delete(provider);
3115
- };
3116
- }
3117
- };
3118
-
3119
3226
  // src/utils/idUtils.tsx
3120
3227
  import { customAlphabet } from "nanoid/non-secure";
3121
3228
  var generateId = customAlphabet(
@@ -3495,7 +3602,9 @@ var getThreadState = (runtime) => {
3495
3602
  });
3496
3603
  };
3497
3604
  var ThreadRuntimeImpl = class {
3498
- // public path = "assistant.threads[main]"; // TODO
3605
+ get path() {
3606
+ return this._threadBinding.path;
3607
+ }
3499
3608
  /**
3500
3609
  * @deprecated Use `getState().threadId` instead. This will be removed in 0.6.0.
3501
3610
  */
@@ -3550,22 +3659,30 @@ var ThreadRuntimeImpl = class {
3550
3659
  _threadBinding;
3551
3660
  constructor(threadBinding) {
3552
3661
  const stateBinding = new LazyMemoizeSubject({
3662
+ path: threadBinding.path,
3553
3663
  getState: () => getThreadState(threadBinding.getState()),
3554
3664
  subscribe: (callback) => threadBinding.subscribe(callback)
3555
3665
  });
3556
3666
  this._threadBinding = {
3667
+ path: threadBinding.path,
3557
3668
  getState: () => threadBinding.getState(),
3558
3669
  getStateState: () => stateBinding.getState(),
3559
3670
  outerSubscribe: (callback) => threadBinding.outerSubscribe(callback),
3560
3671
  subscribe: (callback) => threadBinding.subscribe(callback)
3561
3672
  };
3673
+ this.composer = new ThreadComposerRuntimeImpl(
3674
+ new NestedSubscriptionSubject({
3675
+ path: {
3676
+ ...this.path,
3677
+ ref: this.path.ref + `${this.path.ref}.composer`,
3678
+ composerSource: "thread"
3679
+ },
3680
+ getState: () => this._threadBinding.getState().composer,
3681
+ subscribe: (callback) => this._threadBinding.subscribe(callback)
3682
+ })
3683
+ );
3562
3684
  }
3563
- composer = new ThreadComposerRuntimeImpl(
3564
- new NestedSubscriptionSubject({
3565
- getState: () => this._threadBinding.getState().composer,
3566
- subscribe: (callback) => this._threadBinding.subscribe(callback)
3567
- })
3568
- );
3685
+ composer;
3569
3686
  getState() {
3570
3687
  return this._threadBinding.getStateState();
3571
3688
  }
@@ -3643,20 +3760,49 @@ var ThreadRuntimeImpl = class {
3643
3760
  }
3644
3761
  getMesssageByIndex(idx) {
3645
3762
  if (idx < 0) throw new Error("Message index must be >= 0");
3763
+ return this._getMessageRuntime(
3764
+ {
3765
+ ...this.path,
3766
+ ref: this.path.ref + `${this.path.ref}.messages[${idx}]`,
3767
+ messageSelector: { type: "index", index: idx }
3768
+ },
3769
+ () => {
3770
+ const messages2 = this._threadBinding.getState().messages;
3771
+ const message = messages2[idx];
3772
+ if (!message) return void 0;
3773
+ return {
3774
+ message,
3775
+ parentId: messages2[idx - 1]?.id ?? null
3776
+ };
3777
+ }
3778
+ );
3779
+ }
3780
+ getMesssageById(messageId) {
3781
+ return this._getMessageRuntime(
3782
+ {
3783
+ ...this.path,
3784
+ ref: this.path.ref + `${this.path.ref}.messages[messageId=${JSON.stringify(messageId)}]`,
3785
+ messageSelector: { type: "messageId", messageId }
3786
+ },
3787
+ () => this._threadBinding.getState().getMessageById(messageId)
3788
+ );
3789
+ }
3790
+ _getMessageRuntime(path, callback) {
3646
3791
  return new MessageRuntimeImpl(
3647
3792
  new ShallowMemoizeSubject({
3793
+ path,
3648
3794
  getState: () => {
3649
- const { messages: messages2, speech: speechState } = this.getState();
3650
- const message = messages2[idx];
3651
- if (!message) return SKIP_UPDATE;
3795
+ const { message, parentId } = callback() ?? {};
3796
+ const { messages: messages2, speech: speechState } = this._threadBinding.getState();
3797
+ if (!message || parentId === void 0) return SKIP_UPDATE;
3652
3798
  const thread = this._threadBinding.getState();
3653
3799
  const branches = thread.getBranches(message.id);
3654
3800
  const submittedFeedback = thread.getSubmittedFeedback(message.id);
3655
3801
  return {
3656
3802
  ...message,
3657
3803
  message,
3658
- isLast: idx === messages2.length - 1,
3659
- parentId: messages2[idx - 1]?.id ?? null,
3804
+ isLast: messages2.at(-1)?.id === message.id,
3805
+ parentId,
3660
3806
  branches,
3661
3807
  branchNumber: branches.indexOf(message.id) + 1,
3662
3808
  branchCount: branches.length,
@@ -3664,7 +3810,7 @@ var ThreadRuntimeImpl = class {
3664
3810
  submittedFeedback
3665
3811
  };
3666
3812
  },
3667
- subscribe: (callback) => this._threadBinding.subscribe(callback)
3813
+ subscribe: (callback2) => this._threadBinding.subscribe(callback2)
3668
3814
  }),
3669
3815
  this._threadBinding
3670
3816
  );
@@ -3674,6 +3820,7 @@ var ThreadRuntimeImpl = class {
3674
3820
  let subject = this._eventListenerNestedSubscriptions.get(event);
3675
3821
  if (!subject) {
3676
3822
  subject = new NestedSubscriptionSubject({
3823
+ path: this.path,
3677
3824
  getState: () => ({
3678
3825
  subscribe: (callback2) => this._threadBinding.getState().unstable_on(event, callback2)
3679
3826
  }),
@@ -3685,43 +3832,94 @@ var ThreadRuntimeImpl = class {
3685
3832
  }
3686
3833
  };
3687
3834
 
3835
+ // src/api/ThreadManagerRuntime.ts
3836
+ var getThreadManagerState = (threadManager) => {
3837
+ return {
3838
+ threads: threadManager.threads,
3839
+ archivedThreads: threadManager.archivedThreads
3840
+ };
3841
+ };
3842
+ var THREAD_MANAGER_PATH = {
3843
+ ref: "threadManager"
3844
+ };
3845
+ var ThreadManagerRuntimeImpl = class {
3846
+ constructor(_core) {
3847
+ this._core = _core;
3848
+ const stateBinding = new LazyMemoizeSubject({
3849
+ path: THREAD_MANAGER_PATH,
3850
+ getState: () => getThreadManagerState(_core),
3851
+ subscribe: (callback) => _core.subscribe(callback)
3852
+ });
3853
+ this._getState = stateBinding.getState.bind(stateBinding);
3854
+ }
3855
+ get path() {
3856
+ return THREAD_MANAGER_PATH;
3857
+ }
3858
+ _getState;
3859
+ getState() {
3860
+ return this._getState();
3861
+ }
3862
+ rename(threadId, newTitle) {
3863
+ return this._core.rename(threadId, newTitle);
3864
+ }
3865
+ archive(threadId) {
3866
+ return this._core.archive(threadId);
3867
+ }
3868
+ unarchive(threadId) {
3869
+ return this._core.unarchive(threadId);
3870
+ }
3871
+ delete(threadId) {
3872
+ return this._core.delete(threadId);
3873
+ }
3874
+ subscribe(callback) {
3875
+ return this._core.subscribe(callback);
3876
+ }
3877
+ };
3878
+
3688
3879
  // src/api/AssistantRuntime.ts
3689
3880
  var AssistantRuntimeImpl = class _AssistantRuntimeImpl {
3690
3881
  constructor(_core, _thread) {
3691
3882
  this._core = _core;
3692
3883
  this._thread = _thread;
3884
+ this.threadManager = new ThreadManagerRuntimeImpl(_core.threadManager);
3693
3885
  }
3886
+ threadManager;
3694
3887
  get thread() {
3695
3888
  return this._thread;
3696
3889
  }
3697
3890
  switchToNewThread() {
3698
- return this._core.switchToNewThread();
3891
+ return this._core.threadManager.switchToNewThread();
3699
3892
  }
3700
3893
  switchToThread(threadId) {
3701
- return this._core.switchToThread(threadId);
3894
+ if (threadId === null) return this.switchToNewThread();
3895
+ return this._core.threadManager.switchToThread(threadId);
3702
3896
  }
3703
3897
  registerModelConfigProvider(provider) {
3704
3898
  return this._core.registerModelConfigProvider(provider);
3705
3899
  }
3706
- // TODO events for thread switching
3707
3900
  /**
3708
3901
  * @deprecated Thread is now static and never gets updated. This will be removed in 0.6.0.
3709
3902
  */
3710
- subscribe(callback) {
3711
- return this._core.subscribe(callback);
3903
+ subscribe() {
3904
+ return () => {
3905
+ };
3712
3906
  }
3713
- static createThreadRuntime(_core, CustomThreadRuntime = ThreadRuntimeImpl) {
3907
+ static createMainThreadRuntime(_core, CustomThreadRuntime = ThreadRuntimeImpl) {
3714
3908
  return new CustomThreadRuntime(
3715
3909
  new NestedSubscriptionSubject({
3716
- getState: () => _core.thread,
3717
- subscribe: (callback) => _core.subscribe(callback)
3910
+ path: {
3911
+ ref: "threads.main",
3912
+ threadSelector: { type: "main" }
3913
+ },
3914
+ getState: () => _core.threadManager.mainThread,
3915
+ subscribe: (callback) => _core.threadManager.subscribe(callback)
3718
3916
  })
3719
3917
  );
3720
3918
  }
3721
3919
  static create(_core, CustomThreadRuntime = ThreadRuntimeImpl) {
3722
3920
  return new _AssistantRuntimeImpl(
3723
3921
  _core,
3724
- _AssistantRuntimeImpl.createThreadRuntime(_core, CustomThreadRuntime)
3922
+ _AssistantRuntimeImpl.createMainThreadRuntime(_core, CustomThreadRuntime)
3725
3923
  );
3726
3924
  }
3727
3925
  };
@@ -3893,7 +4091,7 @@ var streamUtils = {
3893
4091
  };
3894
4092
 
3895
4093
  // src/runtimes/edge/useEdgeRuntime.ts
3896
- import { useState as useState10 } from "react";
4094
+ import { useState as useState11 } from "react";
3897
4095
 
3898
4096
  // src/runtimes/edge/streams/assistantDecoderStream.ts
3899
4097
  function assistantDecoderStream() {
@@ -4074,7 +4272,7 @@ var splitLocalRuntimeOptions = (options) => {
4074
4272
  // src/runtimes/edge/useEdgeRuntime.ts
4075
4273
  var useEdgeRuntime = (options) => {
4076
4274
  const { localRuntimeOptions, otherOptions } = splitLocalRuntimeOptions(options);
4077
- const [adapter] = useState10(() => new EdgeChatAdapter(otherOptions));
4275
+ const [adapter] = useState11(() => new EdgeChatAdapter(otherOptions));
4078
4276
  return useLocalRuntime(adapter, localRuntimeOptions);
4079
4277
  };
4080
4278
 
@@ -4153,6 +4351,9 @@ var BaseThreadRuntimeCore = class {
4153
4351
  );
4154
4352
  this._notifySubscribers();
4155
4353
  }
4354
+ getMessageById(messageId) {
4355
+ return this.repository.getMessage(messageId);
4356
+ }
4156
4357
  getBranches(messageId) {
4157
4358
  return this.repository.getBranches(messageId);
4158
4359
  }
@@ -4191,7 +4392,7 @@ var BaseThreadRuntimeCore = class {
4191
4392
  if (!adapter) throw new Error("Speech adapter not configured");
4192
4393
  const { message } = this.repository.getMessage(messageId);
4193
4394
  this._stopSpeaking?.();
4194
- const utterance = adapter.speak(message);
4395
+ const utterance = adapter.speak(getThreadMessageText(message));
4195
4396
  const unsub = utterance.subscribe(() => {
4196
4397
  if (utterance.status.type === "ended") {
4197
4398
  this._stopSpeaking = void 0;
@@ -4224,6 +4425,10 @@ var BaseThreadRuntimeCore = class {
4224
4425
  }
4225
4426
  _eventSubscribers = /* @__PURE__ */ new Map();
4226
4427
  unstable_on(event, callback) {
4428
+ if (event === "model-config-update") {
4429
+ return this.configProvider.subscribe?.(callback) ?? (() => {
4430
+ });
4431
+ }
4227
4432
  const subscribers = this._eventSubscribers.get(event);
4228
4433
  if (!subscribers) {
4229
4434
  this._eventSubscribers.set(event, /* @__PURE__ */ new Set([callback]));
@@ -4239,19 +4444,10 @@ var BaseThreadRuntimeCore = class {
4239
4444
 
4240
4445
  // src/runtimes/local/LocalThreadRuntimeCore.tsx
4241
4446
  var LocalThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4242
- constructor(configProvider, adapter, { initialMessages, ...options }) {
4447
+ constructor(configProvider, threadId, options) {
4243
4448
  super(configProvider);
4244
- this.adapter = adapter;
4245
- this.threadId = generateId();
4246
- this.options = options;
4247
- if (initialMessages) {
4248
- let parentId = null;
4249
- const messages2 = fromCoreMessages(initialMessages);
4250
- for (const message of messages2) {
4251
- this.repository.addOrUpdateMessage(parentId, message);
4252
- parentId = message.id;
4253
- }
4254
- }
4449
+ this.threadId = threadId;
4450
+ this._options = options;
4255
4451
  }
4256
4452
  capabilities = {
4257
4453
  switchToBranch: true,
@@ -4264,20 +4460,17 @@ var LocalThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4264
4460
  feedback: false
4265
4461
  };
4266
4462
  abortController = null;
4267
- threadId;
4268
4463
  isDisabled = false;
4269
4464
  suggestions = [];
4270
4465
  get adapters() {
4271
- return this.options.adapters;
4466
+ return this._options.adapters;
4272
4467
  }
4273
4468
  _options;
4274
- get options() {
4275
- return this._options;
4276
- }
4277
4469
  get extras() {
4278
4470
  return void 0;
4279
4471
  }
4280
- set options({ initialMessages, ...options }) {
4472
+ setOptions(options) {
4473
+ if (this._options === options) return;
4281
4474
  this._options = options;
4282
4475
  let hasUpdates = false;
4283
4476
  const canSpeak = options.adapters?.speech !== void 0;
@@ -4353,7 +4546,7 @@ var LocalThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4353
4546
  this.repository.addOrUpdateMessage(parentId, message);
4354
4547
  this._notifySubscribers();
4355
4548
  };
4356
- const maxSteps = this.options.maxSteps ? this.options.maxSteps : (this.options.maxToolRoundtrips ?? 1) + 1;
4549
+ const maxSteps = this._options.maxSteps ? this._options.maxSteps : (this._options.maxToolRoundtrips ?? 1) + 1;
4357
4550
  const steps = message.metadata?.steps?.length ?? 0;
4358
4551
  if (steps >= maxSteps) {
4359
4552
  updateMessage({
@@ -4371,7 +4564,7 @@ var LocalThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4371
4564
  });
4372
4565
  }
4373
4566
  try {
4374
- const promiseOrGenerator = this.adapter.run({
4567
+ const promiseOrGenerator = this.adapters.chatModel.run({
4375
4568
  messages: messages2,
4376
4569
  abortSignal: this.abortController.signal,
4377
4570
  config: this.getModelConfig(),
@@ -4444,44 +4637,154 @@ var LocalThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4444
4637
  }
4445
4638
  };
4446
4639
 
4447
- // src/runtimes/local/LocalRuntimeCore.tsx
4448
- var LocalRuntimeCore = class extends BaseAssistantRuntimeCore {
4449
- _proxyConfigProvider;
4450
- constructor(adapter, options) {
4451
- const proxyConfigProvider = new ProxyConfigProvider();
4452
- super(new LocalThreadRuntimeCore(proxyConfigProvider, adapter, options));
4453
- this._proxyConfigProvider = proxyConfigProvider;
4640
+ // src/runtimes/local/LocalThreadManagerRuntimeCore.tsx
4641
+ var LocalThreadManagerRuntimeCore = class {
4642
+ constructor(_threadFactory) {
4643
+ this._threadFactory = _threadFactory;
4644
+ this._mainThread = this._threadFactory(generateId(), { messages: [] });
4454
4645
  }
4455
- registerModelConfigProvider(provider) {
4456
- return this._proxyConfigProvider.registerModelConfigProvider(provider);
4646
+ _threadData = /* @__PURE__ */ new Map();
4647
+ _threads = [];
4648
+ _archivedThreads = [];
4649
+ get threads() {
4650
+ return this._threads;
4457
4651
  }
4458
- switchToNewThread() {
4459
- const { initialMessages, ...options } = this.thread.options;
4460
- this.thread = new LocalThreadRuntimeCore(
4461
- this._proxyConfigProvider,
4462
- this.thread.adapter,
4463
- options
4464
- );
4465
- this.thread._notifyEventSubscribers("switched-to");
4652
+ get archivedThreads() {
4653
+ return this._archivedThreads;
4654
+ }
4655
+ _mainThread;
4656
+ get mainThread() {
4657
+ return this._mainThread;
4466
4658
  }
4467
4659
  switchToThread(threadId) {
4468
- if (threadId !== null) {
4469
- throw new Error("LocalRuntime does not yet support switching threads");
4660
+ if (this._mainThread.threadId === threadId) return;
4661
+ const data = this._threadData.get(threadId);
4662
+ if (!data) throw new Error("Thread not found");
4663
+ const thread = this._threadFactory(threadId, data.data);
4664
+ this._performThreadSwitch(thread);
4665
+ }
4666
+ switchToNewThread() {
4667
+ if (!this._mainThread) return;
4668
+ const thread = this._threadFactory(generateId(), { messages: [] });
4669
+ this._performThreadSwitch(thread);
4670
+ }
4671
+ _performThreadSwitch(newThreadCore) {
4672
+ if (this._mainThread) {
4673
+ const data = this._threadData.get(this._mainThread.threadId);
4674
+ if (!data) throw new Error("Thread not found");
4675
+ const exprt = this._mainThread.export();
4676
+ data.data = exprt;
4677
+ }
4678
+ this._mainThread._notifyEventSubscribers("switched-away");
4679
+ this._mainThread = newThreadCore;
4680
+ newThreadCore._notifyEventSubscribers("switched-to");
4681
+ this._notifySubscribers();
4682
+ }
4683
+ _performMoveOp(threadId, operation) {
4684
+ const data = this._threadData.get(threadId);
4685
+ if (!data) throw new Error("Thread not found");
4686
+ if (operation === "archive" && data.isArchived) return;
4687
+ if (operation === "unarchive" && !data.isArchived) return;
4688
+ if (operation === "archive") {
4689
+ data.isArchived = true;
4690
+ this._archivedThreads = [...this._archivedThreads, data.metadata];
4691
+ }
4692
+ if (operation === "unarchive") {
4693
+ data.isArchived = false;
4694
+ this._threads = [...this._threads, data.metadata];
4695
+ }
4696
+ if (operation === "delete") {
4697
+ this._threadData.delete(threadId);
4698
+ }
4699
+ if (operation === "archive" || operation === "delete" && data.isArchived) {
4700
+ this._archivedThreads = this._archivedThreads.filter(
4701
+ (t) => t.threadId !== threadId
4702
+ );
4703
+ }
4704
+ if (operation === "unarchive" || operation === "delete" && !data.isArchived) {
4705
+ this._threads = this._threads.filter((t) => t.threadId !== threadId);
4470
4706
  }
4471
- this.switchToNewThread();
4707
+ this._notifySubscribers();
4708
+ }
4709
+ async rename(threadId, newTitle) {
4710
+ const data = this._threadData.get(threadId);
4711
+ if (!data) throw new Error("Thread not found");
4712
+ data.metadata = {
4713
+ ...data.metadata,
4714
+ title: newTitle
4715
+ };
4716
+ const threadList = data.isArchived ? this.archivedThreads : this.threads;
4717
+ const idx = threadList.findIndex((t) => t.threadId === threadId);
4718
+ const updatedThreadList = threadList.toSpliced(idx, 1, data.metadata);
4719
+ if (data.isArchived) {
4720
+ this._archivedThreads = updatedThreadList;
4721
+ } else {
4722
+ this._threads = updatedThreadList;
4723
+ }
4724
+ this._notifySubscribers();
4725
+ }
4726
+ async archive(threadId) {
4727
+ this._performMoveOp(threadId, "archive");
4728
+ }
4729
+ async unarchive(threadId) {
4730
+ this._performMoveOp(threadId, "unarchive");
4731
+ }
4732
+ async delete(threadId) {
4733
+ this._performMoveOp(threadId, "delete");
4734
+ }
4735
+ _subscriptions = /* @__PURE__ */ new Set();
4736
+ subscribe(callback) {
4737
+ this._subscriptions.add(callback);
4738
+ return () => this._subscriptions.delete(callback);
4739
+ }
4740
+ _notifySubscribers() {
4741
+ for (const callback of this._subscriptions) callback();
4742
+ }
4743
+ };
4744
+
4745
+ // src/runtimes/local/LocalRuntimeCore.tsx
4746
+ var getExportFromInitialMessages = (initialMessages) => {
4747
+ const messages2 = fromCoreMessages(initialMessages);
4748
+ return {
4749
+ messages: messages2.map((m, idx) => ({
4750
+ parentId: messages2[idx - 1]?.id ?? null,
4751
+ message: m
4752
+ }))
4753
+ };
4754
+ };
4755
+ var LocalRuntimeCore = class extends BaseAssistantRuntimeCore {
4756
+ threadManager;
4757
+ _options;
4758
+ constructor(options, initialMessages) {
4759
+ super();
4760
+ this._options = options;
4761
+ this.threadManager = new LocalThreadManagerRuntimeCore((threadId, data) => {
4762
+ const thread = new LocalThreadRuntimeCore(
4763
+ this._proxyConfigProvider,
4764
+ threadId,
4765
+ this._options
4766
+ );
4767
+ thread.import(data);
4768
+ return thread;
4769
+ });
4770
+ if (initialMessages) {
4771
+ this.threadManager.mainThread.import(
4772
+ getExportFromInitialMessages(initialMessages)
4773
+ );
4774
+ }
4775
+ }
4776
+ setOptions(options) {
4777
+ this._options = options;
4778
+ this.threadManager.mainThread.setOptions(options);
4472
4779
  }
4473
4780
  reset({
4474
4781
  initialMessages
4475
4782
  } = {}) {
4476
- this.switchToThread(null);
4783
+ this.threadManager.switchToNewThread();
4477
4784
  if (!initialMessages) return;
4478
- const messages2 = fromCoreMessages(initialMessages);
4479
- this.thread.import({
4480
- messages: messages2.map((m, idx) => ({
4481
- parentId: messages2[idx - 1]?.id ?? null,
4482
- message: m
4483
- }))
4484
- });
4785
+ this.threadManager.mainThread.import(
4786
+ getExportFromInitialMessages(initialMessages)
4787
+ );
4485
4788
  }
4486
4789
  };
4487
4790
 
@@ -4497,21 +4800,113 @@ var LocalRuntimeImpl = class _LocalRuntimeImpl extends AssistantRuntimeImpl {
4497
4800
  static create(_core) {
4498
4801
  return new _LocalRuntimeImpl(
4499
4802
  _core,
4500
- AssistantRuntimeImpl.createThreadRuntime(_core, ThreadRuntimeImpl)
4803
+ AssistantRuntimeImpl.createMainThreadRuntime(_core, ThreadRuntimeImpl)
4501
4804
  );
4502
4805
  }
4503
4806
  };
4504
4807
  var useLocalRuntime = (adapter, options = {}) => {
4505
- const [runtime] = useState11(() => new LocalRuntimeCore(adapter, options));
4506
- useInsertionEffect(() => {
4507
- runtime.thread.adapter = adapter;
4508
- runtime.thread.options = options;
4808
+ const opt = {
4809
+ ...options,
4810
+ adapters: {
4811
+ ...options.adapters,
4812
+ chatModel: adapter
4813
+ }
4814
+ };
4815
+ const [runtime] = useState12(() => new LocalRuntimeCore(opt));
4816
+ useEffect16(() => {
4817
+ runtime.setOptions(opt);
4509
4818
  });
4510
4819
  return useMemo11(() => LocalRuntimeImpl.create(runtime), [runtime]);
4511
4820
  };
4512
4821
 
4513
4822
  // src/runtimes/external-store/useExternalStoreRuntime.tsx
4514
- import { useEffect as useEffect15, useMemo as useMemo12, useState as useState12 } from "react";
4823
+ import { useEffect as useEffect17, useMemo as useMemo12, useState as useState13 } from "react";
4824
+
4825
+ // src/runtimes/external-store/ExternalStoreThreadManagementAdapter.tsx
4826
+ var EMPTY_ARRAY2 = Object.freeze([]);
4827
+ var DEFAULT_THREAD_ID = "DEFAULT_THREAD_ID";
4828
+ var ExternalStoreThreadManagerRuntimeCore = class {
4829
+ constructor(adapter = {}, threadFactory) {
4830
+ this.adapter = adapter;
4831
+ this.threadFactory = threadFactory;
4832
+ this._mainThread = this.threadFactory(DEFAULT_THREAD_ID);
4833
+ }
4834
+ get threads() {
4835
+ return this.adapter.threads ?? EMPTY_ARRAY2;
4836
+ }
4837
+ get archivedThreads() {
4838
+ return this.adapter.archivedThreads ?? EMPTY_ARRAY2;
4839
+ }
4840
+ _mainThread;
4841
+ get mainThread() {
4842
+ return this._mainThread;
4843
+ }
4844
+ setAdapter(adapter) {
4845
+ const previousAdapter = this.adapter;
4846
+ this.adapter = adapter;
4847
+ const newThreadId = adapter.threadId ?? DEFAULT_THREAD_ID;
4848
+ const newThreads = adapter.threads ?? EMPTY_ARRAY2;
4849
+ const newArchivedThreads = adapter.archivedThreads ?? EMPTY_ARRAY2;
4850
+ if (previousAdapter.threadId === newThreadId && previousAdapter.threads === newThreads && previousAdapter.archivedThreads === newArchivedThreads) {
4851
+ return;
4852
+ }
4853
+ if (previousAdapter.threadId !== newThreadId) {
4854
+ this._mainThread._notifyEventSubscribers("switched-away");
4855
+ this._mainThread = this.threadFactory(newThreadId);
4856
+ this._mainThread._notifyEventSubscribers("switched-to");
4857
+ }
4858
+ this._notifySubscribers();
4859
+ }
4860
+ switchToThread(threadId) {
4861
+ if (this._mainThread?.threadId === threadId) return;
4862
+ const onSwitchToThread = this.adapter.onSwitchToThread;
4863
+ if (!onSwitchToThread)
4864
+ throw new Error(
4865
+ "External store adapter does not support switching to thread"
4866
+ );
4867
+ onSwitchToThread(threadId);
4868
+ }
4869
+ switchToNewThread() {
4870
+ const onSwitchToNewThread = this.adapter.onSwitchToNewThread;
4871
+ if (!onSwitchToNewThread)
4872
+ throw new Error(
4873
+ "External store adapter does not support switching to new thread"
4874
+ );
4875
+ onSwitchToNewThread();
4876
+ }
4877
+ async rename(threadId, newTitle) {
4878
+ const onRename = this.adapter.onRename;
4879
+ if (!onRename)
4880
+ throw new Error("External store adapter does not support renaming");
4881
+ onRename(threadId, newTitle);
4882
+ }
4883
+ async archive(threadId) {
4884
+ const onArchive = this.adapter.onArchive;
4885
+ if (!onArchive)
4886
+ throw new Error("External store adapter does not support archiving");
4887
+ onArchive(threadId);
4888
+ }
4889
+ async unarchive(threadId) {
4890
+ const onUnarchive = this.adapter.onUnarchive;
4891
+ if (!onUnarchive)
4892
+ throw new Error("External store adapter does not support unarchiving");
4893
+ onUnarchive(threadId);
4894
+ }
4895
+ async delete(threadId) {
4896
+ const onDelete = this.adapter.onDelete;
4897
+ if (!onDelete)
4898
+ throw new Error("External store adapter does not support deleting");
4899
+ onDelete(threadId);
4900
+ }
4901
+ _subscriptions = /* @__PURE__ */ new Set();
4902
+ subscribe(callback) {
4903
+ this._subscriptions.add(callback);
4904
+ return () => this._subscriptions.delete(callback);
4905
+ }
4906
+ _notifySubscribers() {
4907
+ for (const callback of this._subscriptions) callback();
4908
+ }
4909
+ };
4515
4910
 
4516
4911
  // src/runtimes/external-store/getExternalStoreMessage.tsx
4517
4912
  var symbolInnerMessage = Symbol("innerMessage");
@@ -4616,7 +5011,7 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
4616
5011
  };
4617
5012
 
4618
5013
  // src/runtimes/external-store/ExternalStoreThreadRuntimeCore.tsx
4619
- var EMPTY_ARRAY2 = Object.freeze([]);
5014
+ var EMPTY_ARRAY3 = Object.freeze([]);
4620
5015
  var hasUpcomingMessage = (isRunning, messages2) => {
4621
5016
  return isRunning && messages2[messages2.length - 1]?.role !== "assistant";
4622
5017
  };
@@ -4649,26 +5044,23 @@ var ExternalStoreThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4649
5044
  _converter = new ThreadMessageConverter();
4650
5045
  _store;
4651
5046
  beginEdit(messageId) {
4652
- if (!this.store.onEdit)
5047
+ if (!this._store.onEdit)
4653
5048
  throw new Error("Runtime does not support editing.");
4654
5049
  super.beginEdit(messageId);
4655
5050
  }
4656
- constructor(configProvider, store) {
5051
+ constructor(configProvider, threadId, store) {
4657
5052
  super(configProvider);
4658
- this.store = store;
4659
- }
4660
- get store() {
4661
- return this._store;
5053
+ this.threadId = threadId;
5054
+ this.setStore(store);
4662
5055
  }
4663
- set store(store) {
5056
+ setStore(store) {
4664
5057
  if (this._store === store) return;
4665
- this.threadId = store.threadId ?? this.threadId ?? generateId();
4666
5058
  const isRunning = store.isRunning ?? false;
4667
5059
  this.isDisabled = store.isDisabled ?? false;
4668
5060
  const oldStore = this._store;
4669
5061
  this._store = store;
4670
5062
  this.extras = store.extras;
4671
- this.suggestions = store.suggestions ?? EMPTY_ARRAY2;
5063
+ this.suggestions = store.suggestions ?? EMPTY_ARRAY3;
4672
5064
  this._capabilities = {
4673
5065
  switchToBranch: this._store.setMessages !== void 0,
4674
5066
  edit: this._store.onEdit !== void 0,
@@ -4677,8 +5069,8 @@ var ExternalStoreThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4677
5069
  speech: this._store.adapters?.speech !== void 0,
4678
5070
  unstable_copy: this._store.unstable_capabilities?.copy !== false,
4679
5071
  // default true
4680
- attachments: !!this.store.adapters?.attachments,
4681
- feedback: !!this.store.adapters?.feedback
5072
+ attachments: !!this._store.adapters?.attachments,
5073
+ feedback: !!this._store.adapters?.feedback
4682
5074
  };
4683
5075
  if (oldStore) {
4684
5076
  if (oldStore.convertMessage !== store.convertMessage) {
@@ -4782,57 +5174,41 @@ var ExternalStoreThreadRuntimeCore = class extends BaseThreadRuntimeCore {
4782
5174
  };
4783
5175
 
4784
5176
  // src/runtimes/external-store/ExternalStoreRuntimeCore.tsx
5177
+ var getThreadManagerAdapter = (store) => {
5178
+ return {
5179
+ threadId: store.threadId,
5180
+ onSwitchToNewThread: store.onSwitchToNewThread,
5181
+ onSwitchToThread: store.onSwitchToThread,
5182
+ ...store.adapters?.threadManager
5183
+ };
5184
+ };
4785
5185
  var ExternalStoreRuntimeCore = class extends BaseAssistantRuntimeCore {
4786
- _proxyConfigProvider;
5186
+ threadManager;
5187
+ _store;
4787
5188
  constructor(store) {
4788
- const provider = new ProxyConfigProvider();
4789
- super(new ExternalStoreThreadRuntimeCore(provider, store));
4790
- this._proxyConfigProvider = provider;
4791
- }
4792
- getModelConfig() {
4793
- return this._proxyConfigProvider.getModelConfig();
4794
- }
4795
- registerModelConfigProvider(provider) {
4796
- return this._proxyConfigProvider.registerModelConfigProvider(provider);
4797
- }
4798
- async switchToNewThread() {
4799
- if (!this.thread.store.onSwitchToNewThread)
4800
- throw new Error("Runtime does not support switching to new threads.");
4801
- this.thread = new ExternalStoreThreadRuntimeCore(
4802
- this._proxyConfigProvider,
4803
- {
4804
- ...this.thread.store,
4805
- messages: []
4806
- }
4807
- );
4808
- await this.thread.store.onSwitchToNewThread();
4809
- this.thread._notifyEventSubscribers("switched-to");
4810
- }
4811
- async switchToThread(threadId) {
4812
- if (threadId !== null) {
4813
- if (!this.thread.store.onSwitchToThread)
4814
- throw new Error("Runtime does not support switching threads.");
4815
- this.thread = new ExternalStoreThreadRuntimeCore(
5189
+ super();
5190
+ this._store = store;
5191
+ this.threadManager = new ExternalStoreThreadManagerRuntimeCore(
5192
+ getThreadManagerAdapter(store),
5193
+ (threadId) => new ExternalStoreThreadRuntimeCore(
4816
5194
  this._proxyConfigProvider,
4817
- {
4818
- ...this.thread.store,
4819
- messages: []
4820
- // ignore messages until rerender
4821
- }
4822
- );
4823
- await this.thread.store.onSwitchToThread(threadId);
4824
- this.thread._notifyEventSubscribers("switched-to");
4825
- } else {
4826
- this.switchToNewThread();
4827
- }
5195
+ threadId,
5196
+ this._store
5197
+ )
5198
+ );
5199
+ }
5200
+ setStore(store) {
5201
+ this._store = store;
5202
+ this.threadManager.setAdapter(getThreadManagerAdapter(store));
5203
+ this.threadManager.mainThread.setStore(store);
4828
5204
  }
4829
5205
  };
4830
5206
 
4831
5207
  // src/runtimes/external-store/useExternalStoreRuntime.tsx
4832
5208
  var useExternalStoreRuntime = (store) => {
4833
- const [runtime] = useState12(() => new ExternalStoreRuntimeCore(store));
4834
- useEffect15(() => {
4835
- runtime.thread.store = store;
5209
+ const [runtime] = useState13(() => new ExternalStoreRuntimeCore(store));
5210
+ useEffect17(() => {
5211
+ runtime.setStore(store);
4836
5212
  });
4837
5213
  return useMemo12(
4838
5214
  () => AssistantRuntimeImpl.create(runtime, ThreadRuntimeImpl),
@@ -4987,7 +5363,7 @@ var shallowArrayEqual = (a, b) => {
4987
5363
  };
4988
5364
 
4989
5365
  // src/runtimes/dangerous-in-browser/useDangerousInBrowserRuntime.ts
4990
- import { useState as useState13 } from "react";
5366
+ import { useState as useState14 } from "react";
4991
5367
 
4992
5368
  // src/runtimes/dangerous-in-browser/DangerousInBrowserAdapter.ts
4993
5369
  var DangerousInBrowserAdapter = class {
@@ -5016,14 +5392,13 @@ var DangerousInBrowserAdapter = class {
5016
5392
  // src/runtimes/dangerous-in-browser/useDangerousInBrowserRuntime.ts
5017
5393
  var useDangerousInBrowserRuntime = (options) => {
5018
5394
  const { localRuntimeOptions, otherOptions } = splitLocalRuntimeOptions(options);
5019
- const [adapter] = useState13(() => new DangerousInBrowserAdapter(otherOptions));
5395
+ const [adapter] = useState14(() => new DangerousInBrowserAdapter(otherOptions));
5020
5396
  return useLocalRuntime(adapter, localRuntimeOptions);
5021
5397
  };
5022
5398
 
5023
5399
  // src/runtimes/speech/WebSpeechSynthesisAdapter.ts
5024
5400
  var WebSpeechSynthesisAdapter = class {
5025
- speak(message) {
5026
- const text = getThreadMessageText(message);
5401
+ speak(text) {
5027
5402
  const utterance = new SpeechSynthesisUtterance(text);
5028
5403
  const subscribers = /* @__PURE__ */ new Set();
5029
5404
  const handleEnd = (reason, error) => {
@@ -5603,8 +5978,8 @@ CircleStopIcon.displayName = "CircleStopIcon";
5603
5978
  // src/ui/attachment.tsx
5604
5979
  import {
5605
5980
  forwardRef as forwardRef28,
5606
- useEffect as useEffect16,
5607
- useState as useState14
5981
+ useEffect as useEffect18,
5982
+ useState as useState15
5608
5983
  } from "react";
5609
5984
  import { CircleXIcon, FileIcon } from "lucide-react";
5610
5985
 
@@ -5647,8 +6022,8 @@ var AttachmentRoot = withDefaults(attachment_exports.Root, {
5647
6022
  });
5648
6023
  AttachmentRoot.displayName = "AttachmentRoot";
5649
6024
  var useFileSrc = (file) => {
5650
- const [src, setSrc] = useState14(void 0);
5651
- useEffect16(() => {
6025
+ const [src, setSrc] = useState15(void 0);
6026
+ useEffect18(() => {
5652
6027
  if (!file) {
5653
6028
  setSrc(void 0);
5654
6029
  return;
@@ -5672,7 +6047,7 @@ var useAttachmentSrc = () => {
5672
6047
  return useFileSrc(file) ?? src;
5673
6048
  };
5674
6049
  var AttachmentPreview = ({ src }) => {
5675
- const [isLoaded, setIsLoaded] = useState14(false);
6050
+ const [isLoaded, setIsLoaded] = useState15(false);
5676
6051
  return (
5677
6052
  // eslint-disable-next-line @next/next/no-img-element
5678
6053
  /* @__PURE__ */ jsx46(
@@ -5918,8 +6293,13 @@ var ThreadWelcomeMessageStyled = withDefaults("p", {
5918
6293
  className: "aui-thread-welcome-message"
5919
6294
  });
5920
6295
  var ThreadWelcomeMessage = forwardRef30(({ message: messageProp, ...rest }, ref) => {
5921
- const { welcome: { message = "How can I help you today?" } = {} } = useThreadConfig();
5922
- return /* @__PURE__ */ jsx48(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message });
6296
+ const {
6297
+ welcome: { message } = {},
6298
+ strings: {
6299
+ welcome: { message: defaultMessage = "How can I help you today?" } = {}
6300
+ } = {}
6301
+ } = useThreadConfig();
6302
+ return /* @__PURE__ */ jsx48(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message ?? defaultMessage });
5923
6303
  });
5924
6304
  ThreadWelcomeMessage.displayName = "ThreadWelcomeMessage";
5925
6305
  var ThreadWelcomeSuggestionContainer = withDefaults("div", {
@@ -6371,8 +6751,10 @@ export {
6371
6751
  useThreadContext,
6372
6752
  useThreadEmpty,
6373
6753
  useThreadIf,
6754
+ useThreadManager,
6374
6755
  useThreadMessages,
6375
6756
  useThreadMessagesStore,
6757
+ useThreadModelConfig,
6376
6758
  useThreadRuntime,
6377
6759
  useThreadRuntimeStore,
6378
6760
  useThreadScrollToBottom,