@assistant-ui/react 0.5.1 → 0.5.3

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