@assistant-ui/react 0.5.1 → 0.5.3

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
@@ -1178,7 +1178,7 @@ var COMPLETE_STATUS = {
1178
1178
  };
1179
1179
  var toContentPartStatus = (message, partIndex, part) => {
1180
1180
  if (message.role !== "assistant") return COMPLETE_STATUS;
1181
- const isLastPart = partIndex === message.content.length - 1;
1181
+ const isLastPart = partIndex === Math.max(0, message.content.length - 1);
1182
1182
  if (part.type !== "tool-call") {
1183
1183
  if ("reason" in message.status && message.status.reason === "tool-calls" && isLastPart)
1184
1184
  throw new Error(
@@ -1191,9 +1191,16 @@ var toContentPartStatus = (message, partIndex, part) => {
1191
1191
  }
1192
1192
  return message.status;
1193
1193
  };
1194
+ var EMPTY_CONTENT = Object.freeze({ type: "text", text: "" });
1194
1195
  var syncContentPart = ({ message }, useContentPart, partIndex) => {
1195
- const part = message.content[partIndex];
1196
- if (!part) return;
1196
+ let part = message.content[partIndex];
1197
+ if (!part) {
1198
+ if (message.content.length === 0 && partIndex === 0) {
1199
+ part = EMPTY_CONTENT;
1200
+ } else {
1201
+ return;
1202
+ }
1203
+ }
1197
1204
  const status = toContentPartStatus(message, partIndex, part);
1198
1205
  const currentState = useContentPart.getState();
1199
1206
  if (currentState.part === part && currentState.status === status) return;
@@ -1319,7 +1326,7 @@ var ContentPartPrimitiveText = forwardRef7(({ smooth = true, ...rest }, forwarde
1319
1326
  part: { text }
1320
1327
  } = useContentPartText();
1321
1328
  const smoothText = useSmooth(text, smooth);
1322
- return /* @__PURE__ */ jsx14(Primitive4.span, { "data-status": status, ...rest, ref: forwardedRef, children: smoothText });
1329
+ return /* @__PURE__ */ jsx14(Primitive4.span, { "data-status": status.type, ...rest, ref: forwardedRef, children: smoothText });
1323
1330
  });
1324
1331
  ContentPartPrimitiveText.displayName = "ContentPartPrimitive.Text";
1325
1332
 
@@ -1425,7 +1432,7 @@ var MessagePrimitiveContent = ({
1425
1432
  components
1426
1433
  }) => {
1427
1434
  const { useMessage } = useMessageContext();
1428
- const contentLength = useMessage((s) => s.message.content.length);
1435
+ const contentLength = useMessage((s) => s.message.content.length) || 1;
1429
1436
  return new Array(contentLength).fill(null).map((_, idx) => {
1430
1437
  const partIndex = idx;
1431
1438
  return /* @__PURE__ */ jsx16(
@@ -1729,7 +1736,7 @@ var useThreadViewportAutoScroll = ({
1729
1736
  const div = divRef.current;
1730
1737
  if (!div) return;
1731
1738
  const isAtBottom = useViewport.getState().isAtBottom;
1732
- const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
1739
+ const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight + 1;
1733
1740
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
1734
1741
  } else {
1735
1742
  if (newIsAtBottom) {
@@ -1965,26 +1972,6 @@ var ThreadPrimitiveSuggestion = createActionButton(
1965
1972
  // src/runtimes/local/useLocalRuntime.tsx
1966
1973
  import { useInsertionEffect as useInsertionEffect3, useState as useState8 } from "react";
1967
1974
 
1968
- // src/utils/idUtils.tsx
1969
- import { customAlphabet } from "nanoid/non-secure";
1970
- var generateId = customAlphabet(
1971
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
1972
- 7
1973
- );
1974
- var optimisticPrefix = "__optimistic__";
1975
- var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
1976
-
1977
- // src/internal.ts
1978
- var internal_exports = {};
1979
- __export(internal_exports, {
1980
- BaseAssistantRuntime: () => BaseAssistantRuntime,
1981
- MessageRepository: () => MessageRepository,
1982
- ProxyConfigProvider: () => ProxyConfigProvider,
1983
- TooltipIconButton: () => TooltipIconButton,
1984
- generateId: () => generateId,
1985
- useSmooth: () => useSmooth
1986
- });
1987
-
1988
1975
  // src/runtimes/core/BaseAssistantRuntime.tsx
1989
1976
  var BaseAssistantRuntime = class {
1990
1977
  constructor(_thread) {
@@ -2008,101 +1995,25 @@ var BaseAssistantRuntime = class {
2008
1995
  };
2009
1996
  };
2010
1997
 
2011
- // src/ui/base/tooltip-icon-button.tsx
2012
- import { forwardRef as forwardRef17 } from "react";
2013
-
2014
- // src/ui/base/tooltip.tsx
2015
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
2016
-
2017
- // src/ui/utils/withDefaults.tsx
2018
- import {
2019
- forwardRef as forwardRef15
2020
- } from "react";
2021
- import classNames from "classnames";
2022
- import { jsx as jsx25 } from "react/jsx-runtime";
2023
- var withDefaultProps = ({
2024
- className,
2025
- ...defaultProps
2026
- }) => ({ className: classNameProp, ...props }) => {
2027
- return {
2028
- className: classNames(className, classNameProp),
2029
- ...defaultProps,
2030
- ...props
2031
- };
2032
- };
2033
- var withDefaults = (Component, defaultProps) => {
2034
- const getProps = withDefaultProps(defaultProps);
2035
- const WithDefaults = forwardRef15(
2036
- (props, ref) => {
2037
- const ComponentAsAny = Component;
2038
- return /* @__PURE__ */ jsx25(ComponentAsAny, { ...getProps(props), ref });
2039
- }
2040
- );
2041
- WithDefaults.displayName = "withDefaults(" + (typeof Component === "string" ? Component : Component.displayName) + ")";
2042
- return WithDefaults;
2043
- };
2044
-
2045
- // src/ui/base/tooltip.tsx
2046
- import { jsx as jsx26 } from "react/jsx-runtime";
2047
- var Tooltip = (props) => {
2048
- return /* @__PURE__ */ jsx26(TooltipPrimitive.Provider, { children: /* @__PURE__ */ jsx26(TooltipPrimitive.Root, { ...props }) });
2049
- };
2050
- Tooltip.displayName = "Tooltip";
2051
- var TooltipTrigger = TooltipPrimitive.Trigger;
2052
- var TooltipContent = withDefaults(TooltipPrimitive.Content, {
2053
- sideOffset: 4,
2054
- className: "aui-tooltip-content"
1998
+ // src/internal.ts
1999
+ var internal_exports = {};
2000
+ __export(internal_exports, {
2001
+ BaseAssistantRuntime: () => BaseAssistantRuntime,
2002
+ MessageRepository: () => MessageRepository,
2003
+ ProxyConfigProvider: () => ProxyConfigProvider,
2004
+ TooltipIconButton: () => TooltipIconButton,
2005
+ generateId: () => generateId,
2006
+ useSmooth: () => useSmooth
2055
2007
  });
2056
- TooltipContent.displayName = "TooltipContent";
2057
2008
 
2058
- // src/ui/base/button.tsx
2059
- import { cva } from "class-variance-authority";
2060
- import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
2061
- import { forwardRef as forwardRef16 } from "react";
2062
- import { jsx as jsx27 } from "react/jsx-runtime";
2063
- var buttonVariants = cva("aui-button", {
2064
- variants: {
2065
- variant: {
2066
- default: "aui-button-primary",
2067
- outline: "aui-button-outline",
2068
- ghost: "aui-button-ghost"
2069
- },
2070
- size: {
2071
- default: "aui-button-medium",
2072
- icon: "aui-button-icon"
2073
- }
2074
- },
2075
- defaultVariants: {
2076
- variant: "default",
2077
- size: "default"
2078
- }
2079
- });
2080
- var Button = forwardRef16(
2081
- ({ className, variant, size, ...props }, ref) => {
2082
- return /* @__PURE__ */ jsx27(
2083
- Primitive11.button,
2084
- {
2085
- className: buttonVariants({ variant, size, className }),
2086
- ...props,
2087
- ref
2088
- }
2089
- );
2090
- }
2009
+ // src/utils/idUtils.tsx
2010
+ import { customAlphabet } from "nanoid/non-secure";
2011
+ var generateId = customAlphabet(
2012
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
2013
+ 7
2091
2014
  );
2092
- Button.displayName = "Button";
2093
-
2094
- // src/ui/base/tooltip-icon-button.tsx
2095
- import { jsx as jsx28, jsxs as jsxs4 } from "react/jsx-runtime";
2096
- var TooltipIconButton = forwardRef17(({ children, tooltip, side = "bottom", ...rest }, ref) => {
2097
- return /* @__PURE__ */ jsxs4(Tooltip, { children: [
2098
- /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(Button, { variant: "ghost", size: "icon", ...rest, ref, children: [
2099
- children,
2100
- /* @__PURE__ */ jsx28("span", { className: "aui-sr-only", children: tooltip })
2101
- ] }) }),
2102
- /* @__PURE__ */ jsx28(TooltipContent, { side, children: tooltip })
2103
- ] });
2104
- });
2105
- TooltipIconButton.displayName = "TooltipIconButton";
2015
+ var optimisticPrefix = "__optimistic__";
2016
+ var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
2106
2017
 
2107
2018
  // src/runtimes/edge/converters/fromCoreMessage.ts
2108
2019
  var fromCoreMessages = (message) => {
@@ -2315,6 +2226,102 @@ var MessageRepository = class {
2315
2226
  }
2316
2227
  };
2317
2228
 
2229
+ // src/ui/base/tooltip-icon-button.tsx
2230
+ import { forwardRef as forwardRef17 } from "react";
2231
+
2232
+ // src/ui/base/tooltip.tsx
2233
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
2234
+
2235
+ // src/ui/utils/withDefaults.tsx
2236
+ import {
2237
+ forwardRef as forwardRef15
2238
+ } from "react";
2239
+ import classNames from "classnames";
2240
+ import { jsx as jsx25 } from "react/jsx-runtime";
2241
+ var withDefaultProps = ({
2242
+ className,
2243
+ ...defaultProps
2244
+ }) => ({ className: classNameProp, ...props }) => {
2245
+ return {
2246
+ className: classNames(className, classNameProp),
2247
+ ...defaultProps,
2248
+ ...props
2249
+ };
2250
+ };
2251
+ var withDefaults = (Component, defaultProps) => {
2252
+ const getProps = withDefaultProps(defaultProps);
2253
+ const WithDefaults = forwardRef15(
2254
+ (props, ref) => {
2255
+ const ComponentAsAny = Component;
2256
+ return /* @__PURE__ */ jsx25(ComponentAsAny, { ...getProps(props), ref });
2257
+ }
2258
+ );
2259
+ WithDefaults.displayName = "withDefaults(" + (typeof Component === "string" ? Component : Component.displayName) + ")";
2260
+ return WithDefaults;
2261
+ };
2262
+
2263
+ // src/ui/base/tooltip.tsx
2264
+ import { jsx as jsx26 } from "react/jsx-runtime";
2265
+ var Tooltip = (props) => {
2266
+ return /* @__PURE__ */ jsx26(TooltipPrimitive.Provider, { children: /* @__PURE__ */ jsx26(TooltipPrimitive.Root, { ...props }) });
2267
+ };
2268
+ Tooltip.displayName = "Tooltip";
2269
+ var TooltipTrigger = TooltipPrimitive.Trigger;
2270
+ var TooltipContent = withDefaults(TooltipPrimitive.Content, {
2271
+ sideOffset: 4,
2272
+ className: "aui-tooltip-content"
2273
+ });
2274
+ TooltipContent.displayName = "TooltipContent";
2275
+
2276
+ // src/ui/base/button.tsx
2277
+ import { cva } from "class-variance-authority";
2278
+ import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
2279
+ import { forwardRef as forwardRef16 } from "react";
2280
+ import { jsx as jsx27 } from "react/jsx-runtime";
2281
+ var buttonVariants = cva("aui-button", {
2282
+ variants: {
2283
+ variant: {
2284
+ default: "aui-button-primary",
2285
+ outline: "aui-button-outline",
2286
+ ghost: "aui-button-ghost"
2287
+ },
2288
+ size: {
2289
+ default: "aui-button-medium",
2290
+ icon: "aui-button-icon"
2291
+ }
2292
+ },
2293
+ defaultVariants: {
2294
+ variant: "default",
2295
+ size: "default"
2296
+ }
2297
+ });
2298
+ var Button = forwardRef16(
2299
+ ({ className, variant, size, ...props }, ref) => {
2300
+ return /* @__PURE__ */ jsx27(
2301
+ Primitive11.button,
2302
+ {
2303
+ className: buttonVariants({ variant, size, className }),
2304
+ ...props,
2305
+ ref
2306
+ }
2307
+ );
2308
+ }
2309
+ );
2310
+ Button.displayName = "Button";
2311
+
2312
+ // src/ui/base/tooltip-icon-button.tsx
2313
+ import { jsx as jsx28, jsxs as jsxs4 } from "react/jsx-runtime";
2314
+ var TooltipIconButton = forwardRef17(({ children, tooltip, side = "bottom", ...rest }, ref) => {
2315
+ return /* @__PURE__ */ jsxs4(Tooltip, { children: [
2316
+ /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(Button, { variant: "ghost", size: "icon", ...rest, ref, children: [
2317
+ children,
2318
+ /* @__PURE__ */ jsx28("span", { className: "aui-sr-only", children: tooltip })
2319
+ ] }) }),
2320
+ /* @__PURE__ */ jsx28(TooltipContent, { side, children: tooltip })
2321
+ ] });
2322
+ });
2323
+ TooltipIconButton.displayName = "TooltipIconButton";
2324
+
2318
2325
  // src/runtimes/edge/converters/toLanguageModelMessages.ts
2319
2326
  var assistantMessageSplitter = () => {
2320
2327
  const stash = [];
@@ -3323,9 +3330,7 @@ var EdgeChatAdapter = class {
3323
3330
  signal: abortSignal
3324
3331
  });
3325
3332
  if (result.status !== 200) {
3326
- throw new Error(
3327
- `Edge runtime returned status ${result.status}: ${await result.text()}`
3328
- );
3333
+ throw new Error(`Status ${result.status}: ${await result.text()}`);
3329
3334
  }
3330
3335
  const stream = result.body.pipeThrough(new TextDecoderStream()).pipeThrough(chunkByLineStream()).pipeThrough(assistantDecoderStream()).pipeThrough(toolResultStream(config.tools)).pipeThrough(runResultStream());
3331
3336
  let update;
@@ -3347,31 +3352,10 @@ var useEdgeRuntime = ({
3347
3352
  return useLocalRuntime(adapter, { initialMessages });
3348
3353
  };
3349
3354
 
3350
- // src/runtimes/local/LocalRuntime.tsx
3355
+ // src/runtimes/local/shouldContinue.tsx
3351
3356
  var shouldContinue = (result) => result.status?.type === "requires-action" && result.status.reason === "tool-calls" && result.content.every((c) => c.type !== "tool-call" || !!c.result);
3352
- var LocalRuntime = class extends BaseAssistantRuntime {
3353
- _proxyConfigProvider;
3354
- constructor(adapter, options) {
3355
- const proxyConfigProvider = new ProxyConfigProvider();
3356
- super(new LocalThreadRuntime(proxyConfigProvider, adapter, options));
3357
- this._proxyConfigProvider = proxyConfigProvider;
3358
- }
3359
- set adapter(adapter) {
3360
- this.thread.adapter = adapter;
3361
- }
3362
- registerModelConfigProvider(provider) {
3363
- return this._proxyConfigProvider.registerModelConfigProvider(provider);
3364
- }
3365
- switchToThread(threadId) {
3366
- if (threadId) {
3367
- throw new Error("LocalRuntime does not yet support switching threads");
3368
- }
3369
- return this.thread = new LocalThreadRuntime(
3370
- this._proxyConfigProvider,
3371
- this.thread.adapter
3372
- );
3373
- }
3374
- };
3357
+
3358
+ // src/runtimes/local/LocalThreadRuntime.tsx
3375
3359
  var CAPABILITIES = Object.freeze({
3376
3360
  edit: true,
3377
3361
  reload: true,
@@ -3431,7 +3415,7 @@ var LocalThreadRuntime = class {
3431
3415
  id,
3432
3416
  role: "assistant",
3433
3417
  status: { type: "running" },
3434
- content: [{ type: "text", text: "" }],
3418
+ content: [],
3435
3419
  createdAt: /* @__PURE__ */ new Date()
3436
3420
  };
3437
3421
  do {
@@ -3543,6 +3527,31 @@ var LocalThreadRuntime = class {
3543
3527
  }
3544
3528
  };
3545
3529
 
3530
+ // src/runtimes/local/LocalRuntime.tsx
3531
+ var LocalRuntime = class extends BaseAssistantRuntime {
3532
+ _proxyConfigProvider;
3533
+ constructor(adapter, options) {
3534
+ const proxyConfigProvider = new ProxyConfigProvider();
3535
+ super(new LocalThreadRuntime(proxyConfigProvider, adapter, options));
3536
+ this._proxyConfigProvider = proxyConfigProvider;
3537
+ }
3538
+ set adapter(adapter) {
3539
+ this.thread.adapter = adapter;
3540
+ }
3541
+ registerModelConfigProvider(provider) {
3542
+ return this._proxyConfigProvider.registerModelConfigProvider(provider);
3543
+ }
3544
+ switchToThread(threadId) {
3545
+ if (threadId) {
3546
+ throw new Error("LocalRuntime does not yet support switching threads");
3547
+ }
3548
+ return this.thread = new LocalThreadRuntime(
3549
+ this._proxyConfigProvider,
3550
+ this.thread.adapter
3551
+ );
3552
+ }
3553
+ };
3554
+
3546
3555
  // src/runtimes/local/useLocalRuntime.tsx
3547
3556
  var useLocalRuntime = (adapter, options) => {
3548
3557
  const [runtime] = useState8(() => new LocalRuntime(adapter, options));
@@ -3552,6 +3561,213 @@ var useLocalRuntime = (adapter, options) => {
3552
3561
  return runtime;
3553
3562
  };
3554
3563
 
3564
+ // src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
3565
+ import { create as create14 } from "zustand";
3566
+
3567
+ // src/runtimes/external-store/getExternalStoreMessage.tsx
3568
+ var symbolInnerMessage = Symbol("innerMessage");
3569
+ var getExternalStoreMessage = (message) => {
3570
+ return message[symbolInnerMessage];
3571
+ };
3572
+
3573
+ // src/runtimes/external-store/useExternalStoreSync.tsx
3574
+ import { useEffect as useEffect11, useMemo as useMemo3 } from "react";
3575
+
3576
+ // src/runtimes/external-store/ThreadMessageConverter.ts
3577
+ var ThreadMessageConverter = class {
3578
+ cache = /* @__PURE__ */ new WeakMap();
3579
+ convertMessages(messages, converter, keyMapper = (key) => key) {
3580
+ return messages.map((m, idx) => {
3581
+ const key = keyMapper(m);
3582
+ const cached = this.cache.get(key);
3583
+ const newMessage = converter(cached, m, idx);
3584
+ this.cache.set(key, newMessage);
3585
+ return newMessage;
3586
+ });
3587
+ }
3588
+ };
3589
+
3590
+ // src/runtimes/external-store/useExternalStoreSync.tsx
3591
+ var useExternalStoreSync = (adapter, updateData) => {
3592
+ const [converter, convertCallback] = useMemo3(() => {
3593
+ const converter2 = adapter.convertMessage ?? ((m) => m);
3594
+ const convertCallback2 = (cache, m, idx) => {
3595
+ if (cache) return cache;
3596
+ const newMessage = converter2(m, idx);
3597
+ newMessage[symbolInnerMessage] = m;
3598
+ return newMessage;
3599
+ };
3600
+ return [new ThreadMessageConverter(), convertCallback2];
3601
+ }, [adapter.convertMessage]);
3602
+ useEffect11(() => {
3603
+ updateData(
3604
+ adapter.isRunning ?? false,
3605
+ converter.convertMessages(adapter.messages, convertCallback)
3606
+ );
3607
+ }, [
3608
+ updateData,
3609
+ converter,
3610
+ convertCallback,
3611
+ adapter.messages,
3612
+ adapter.isRunning
3613
+ ]);
3614
+ };
3615
+
3616
+ // src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
3617
+ var hasUpcomingMessage = (isRunning, messages) => {
3618
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
3619
+ };
3620
+ var ExternalStoreThreadRuntime = class {
3621
+ constructor(store) {
3622
+ this.store = store;
3623
+ this.useStore = create14(() => ({
3624
+ store
3625
+ }));
3626
+ }
3627
+ _subscriptions = /* @__PURE__ */ new Set();
3628
+ repository = new MessageRepository();
3629
+ assistantOptimisticId = null;
3630
+ useStore;
3631
+ get capabilities() {
3632
+ return {
3633
+ edit: this.store.onEdit !== void 0,
3634
+ reload: this.store.onReload !== void 0,
3635
+ cancel: this.store.onCancel !== void 0,
3636
+ copy: true
3637
+ };
3638
+ }
3639
+ messages = [];
3640
+ isRunning = false;
3641
+ getBranches(messageId) {
3642
+ return this.repository.getBranches(messageId);
3643
+ }
3644
+ switchToBranch(branchId) {
3645
+ this.repository.switchToBranch(branchId);
3646
+ this.updateMessages(this.repository.getMessages());
3647
+ }
3648
+ async append(message) {
3649
+ if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
3650
+ if (!this.store.onEdit)
3651
+ throw new Error("Runtime does not support editing messages.");
3652
+ await this.store.onEdit(message);
3653
+ } else {
3654
+ await this.store.onNew(message);
3655
+ }
3656
+ }
3657
+ async startRun(parentId) {
3658
+ if (!this.store.onReload)
3659
+ throw new Error("Runtime does not support reloading messages.");
3660
+ await this.store.onReload(parentId);
3661
+ }
3662
+ cancelRun() {
3663
+ if (!this.store.onCancel)
3664
+ throw new Error("Runtime does not support cancelling runs.");
3665
+ this.store.onCancel();
3666
+ if (this.assistantOptimisticId) {
3667
+ this.repository.deleteMessage(this.assistantOptimisticId);
3668
+ this.assistantOptimisticId = null;
3669
+ }
3670
+ let messages = this.repository.getMessages();
3671
+ setTimeout(() => {
3672
+ this.updateMessages(messages);
3673
+ }, 0);
3674
+ }
3675
+ subscribe(callback) {
3676
+ this._subscriptions.add(callback);
3677
+ return () => this._subscriptions.delete(callback);
3678
+ }
3679
+ updateMessages = (messages) => {
3680
+ this.store.setMessages?.(
3681
+ messages.flatMap(getExternalStoreMessage).filter((m) => m != null)
3682
+ );
3683
+ };
3684
+ onStoreUpdated() {
3685
+ if (this.useStore.getState().store !== this.store) {
3686
+ this.useStore.setState({ store: this.store });
3687
+ }
3688
+ }
3689
+ updateData = (isRunning, vm) => {
3690
+ for (let i = 0; i < vm.length; i++) {
3691
+ const message = vm[i];
3692
+ const parent = vm[i - 1];
3693
+ this.repository.addOrUpdateMessage(parent?.id ?? null, message);
3694
+ }
3695
+ if (this.assistantOptimisticId) {
3696
+ this.repository.deleteMessage(this.assistantOptimisticId);
3697
+ this.assistantOptimisticId = null;
3698
+ }
3699
+ if (hasUpcomingMessage(isRunning, vm)) {
3700
+ this.assistantOptimisticId = this.repository.appendOptimisticMessage(
3701
+ vm.at(-1)?.id ?? null,
3702
+ {
3703
+ role: "assistant",
3704
+ content: []
3705
+ }
3706
+ );
3707
+ }
3708
+ this.repository.resetHead(
3709
+ this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
3710
+ );
3711
+ this.messages = this.repository.getMessages();
3712
+ this.isRunning = isRunning;
3713
+ for (const callback of this._subscriptions) callback();
3714
+ };
3715
+ unstable_synchronizer = () => {
3716
+ const { store } = this.useStore();
3717
+ useExternalStoreSync(store, this.updateData);
3718
+ return null;
3719
+ };
3720
+ addToolResult(options) {
3721
+ if (!this.store.onAddToolResult)
3722
+ throw new Error("Runtime does not support tool results.");
3723
+ this.store.onAddToolResult(options);
3724
+ }
3725
+ };
3726
+
3727
+ // src/runtimes/external-store/ExternalStoreRuntime.tsx
3728
+ var ExternalStoreRuntime = class extends BaseAssistantRuntime {
3729
+ _proxyConfigProvider = new ProxyConfigProvider();
3730
+ constructor(store) {
3731
+ super(new ExternalStoreThreadRuntime(store));
3732
+ }
3733
+ set store(store) {
3734
+ this.thread.store = store;
3735
+ }
3736
+ onStoreUpdated() {
3737
+ return this.thread.onStoreUpdated();
3738
+ }
3739
+ getModelConfig() {
3740
+ return this._proxyConfigProvider.getModelConfig();
3741
+ }
3742
+ registerModelConfigProvider(provider) {
3743
+ return this._proxyConfigProvider.registerModelConfigProvider(provider);
3744
+ }
3745
+ switchToThread(threadId) {
3746
+ if (threadId) {
3747
+ if (!this.store.onSwitchThread)
3748
+ throw new Error("Runtime does not support switching threads.");
3749
+ return this.store.onSwitchThread(threadId);
3750
+ } else {
3751
+ if (!this.store.onNewThread)
3752
+ throw new Error("Runtime does not support switching to new threads.");
3753
+ return this.store.onNewThread();
3754
+ }
3755
+ }
3756
+ };
3757
+
3758
+ // src/runtimes/external-store/useExternalStoreRuntime.tsx
3759
+ import { useEffect as useEffect12, useInsertionEffect as useInsertionEffect4, useState as useState9 } from "react";
3760
+ var useExternalStoreRuntime = (store) => {
3761
+ const [runtime] = useState9(() => new ExternalStoreRuntime(store));
3762
+ useInsertionEffect4(() => {
3763
+ runtime.store = store;
3764
+ });
3765
+ useEffect12(() => {
3766
+ runtime.onStoreUpdated();
3767
+ });
3768
+ return runtime;
3769
+ };
3770
+
3555
3771
  // src/ui/thread-config.tsx
3556
3772
  import { createContext as createContext5, useContext as useContext5 } from "react";
3557
3773
  import { Fragment as Fragment3, jsx as jsx29 } from "react/jsx-runtime";
@@ -4252,6 +4468,7 @@ export {
4252
4468
  contentPart_exports as ContentPartPrimitive,
4253
4469
  EdgeChatAdapter,
4254
4470
  edit_composer_default as EditComposer,
4471
+ ExternalStoreRuntime,
4255
4472
  internal_exports as INTERNAL,
4256
4473
  message_exports as MessagePrimitive,
4257
4474
  thread_default as Thread,
@@ -4264,6 +4481,7 @@ export {
4264
4481
  fromCoreMessages,
4265
4482
  fromLanguageModelMessages,
4266
4483
  fromLanguageModelTools,
4484
+ getExternalStoreMessage,
4267
4485
  makeAssistantTool,
4268
4486
  makeAssistantToolUI,
4269
4487
  toCoreMessage,
@@ -4291,6 +4509,7 @@ export {
4291
4509
  useContentPartImage,
4292
4510
  useContentPartText,
4293
4511
  useEdgeRuntime,
4512
+ useExternalStoreRuntime,
4294
4513
  useLocalRuntime,
4295
4514
  useMessageContext,
4296
4515
  useMessageIf,