@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.js CHANGED
@@ -45,6 +45,7 @@ __export(src_exports, {
45
45
  ContentPartPrimitive: () => contentPart_exports,
46
46
  EdgeChatAdapter: () => EdgeChatAdapter,
47
47
  EditComposer: () => edit_composer_default,
48
+ ExternalStoreRuntime: () => ExternalStoreRuntime,
48
49
  INTERNAL: () => internal_exports,
49
50
  MessagePrimitive: () => message_exports,
50
51
  Thread: () => thread_default,
@@ -57,6 +58,7 @@ __export(src_exports, {
57
58
  fromCoreMessages: () => fromCoreMessages,
58
59
  fromLanguageModelMessages: () => fromLanguageModelMessages,
59
60
  fromLanguageModelTools: () => fromLanguageModelTools,
61
+ getExternalStoreMessage: () => getExternalStoreMessage,
60
62
  makeAssistantTool: () => makeAssistantTool,
61
63
  makeAssistantToolUI: () => makeAssistantToolUI,
62
64
  toCoreMessage: () => toCoreMessage,
@@ -84,6 +86,7 @@ __export(src_exports, {
84
86
  useContentPartImage: () => useContentPartImage,
85
87
  useContentPartText: () => useContentPartText,
86
88
  useEdgeRuntime: () => useEdgeRuntime,
89
+ useExternalStoreRuntime: () => useExternalStoreRuntime,
87
90
  useLocalRuntime: () => useLocalRuntime,
88
91
  useMessageContext: () => useMessageContext,
89
92
  useMessageIf: () => useMessageIf,
@@ -1267,7 +1270,7 @@ var COMPLETE_STATUS = {
1267
1270
  };
1268
1271
  var toContentPartStatus = (message, partIndex, part) => {
1269
1272
  if (message.role !== "assistant") return COMPLETE_STATUS;
1270
- const isLastPart = partIndex === message.content.length - 1;
1273
+ const isLastPart = partIndex === Math.max(0, message.content.length - 1);
1271
1274
  if (part.type !== "tool-call") {
1272
1275
  if ("reason" in message.status && message.status.reason === "tool-calls" && isLastPart)
1273
1276
  throw new Error(
@@ -1280,9 +1283,16 @@ var toContentPartStatus = (message, partIndex, part) => {
1280
1283
  }
1281
1284
  return message.status;
1282
1285
  };
1286
+ var EMPTY_CONTENT = Object.freeze({ type: "text", text: "" });
1283
1287
  var syncContentPart = ({ message }, useContentPart, partIndex) => {
1284
- const part = message.content[partIndex];
1285
- if (!part) return;
1288
+ let part = message.content[partIndex];
1289
+ if (!part) {
1290
+ if (message.content.length === 0 && partIndex === 0) {
1291
+ part = EMPTY_CONTENT;
1292
+ } else {
1293
+ return;
1294
+ }
1295
+ }
1286
1296
  const status = toContentPartStatus(message, partIndex, part);
1287
1297
  const currentState = useContentPart.getState();
1288
1298
  if (currentState.part === part && currentState.status === status) return;
@@ -1408,7 +1418,7 @@ var ContentPartPrimitiveText = (0, import_react36.forwardRef)(({ smooth = true,
1408
1418
  part: { text }
1409
1419
  } = useContentPartText();
1410
1420
  const smoothText = useSmooth(text, smooth);
1411
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_primitive4.Primitive.span, { "data-status": status, ...rest, ref: forwardedRef, children: smoothText });
1421
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_react_primitive4.Primitive.span, { "data-status": status.type, ...rest, ref: forwardedRef, children: smoothText });
1412
1422
  });
1413
1423
  ContentPartPrimitiveText.displayName = "ContentPartPrimitive.Text";
1414
1424
 
@@ -1514,7 +1524,7 @@ var MessagePrimitiveContent = ({
1514
1524
  components
1515
1525
  }) => {
1516
1526
  const { useMessage } = useMessageContext();
1517
- const contentLength = useMessage((s) => s.message.content.length);
1527
+ const contentLength = useMessage((s) => s.message.content.length) || 1;
1518
1528
  return new Array(contentLength).fill(null).map((_, idx) => {
1519
1529
  const partIndex = idx;
1520
1530
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -1811,7 +1821,7 @@ var useThreadViewportAutoScroll = ({
1811
1821
  const div = divRef.current;
1812
1822
  if (!div) return;
1813
1823
  const isAtBottom = useViewport.getState().isAtBottom;
1814
- const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
1824
+ const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight + 1;
1815
1825
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
1816
1826
  } else {
1817
1827
  if (newIsAtBottom) {
@@ -2047,26 +2057,6 @@ var ThreadPrimitiveSuggestion = createActionButton(
2047
2057
  // src/runtimes/local/useLocalRuntime.tsx
2048
2058
  var import_react54 = require("react");
2049
2059
 
2050
- // src/utils/idUtils.tsx
2051
- var import_non_secure = require("nanoid/non-secure");
2052
- var generateId = (0, import_non_secure.customAlphabet)(
2053
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
2054
- 7
2055
- );
2056
- var optimisticPrefix = "__optimistic__";
2057
- var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
2058
-
2059
- // src/internal.ts
2060
- var internal_exports = {};
2061
- __export(internal_exports, {
2062
- BaseAssistantRuntime: () => BaseAssistantRuntime,
2063
- MessageRepository: () => MessageRepository,
2064
- ProxyConfigProvider: () => ProxyConfigProvider,
2065
- TooltipIconButton: () => TooltipIconButton,
2066
- generateId: () => generateId,
2067
- useSmooth: () => useSmooth
2068
- });
2069
-
2070
2060
  // src/runtimes/core/BaseAssistantRuntime.tsx
2071
2061
  var BaseAssistantRuntime = class {
2072
2062
  constructor(_thread) {
@@ -2090,99 +2080,25 @@ var BaseAssistantRuntime = class {
2090
2080
  };
2091
2081
  };
2092
2082
 
2093
- // src/ui/base/tooltip-icon-button.tsx
2094
- var import_react52 = require("react");
2095
-
2096
- // src/ui/base/tooltip.tsx
2097
- var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"));
2098
-
2099
- // src/ui/utils/withDefaults.tsx
2100
- var import_react50 = require("react");
2101
- var import_classnames = __toESM(require("classnames"));
2102
- var import_jsx_runtime25 = require("react/jsx-runtime");
2103
- var withDefaultProps = ({
2104
- className,
2105
- ...defaultProps
2106
- }) => ({ className: classNameProp, ...props }) => {
2107
- return {
2108
- className: (0, import_classnames.default)(className, classNameProp),
2109
- ...defaultProps,
2110
- ...props
2111
- };
2112
- };
2113
- var withDefaults = (Component, defaultProps) => {
2114
- const getProps = withDefaultProps(defaultProps);
2115
- const WithDefaults = (0, import_react50.forwardRef)(
2116
- (props, ref) => {
2117
- const ComponentAsAny = Component;
2118
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComponentAsAny, { ...getProps(props), ref });
2119
- }
2120
- );
2121
- WithDefaults.displayName = "withDefaults(" + (typeof Component === "string" ? Component : Component.displayName) + ")";
2122
- return WithDefaults;
2123
- };
2124
-
2125
- // src/ui/base/tooltip.tsx
2126
- var import_jsx_runtime26 = require("react/jsx-runtime");
2127
- var Tooltip = (props) => {
2128
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipPrimitive.Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipPrimitive.Root, { ...props }) });
2129
- };
2130
- Tooltip.displayName = "Tooltip";
2131
- var TooltipTrigger = TooltipPrimitive.Trigger;
2132
- var TooltipContent = withDefaults(TooltipPrimitive.Content, {
2133
- sideOffset: 4,
2134
- className: "aui-tooltip-content"
2083
+ // src/internal.ts
2084
+ var internal_exports = {};
2085
+ __export(internal_exports, {
2086
+ BaseAssistantRuntime: () => BaseAssistantRuntime,
2087
+ MessageRepository: () => MessageRepository,
2088
+ ProxyConfigProvider: () => ProxyConfigProvider,
2089
+ TooltipIconButton: () => TooltipIconButton,
2090
+ generateId: () => generateId,
2091
+ useSmooth: () => useSmooth
2135
2092
  });
2136
- TooltipContent.displayName = "TooltipContent";
2137
2093
 
2138
- // src/ui/base/button.tsx
2139
- var import_class_variance_authority = require("class-variance-authority");
2140
- var import_react_primitive11 = require("@radix-ui/react-primitive");
2141
- var import_react51 = require("react");
2142
- var import_jsx_runtime27 = require("react/jsx-runtime");
2143
- var buttonVariants = (0, import_class_variance_authority.cva)("aui-button", {
2144
- variants: {
2145
- variant: {
2146
- default: "aui-button-primary",
2147
- outline: "aui-button-outline",
2148
- ghost: "aui-button-ghost"
2149
- },
2150
- size: {
2151
- default: "aui-button-medium",
2152
- icon: "aui-button-icon"
2153
- }
2154
- },
2155
- defaultVariants: {
2156
- variant: "default",
2157
- size: "default"
2158
- }
2159
- });
2160
- var Button = (0, import_react51.forwardRef)(
2161
- ({ className, variant, size, ...props }, ref) => {
2162
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2163
- import_react_primitive11.Primitive.button,
2164
- {
2165
- className: buttonVariants({ variant, size, className }),
2166
- ...props,
2167
- ref
2168
- }
2169
- );
2170
- }
2094
+ // src/utils/idUtils.tsx
2095
+ var import_non_secure = require("nanoid/non-secure");
2096
+ var generateId = (0, import_non_secure.customAlphabet)(
2097
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
2098
+ 7
2171
2099
  );
2172
- Button.displayName = "Button";
2173
-
2174
- // src/ui/base/tooltip-icon-button.tsx
2175
- var import_jsx_runtime28 = require("react/jsx-runtime");
2176
- var TooltipIconButton = (0, import_react52.forwardRef)(({ children, tooltip, side = "bottom", ...rest }, ref) => {
2177
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Tooltip, { children: [
2178
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Button, { variant: "ghost", size: "icon", ...rest, ref, children: [
2179
- children,
2180
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "aui-sr-only", children: tooltip })
2181
- ] }) }),
2182
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipContent, { side, children: tooltip })
2183
- ] });
2184
- });
2185
- TooltipIconButton.displayName = "TooltipIconButton";
2100
+ var optimisticPrefix = "__optimistic__";
2101
+ var generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
2186
2102
 
2187
2103
  // src/runtimes/edge/converters/fromCoreMessage.ts
2188
2104
  var fromCoreMessages = (message) => {
@@ -2395,6 +2311,100 @@ var MessageRepository = class {
2395
2311
  }
2396
2312
  };
2397
2313
 
2314
+ // src/ui/base/tooltip-icon-button.tsx
2315
+ var import_react52 = require("react");
2316
+
2317
+ // src/ui/base/tooltip.tsx
2318
+ var TooltipPrimitive = __toESM(require("@radix-ui/react-tooltip"));
2319
+
2320
+ // src/ui/utils/withDefaults.tsx
2321
+ var import_react50 = require("react");
2322
+ var import_classnames = __toESM(require("classnames"));
2323
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2324
+ var withDefaultProps = ({
2325
+ className,
2326
+ ...defaultProps
2327
+ }) => ({ className: classNameProp, ...props }) => {
2328
+ return {
2329
+ className: (0, import_classnames.default)(className, classNameProp),
2330
+ ...defaultProps,
2331
+ ...props
2332
+ };
2333
+ };
2334
+ var withDefaults = (Component, defaultProps) => {
2335
+ const getProps = withDefaultProps(defaultProps);
2336
+ const WithDefaults = (0, import_react50.forwardRef)(
2337
+ (props, ref) => {
2338
+ const ComponentAsAny = Component;
2339
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ComponentAsAny, { ...getProps(props), ref });
2340
+ }
2341
+ );
2342
+ WithDefaults.displayName = "withDefaults(" + (typeof Component === "string" ? Component : Component.displayName) + ")";
2343
+ return WithDefaults;
2344
+ };
2345
+
2346
+ // src/ui/base/tooltip.tsx
2347
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2348
+ var Tooltip = (props) => {
2349
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipPrimitive.Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipPrimitive.Root, { ...props }) });
2350
+ };
2351
+ Tooltip.displayName = "Tooltip";
2352
+ var TooltipTrigger = TooltipPrimitive.Trigger;
2353
+ var TooltipContent = withDefaults(TooltipPrimitive.Content, {
2354
+ sideOffset: 4,
2355
+ className: "aui-tooltip-content"
2356
+ });
2357
+ TooltipContent.displayName = "TooltipContent";
2358
+
2359
+ // src/ui/base/button.tsx
2360
+ var import_class_variance_authority = require("class-variance-authority");
2361
+ var import_react_primitive11 = require("@radix-ui/react-primitive");
2362
+ var import_react51 = require("react");
2363
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2364
+ var buttonVariants = (0, import_class_variance_authority.cva)("aui-button", {
2365
+ variants: {
2366
+ variant: {
2367
+ default: "aui-button-primary",
2368
+ outline: "aui-button-outline",
2369
+ ghost: "aui-button-ghost"
2370
+ },
2371
+ size: {
2372
+ default: "aui-button-medium",
2373
+ icon: "aui-button-icon"
2374
+ }
2375
+ },
2376
+ defaultVariants: {
2377
+ variant: "default",
2378
+ size: "default"
2379
+ }
2380
+ });
2381
+ var Button = (0, import_react51.forwardRef)(
2382
+ ({ className, variant, size, ...props }, ref) => {
2383
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2384
+ import_react_primitive11.Primitive.button,
2385
+ {
2386
+ className: buttonVariants({ variant, size, className }),
2387
+ ...props,
2388
+ ref
2389
+ }
2390
+ );
2391
+ }
2392
+ );
2393
+ Button.displayName = "Button";
2394
+
2395
+ // src/ui/base/tooltip-icon-button.tsx
2396
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2397
+ var TooltipIconButton = (0, import_react52.forwardRef)(({ children, tooltip, side = "bottom", ...rest }, ref) => {
2398
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Tooltip, { children: [
2399
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Button, { variant: "ghost", size: "icon", ...rest, ref, children: [
2400
+ children,
2401
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "aui-sr-only", children: tooltip })
2402
+ ] }) }),
2403
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipContent, { side, children: tooltip })
2404
+ ] });
2405
+ });
2406
+ TooltipIconButton.displayName = "TooltipIconButton";
2407
+
2398
2408
  // src/runtimes/edge/converters/toLanguageModelMessages.ts
