@assistant-ui/react 0.5.81 → 0.5.83

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