2399
2409
  var assistantMessageSplitter = () => {
2400
2410
  const stash = [];
@@ -3403,9 +3413,7 @@ var EdgeChatAdapter = class {
3403
3413
  signal: abortSignal
3404
3414
  });
3405
3415
  if (result.status !== 200) {
3406
- throw new Error(
3407
- `Edge runtime returned status ${result.status}: ${await result.text()}`
3408
- );
3416
+ throw new Error(`Status ${result.status}: ${await result.text()}`);
3409
3417
  }
3410
3418
  const stream = result.body.pipeThrough(new TextDecoderStream()).pipeThrough(chunkByLineStream()).pipeThrough(assistantDecoderStream()).pipeThrough(toolResultStream(config.tools)).pipeThrough(runResultStream());
3411
3419
  let update;
@@ -3427,31 +3435,10 @@ var useEdgeRuntime = ({
3427
3435
  return useLocalRuntime(adapter, { initialMessages });
3428
3436
  };
3429
3437
 
3430
- // src/runtimes/local/LocalRuntime.tsx
3438
+ // src/runtimes/local/shouldContinue.tsx
3431
3439
  var shouldContinue = (result) => result.status?.type === "requires-action" && result.status.reason === "tool-calls" && result.content.every((c) => c.type !== "tool-call" || !!c.result);
3432
- var LocalRuntime = class extends BaseAssistantRuntime {
3433
- _proxyConfigProvider;
3434
- constructor(adapter, options) {
3435
- const proxyConfigProvider = new ProxyConfigProvider();
3436
- super(new LocalThreadRuntime(proxyConfigProvider, adapter, options));
3437
- this._proxyConfigProvider = proxyConfigProvider;
3438
- }
3439
- set adapter(adapter) {
3440
- this.thread.adapter = adapter;
3441
- }
3442
- registerModelConfigProvider(provider) {
3443
- return this._proxyConfigProvider.registerModelConfigProvider(provider);
3444
- }
3445
- switchToThread(threadId) {
3446
- if (threadId) {
3447
- throw new Error("LocalRuntime does not yet support switching threads");
3448
- }
3449
- return this.thread = new LocalThreadRuntime(
3450
- this._proxyConfigProvider,
3451
- this.thread.adapter
3452
- );
3453
- }
3454
- };
3440
+
3441
+ // src/runtimes/local/LocalThreadRuntime.tsx
3455
3442
  var CAPABILITIES = Object.freeze({
3456
3443
  edit: true,
3457
3444
  reload: true,
@@ -3511,7 +3498,7 @@ var LocalThreadRuntime = class {
3511
3498
  id,
3512
3499
  role: "assistant",
3513
3500
  status: { type: "running" },
3514
- content: [{ type: "text", text: "" }],
3501
+ content: [],
3515
3502
  createdAt: /* @__PURE__ */ new Date()
3516
3503
  };
3517
3504
  do {
@@ -3623,6 +3610,31 @@ var LocalThreadRuntime = class {
3623
3610
  }
3624
3611
  };
3625
3612
 
3613
+ // src/runtimes/local/LocalRuntime.tsx
3614
+ var LocalRuntime = class extends BaseAssistantRuntime {
3615
+ _proxyConfigProvider;
3616
+ constructor(adapter, options) {
3617
+ const proxyConfigProvider = new ProxyConfigProvider();
3618
+ super(new LocalThreadRuntime(proxyConfigProvider, adapter, options));
3619
+ this._proxyConfigProvider = proxyConfigProvider;
3620
+ }
3621
+ set adapter(adapter) {
3622
+ this.thread.adapter = adapter;
3623
+ }
3624
+ registerModelConfigProvider(provider) {
3625
+ return this._proxyConfigProvider.registerModelConfigProvider(provider);
3626
+ }
3627
+ switchToThread(threadId) {
3628
+ if (threadId) {
3629
+ throw new Error("LocalRuntime does not yet support switching threads");
3630
+ }
3631
+ return this.thread = new LocalThreadRuntime(
3632
+ this._proxyConfigProvider,
3633
+ this.thread.adapter
3634
+ );
3635
+ }
3636
+ };
3637
+
3626
3638
  // src/runtimes/local/useLocalRuntime.tsx
3627
3639
  var useLocalRuntime = (adapter, options) => {
3628
3640
  const [runtime] = (0, import_react54.useState)(() => new LocalRuntime(adapter, options));
@@ -3632,12 +3644,219 @@ var useLocalRuntime = (adapter, options) => {
3632
3644
  return runtime;
3633
3645
  };
3634
3646
 
3635
- // src/ui/thread-config.tsx
3647
+ // src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
3648
+ var import_zustand14 = require("zustand");
3649
+
3650
+ // src/runtimes/external-store/getExternalStoreMessage.tsx
3651
+ var symbolInnerMessage = Symbol("innerMessage");
3652
+ var getExternalStoreMessage = (message) => {
3653
+ return message[symbolInnerMessage];
3654
+ };
3655
+
3656
+ // src/runtimes/external-store/useExternalStoreSync.tsx
3636
3657
  var import_react55 = require("react");
3658
+
3659
+ // src/runtimes/external-store/ThreadMessageConverter.ts
3660
+ var ThreadMessageConverter = class {
3661
+ cache = /* @__PURE__ */ new WeakMap();
3662
+ convertMessages(messages, converter, keyMapper = (key) => key) {
3663
+ return messages.map((m, idx) => {
3664
+ const key = keyMapper(m);
3665
+ const cached = this.cache.get(key);
3666
+ const newMessage = converter(cached, m, idx);
3667
+ this.cache.set(key, newMessage);
3668
+ return newMessage;
3669
+ });
3670
+ }
3671
+ };
3672
+
3673
+ // src/runtimes/external-store/useExternalStoreSync.tsx
3674
+ var useExternalStoreSync = (adapter, updateData) => {
3675
+ const [converter, convertCallback] = (0, import_react55.useMemo)(() => {
3676
+ const converter2 = adapter.convertMessage ?? ((m) => m);
3677
+ const convertCallback2 = (cache, m, idx) => {
3678
+ if (cache) return cache;
3679
+ const newMessage = converter2(m, idx);
3680
+ newMessage[symbolInnerMessage] = m;
3681
+ return newMessage;
3682
+ };
3683
+ return [new ThreadMessageConverter(), convertCallback2];
3684
+ }, [adapter.convertMessage]);
3685
+ (0, import_react55.useEffect)(() => {
3686
+ updateData(
3687
+ adapter.isRunning ?? false,
3688
+ converter.convertMessages(adapter.messages, convertCallback)
3689
+ );
3690
+ }, [
3691
+ updateData,
3692
+ converter,
3693
+ convertCallback,
3694
+ adapter.messages,
3695
+ adapter.isRunning
3696
+ ]);
3697
+ };
3698
+
3699
+ // src/runtimes/external-store/ExternalStoreThreadRuntime.tsx
3700
+ var hasUpcomingMessage = (isRunning, messages) => {
3701
+ return isRunning && messages[messages.length - 1]?.role !== "assistant";
3702
+ };
3703
+ var ExternalStoreThreadRuntime = class {
3704
+ constructor(store) {
3705
+ this.store = store;
3706
+ this.useStore = (0, import_zustand14.create)(() => ({
3707
+ store
3708
+ }));
3709
+ }
3710
+ _subscriptions = /* @__PURE__ */ new Set();
3711
+ repository = new MessageRepository();
3712
+ assistantOptimisticId = null;
3713
+ useStore;
3714
+ get capabilities() {
3715
+ return {
3716
+ edit: this.store.onEdit !== void 0,
3717
+ reload: this.store.onReload !== void 0,
3718
+ cancel: this.store.onCancel !== void 0,
3719
+ copy: true
3720
+ };
3721
+ }
3722
+ messages = [];
3723
+ isRunning = false;
3724
+ getBranches(messageId) {
3725
+ return this.repository.getBranches(messageId);
3726
+ }
3727
+ switchToBranch(branchId) {
3728
+ this.repository.switchToBranch(branchId);
3729
+ this.updateMessages(this.repository.getMessages());
3730
+ }
3731
+ async append(message) {
3732
+ if (message.parentId !== (this.messages.at(-1)?.id ?? null)) {
3733
+ if (!this.store.onEdit)
3734
+ throw new Error("Runtime does not support editing messages.");
3735
+ await this.store.onEdit(message);
3736
+ } else {
3737
+ await this.store.onNew(message);
3738
+ }
3739
+ }
3740
+ async startRun(parentId) {
3741
+ if (!this.store.onReload)
3742
+ throw new Error("Runtime does not support reloading messages.");
3743
+ await this.store.onReload(parentId);
3744
+ }
3745
+ cancelRun() {
3746
+ if (!this.store.onCancel)
3747
+ throw new Error("Runtime does not support cancelling runs.");
3748
+ this.store.onCancel();
3749
+ if (this.assistantOptimisticId) {
3750
+ this.repository.deleteMessage(this.assistantOptimisticId);
3751
+ this.assistantOptimisticId = null;
3752
+ }
3753
+ let messages = this.repository.getMessages();
3754
+ setTimeout(() => {
3755
+ this.updateMessages(messages);
3756
+ }, 0);
3757
+ }
3758
+ subscribe(callback) {
3759
+ this._subscriptions.add(callback);
3760
+ return () => this._subscriptions.delete(callback);
3761
+ }
3762
+ updateMessages = (messages) => {
3763
+ this.store.setMessages?.(
3764
+ messages.flatMap(getExternalStoreMessage).filter((m) => m != null)
3765
+ );
3766
+ };
3767
+ onStoreUpdated() {
3768
+ if (this.useStore.getState().store !== this.store) {
3769
+ this.useStore.setState({ store: this.store });
3770
+ }
3771
+ }
3772
+ updateData = (isRunning, vm) => {
3773
+ for (let i = 0; i < vm.length; i++) {
3774
+ const message = vm[i];
3775
+ const parent = vm[i - 1];
3776
+ this.repository.addOrUpdateMessage(parent?.id ?? null, message);
3777
+ }
3778
+ if (this.assistantOptimisticId) {
3779
+ this.repository.deleteMessage(this.assistantOptimisticId);
3780
+ this.assistantOptimisticId = null;
3781
+ }
3782
+ if (hasUpcomingMessage(isRunning, vm)) {
3783
+ this.assistantOptimisticId = this.repository.appendOptimisticMessage(
3784
+ vm.at(-1)?.id ?? null,
3785
+ {
3786
+ role: "assistant",
3787
+ content: []
3788
+ }
3789
+ );
3790
+ }
3791
+ this.repository.resetHead(
3792
+ this.assistantOptimisticId ?? vm.at(-1)?.id ?? null
3793
+ );
3794
+ this.messages = this.repository.getMessages();
3795
+ this.isRunning = isRunning;
3796
+ for (const callback of this._subscriptions) callback();
3797
+ };
3798
+ unstable_synchronizer = () => {
3799
+ const { store } = this.useStore();
3800
+ useExternalStoreSync(store, this.updateData);
3801
+ return null;
3802
+ };
3803
+ addToolResult(options) {
3804
+ if (!this.store.onAddToolResult)
3805
+ throw new Error("Runtime does not support tool results.");
3806
+ this.store.onAddToolResult(options);
3807
+ }
3808
+ };
3809
+
3810
+ // src/runtimes/external-store/ExternalStoreRuntime.tsx
3811
+ var ExternalStoreRuntime = class extends BaseAssistantRuntime {
3812
+ _proxyConfigProvider = new ProxyConfigProvider();
3813
+ constructor(store) {
3814
+ super(new ExternalStoreThreadRuntime(store));
3815
+ }
3816
+ set store(store) {
3817
+ this.thread.store = store;
3818
+ }
3819
+ onStoreUpdated() {
3820
+ return this.thread.onStoreUpdated();
3821
+ }
3822
+ getModelConfig() {
3823
+ return this._proxyConfigProvider.getModelConfig();
3824
+ }
3825
+ registerModelConfigProvider(provider) {
3826
+ return this._proxyConfigProvider.registerModelConfigProvider(provider);
3827
+ }
3828
+ switchToThread(threadId) {
3829
+ if (threadId) {
3830
+ if (!this.store.onSwitchThread)
3831
+ throw new Error("Runtime does not support switching threads.");
3832
+ return this.store.onSwitchThread(threadId);
3833
+ } else {
3834
+ if (!this.store.onNewThread)
3835
+ throw new Error("Runtime does not support switching to new threads.");
3836
+ return this.store.onNewThread();
3837
+ }
3838
+ }
3839
+ };
3840
+
3841
+ // src/runtimes/external-store/useExternalStoreRuntime.tsx
3842
+ var import_react56 = require("react");
3843
+ var useExternalStoreRuntime = (store) => {
3844
+ const [runtime] = (0, import_react56.useState)(() => new ExternalStoreRuntime(store));
3845
+ (0, import_react56.useInsertionEffect)(() => {
3846
+ runtime.store = store;
3847
+ });
3848
+ (0, import_react56.useEffect)(() => {
3849
+ runtime.onStoreUpdated();
3850
+ });
3851
+ return runtime;
3852
+ };
3853
+
3854
+ // src/ui/thread-config.tsx
3855
+ var import_react57 = require("react");
3637
3856
  var import_jsx_runtime29 = require("react/jsx-runtime");
3638
- var ThreadConfigContext = (0, import_react55.createContext)({});
3857
+ var ThreadConfigContext = (0, import_react57.createContext)({});
3639
3858
  var useThreadConfig = () => {
3640
- return (0, import_react55.useContext)(ThreadConfigContext);
3859
+ return (0, import_react57.useContext)(ThreadConfigContext);
3641
3860
  };
3642
3861
  var ThreadConfigProvider = ({
3643
3862
  children,
@@ -3656,7 +3875,7 @@ var ThreadConfigProvider = ({
3656
3875
  ThreadConfigProvider.displayName = "ThreadConfigProvider";
3657
3876
 
3658
3877
  // src/ui/assistant-action-bar.tsx
3659
- var import_react56 = require("react");
3878
+ var import_react58 = require("react");
3660
3879
  var import_lucide_react = require("lucide-react");
3661
3880
  var import_jsx_runtime30 = require("react/jsx-runtime");
3662
3881
  var useAllowCopy = () => {
@@ -3693,7 +3912,7 @@ var AssistantActionBarRoot = withDefaults(actionBar_exports.Root, {
3693
3912
  className: "aui-assistant-action-bar-root"
3694
3913
  });
3695
3914
  AssistantActionBarRoot.displayName = "AssistantActionBarRoot";
3696
- var AssistantActionBarCopy = (0, import_react56.forwardRef)((props, ref) => {
3915
+ var AssistantActionBarCopy = (0, import_react58.forwardRef)((props, ref) => {
3697
3916
  const {
3698
3917
  strings: {
3699
3918
  assistantMessage: { reload: { tooltip = "Copy" } = {} } = {}
@@ -3707,7 +3926,7 @@ var AssistantActionBarCopy = (0, import_react56.forwardRef)((props, ref) => {
3707
3926
  ] }) }) });
3708
3927
  });
3709
3928
  AssistantActionBarCopy.displayName = "AssistantActionBarCopy";
3710
- var AssistantActionBarReload = (0, import_react56.forwardRef)((props, ref) => {
3929
+ var AssistantActionBarReload = (0, import_react58.forwardRef)((props, ref) => {
3711
3930
  const {
3712
3931
  strings: {
3713
3932
  assistantMessage: { reload: { tooltip = "Refresh" } = {} } = {}
@@ -3729,10 +3948,10 @@ var assistant_action_bar_default = Object.assign(
3729
3948
  );
3730
3949
 
3731
3950
  // src/ui/assistant-message.tsx
3732
- var import_react58 = require("react");
3951
+ var import_react60 = require("react");
3733
3952
 
3734
3953
  // src/ui/branch-picker.tsx
3735
- var import_react57 = require("react");
3954
+ var import_react59 = require("react");
3736
3955
  var import_lucide_react2 = require("lucide-react");
3737
3956
  var import_jsx_runtime31 = require("react/jsx-runtime");
3738
3957
  var BranchPicker = () => {
@@ -3747,7 +3966,7 @@ var BranchPickerRoot = withDefaults(branchPicker_exports.Root, {
3747
3966
  className: "aui-branch-picker-root"
3748
3967
  });
3749
3968
  BranchPickerRoot.displayName = "BranchPickerRoot";
3750
- var BranchPickerPrevious2 = (0, import_react57.forwardRef)((props, ref) => {
3969
+ var BranchPickerPrevious2 = (0, import_react59.forwardRef)((props, ref) => {
3751
3970
  const {
3752
3971
  strings: {
3753
3972
  branchPicker: { previous: { tooltip = "Previous" } = {} } = {}
@@ -3759,7 +3978,7 @@ BranchPickerPrevious2.displayName = "BranchPickerPrevious";
3759
3978
  var BranchPickerStateWrapper = withDefaults("span", {
3760
3979
  className: "aui-branch-picker-state"
3761
3980
  });
3762
- var BranchPickerState = (0, import_react57.forwardRef)((props, ref) => {
3981
+ var BranchPickerState = (0, import_react59.forwardRef)((props, ref) => {
3763
3982
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(BranchPickerStateWrapper, { ...props, ref, children: [
3764
3983
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(branchPicker_exports.Number, {}),
3765
3984
  " / ",
@@ -3767,7 +3986,7 @@ var BranchPickerState = (0, import_react57.forwardRef)((props, ref) => {
3767
3986
  ] });
3768
3987
  });
3769
3988
  BranchPickerState.displayName = "BranchPickerState";
3770
- var BranchPickerNext = (0, import_react57.forwardRef)((props, ref) => {
3989
+ var BranchPickerNext = (0, import_react59.forwardRef)((props, ref) => {
3771
3990
  const {
3772
3991
  strings: { branchPicker: { next: { tooltip = "Next" } = {} } = {} } = {}
3773
3992
  } = useThreadConfig();
@@ -3845,7 +4064,7 @@ AssistantMessageRoot.displayName = "AssistantMessageRoot";
3845
4064
  var AssistantMessageContentWrapper = withDefaults("div", {
3846
4065
  className: "aui-assistant-message-content"
3847
4066
  });
3848
- var AssistantMessageContent = (0, import_react58.forwardRef)(({ components: componentsProp, ...rest }, ref) => {
4067
+ var AssistantMessageContent = (0, import_react60.forwardRef)(({ components: componentsProp, ...rest }, ref) => {
3849
4068
  const { assistantMessage: { components = {} } = {} } = useThreadConfig();
3850
4069
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(AssistantMessageContentWrapper, { ...rest, ref, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
3851
4070
  message_exports.Content,
@@ -3869,15 +4088,15 @@ var assistant_message_default = Object.assign(
3869
4088
  );
3870
4089
 
3871
4090
  // src/ui/assistant-modal.tsx
3872
- var import_react65 = require("react");
4091
+ var import_react67 = require("react");
3873
4092
  var import_lucide_react6 = require("lucide-react");
3874
4093
 
3875
4094
  // src/ui/thread.tsx
3876
- var import_react64 = require("react");
4095
+ var import_react66 = require("react");
3877
4096
  var import_lucide_react5 = require("lucide-react");
3878
4097
 
3879
4098
  // src/ui/composer.tsx
3880
- var import_react59 = require("react");
4099
+ var import_react61 = require("react");
3881
4100
  var import_lucide_react3 = require("lucide-react");
3882
4101
 
3883
4102
  // src/ui/base/CircleStopIcon.tsx
@@ -3913,7 +4132,7 @@ var ComposerInputStyled = withDefaults(composer_exports.Input, {
3913
4132
  autoFocus: true,
3914
4133
  className: "aui-composer-input"
3915
4134
  });
3916
- var ComposerInput = (0, import_react59.forwardRef)(
4135
+ var ComposerInput = (0, import_react61.forwardRef)(
3917
4136
  (props, ref) => {
3918
4137
  const {
3919
4138
  strings: {
@@ -3942,7 +4161,7 @@ var ComposerSendButton = withDefaults(TooltipIconButton, {
3942
4161
  variant: "default",
3943
4162
  className: "aui-composer-send"
3944
4163
  });
3945
- var ComposerSend = (0, import_react59.forwardRef)((props, ref) => {
4164
+ var ComposerSend = (0, import_react61.forwardRef)((props, ref) => {
3946
4165
  const {
3947
4166
  strings: { composer: { send: { tooltip = "Send" } = {} } = {} } = {}
3948
4167
  } = useThreadConfig();
@@ -3953,7 +4172,7 @@ var ComposerCancelButton = withDefaults(TooltipIconButton, {
3953
4172
  variant: "default",
3954
4173
  className: "aui-composer-cancel"
3955
4174
  });
3956
- var ComposerCancel = (0, import_react59.forwardRef)((props, ref) => {
4175
+ var ComposerCancel = (0, import_react61.forwardRef)((props, ref) => {
3957
4176
  const {
3958
4177
  strings: { composer: { cancel: { tooltip = "Cancel" } = {} } = {} } = {}
3959
4178
  } = useThreadConfig();
@@ -3970,7 +4189,7 @@ var exports6 = {
3970
4189
  var composer_default = Object.assign(Composer, exports6);
3971
4190
 
3972
4191
  // src/ui/thread-welcome.tsx
3973
- var import_react60 = require("react");
4192
+ var import_react62 = require("react");
3974
4193
  var import_jsx_runtime37 = require("react/jsx-runtime");
3975
4194
  var ThreadWelcome = () => {
3976
4195
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(ThreadWelcomeRoot, { children: [
@@ -3988,7 +4207,7 @@ var ThreadWelcomeRootStyled = withDefaults("div", {
3988
4207
  var ThreadWelcomeCenter = withDefaults("div", {
3989
4208
  className: "aui-thread-welcome-center"
3990
4209
  });
3991
- var ThreadWelcomeRoot = (0, import_react60.forwardRef)(
4210
+ var ThreadWelcomeRoot = (0, import_react62.forwardRef)(
3992
4211
  (props, ref) => {
3993
4212
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(thread_exports.Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ThreadWelcomeRootStyled, { ...props, ref }) });
3994
4213
  }
@@ -4001,7 +4220,7 @@ var ThreadWelcomeAvatar = () => {
4001
4220
  var ThreadWelcomeMessageStyled = withDefaults("p", {
4002
4221
  className: "aui-thread-welcome-message"
4003
4222
  });
4004
- var ThreadWelcomeMessage = (0, import_react60.forwardRef)(({ message: messageProp, ...rest }, ref) => {
4223
+ var ThreadWelcomeMessage = (0, import_react62.forwardRef)(({ message: messageProp, ...rest }, ref) => {
4005
4224
  const { welcome: { message = "How can I help you today?" } = {} } = useThreadConfig();
4006
4225
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message });
4007
4226
  });
@@ -4044,10 +4263,10 @@ var exports7 = {
4044
4263
  var thread_welcome_default = Object.assign(ThreadWelcome, exports7);
4045
4264
 
4046
4265
  // src/ui/user-message.tsx
4047
- var import_react62 = require("react");
4266
+ var import_react64 = require("react");
4048
4267
 
4049
4268
  // src/ui/user-action-bar.tsx
4050
- var import_react61 = require("react");
4269
+ var import_react63 = require("react");
4051
4270
  var import_lucide_react4 = require("lucide-react");
4052
4271
  var import_jsx_runtime38 = require("react/jsx-runtime");
4053
4272
  var useAllowEdit = () => {
@@ -4066,7 +4285,7 @@ var UserActionBarRoot = withDefaults(actionBar_exports.Root, {
4066
4285
  className: "aui-user-action-bar-root"
4067
4286
  });
4068
4287
  UserActionBarRoot.displayName = "UserActionBarRoot";
4069
- var UserActionBarEdit = (0, import_react61.forwardRef)((props, ref) => {
4288
+ var UserActionBarEdit = (0, import_react63.forwardRef)((props, ref) => {
4070
4289
  const {
4071
4290
  strings: { userMessage: { edit: { tooltip = "Edit" } = {} } = {} } = {}
4072
4291
  } = useThreadConfig();
@@ -4098,7 +4317,7 @@ UserMessageRoot.displayName = "UserMessageRoot";
4098
4317
  var UserMessageContentWrapper = withDefaults("div", {
4099
4318
  className: "aui-user-message-content"
4100
4319
  });
4101
- var UserMessageContent = (0, import_react62.forwardRef)(
4320
+ var UserMessageContent = (0, import_react64.forwardRef)(
4102
4321
  ({ components, ...props }, ref) => {
4103
4322
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
4104
4323
  message_exports.Content,
@@ -4119,7 +4338,7 @@ var exports9 = {
4119
4338
  var user_message_default = Object.assign(UserMessage, exports9);
4120
4339
 
4121
4340
  // src/ui/edit-composer.tsx
4122
- var import_react63 = require("react");
4341
+ var import_react65 = require("react");
4123
4342
  var import_jsx_runtime40 = require("react/jsx-runtime");
4124
4343
  var EditComposer = () => {
4125
4344
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(EditComposerRoot, { children: [
@@ -4143,7 +4362,7 @@ var EditComposerFooter = withDefaults("div", {
4143
4362
  className: "aui-edit-composer-footer"
4144
4363
  });
4145
4364
  EditComposerFooter.displayName = "EditComposerFooter";
4146
- var EditComposerCancel = (0, import_react63.forwardRef)(
4365
+ var EditComposerCancel = (0, import_react65.forwardRef)(
4147
4366
  (props, ref) => {
4148
4367
  const {
4149
4368
  strings: {
@@ -4154,7 +4373,7 @@ var EditComposerCancel = (0, import_react63.forwardRef)(
4154
4373
  }
4155
4374
  );
4156
4375
  EditComposerCancel.displayName = "EditComposerCancel";
4157
- var EditComposerSend = (0, import_react63.forwardRef)(
4376
+ var EditComposerSend = (0, import_react65.forwardRef)(
4158
4377
  (props, ref) => {
4159
4378
  const {
4160
4379
  strings: { editComposer: { send: { label = "Send" } = {} } = {} } = {}
@@ -4187,7 +4406,7 @@ var Thread = (config) => {
4187
4406
  var ThreadRootStyled = withDefaults(thread_exports.Root, {
4188
4407
  className: "aui-root aui-thread-root"
4189
4408
  });
4190
- var ThreadRoot = (0, import_react64.forwardRef)(
4409
+ var ThreadRoot = (0, import_react66.forwardRef)(
4191
4410
  ({ config, ...props }, ref) => {
4192
4411
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ThreadConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ThreadRootStyled, { ...props, ref }) });
4193
4412
  }
@@ -4221,7 +4440,7 @@ var ThreadScrollToBottomIconButton = withDefaults(TooltipIconButton, {
4221
4440
  variant: "outline",
4222
4441
  className: "aui-thread-scroll-to-bottom"
4223
4442
  });
4224
- var ThreadScrollToBottom = (0, import_react64.forwardRef)((props, ref) => {
4443
+ var ThreadScrollToBottom = (0, import_react66.forwardRef)((props, ref) => {
4225
4444
  const {
4226
4445
  strings: {
4227
4446
  thread: { scrollToBottom: { tooltip = "Scroll to bottom" } = {} } = {}
@@ -4252,7 +4471,7 @@ var AssistantModalRoot = ({ config, ...props }) => {
4252
4471
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ThreadConfigProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(assistantModal_exports.Root, { ...props }) });
4253
4472
  };
4254
4473
  AssistantModalRoot.displayName = "AssistantModalRoot";
4255
- var AssistantModalTrigger = (0, import_react65.forwardRef)((props, ref) => {
4474
+ var AssistantModalTrigger = (0, import_react67.forwardRef)((props, ref) => {
4256
4475
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AssistantModalAnchor, { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(assistantModal_exports.Trigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AssistantModalButton, { ...props, ref }) }) });
4257
4476
  });
4258
4477
  AssistantModalTrigger.displayName = "AssistantModalTrigger";
@@ -4264,7 +4483,7 @@ var ModalButtonStyled = withDefaults(TooltipIconButton, {
4264
4483
  variant: "default",
4265
4484
  className: "aui-modal-button"
4266
4485
  });
4267
- var AssistantModalButton = (0, import_react65.forwardRef)(({ "data-state": state, ...rest }, ref) => {
4486
+ var AssistantModalButton = (0, import_react67.forwardRef)(({ "data-state": state, ...rest }, ref) => {
4268
4487
  const {
4269
4488
  strings: {
4270
4489
  assistantModal: {
@@ -4333,6 +4552,7 @@ var assistant_modal_default = Object.assign(AssistantModal, exports12);
4333
4552
  ContentPartPrimitive,
4334
4553
  EdgeChatAdapter,
4335
4554
  EditComposer,
4555
+ ExternalStoreRuntime,
4336
4556
  INTERNAL,
4337
4557
  MessagePrimitive,
4338
4558
  Thread,
@@ -4345,6 +4565,7 @@ var assistant_modal_default = Object.assign(AssistantModal, exports12);
4345
4565
  fromCoreMessages,
4346
4566
  fromLanguageModelMessages,
4347
4567
  fromLanguageModelTools,
4568
+ getExternalStoreMessage,
4348
4569
  makeAssistantTool,
4349
4570
  makeAssistantToolUI,
4350
4571
  toCoreMessage,
@@ -4372,6 +4593,7 @@ var assistant_modal_default = Object.assign(AssistantModal, exports12);
4372
4593
  useContentPartImage,
4373
4594
  useContentPartText,
4374
4595
  useEdgeRuntime,
4596
+ useExternalStoreRuntime,
4375
4597
  useLocalRuntime,
4376
4598
  useMessageContext,
4377
4599
  useMessageIf,