@assistant-ui/react 0.5.45 → 0.5.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  toLanguageModelMessages,
11
11
  toLanguageModelTools,
12
12
  toolResultStream
13
- } from "./chunk-5ZTUOAPH.mjs";
13
+ } from "./chunk-TZO3D3VQ.mjs";
14
14
  import {
15
15
  __export
16
16
  } from "./chunk-BJPOCE4O.mjs";
@@ -125,21 +125,26 @@ var makeComposerStore = (useThreadRuntime) => {
125
125
  setValue(value) {
126
126
  get().setText(value);
127
127
  },
128
+ attachments: runtime.composer.attachments,
129
+ addAttachment: (file) => {
130
+ useThreadRuntime.getState().composer.addAttachment(file);
131
+ },
132
+ removeAttachment: (attachmentId) => {
133
+ useThreadRuntime.getState().composer.removeAttachment(attachmentId);
134
+ },
135
+ reset: () => {
136
+ useThreadRuntime.getState().composer.reset();
137
+ },
128
138
  text: runtime.composer.text,
129
- setText: (value) => {
130
- useThreadRuntime.getState().composer.setText(value);
139
+ setText: (text) => {
140
+ useThreadRuntime.getState().composer.setText(text);
131
141
  },
132
142
  canCancel: runtime.capabilities.cancel,
133
143
  isEditing: true,
144
+ isEmpty: runtime.composer.isEmpty,
134
145
  send: () => {
135
146
  const runtime2 = useThreadRuntime.getState();
136
- const text = runtime2.composer.text;
137
- runtime2.composer.setText("");
138
- runtime2.append({
139
- parentId: runtime2.messages.at(-1)?.id ?? null,
140
- role: "user",
141
- content: [{ type: "text", text }]
142
- });
147
+ runtime2.composer.send();
143
148
  },
144
149
  cancel: () => {
145
150
  useThreadRuntime.getState().cancelRun();
@@ -275,6 +280,7 @@ __export(internal_exports, {
275
280
  BaseAssistantRuntime: () => BaseAssistantRuntime,
276
281
  MessageRepository: () => MessageRepository,
277
282
  ProxyConfigProvider: () => ProxyConfigProvider,
283
+ ThreadRuntimeComposer: () => ThreadRuntimeComposer,
278
284
  TooltipIconButton: () => TooltipIconButton,
279
285
  generateId: () => generateId,
280
286
  useSmooth: () => useSmooth,
@@ -282,6 +288,76 @@ __export(internal_exports, {
282
288
  withSmoothContextProvider: () => withSmoothContextProvider
283
289
  });
284
290
 
291
+ // src/runtimes/utils/ThreadRuntimeComposer.tsx
292
+ var ThreadRuntimeComposer = class {
293
+ constructor(runtime, notifySubscribers) {
294
+ this.runtime = runtime;
295
+ this.notifySubscribers = notifySubscribers;
296
+ }
297
+ _attachmentAdapter;
298
+ attachmentAccept = "*";
299
+ get isEmpty() {
300
+ return !this.text.trim() && !this.attachments.length;
301
+ }
302
+ setAttachmentAdapter(adapter) {
303
+ this._attachmentAdapter = adapter;
304
+ const accept = adapter?.accept ?? "*";
305
+ if (this.attachmentAccept !== accept) {
306
+ this.attachmentAccept = accept;
307
+ return true;
308
+ }
309
+ return false;
310
+ }
311
+ _attachments = [];
312
+ get attachments() {
313
+ return this._attachments;
314
+ }
315
+ async addAttachment(file) {
316
+ if (!this._attachmentAdapter)
317
+ throw new Error("Attachments are not supported");
318
+ const attachment = await this._attachmentAdapter.add({ file });
319
+ this._attachments = [...this._attachments, attachment];
320
+ this.notifySubscribers();
321
+ }
322
+ async removeAttachment(attachmentId) {
323
+ if (!this._attachmentAdapter)
324
+ throw new Error("Attachments are not supported");
325
+ const index = this._attachments.findIndex((a) => a.id === attachmentId);
326
+ if (index === -1) throw new Error("Attachment not found");
327
+ const attachment = this._attachments[index];
328
+ await this._attachmentAdapter.remove(attachment);
329
+ this._attachments = this._attachments.toSpliced(index, 1);
330
+ this.notifySubscribers();
331
+ }
332
+ _text = "";
333
+ get text() {
334
+ return this._text;
335
+ }
336
+ setText(value) {
337
+ this._text = value;
338
+ this.notifySubscribers();
339
+ }
340
+ reset() {
341
+ this._text = "";
342
+ this._attachments = [];
343
+ this.notifySubscribers();
344
+ }
345
+ async send() {
346
+ const attachments = this._attachmentAdapter ? await Promise.all(
347
+ this.attachments.map(
348
+ async (a) => await this._attachmentAdapter.send(a)
349
+ )
350
+ ) : [];
351
+ this.runtime.append({
352
+ parentId: this.runtime.messages.at(-1)?.id ?? null,
353
+ role: "user",
354
+ content: this.text ? [{ type: "text", text: this.text }] : [],
355
+ attachments
356
+ });
357
+ this.reset();
358
+ }
359
+ };
360
+
285
361
  // src/utils/idUtils.tsx
286
362
  import { customAlphabet } from "nanoid/non-secure";
287
363
  var generateId = customAlphabet(
@@ -324,7 +400,8 @@ var fromCoreMessage = (message, {
324
400
  return {
325
401
  ...commonProps,
326
402
  role,
327
- content: message.content
403
+ content: message.content,
404
+ attachments: []
328
405
  };
329
406
  case "system":
330
407
  return {
@@ -1101,31 +1178,37 @@ var LocalThreadRuntime = class {
1101
1178
  reload: true,
1102
1179
  cancel: true,
1103
1180
  unstable_copy: true,
1104
- speak: false
1181
+ speak: false,
1182
+ attachments: false
1105
1183
  };
1106
1184
  threadId;
1107
1185
  isDisabled = false;
1108
1186
  get messages() {
1109
1187
  return this.repository.getMessages();
1110
1188
  }
1111
- composer = {
1112
- text: "",
1113
- setText: (value) => {
1114
- this.composer.text = value;
1115
- this.notifySubscribers();
1116
- }
1117
- };
1189
+ composer = new ThreadRuntimeComposer(
1190
+ this,
1191
+ this.notifySubscribers.bind(this)
1192
+ );
1118
1193
  _options;
1119
1194
  get options() {
1120
1195
  return this._options;
1121
1196
  }
1122
1197
  set options({ initialMessages, ...options }) {
1123
1198
  this._options = options;
1199
+ let hasUpdates = false;
1124
1200
  const canSpeak = options.adapters?.speech !== void 0;
1125
1201
  if (this.capabilities.speak !== canSpeak) {
1126
1202
  this.capabilities.speak = canSpeak;
1127
- this.notifySubscribers();
1203
+ hasUpdates = true;
1128
1204
  }
1205
+ this.composer.setAttachmentAdapter(options.adapters?.attachments);
1206
+ const canAttach = options.adapters?.attachments !== void 0;
1207
+ if (this.capabilities.attachments !== canAttach) {
1208
+ this.capabilities.attachments = canAttach;
1209
+ hasUpdates = true;
1210
+ }
1211
+ if (hasUpdates) this.notifySubscribers();
1129
1212
  }
1130
1213
  getBranches(messageId) {
1131
1214
  return this.repository.getBranches(messageId);
@@ -1144,6 +1227,7 @@ var LocalThreadRuntime = class {
1144
1227
  id: userMessageId,
1145
1228
  role: "user",
1146
1229
  content: message.content,
1230
+ attachments: message.attachments ?? [],
1147
1231
  createdAt: /* @__PURE__ */ new Date()
1148
1232
  };
1149
1233
  this.repository.addOrUpdateMessage(message.parentId, userMessage);
@@ -1406,12 +1490,14 @@ var getAutoStatus = (isLast, isRunning) => isLast && isRunning ? AUTO_STATUS_RUN
1406
1490
 
1407
1491
  // src/runtimes/external-store/ThreadMessageLike.tsx
1408
1492
  var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
1409
- const { role, id, createdAt, status } = like;
1493
+ const { role, id, createdAt, attachments, status } = like;
1410
1494
  const common = {
1411
1495
  id: id ?? fallbackId,
1412
1496
  createdAt: createdAt ?? /* @__PURE__ */ new Date()
1413
1497
  };
1414
1498
  const content = typeof like.content === "string" ? [{ type: "text", text: like.content }] : like.content;
1499
+ if (role !== "user" && attachments)
1500
+ throw new Error("Attachments are only supported for user messages");
1415
1501
  switch (role) {
1416
1502
  case "assistant":
1417
1503
  return {
@@ -1456,7 +1542,8 @@ var fromThreadMessageLike = (like, fallbackId, fallbackStatus) => {
1456
1542
  throw new Error(`Unknown content part type: ${unhandledType}`);
1457
1543
  }
1458
1544
  }
1459
- })
1545
+ }),
1546
+ attachments: attachments ?? []
1460
1547
  };
1461
1548
  case "system":
1462
1549
  if (content.length !== 1 || content[0].type !== "text")
@@ -1497,7 +1584,8 @@ var ExternalStoreThreadRuntime = class {
1497
1584
  reload: false,
1498
1585
  cancel: false,
1499
1586
  unstable_copy: false,
1500
- speak: false
1587
+ speak: false,
1588
+ attachments: false
1501
1589
  };
1502
1590
  get capabilities() {
1503
1591
  return this._capabilities;
@@ -1507,13 +1595,10 @@ var ExternalStoreThreadRuntime = class {
1507
1595
  isDisabled;
1508
1596
  converter = new ThreadMessageConverter();
1509
1597
  _store;
1510
- composer = {
1511
- text: "",
1512
- setText: (value) => {
1513
- this.composer.text = value;
1514
- this.notifySubscribers();
1515
- }
1516
- };
1598
+ composer = new ThreadRuntimeComposer(
1599
+ this,
1600
+ this.notifySubscribers.bind(this)
1601
+ );
1517
1602
  constructor(store) {
1518
1603
  this.store = store;
1519
1604
  }
@@ -1532,9 +1617,12 @@ var ExternalStoreThreadRuntime = class {
1532
1617
  edit: this._store.onEdit !== void 0,
1533
1618
  reload: this._store.onReload !== void 0,
1534
1619
  cancel: this._store.onCancel !== void 0,
1535
- unstable_copy: this._store.unstable_capabilities?.copy !== null,
1536
- speak: this._store.onSpeak !== void 0
1620
+ speak: this._store.onSpeak !== void 0,
1621
+ unstable_copy: this._store.unstable_capabilities?.copy !== false,
1622
+ // default true
1623
+ attachments: !!this.store.adapters?.attachments
1537
1624
  };
1625
+ this.composer.setAttachmentAdapter(this._store.adapters?.attachments);
1538
1626
  if (oldStore) {
1539
1627
  if (oldStore.convertMessage !== store.convertMessage) {
1540
1628
  this.converter = new ThreadMessageConverter();
@@ -1925,6 +2013,147 @@ var WebSpeechSynthesisAdapter = class {
1925
2013
  }
1926
2014
  };
1927
2015
 
2016
+ // src/runtimes/attachment/SimpleImageAttachmentAdapter.ts
2017
+ var SimpleImageAttachmentAdapter = class {
2018
+ accept = "image/*";
2019
+ async add(state) {
2020
+ return {
2021
+ id: state.file.name,
2022
+ type: "image",
2023
+ name: state.file.name,
2024
+ file: state.file
2025
+ };
2026
+ }
2027
+ async send(attachment) {
2028
+ return {
2029
+ ...attachment,
2030
+ content: [
2031
+ {
2032
+ type: "image",
2033
+ image: await getFileDataURL(attachment.file)
2034
+ }
2035
+ ]
2036
+ };
2037
+ }
2038
+ async remove() {
2039
+ }
2040
+ };
2041
+ var getFileDataURL = (file) => new Promise((resolve, reject) => {
2042
+ const reader = new FileReader();
2043
+ reader.onload = () => resolve(reader.result);
2044
+ reader.onerror = (error) => reject(error);
2045
+ reader.readAsDataURL(file);
2046
+ });
2047
+
2048
+ // src/runtimes/attachment/SimpleTextAttachmentAdapter.ts
2049
+ var SimpleTextAttachmentAdapter = class {
2050
+ accept = "text/plain,text/html,text/markdown,text/csv,text/xml,text/json,text/css";
2051
+ async add(state) {
2052
+ return {
2053
+ id: state.file.name,
2054
+ type: "document",
2055
+ name: state.file.name,
2056
+ file: state.file
2057
+ };
2058
+ }
2059
+ async send(attachment) {
2060
+ return {
2061
+ ...attachment,
2062
+ content: [
2063
+ {
2064
+ type: "text",
2065
+ text: `<attachment name=${attachment.name}>
2066
+ ${await getFileText(attachment.file)}
2067
+ </attachment>`
2068
+ }
2069
+ ]
2070
+ };
2071
+ }
2072
+ async remove() {
2073
+ }
2074
+ };
2075
+ var getFileText = (file) => new Promise((resolve, reject) => {
2076
+ const reader = new FileReader();
2077
+ reader.onload = () => resolve(reader.result);
2078
+ reader.onerror = (error) => reject(error);
2079
+ reader.readAsText(file);
2080
+ });
2081
+
2082
+ // src/runtimes/attachment/CompositeAttachmentAdapter.ts
2083
+ function fileMatchesAccept(file, acceptString) {
2084
+ if (acceptString === "*") {
2085
+ return true;
2086
+ }
2087
+ const allowedTypes = acceptString.split(",").map((type) => type.trim().toLowerCase());
2088
+ const fileExtension = "." + file.name.split(".").pop().toLowerCase();
2089
+ const fileMimeType = file.type.toLowerCase();
2090
+ for (const type of allowedTypes) {
2091
+ if (type.startsWith(".") && type === fileExtension) {
2092
+ return true;
2093
+ }
2094
+ if (type.includes("/") && type === fileMimeType) {
2095
+ return true;
2096
+ }
2097
+ if (type === "image/*" || type === "video/*" || type === "audio/*") {
2098
+ if (type.endsWith("/*")) {
2099
+ const generalType = type.split("/")[0];
2100
+ if (fileMimeType.startsWith(generalType + "/")) {
2101
+ return true;
2102
+ }
2103
+ }
2104
+ }
2105
+ }
2106
+ return false;
2107
+ }
2108
+ var CompositeAttachmentAdapter = class {
2109
+ _adapters;
2110
+ accept;
2111
+ constructor(adapters) {
2112
+ this._adapters = adapters;
2113
+ const wildcardIdx = adapters.findIndex((a) => a.accept === "*");
2114
+ if (wildcardIdx !== -1) {
2115
+ if (wildcardIdx !== adapters.length - 1)
2116
+ throw new Error(
2117
+ "A wildcard adapter (handling all files) can only be specified as the last adapter."
2118
+ );
2119
+ this.accept = "*";
2120
+ } else {
2121
+ this.accept = adapters.map((a) => a.accept).join(",");
2122
+ }
2123
+ }
2124
+ async add(state) {
2125
+ for (const adapter of this._adapters) {
2126
+ if (fileMatchesAccept(state.file, adapter.accept)) {
2127
+ return adapter.add(state);
2128
+ }
2129
+ }
2130
+ throw new Error("No matching adapter found for file");
2131
+ }
2132
+ async send(attachment) {
2133
+ const adapters = this._adapters.slice();
2134
+ for (const adapter of adapters) {
2135
+ if (fileMatchesAccept(attachment.file, adapter.accept)) {
2136
+ return adapter.send(attachment);
2137
+ }
2138
+ }
2139
+ throw new Error("No matching adapter found for attachment");
2140
+ }
2141
+ async remove(attachment) {
2142
+ const adapters = this._adapters.slice();
2143
+ for (const adapter of adapters) {
2144
+ if (fileMatchesAccept(attachment.file, adapter.accept)) {
2145
+ return adapter.remove(attachment);
2146
+ }
2147
+ }
2148
+ throw new Error("No matching adapter found for attachment");
2149
+ }
2150
+ };
2151
+
2152
+ // src/context/ReadonlyStore.ts
2153
+ var writableStore = (store) => {
2154
+ return store;
2155
+ };
2156
+
1928
2157
  // src/context/providers/ThreadProvider.tsx
1929
2158
  import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
1930
2159
  var ThreadProvider = ({
@@ -1954,18 +2183,20 @@ var ThreadProvider = ({
1954
2183
  const state = getThreadStateFromRuntime(thread);
1955
2184
  if (oldState.threadId !== state.threadId || oldState.isDisabled !== state.isDisabled || oldState.isRunning !== state.isRunning || // TODO ensure capabilities is memoized
1956
2185
  oldState.capabilities !== state.capabilities) {
1957
- context.useThread.setState(
1958
- state,
1959
- true
1960
- );
2186
+ writableStore(context.useThread).setState(state, true);
1961
2187
  }
1962
2188
  if (thread.messages !== context.useThreadMessages.getState()) {
1963
- context.useThreadMessages.setState(thread.messages, true);
2189
+ writableStore(context.useThreadMessages).setState(
2190
+ thread.messages,
2191
+ true
2192
+ );
1964
2193
  }
1965
2194
  const composerState = context.useComposer.getState();
1966
- if (thread.composer.text !== composerState.text || state.capabilities.cancel !== composerState.canCancel) {
1967
- context.useComposer.setState({
2195
+ if (thread.composer.isEmpty !== composerState.isEmpty || thread.composer.text !== composerState.text || thread.composer.attachments !== composerState.attachments || state.capabilities.cancel !== composerState.canCancel) {
2196
+ writableStore(context.useComposer).setState({
2197
+ isEmpty: thread.composer.isEmpty,
1968
2198
  text: thread.composer.text,
2199
+ attachments: thread.composer.attachments,
1969
2200
  canCancel: state.capabilities.cancel
1970
2201
  });
1971
2202
  }
@@ -1975,7 +2206,7 @@ var ThreadProvider = ({
1975
2206
  }, [provider, context]);
1976
2207
  useInsertionEffect2(
1977
2208
  () => provider.subscribe(() => {
1978
- context.useThreadRuntime.setState(provider.thread, true);
2209
+ writableStore(context.useThreadRuntime).setState(provider.thread, true);
1979
2210
  }),
1980
2211
  [provider, context]
1981
2212
  );
@@ -2027,7 +2258,7 @@ var AssistantProvider = ({ children, runtime }) => {
2027
2258
  return runtime.registerModelConfigProvider(getModelConfig);
2028
2259
  }, [runtime, getModelConfig]);
2029
2260
  useEffect4(
2030
- () => context.useAssistantRuntime.setState(runtime, true),
2261
+ () => writableStore(context.useAssistantRuntime).setState(runtime, true),
2031
2262
  [runtime, context]
2032
2263
  );
2033
2264
  return /* @__PURE__ */ jsx7(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx7(ThreadProvider, { provider: runtime, children }) });
@@ -2089,13 +2320,15 @@ var toAppendMessage = (useThreadMessages, message) => {
2089
2320
  return {
2090
2321
  parentId: useThreadMessages.getState().at(-1)?.id ?? null,
2091
2322
  role: "user",
2092
- content: [{ type: "text", text: message }]
2323
+ content: [{ type: "text", text: message }],
2324
+ attachments: []
2093
2325
  };
2094
2326
  }
2095
2327
  return {
2096
2328
  parentId: message.parentId ?? useThreadMessages.getState().at(-1)?.id ?? null,
2097
2329
  role: message.role ?? "user",
2098
- content: message.content
2330
+ content: message.content,
2331
+ attachments: message.attachments ?? []
2099
2332
  };
2100
2333
  };
2101
2334
  var useAppendMessage = () => {
@@ -2156,6 +2389,7 @@ var makeAssistantTool = (tool) => {
2156
2389
  useAssistantTool(tool);
2157
2390
  return null;
2158
2391
  };
2392
+ Tool.unstable_tool = tool;
2159
2393
  return Tool;
2160
2394
  };
2161
2395
 
@@ -2177,6 +2411,7 @@ var makeAssistantToolUI = (tool) => {
2177
2411
  useAssistantToolUI(tool);
2178
2412
  return null;
2179
2413
  };
2414
+ ToolUI.unstable_tool = tool;
2180
2415
  return ToolUI;
2181
2416
  };
2182
2417
 
@@ -2398,7 +2633,7 @@ var useComposerSend = () => {
2398
2633
  const { useComposer } = useComposerContext();
2399
2634
  const disabled = useCombinedStore(
2400
2635
  [useThread, useComposer],
2401
- (t, c) => t.isRunning || !c.isEditing || c.text.length === 0
2636
+ (t, c) => t.isRunning || !c.isEditing || c.isEmpty
2402
2637
  );
2403
2638
  const callback = useCallback11(() => {
2404
2639
  const composerState = useComposer.getState();
@@ -2411,6 +2646,30 @@ var useComposerSend = () => {
2411
2646
  return callback;
2412
2647
  };
2413
2648
 
2649
+ // src/primitive-hooks/composer/useComposerAddAttachment.tsx
2650
+ import { useCallback as useCallback12 } from "react";
2651
+ var useComposerAddAttachment = () => {
2652
+ const { useComposer, useThreadRuntime } = useThreadContext();
2653
+ const disabled = useComposer((c) => !c.isEditing);
2654
+ const callback = useCallback12(() => {
2655
+ const { addAttachment } = useComposer.getState();
2656
+ const { attachmentAccept } = useThreadRuntime.getState().composer;
2657
+ const input = document.createElement("input");
2658
+ input.type = "file";
2659
+ if (attachmentAccept !== "*") {
2660
+ input.accept = attachmentAccept;
2661
+ }
2662
+ input.onchange = (e) => {
2663
+ const file = e.target.files?.[0];
2664
+ if (!file) return;
2665
+ addAttachment(file);
2666
+ };
2667
+ input.click();
2668
+ }, [useComposer, useThreadRuntime]);
2669
+ if (disabled) return null;
2670
+ return callback;
2671
+ };
2672
+
2414
2673
  // src/primitive-hooks/contentPart/useContentPartDisplay.tsx
2415
2674
  var useContentPartDisplay = () => {
2416
2675
  const { useContentPart } = useContentPartContext();
@@ -2465,6 +2724,10 @@ var useMessageIf = (props) => {
2465
2724
  if (props.copied === false && isCopied) return false;
2466
2725
  if (props.speaking === true && !isSpeaking) return false;
2467
2726
  if (props.speaking === false && isSpeaking) return false;
2727
+ if (props.hasAttachments === true && (message.role !== "user" || !message.attachments.length))
2728
+ return false;
2729
+ if (props.hasAttachments === false && message.role === "user" && !!message.attachments.length)
2730
+ return false;
2468
2731
  return true;
2469
2732
  }
2470
2733
  );
@@ -2493,11 +2756,11 @@ var useThreadEmpty = () => {
2493
2756
  };
2494
2757
 
2495
2758
  // src/primitive-hooks/thread/useThreadScrollToBottom.tsx
2496
- import { useCallback as useCallback12 } from "react";
2759
+ import { useCallback as useCallback13 } from "react";
2497
2760
  var useThreadScrollToBottom = () => {
2498
2761
  const { useComposer, useViewport } = useThreadContext();
2499
2762
  const isAtBottom = useViewport((s) => s.isAtBottom);
2500
- const handleScrollToBottom = useCallback12(() => {
2763
+ const handleScrollToBottom = useCallback13(() => {
2501
2764
  useViewport.getState().scrollToBottom();
2502
2765
  useComposer.getState().focus();
2503
2766
  }, [useViewport, useComposer]);
@@ -2506,7 +2769,7 @@ var useThreadScrollToBottom = () => {
2506
2769
  };
2507
2770
 
2508
2771
  // src/primitive-hooks/thread/useThreadSuggestion.tsx
2509
- import { useCallback as useCallback13 } from "react";
2772
+ import { useCallback as useCallback14 } from "react";
2510
2773
  var useThreadSuggestion = ({
2511
2774
  prompt,
2512
2775
  autoSend
@@ -2514,7 +2777,7 @@ var useThreadSuggestion = ({
2514
2777
  const { useThread, useComposer } = useThreadContext();
2515
2778
  const append = useAppendMessage();
2516
2779
  const disabled = useThread((t) => t.isDisabled);
2517
- const callback = useCallback13(() => {
2780
+ const callback = useCallback14(() => {
2518
2781
  const thread = useThread.getState();
2519
2782
  const composer = useComposer.getState();
2520
2783
  if (autoSend && !thread.isRunning) {
@@ -2842,6 +3105,7 @@ import { forwardRef as forwardRef14 } from "react";
2842
3105
  // src/primitives/message/index.ts
2843
3106
  var message_exports = {};
2844
3107
  __export(message_exports, {
3108
+ Attachments: () => MessagePrimitiveAttachments,
2845
3109
  Content: () => MessagePrimitiveContent,
2846
3110
  If: () => MessagePrimitiveIf,
2847
3111
  InProgress: () => MessagePrimitiveInProgress,
@@ -2852,14 +3116,14 @@ __export(message_exports, {
2852
3116
  import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
2853
3117
  import {
2854
3118
  forwardRef as forwardRef11,
2855
- useCallback as useCallback15
3119
+ useCallback as useCallback16
2856
3120
  } from "react";
2857
3121
 
2858
3122
  // src/utils/hooks/useManagedRef.ts
2859
- import { useCallback as useCallback14, useRef as useRef3 } from "react";
3123
+ import { useCallback as useCallback15, useRef as useRef3 } from "react";
2860
3124
  var useManagedRef = (callback) => {
2861
3125
  const cleanupRef = useRef3();
2862
- const ref = useCallback14(
3126
+ const ref = useCallback15(
2863
3127
  (el) => {
2864
3128
  if (cleanupRef.current) {
2865
3129
  cleanupRef.current();
@@ -2878,7 +3142,7 @@ import { useComposedRefs } from "@radix-ui/react-compose-refs";
2878
3142
  import { jsx as jsx18 } from "react/jsx-runtime";
2879
3143
  var useIsHoveringRef = () => {
2880
3144
  const { useMessageUtils } = useMessageContext();
2881
- const callbackRef = useCallback15(
3145
+ const callbackRef = useCallback16(
2882
3146
  (el) => {
2883
3147
  const setIsHovering = useMessageUtils.getState().setIsHovering;
2884
3148
  const handleMouseEnter = () => {
@@ -2973,7 +3237,7 @@ var useContentPartContext2 = (partIndex) => {
2973
3237
  partIndex
2974
3238
  );
2975
3239
  if (!newState) return;
2976
- context.useContentPart.setState(newState, true);
3240
+ writableStore(context.useContentPart).setState(newState, true);
2977
3241
  };
2978
3242
  syncContentPart(useMessage.getState());
2979
3243
  return useMessage.subscribe(syncContentPart);
@@ -3033,21 +3297,22 @@ ContentPartPrimitiveInProgress.displayName = "ContentPartPrimitive.InProgress";
3033
3297
 
3034
3298
  // src/primitives/message/MessageContent.tsx
3035
3299
  import { jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
3300
+ var ToolUIDisplay = ({
3301
+ UI,
3302
+ ...props
3303
+ }) => {
3304
+ const { useToolUIs } = useAssistantContext();
3305
+ const Render = useToolUIs((s) => s.getToolUI(props.part.toolName)) ?? UI;
3306
+ if (!Render) return null;
3307
+ return /* @__PURE__ */ jsx22(Render, { ...props });
3308
+ };
3036
3309
  var defaultComponents = {
3037
3310
  Text: () => /* @__PURE__ */ jsxs3("p", { style: { whiteSpace: "pre-line" }, children: [
3038
3311
  /* @__PURE__ */ jsx22(ContentPartPrimitiveText, {}),
3039
3312
  /* @__PURE__ */ jsx22(ContentPartPrimitiveInProgress, { children: /* @__PURE__ */ jsx22("span", { style: { fontFamily: "revert" }, children: " \u25CF" }) })
3040
3313
  ] }),
3041
3314
  Image: () => /* @__PURE__ */ jsx22(ContentPartPrimitiveImage, {}),
3042
- UI: () => /* @__PURE__ */ jsx22(ContentPartPrimitiveDisplay, {}),
3043
- tools: {
3044
- Fallback: (props) => {
3045
- const { useToolUIs } = useAssistantContext();
3046
- const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
3047
- if (!Render) return null;
3048
- return /* @__PURE__ */ jsx22(Render, { ...props });
3049
- }
3050
- }
3315
+ UI: () => /* @__PURE__ */ jsx22(ContentPartPrimitiveDisplay, {})
3051
3316
  };
3052
3317
  var MessageContentPartComponent = ({
3053
3318
  components: {
@@ -3055,7 +3320,7 @@ var MessageContentPartComponent = ({
3055
3320
  Text: Text2 = defaultComponents.Text,
3056
3321
  Image: Image2 = defaultComponents.Image,
3057
3322
  UI = defaultComponents.UI,
3058
- tools: { by_name = {}, Fallback: Fallback2 = defaultComponents.tools.Fallback } = {}
3323
+ tools: { by_name = {}, Fallback: Fallback2 = void 0 } = {}
3059
3324
  } = {}
3060
3325
  }) => {
3061
3326
  const { useThreadActions } = useThreadContext();
@@ -3086,7 +3351,15 @@ var MessageContentPartComponent = ({
3086
3351
  toolCallId: part.toolCallId,
3087
3352
  result
3088
3353
  });
3089
- return /* @__PURE__ */ jsx22(Tool, { part, status, addResult });
3354
+ return /* @__PURE__ */ jsx22(
3355
+ ToolUIDisplay,
3356
+ {
3357
+ UI: Tool,
3358
+ part,
3359
+ status,
3360
+ addResult
3361
+ }
3362
+ );
3090
3363
  }
3091
3364
  default:
3092
3365
  const unhandledType = type;
@@ -3108,17 +3381,7 @@ var MessagePrimitiveContent = ({
3108
3381
  }) => {
3109
3382
  const { useMessage } = useMessageContext();
3110
3383
  const contentLength = useMessage((s) => s.message.content.length) || 1;
3111
- return new Array(contentLength).fill(null).map((_, idx) => {
3112
- const partIndex = idx;
3113
- return /* @__PURE__ */ jsx22(
3114
- MessageContentPart,
3115
- {
3116
- partIndex,
3117
- components
3118
- },
3119
- partIndex
3120
- );
3121
- });
3384
+ return Array.from({ length: contentLength }, (_, index) => /* @__PURE__ */ jsx22(MessageContentPart, { partIndex: index, components }, index));
3122
3385
  };
3123
3386
  MessagePrimitiveContent.displayName = "MessagePrimitive.Content";
3124
3387
 
@@ -3128,16 +3391,137 @@ var MessagePrimitiveInProgress = () => {
3128
3391
  };
3129
3392
  MessagePrimitiveInProgress.displayName = "MessagePrimitive.InProgress";
3130
3393
 
3131
- // src/primitives/branchPicker/BranchPickerRoot.tsx
3394
+ // src/primitives/message/MessageAttachments.tsx
3395
+ import { memo as memo3 } from "react";
3396
+
3397
+ // src/context/react/AttachmentContext.ts
3398
+ import { createContext as createContext6, useContext as useContext6 } from "react";
3399
+ var AttachmentContext = createContext6(
3400
+ null
3401
+ );
3402
+ function useAttachmentContext(options) {
3403
+ const context = useContext6(AttachmentContext);
3404
+ if (options?.type === "composer" && context?.type !== "composer")
3405
+ throw new Error(
3406
+ "This component must be used within a ComposerPrimitive.Attachments component."
3407
+ );
3408
+ if (options?.type === "message" && context?.type !== "message")
3409
+ throw new Error(
3410
+ "This component must be used within a MessagePrimitive.Attachments component."
3411
+ );
3412
+ if (!options?.optional && !context)
3413
+ throw new Error(
3414
+ "This component must be used within a ComposerPrimitive.Attachments or MessagePrimitive.Attachments component."
3415
+ );
3416
+ return context;
3417
+ }
3418
+
3419
+ // src/context/providers/MessageAttachmentProvider.tsx
3420
+ import { useEffect as useEffect10, useState as useState11 } from "react";
3421
+ import { create as create13 } from "zustand";
3132
3422
  import { jsx as jsx23 } from "react/jsx-runtime";
3423
+ var getAttachment = ({ message }, useAttachment, partIndex) => {
3424
+ if (message.role !== "user") return null;
3425
+ const attachments = message.attachments;
3426
+ let attachment = attachments[partIndex];
3427
+ if (!attachment) return null;
3428
+ const currentState = useAttachment?.getState();
3429
+ if (currentState && currentState.attachment === attachment) return null;
3430
+ return Object.freeze({ attachment });
3431
+ };
3432
+ var useMessageAttachmentContext = (partIndex) => {
3433
+ const { useMessage } = useMessageContext();
3434
+ const [context] = useState11(
3435
+ () => {
3436
+ const useAttachment = create13(
3437
+ () => getAttachment(useMessage.getState(), void 0, partIndex)
3438
+ );
3439
+ return { type: "message", useAttachment };
3440
+ }
3441
+ );
3442
+ useEffect10(() => {
3443
+ const syncAttachment = (messageState) => {
3444
+ const newState = getAttachment(
3445
+ messageState,
3446
+ context.useAttachment,
3447
+ partIndex
3448
+ );
3449
+ if (!newState) return;
3450
+ writableStore(context.useAttachment).setState(newState, true);
3451
+ };
3452
+ syncAttachment(useMessage.getState());
3453
+ return useMessage.subscribe(syncAttachment);
3454
+ }, [context, useMessage, partIndex]);
3455
+ return context;
3456
+ };
3457
+ var MessageAttachmentProvider = ({
3458
+ attachmentIndex: partIndex,
3459
+ children
3460
+ }) => {
3461
+ const context = useMessageAttachmentContext(partIndex);
3462
+ return /* @__PURE__ */ jsx23(AttachmentContext.Provider, { value: context, children });
3463
+ };
3464
+
3465
+ // src/primitives/message/MessageAttachments.tsx
3466
+ import { jsx as jsx24 } from "react/jsx-runtime";
3467
+ var getComponent = (components, attachment) => {
3468
+ const type = attachment.type;
3469
+ switch (type) {
3470
+ case "image":
3471
+ return components?.Image ?? components?.Attachment;
3472
+ case "document":
3473
+ return components?.Document ?? components?.Attachment;
3474
+ case "file":
3475
+ return components?.File ?? components?.Attachment;
3476
+ default:
3477
+ const _exhaustiveCheck = type;
3478
+ throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
3479
+ }
3480
+ };
3481
+ var AttachmentComponent = ({ components }) => {
3482
+ const { useAttachment } = useAttachmentContext({ type: "message" });
3483
+ const Component = useAttachment(
3484
+ (a) => getComponent(components, a.attachment)
3485
+ );
3486
+ if (!Component) return null;
3487
+ return /* @__PURE__ */ jsx24(Component, {});
3488
+ };
3489
+ var MessageAttachmentImpl = ({ components, attachmentIndex }) => {
3490
+ return /* @__PURE__ */ jsx24(MessageAttachmentProvider, { attachmentIndex, children: /* @__PURE__ */ jsx24(AttachmentComponent, { components }) });
3491
+ };
3492
+ var MessageAttachment = memo3(
3493
+ MessageAttachmentImpl,
3494
+ (prev, next) => prev.attachmentIndex === next.attachmentIndex && prev.components?.Image === next.components?.Image && prev.components?.Document === next.components?.Document && prev.components?.File === next.components?.File && prev.components?.Attachment === next.components?.Attachment
3495
+ );
3496
+ var MessagePrimitiveAttachments = ({ components }) => {
3497
+ const { useMessage } = useMessageContext();
3498
+ const attachmentsCount = useMessage(({ message }) => {
3499
+ if (message.role !== "user") return 0;
3500
+ return message.attachments.length;
3501
+ });
3502
+ return Array.from({ length: attachmentsCount }, (_, index) => /* @__PURE__ */ jsx24(
3503
+ MessageAttachment,
3504
+ {
3505
+ attachmentIndex: index,
3506
+ components
3507
+ },
3508
+ index
3509
+ ));
3510
+ };
3511
+ MessagePrimitiveAttachments.displayName = "MessagePrimitive.Attachments";
3512
+
3513
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
3514
+ import { jsx as jsx25 } from "react/jsx-runtime";
3133
3515
  var BranchPickerPrimitiveRoot = forwardRef14(({ hideWhenSingleBranch, ...rest }, ref) => {
3134
- return /* @__PURE__ */ jsx23(MessagePrimitiveIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx23(Primitive7.div, { ...rest, ref }) });
3516
+ return /* @__PURE__ */ jsx25(MessagePrimitiveIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx25(Primitive7.div, { ...rest, ref }) });
3135
3517
  });
3136
3518
  BranchPickerPrimitiveRoot.displayName = "BranchPickerPrimitive.Root";
3137
3519
 
3138
3520
  // src/primitives/composer/index.ts
3139
3521
  var composer_exports = {};
3140
3522
  __export(composer_exports, {
3523
+ AddAttachment: () => ComposerPrimitiveAddAttachment,
3524
+ Attachments: () => ComposerPrimitiveAttachments,
3141
3525
  Cancel: () => ComposerPrimitiveCancel,
3142
3526
  If: () => ComposerPrimitiveIf,
3143
3527
  Input: () => ComposerPrimitiveInput,
@@ -3151,7 +3535,7 @@ import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
3151
3535
  import {
3152
3536
  forwardRef as forwardRef15
3153
3537
  } from "react";
3154
- import { jsx as jsx24 } from "react/jsx-runtime";
3538
+ import { jsx as jsx26 } from "react/jsx-runtime";
3155
3539
  var ComposerPrimitiveRoot = forwardRef15(({ onSubmit, ...rest }, forwardedRef) => {
3156
3540
  const send = useComposerSend();
3157
3541
  const handleSubmit = (e) => {
@@ -3159,7 +3543,7 @@ var ComposerPrimitiveRoot = forwardRef15(({ onSubmit, ...rest }, forwardedRef) =
3159
3543
  if (!send) return;
3160
3544
  send();
3161
3545
  };
3162
- return /* @__PURE__ */ jsx24(
3546
+ return /* @__PURE__ */ jsx26(
3163
3547
  Primitive8.form,
3164
3548
  {
3165
3549
  ...rest,
@@ -3176,13 +3560,13 @@ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-ref
3176
3560
  import { Slot } from "@radix-ui/react-slot";
3177
3561
  import {
3178
3562
  forwardRef as forwardRef16,
3179
- useCallback as useCallback16,
3180
- useEffect as useEffect10,
3563
+ useCallback as useCallback17,
3564
+ useEffect as useEffect11,
3181
3565
  useRef as useRef4
3182
3566
  } from "react";
3183
3567
  import TextareaAutosize from "react-textarea-autosize";
3184
3568
  import { useEscapeKeydown as useEscapeKeydown2 } from "@radix-ui/react-use-escape-keydown";
3185
- import { jsx as jsx25 } from "react/jsx-runtime";
3569
+ import { jsx as jsx27 } from "react/jsx-runtime";
3186
3570
  var ComposerPrimitiveInput = forwardRef16(
3187
3571
  ({
3188
3572
  autoFocus = false,
@@ -3221,7 +3605,7 @@ var ComposerPrimitiveInput = forwardRef16(
3221
3605
  }
3222
3606
  };
3223
3607
  const autoFocusEnabled = autoFocus && !isDisabled;
3224
- const focus = useCallback16(() => {
3608
+ const focus = useCallback17(() => {
3225
3609
  const textarea = textareaRef.current;
3226
3610
  if (!textarea || !autoFocusEnabled) return;
3227
3611
  textarea.focus({ preventScroll: true });
@@ -3230,13 +3614,13 @@ var ComposerPrimitiveInput = forwardRef16(
3230
3614
  textareaRef.current.value.length
3231
3615
  );
3232
3616
  }, [autoFocusEnabled]);
3233
- useEffect10(() => focus(), [focus]);
3617
+ useEffect11(() => focus(), [focus]);
3234
3618
  useOnComposerFocus(() => {
3235
3619
  if (type === "new") {
3236
3620
  focus();
3237
3621
  }
3238
3622
  });
3239
- return /* @__PURE__ */ jsx25(
3623
+ return /* @__PURE__ */ jsx27(
3240
3624
  Component,
3241
3625
  {
3242
3626
  name: "input",
@@ -3257,23 +3641,10 @@ var ComposerPrimitiveInput = forwardRef16(
3257
3641
  ComposerPrimitiveInput.displayName = "ComposerPrimitive.Input";
3258
3642
 
3259
3643
  // src/primitives/composer/ComposerSend.tsx
3260
- import { forwardRef as forwardRef17 } from "react";
3261
- import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
3262
- import { jsx as jsx26 } from "react/jsx-runtime";
3263
- var ComposerPrimitiveSend = forwardRef17(({ disabled, ...rest }, ref) => {
3264
- const { useComposer } = useComposerContext();
3265
- const hasValue = useComposer((c) => c.isEditing && c.text.length > 0);
3266
- return /* @__PURE__ */ jsx26(
3267
- Primitive9.button,
3268
- {
3269
- type: "submit",
3270
- ...rest,
3271
- ref,
3272
- disabled: disabled || !hasValue
3273
- }
3274
- );
3275
- });
3276
- ComposerPrimitiveSend.displayName = "ComposerPrimitive.Send";
3644
+ var ComposerPrimitiveSend = createActionButton(
3645
+ "ComposerPrimitive.Send",
3646
+ useComposerSend
3647
+ );
3277
3648
 
3278
3649
  // src/primitives/composer/ComposerCancel.tsx
3279
3650
  var ComposerPrimitiveCancel = createActionButton(
@@ -3281,6 +3652,101 @@ var ComposerPrimitiveCancel = createActionButton(
3281
3652
  useComposerCancel
3282
3653
  );
3283
3654
 
3655
+ // src/primitives/composer/ComposerAddAttachment.tsx
3656
+ var ComposerPrimitiveAddAttachment = createActionButton(
3657
+ "ComposerPrimitive.AddAttachment",
3658
+ useComposerAddAttachment
3659
+ );
3660
+
3661
+ // src/primitives/composer/ComposerAttachments.tsx
3662
+ import { memo as memo4 } from "react";
3663
+
3664
+ // src/context/providers/ComposerAttachmentProvider.tsx
3665
+ import { useEffect as useEffect12, useState as useState12 } from "react";
3666
+ import { create as create14 } from "zustand";
3667
+ import { jsx as jsx28 } from "react/jsx-runtime";
3668
+ var getAttachment2 = ({ attachments }, useAttachment, partIndex) => {
3669
+ let attachment = attachments[partIndex];
3670
+ if (!attachment) return null;
3671
+ const currentState = useAttachment?.getState();
3672
+ if (currentState && currentState.attachment === attachment) return null;
3673
+ return Object.freeze({ attachment });
3674
+ };
3675
+ var useComposerAttachmentContext = (partIndex) => {
3676
+ const { useComposer } = useThreadContext();
3677
+ const [context] = useState12(
3678
+ () => {
3679
+ const useAttachment = create14(
3680
+ () => getAttachment2(useComposer.getState(), void 0, partIndex)
3681
+ );
3682
+ return { type: "composer", useAttachment };
3683
+ }
3684
+ );
3685
+ useEffect12(() => {
3686
+ const syncAttachment = (composer) => {
3687
+ const newState = getAttachment2(
3688
+ composer,
3689
+ context.useAttachment,
3690
+ partIndex
3691
+ );
3692
+ if (!newState) return;
3693
+ writableStore(context.useAttachment).setState(newState, true);
3694
+ };
3695
+ syncAttachment(useComposer.getState());
3696
+ return useComposer.subscribe(syncAttachment);
3697
+ }, [context, useComposer, partIndex]);
3698
+ return context;
3699
+ };
3700
+ var ComposerAttachmentProvider = ({ attachmentIndex: partIndex, children }) => {
3701
+ const context = useComposerAttachmentContext(partIndex);
3702
+ return /* @__PURE__ */ jsx28(AttachmentContext.Provider, { value: context, children });
3703
+ };
3704
+
3705
+ // src/primitives/composer/ComposerAttachments.tsx
3706
+ import { jsx as jsx29 } from "react/jsx-runtime";
3707
+ var getComponent2 = (components, attachment) => {
3708
+ const type = attachment.type;
3709
+ switch (type) {
3710
+ case "image":
3711
+ return components?.Image ?? components?.Attachment;
3712
+ case "document":
3713
+ return components?.Document ?? components?.Attachment;
3714
+ case "file":
3715
+ return components?.File ?? components?.Attachment;
3716
+ default:
3717
+ const _exhaustiveCheck = type;
3718
+ throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
3719
+ }
3720
+ };
3721
+ var AttachmentComponent2 = ({ components }) => {
3722
+ const { useAttachment } = useAttachmentContext({ type: "composer" });
3723
+ const Component = useAttachment(
3724
+ (a) => getComponent2(components, a.attachment)
3725
+ );
3726
+ if (!Component) return null;
3727
+ return /* @__PURE__ */ jsx29(Component, {});
3728
+ };
3729
+ var ComposerAttachmentImpl = ({ components, attachmentIndex }) => {
3730
+ return /* @__PURE__ */ jsx29(ComposerAttachmentProvider, { attachmentIndex, children: /* @__PURE__ */ jsx29(AttachmentComponent2, { components }) });
3731
+ };
3732
+ var ComposerAttachment = memo4(
3733
+ ComposerAttachmentImpl,
3734
+ (prev, next) => prev.attachmentIndex === next.attachmentIndex && prev.components?.Image === next.components?.Image && prev.components?.Document === next.components?.Document && prev.components?.File === next.components?.File && prev.components?.Attachment === next.components?.Attachment
3735
+ );
3736
+ var ComposerPrimitiveAttachments = ({ components }) => {
3737
+ const { useComposer } = useThreadContext();
3738
+ const attachmentsCount = useComposer((s) => s.attachments.length);
3739
+ return Array.from({ length: attachmentsCount }, (_, index) => /* @__PURE__ */ jsx29(
3740
+ ComposerAttachment,
3741
+ {
3742
+ attachmentIndex: index,
3743
+ components
3744
+ },
3745
+ index
3746
+ ));
3747
+ };
3748
+ ComposerPrimitiveAttachments.displayName = "ComposerPrimitive.Attachments";
3749
+
3284
3750
  // src/primitives/composer/ComposerIf.tsx
3285
3751
  var ComposerPrimitiveIf = ({
3286
3752
  children,
@@ -3313,11 +3779,11 @@ __export(thread_exports, {
3313
3779
  });
3314
3780
 
3315
3781
  // src/primitives/thread/ThreadRoot.tsx
3316
- import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
3317
- import { forwardRef as forwardRef18 } from "react";
3318
- import { jsx as jsx27 } from "react/jsx-runtime";
3319
- var ThreadPrimitiveRoot = forwardRef18((props, ref) => {
3320
- return /* @__PURE__ */ jsx27(Primitive10.div, { ...props, ref });
3782
+ import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
3783
+ import { forwardRef as forwardRef17 } from "react";
3784
+ import { jsx as jsx30 } from "react/jsx-runtime";
3785
+ var ThreadPrimitiveRoot = forwardRef17((props, ref) => {
3786
+ return /* @__PURE__ */ jsx30(Primitive9.div, { ...props, ref });
3321
3787
  });
3322
3788
  ThreadPrimitiveRoot.displayName = "ThreadPrimitive.Root";
3323
3789
 
@@ -3342,8 +3808,8 @@ ThreadPrimitiveIf.displayName = "ThreadPrimitive.If";
3342
3808
 
3343
3809
  // src/primitives/thread/ThreadViewport.tsx
3344
3810
  import { useComposedRefs as useComposedRefs4 } from "@radix-ui/react-compose-refs";
3345
- import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
3346
- import { forwardRef as forwardRef19 } from "react";
3811
+ import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
3812
+ import { forwardRef as forwardRef18 } from "react";
3347
3813
 
3348
3814
  // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
3349
3815
  import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
@@ -3351,10 +3817,10 @@ import { useRef as useRef5 } from "react";
3351
3817
 
3352
3818
  // src/utils/hooks/useOnResizeContent.tsx
3353
3819
  import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
3354
- import { useCallback as useCallback17 } from "react";
3820
+ import { useCallback as useCallback18 } from "react";
3355
3821
  var useOnResizeContent = (callback) => {
3356
3822
  const callbackRef = useCallbackRef3(callback);
3357
- const refCallback = useCallback17(
3823
+ const refCallback = useCallback18(
3358
3824
  (el) => {
3359
3825
  const resizeObserver = new ResizeObserver(() => {
3360
3826
  callbackRef();
@@ -3391,11 +3857,11 @@ var useOnResizeContent = (callback) => {
3391
3857
 
3392
3858
  // src/utils/hooks/useOnScrollToBottom.tsx
3393
3859
  import { useCallbackRef as useCallbackRef4 } from "@radix-ui/react-use-callback-ref";
3394
- import { useEffect as useEffect11 } from "react";
3860
+ import { useEffect as useEffect13 } from "react";
3395
3861
  var useOnScrollToBottom = (callback) => {
3396
3862
  const callbackRef = useCallbackRef4(callback);
3397
3863
  const { useViewport } = useThreadContext();
3398
- useEffect11(() => {
3864
+ useEffect13(() => {
3399
3865
  return useViewport.getState().onScrollToBottom(() => {
3400
3866
  callbackRef();
3401
3867
  });
@@ -3427,9 +3893,7 @@ var useThreadViewportAutoScroll = ({
3427
3893
  isScrollingToBottomRef.current = false;
3428
3894
  }
3429
3895
  if (newIsAtBottom !== isAtBottom) {
3430
- useViewport.setState({
3431
- isAtBottom: newIsAtBottom
3432
- });
3896
+ writableStore(useViewport).setState({ isAtBottom: newIsAtBottom });
3433
3897
  }
3434
3898
  }
3435
3899
  lastScrollTop.current = div.scrollTop;
@@ -3454,29 +3918,29 @@ var useThreadViewportAutoScroll = ({
3454
3918
  };
3455
3919
 
3456
3920
  // src/primitives/thread/ThreadViewport.tsx
3457
- import { jsx as jsx28 } from "react/jsx-runtime";
3458
- var ThreadPrimitiveViewport = forwardRef19(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
3921
+ import { jsx as jsx31 } from "react/jsx-runtime";
3922
+ var ThreadPrimitiveViewport = forwardRef18(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
3459
3923
  const autoScrollRef = useThreadViewportAutoScroll({
3460
3924
  autoScroll
3461
3925
  });
3462
3926
  const ref = useComposedRefs4(forwardedRef, autoScrollRef);
3463
- return /* @__PURE__ */ jsx28(Primitive11.div, { ...rest, ref, children });
3927
+ return /* @__PURE__ */ jsx31(Primitive10.div, { ...rest, ref, children });
3464
3928
  });
3465
3929
  ThreadPrimitiveViewport.displayName = "ThreadPrimitive.Viewport";
3466
3930
 
3467
3931
  // src/primitives/thread/ThreadMessages.tsx
3468
- import { memo as memo3 } from "react";
3932
+ import { memo as memo5 } from "react";
3469
3933
 
3470
3934
  // src/context/providers/MessageProvider.tsx
3471
- import { useEffect as useEffect12, useState as useState11 } from "react";
3472
- import { create as create15 } from "zustand";
3935
+ import { useEffect as useEffect14, useState as useState13 } from "react";
3936
+ import { create as create17 } from "zustand";
3473
3937
 
3474
3938
  // src/context/stores/EditComposer.ts
3475
- import { create as create13 } from "zustand";
3939
+ import { create as create15 } from "zustand";
3476
3940
  var makeEditComposerStore = ({
3477
3941
  onEdit,
3478
3942
  onSend
3479
- }) => create13()((set, get) => ({
3943
+ }) => create15()((set, get) => ({
3480
3944
  get value() {
3481
3945
  return get().text;
3482
3946
  },
@@ -3485,13 +3949,19 @@ var makeEditComposerStore = ({
3485
3949
  },
3486
3950
  text: "",
3487
3951
  setText: (text) => {
3488
- set({ text });
3952
+ set({ text, isEmpty: text.trim().length === 0 });
3489
3953
  },
3490
3954
  canCancel: false,
3491
3955
  isEditing: false,
3956
+ isEmpty: true,
3492
3957
  edit: () => {
3493
3958
  const text = onEdit();
3494
- set({ isEditing: true, canCancel: true, text });
3959
+ set({
3960
+ isEditing: true,
3961
+ canCancel: true,
3962
+ isEmpty: text.trim().length === 0,
3963
+ text
3964
+ });
3495
3965
  },
3496
3966
  send: () => {
3497
3967
  const text = get().text;
@@ -3504,8 +3974,8 @@ var makeEditComposerStore = ({
3504
3974
  }));
3505
3975
 
3506
3976
  // src/context/stores/MessageUtils.ts
3507
- import { create as create14 } from "zustand";
3508
- var makeMessageUtilsStore = () => create14((set) => {
3977
+ import { create as create16 } from "zustand";
3978
+ var makeMessageUtilsStore = () => create16((set) => {
3509
3979
  let utterance = null;
3510
3980
  return {
3511
3981
  isCopied: false,
@@ -3531,7 +4001,7 @@ var makeMessageUtilsStore = () => create14((set) => {
3531
4001
  });
3532
4002
 
3533
4003
  // src/context/providers/MessageProvider.tsx
3534
- import { jsx as jsx29 } from "react/jsx-runtime";
4004
+ import { jsx as jsx32 } from "react/jsx-runtime";
3535
4005
  var getIsLast = (messages, message) => {
3536
4006
  return messages[messages.length - 1]?.id === message.id;
3537
4007
  };
@@ -3553,8 +4023,8 @@ var getMessageState = (messages, getBranches, useMessage, messageIndex) => {
3553
4023
  };
3554
4024
  var useMessageContext2 = (messageIndex) => {
3555
4025
  const { useThreadMessages, useThreadActions } = useThreadContext();
3556
- const [context] = useState11(() => {
3557
- const useMessage = create15(
4026
+ const [context] = useState13(() => {
4027
+ const useMessage = create17(
3558
4028
  () => getMessageState(
3559
4029
  useThreadMessages.getState(),
3560
4030
  useThreadActions.getState().getBranches,
@@ -3585,13 +4055,14 @@ var useMessageContext2 = (messageIndex) => {
3585
4055
  useThreadActions.getState().append({
3586
4056
  parentId,
3587
4057
  role: "user",
3588
- content: [{ type: "text", text }, ...nonTextParts]
4058
+ content: [{ type: "text", text }, ...nonTextParts],
4059
+ attachments: message.attachments
3589
4060
  });
3590
4061
  }
3591
4062
  });
3592
4063
  return { useMessage, useMessageUtils, useEditComposer };
3593
4064
  });
3594
- useEffect12(() => {
4065
+ useEffect14(() => {
3595
4066
  const syncMessage = (thread) => {
3596
4067
  const newState = getMessageState(
3597
4068
  thread,
@@ -3600,10 +4071,7 @@ var useMessageContext2 = (messageIndex) => {
3600
4071
  messageIndex
3601
4072
  );
3602
4073
  if (!newState) return;
3603
- context.useMessage.setState(
3604
- newState,
3605
- true
3606
- );
4074
+ writableStore(context.useMessage).setState(newState, true);
3607
4075
  };
3608
4076
  syncMessage(useThreadMessages.getState());
3609
4077
  return useThreadMessages.subscribe(syncMessage);
@@ -3615,11 +4083,11 @@ var MessageProvider = ({
3615
4083
  children
3616
4084
  }) => {
3617
4085
  const context = useMessageContext2(messageIndex);
3618
- return /* @__PURE__ */ jsx29(MessageContext.Provider, { value: context, children });
4086
+ return /* @__PURE__ */ jsx32(MessageContext.Provider, { value: context, children });
3619
4087
  };
3620
4088
 
3621
4089
  // src/primitives/thread/ThreadMessages.tsx
3622
- import { jsx as jsx30, jsxs as jsxs4 } from "react/jsx-runtime";
4090
+ import { jsx as jsx33, jsxs as jsxs4 } from "react/jsx-runtime";
3623
4091
  var DEFAULT_SYSTEM_MESSAGE = () => null;
3624
4092
  var getComponents = (components) => {
3625
4093
  return {
@@ -3636,14 +4104,14 @@ var ThreadMessageImpl = ({
3636
4104
  const { UserMessage: UserMessage2, EditComposer: EditComposer2, AssistantMessage: AssistantMessage2, SystemMessage: SystemMessage2 } = getComponents(components);
3637
4105
  return /* @__PURE__ */ jsxs4(MessageProvider, { messageIndex, children: [
3638
4106
  /* @__PURE__ */ jsxs4(MessagePrimitiveIf, { user: true, children: [
3639
- /* @__PURE__ */ jsx30(ComposerPrimitiveIf, { editing: false, children: /* @__PURE__ */ jsx30(UserMessage2, {}) }),
3640
- /* @__PURE__ */ jsx30(ComposerPrimitiveIf, { editing: true, children: /* @__PURE__ */ jsx30(EditComposer2, {}) })
4107
+ /* @__PURE__ */ jsx33(ComposerPrimitiveIf, { editing: false, children: /* @__PURE__ */ jsx33(UserMessage2, {}) }),
4108
+ /* @__PURE__ */ jsx33(ComposerPrimitiveIf, { editing: true, children: /* @__PURE__ */ jsx33(EditComposer2, {}) })
3641
4109
  ] }),
3642
- /* @__PURE__ */ jsx30(MessagePrimitiveIf, { assistant: true, children: /* @__PURE__ */ jsx30(AssistantMessage2, {}) }),
3643
- /* @__PURE__ */ jsx30(MessagePrimitiveIf, { system: true, children: /* @__PURE__ */ jsx30(SystemMessage2, {}) })
4110
+ /* @__PURE__ */ jsx33(MessagePrimitiveIf, { assistant: true, children: /* @__PURE__ */ jsx33(AssistantMessage2, {}) }),
4111
+ /* @__PURE__ */ jsx33(MessagePrimitiveIf, { system: true, children: /* @__PURE__ */ jsx33(SystemMessage2, {}) })
3644
4112
  ] });
3645
4113
  };
3646
- var ThreadMessage = memo3(
4114
+ var ThreadMessage = memo5(
3647
4115
  ThreadMessageImpl,
3648
4116
  (prev, next) => prev.messageIndex === next.messageIndex && prev.components.Message === next.components.Message && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage && prev.components.SystemMessage === next.components.SystemMessage
3649
4117
  );
@@ -3653,20 +4121,10 @@ var ThreadPrimitiveMessagesImpl = ({
3653
4121
  const { useThreadMessages } = useThreadContext();
3654
4122
  const messagesLength = useThreadMessages((t) => t.length);
3655
4123
  if (messagesLength === 0) return null;
3656
- return new Array(messagesLength).fill(null).map((_, idx) => {
3657
- const messageIndex = idx;
3658
- return /* @__PURE__ */ jsx30(
3659
- ThreadMessage,
3660
- {
3661
- messageIndex,
3662
- components
3663
- },
3664
- messageIndex
3665
- );
3666
- });
4124
+ return Array.from({ length: messagesLength }, (_, index) => /* @__PURE__ */ jsx33(ThreadMessage, { messageIndex: index, components }, index));
3667
4125
  };
3668
4126
  ThreadPrimitiveMessagesImpl.displayName = "ThreadPrimitive.Messages";
3669
- var ThreadPrimitiveMessages = memo3(
4127
+ var ThreadPrimitiveMessages = memo5(
3670
4128
  ThreadPrimitiveMessagesImpl,
3671
4129
  (prev, next) => prev.components?.Message === next.components?.Message && prev.components?.UserMessage === next.components?.UserMessage && prev.components?.EditComposer === next.components?.EditComposer && prev.components?.AssistantMessage === next.components?.AssistantMessage && prev.components?.SystemMessage === next.components?.SystemMessage
3672
4130
  );
@@ -3686,32 +4144,32 @@ var ThreadPrimitiveSuggestion = createActionButton(
3686
4144
 
3687
4145
  // src/ui/thread-config.tsx
3688
4146
  import {
3689
- createContext as createContext6,
3690
- useContext as useContext6
4147
+ createContext as createContext7,
4148
+ useContext as useContext7
3691
4149
  } from "react";
3692
- import { Fragment as Fragment3, jsx as jsx31 } from "react/jsx-runtime";
3693
- var ThreadConfigContext = createContext6({});
4150
+ import { Fragment as Fragment3, jsx as jsx34 } from "react/jsx-runtime";
4151
+ var ThreadConfigContext = createContext7({});
3694
4152
  var useThreadConfig = () => {
3695
- return useContext6(ThreadConfigContext);
4153
+ return useContext7(ThreadConfigContext);
3696
4154
  };
3697
4155
  var ThreadConfigProvider = ({
3698
4156
  children,
3699
4157
  config
3700
4158
  }) => {
3701
4159
  const assistant = useAssistantContext({ optional: true });
3702
- const configProvider = config && Object.keys(config ?? {}).length > 0 ? /* @__PURE__ */ jsx31(ThreadConfigContext.Provider, { value: config, children }) : /* @__PURE__ */ jsx31(Fragment3, { children });
4160
+ const configProvider = config && Object.keys(config ?? {}).length > 0 ? /* @__PURE__ */ jsx34(ThreadConfigContext.Provider, { value: config, children }) : /* @__PURE__ */ jsx34(Fragment3, { children });
3703
4161
  if (!config?.runtime) return configProvider;
3704
4162
  if (assistant) {
3705
4163
  throw new Error(
3706
4164
  "You provided a runtime to <Thread> while simulataneously using <AssistantRuntimeProvider>. This is not allowed."
3707
4165
  );
3708
4166
  }
3709
- return /* @__PURE__ */ jsx31(AssistantRuntimeProvider, { runtime: config.runtime, children: configProvider });
4167
+ return /* @__PURE__ */ jsx34(AssistantRuntimeProvider, { runtime: config.runtime, children: configProvider });
3710
4168
  };
3711
4169
  ThreadConfigProvider.displayName = "ThreadConfigProvider";
3712
4170
 
3713
4171
  // src/ui/assistant-action-bar.tsx
3714
- import { forwardRef as forwardRef20 } from "react";
4172
+ import { forwardRef as forwardRef19 } from "react";
3715
4173
  import {
3716
4174
  AudioLinesIcon,
3717
4175
  CheckIcon,
@@ -3719,7 +4177,7 @@ import {
3719
4177
  RefreshCwIcon,
3720
4178
  StopCircleIcon
3721
4179
  } from "lucide-react";
3722
- import { Fragment as Fragment4, jsx as jsx32, jsxs as jsxs5 } from "react/jsx-runtime";
4180
+ import { Fragment as Fragment4, jsx as jsx35, jsxs as jsxs5 } from "react/jsx-runtime";
3723
4181
  var useAllowCopy = (ensureCapability = false) => {
3724
4182
  const { assistantMessage: { allowCopy = true } = {} } = useThreadConfig();
3725
4183
  const { useThread } = useThreadContext();
@@ -3750,9 +4208,9 @@ var AssistantActionBar = () => {
3750
4208
  autohide: "not-last",
3751
4209
  autohideFloat: "single-branch",
3752
4210
  children: [
3753
- allowSpeak && /* @__PURE__ */ jsx32(AssistantActionBarSpeechControl, {}),
3754
- allowCopy && /* @__PURE__ */ jsx32(AssistantActionBarCopy, {}),
3755
- allowReload && /* @__PURE__ */ jsx32(AssistantActionBarReload, {})
4211
+ allowSpeak && /* @__PURE__ */ jsx35(AssistantActionBarSpeechControl, {}),
4212
+ allowCopy && /* @__PURE__ */ jsx35(AssistantActionBarCopy, {}),
4213
+ allowReload && /* @__PURE__ */ jsx35(AssistantActionBarReload, {})
3756
4214
  ]
3757
4215
  }
3758
4216
  );
@@ -3762,36 +4220,35 @@ var AssistantActionBarRoot = withDefaults(actionBar_exports.Root, {
3762
4220
  className: "aui-assistant-action-bar-root"
3763
4221
  });
3764
4222
  AssistantActionBarRoot.displayName = "AssistantActionBarRoot";
3765
- var AssistantActionBarCopy = forwardRef20((props, ref) => {
4223
+ var AssistantActionBarCopy = forwardRef19((props, ref) => {
3766
4224
  const {
3767
4225
  strings: {
3768
4226
  assistantMessage: { copy: { tooltip = "Copy" } = {} } = {}
3769
4227
  } = {}
3770
4228
  } = useThreadConfig();
3771
- return /* @__PURE__ */ jsx32(actionBar_exports.Copy, { asChild: true, children: /* @__PURE__ */ jsx32(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
3772
- /* @__PURE__ */ jsx32(message_exports.If, { copied: true, children: /* @__PURE__ */ jsx32(CheckIcon, {}) }),
3773
- /* @__PURE__ */ jsx32(message_exports.If, { copied: false, children: /* @__PURE__ */ jsx32(CopyIcon, {}) })
4229
+ return /* @__PURE__ */ jsx35(actionBar_exports.Copy, { asChild: true, children: /* @__PURE__ */ jsx35(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
4230
+ /* @__PURE__ */ jsx35(message_exports.If, { copied: true, children: /* @__PURE__ */ jsx35(CheckIcon, {}) }),
4231
+ /* @__PURE__ */ jsx35(message_exports.If, { copied: false, children: /* @__PURE__ */ jsx35(CopyIcon, {}) })
3774
4232
  ] }) }) });
3775
4233
  });
3776
4234
  AssistantActionBarCopy.displayName = "AssistantActionBarCopy";
3777
4235
  var AssistantActionBarSpeechControl = () => {
3778
4236
  return /* @__PURE__ */ jsxs5(Fragment4, { children: [
3779
- /* @__PURE__ */ jsx32(message_exports.If, { speaking: false, children: /* @__PURE__ */ jsx32(AssistantActionBarSpeak, {}) }),
3780
- /* @__PURE__ */ jsx32(message_exports.If, { speaking: true, children: /* @__PURE__ */ jsx32(AssistantActionBarStopSpeaking, {}) })
4237
+ /* @__PURE__ */ jsx35(message_exports.If, { speaking: false, children: /* @__PURE__ */ jsx35(AssistantActionBarSpeak, {}) }),
4238
+ /* @__PURE__ */ jsx35(message_exports.If, { speaking: true, children: /* @__PURE__ */ jsx35(AssistantActionBarStopSpeaking, {}) })
3781
4239
  ] });
3782
4240
  };
3783
- var AssistantActionBarSpeak = forwardRef20((props, ref) => {
4241
+ var AssistantActionBarSpeak = forwardRef19((props, ref) => {
3784
4242
  const {
3785
4243
  strings: {
3786
4244
  assistantMessage: { speak: { tooltip = "Read aloud" } = {} } = {}
3787
4245
  } = {}
3788
4246
  } = useThreadConfig();
3789
4247
  const allowSpeak = useAllowSpeak();
3790
- if (!allowSpeak) return null;
3791
- return /* @__PURE__ */ jsx32(actionBar_exports.Speak, { asChild: true, children: /* @__PURE__ */ jsx32(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx32(AudioLinesIcon, {}) }) });
4248
+ return /* @__PURE__ */ jsx35(actionBar_exports.Speak, { disabled: !allowSpeak, asChild: true, children: /* @__PURE__ */ jsx35(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx35(AudioLinesIcon, {}) }) });
3792
4249
  });
3793
4250
  AssistantActionBarSpeak.displayName = "AssistantActionBarSpeak";
3794
- var AssistantActionBarStopSpeaking = forwardRef20((props, ref) => {
4251
+ var AssistantActionBarStopSpeaking = forwardRef19((props, ref) => {
3795
4252
  const {
3796
4253
  strings: {
3797
4254
  assistantMessage: {
@@ -3800,19 +4257,17 @@ var AssistantActionBarStopSpeaking = forwardRef20((props, ref) => {
3800
4257
  } = {}
3801
4258
  } = useThreadConfig();
3802
4259
  const allowSpeak = useAllowSpeak();
3803
- if (!allowSpeak) return null;
3804
- return /* @__PURE__ */ jsx32(actionBar_exports.StopSpeaking, { asChild: true, children: /* @__PURE__ */ jsx32(TooltipIconButton, { tooltip: stopTooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx32(StopCircleIcon, {}) }) });
4260
+ return /* @__PURE__ */ jsx35(actionBar_exports.StopSpeaking, { disabled: !allowSpeak, asChild: true, children: /* @__PURE__ */ jsx35(TooltipIconButton, { tooltip: stopTooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx35(StopCircleIcon, {}) }) });
3805
4261
  });
3806
4262
  AssistantActionBarStopSpeaking.displayName = "AssistantActionBarStopSpeaking";
3807
- var AssistantActionBarReload = forwardRef20((props, ref) => {
4263
+ var AssistantActionBarReload = forwardRef19((props, ref) => {
3808
4264
  const {
3809
4265
  strings: {
3810
4266
  assistantMessage: { reload: { tooltip = "Refresh" } = {} } = {}
3811
4267
  } = {}
3812
4268
  } = useThreadConfig();
3813
4269
  const allowReload = useAllowReload();
3814
- if (!allowReload) return null;
3815
- return /* @__PURE__ */ jsx32(actionBar_exports.Reload, { asChild: true, children: /* @__PURE__ */ jsx32(TooltipIconButton, { tooltip, ...props, ref, children: /* @__PURE__ */ jsx32(RefreshCwIcon, {}) }) });
4270
+ return /* @__PURE__ */ jsx35(actionBar_exports.Reload, { disabled: !allowReload, asChild: true, children: /* @__PURE__ */ jsx35(TooltipIconButton, { tooltip, ...props, ref, children: /* @__PURE__ */ jsx35(RefreshCwIcon, {}) }) });
3816
4271
  });
3817
4272
  AssistantActionBarReload.displayName = "AssistantActionBarReload";
3818
4273
  var exports = {
@@ -3829,25 +4284,25 @@ var assistant_action_bar_default = Object.assign(
3829
4284
  );
3830
4285
 
3831
4286
  // src/ui/assistant-message.tsx
3832
- import { forwardRef as forwardRef22 } from "react";
4287
+ import { forwardRef as forwardRef21, useMemo as useMemo5 } from "react";
3833
4288
 
3834
4289
  // src/ui/branch-picker.tsx
3835
- import { forwardRef as forwardRef21 } from "react";
4290
+ import { forwardRef as forwardRef20 } from "react";
3836
4291
  import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
3837
- import { jsx as jsx33, jsxs as jsxs6 } from "react/jsx-runtime";
3838
- var useAllowBranchPicker = () => {
4292
+ import { jsx as jsx36, jsxs as jsxs6 } from "react/jsx-runtime";
4293
+ var useAllowBranchPicker = (ensureCapability = false) => {
3839
4294
  const { branchPicker: { allowBranchPicker = true } = {} } = useThreadConfig();
3840
4295
  const { useThread } = useThreadContext();
3841
4296
  const branchPickerSupported = useThread((t) => t.capabilities.edit);
3842
- return branchPickerSupported && allowBranchPicker;
4297
+ return allowBranchPicker && (!ensureCapability || branchPickerSupported);
3843
4298
  };
3844
4299
  var BranchPicker = () => {
3845
4300
  const allowBranchPicker = useAllowBranchPicker();
3846
4301
  if (!allowBranchPicker) return null;
3847
4302
  return /* @__PURE__ */ jsxs6(BranchPickerRoot, { hideWhenSingleBranch: true, children: [
3848
- /* @__PURE__ */ jsx33(BranchPickerPrevious2, {}),
3849
- /* @__PURE__ */ jsx33(BranchPickerState, {}),
3850
- /* @__PURE__ */ jsx33(BranchPickerNext, {})
4303
+ /* @__PURE__ */ jsx36(BranchPickerPrevious2, {}),
4304
+ /* @__PURE__ */ jsx36(BranchPickerState, {}),
4305
+ /* @__PURE__ */ jsx36(BranchPickerNext, {})
3851
4306
  ] });
3852
4307
  };
3853
4308
  BranchPicker.displayName = "BranchPicker";
@@ -3855,31 +4310,33 @@ var BranchPickerRoot = withDefaults(branchPicker_exports.Root, {
3855
4310
  className: "aui-branch-picker-root"
3856
4311
  });
3857
4312
  BranchPickerRoot.displayName = "BranchPickerRoot";
3858
- var BranchPickerPrevious2 = forwardRef21((props, ref) => {
4313
+ var BranchPickerPrevious2 = forwardRef20((props, ref) => {
3859
4314
  const {
3860
4315
  strings: {
3861
4316
  branchPicker: { previous: { tooltip = "Previous" } = {} } = {}
3862
4317
  } = {}
3863
4318
  } = useThreadConfig();
3864
- return /* @__PURE__ */ jsx33(branchPicker_exports.Previous, { asChild: true, children: /* @__PURE__ */ jsx33(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx33(ChevronLeftIcon, {}) }) });
4319
+ const allowBranchPicker = useAllowBranchPicker();
4320
+ return /* @__PURE__ */ jsx36(branchPicker_exports.Previous, { disabled: !allowBranchPicker, asChild: true, children: /* @__PURE__ */ jsx36(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx36(ChevronLeftIcon, {}) }) });
3865
4321
  });
3866
4322
  BranchPickerPrevious2.displayName = "BranchPickerPrevious";
3867
4323
  var BranchPickerStateWrapper = withDefaults("span", {
3868
4324
  className: "aui-branch-picker-state"
3869
4325
  });
3870
- var BranchPickerState = forwardRef21((props, ref) => {
4326
+ var BranchPickerState = forwardRef20((props, ref) => {
3871
4327
  return /* @__PURE__ */ jsxs6(BranchPickerStateWrapper, { ...props, ref, children: [
3872
- /* @__PURE__ */ jsx33(branchPicker_exports.Number, {}),
4328
+ /* @__PURE__ */ jsx36(branchPicker_exports.Number, {}),
3873
4329
  " / ",
3874
- /* @__PURE__ */ jsx33(branchPicker_exports.Count, {})
4330
+ /* @__PURE__ */ jsx36(branchPicker_exports.Count, {})
3875
4331
  ] });
3876
4332
  });
3877
4333
  BranchPickerState.displayName = "BranchPickerState";
3878
- var BranchPickerNext = forwardRef21((props, ref) => {
4334
+ var BranchPickerNext = forwardRef20((props, ref) => {
3879
4335
  const {
3880
4336
  strings: { branchPicker: { next: { tooltip = "Next" } = {} } = {} } = {}
3881
4337
  } = useThreadConfig();
3882
- return /* @__PURE__ */ jsx33(branchPicker_exports.Next, { asChild: true, children: /* @__PURE__ */ jsx33(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx33(ChevronRightIcon, {}) }) });
4338
+ const allowBranchPicker = useAllowBranchPicker();
4339
+ return /* @__PURE__ */ jsx36(branchPicker_exports.Next, { disabled: !allowBranchPicker, asChild: true, children: /* @__PURE__ */ jsx36(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx36(ChevronRightIcon, {}) }) });
3883
4340
  });
3884
4341
  BranchPickerNext.displayName = "BranchPickerNext";
3885
4342
  var exports2 = {
@@ -3891,12 +4348,12 @@ var branch_picker_default = Object.assign(BranchPicker, exports2);
3891
4348
 
3892
4349
  // src/ui/base/avatar.tsx
3893
4350
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
3894
- import { jsx as jsx34, jsxs as jsxs7 } from "react/jsx-runtime";
4351
+ import { jsx as jsx37, jsxs as jsxs7 } from "react/jsx-runtime";
3895
4352
  var Avatar = ({ src, alt, fallback }) => {
3896
4353
  if (src == null && fallback == null) return null;
3897
4354
  return /* @__PURE__ */ jsxs7(AvatarRoot, { children: [
3898
- src != null && /* @__PURE__ */ jsx34(AvatarImage, { src, alt }),
3899
- fallback != null && /* @__PURE__ */ jsx34(AvatarFallback, { children: fallback })
4355
+ src != null && /* @__PURE__ */ jsx37(AvatarImage, { src, alt }),
4356
+ fallback != null && /* @__PURE__ */ jsx37(AvatarFallback, { children: fallback })
3900
4357
  ] });
3901
4358
  };
3902
4359
  Avatar.displayName = "Avatar";
@@ -3915,10 +4372,10 @@ AvatarFallback.displayName = "AvatarFallback";
3915
4372
 
3916
4373
  // src/ui/content-part.tsx
3917
4374
  import classNames2 from "classnames";
3918
- import { jsx as jsx35 } from "react/jsx-runtime";
4375
+ import { jsx as jsx38 } from "react/jsx-runtime";
3919
4376
  var Text = () => {
3920
4377
  const status = useSmoothStatus();
3921
- return /* @__PURE__ */ jsx35(
4378
+ return /* @__PURE__ */ jsx38(
3922
4379
  contentPart_exports.Text,
3923
4380
  {
3924
4381
  className: classNames2(
@@ -3933,19 +4390,19 @@ var exports3 = { Text: withSmoothContextProvider(Text) };
3933
4390
  var content_part_default = exports3;
3934
4391
 
3935
4392
  // src/ui/assistant-message.tsx
3936
- import { jsx as jsx36, jsxs as jsxs8 } from "react/jsx-runtime";
4393
+ import { jsx as jsx39, jsxs as jsxs8 } from "react/jsx-runtime";
3937
4394
  var AssistantMessage = () => {
3938
4395
  return /* @__PURE__ */ jsxs8(AssistantMessageRoot, { children: [
3939
- /* @__PURE__ */ jsx36(AssistantMessageAvatar, {}),
3940
- /* @__PURE__ */ jsx36(AssistantMessageContent, {}),
3941
- /* @__PURE__ */ jsx36(branch_picker_default, {}),
3942
- /* @__PURE__ */ jsx36(assistant_action_bar_default, {})
4396
+ /* @__PURE__ */ jsx39(AssistantMessageAvatar, {}),
4397
+ /* @__PURE__ */ jsx39(AssistantMessageContent, {}),
4398
+ /* @__PURE__ */ jsx39(branch_picker_default, {}),
4399
+ /* @__PURE__ */ jsx39(assistant_action_bar_default, {})
3943
4400
  ] });
3944
4401
  };
3945
4402
  AssistantMessage.displayName = "AssistantMessage";
3946
4403
  var AssistantMessageAvatar = () => {
3947
4404
  const { assistantAvatar: avatar = { fallback: "A" } } = useThreadConfig();
3948
- return /* @__PURE__ */ jsx36(Avatar, { ...avatar });
4405
+ return /* @__PURE__ */ jsx39(Avatar, { ...avatar });
3949
4406
  };
3950
4407
  var AssistantMessageRoot = withDefaults(message_exports.Root, {
3951
4408
  className: "aui-assistant-message-root"
@@ -3954,14 +4411,28 @@ AssistantMessageRoot.displayName = "AssistantMessageRoot";
3954
4411
  var AssistantMessageContentWrapper = withDefaults("div", {
3955
4412
  className: "aui-assistant-message-content"
3956
4413
  });
3957
- var AssistantMessageContent = forwardRef22(({ components: componentsProp, ...rest }, ref) => {
3958
- const { assistantMessage: { components = {} } = {} } = useThreadConfig();
3959
- return /* @__PURE__ */ jsx36(AssistantMessageContentWrapper, { ...rest, ref, children: /* @__PURE__ */ jsx36(
4414
+ var AssistantMessageContent = forwardRef21(({ components: componentsProp, ...rest }, ref) => {
4415
+ const { tools, assistantMessage: { components = {} } = {} } = useThreadConfig();
4416
+ const toolsComponents = useMemo5(
4417
+ () => ({
4418
+ by_name: !tools ? void 0 : Object.fromEntries(
4419
+ tools.map((t) => [
4420
+ t.unstable_tool.toolName,
4421
+ t.unstable_tool.render
4422
+ ])
4423
+ ),
4424
+ Fallback: components.ToolFallback
4425
+ }),
4426
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4427
+ [...tools ?? [], components.ToolFallback]
4428
+ );
4429
+ return /* @__PURE__ */ jsx39(AssistantMessageContentWrapper, { ...rest, ref, children: /* @__PURE__ */ jsx39(
3960
4430
  message_exports.Content,
3961
4431
  {
3962
4432
  components: {
3963
4433
  ...componentsProp,
3964
- Text: componentsProp?.Text ?? components.Text ?? content_part_default.Text
4434
+ Text: componentsProp?.Text ?? components.Text ?? content_part_default.Text,
4435
+ tools: toolsComponents
3965
4436
  }
3966
4437
  }
3967
4438
  ) });
@@ -3987,12 +4458,12 @@ import { ArrowDownIcon } from "lucide-react";
3987
4458
 
3988
4459
  // src/ui/composer.tsx
3989
4460
  import { forwardRef as forwardRef23 } from "react";
3990
- import { SendHorizontalIcon } from "lucide-react";
4461
+ import { PaperclipIcon, SendHorizontalIcon } from "lucide-react";
3991
4462
 
3992
4463
  // src/ui/base/CircleStopIcon.tsx
3993
- import { jsx as jsx37 } from "react/jsx-runtime";
4464
+ import { jsx as jsx40 } from "react/jsx-runtime";
3994
4465
  var CircleStopIcon = () => {
3995
- return /* @__PURE__ */ jsx37(
4466
+ return /* @__PURE__ */ jsx40(
3996
4467
  "svg",
3997
4468
  {
3998
4469
  xmlns: "http://www.w3.org/2000/svg",
@@ -4000,18 +4471,79 @@ var CircleStopIcon = () => {
4000
4471
  fill: "currentColor",
4001
4472
  width: "16",
4002
4473
  height: "16",
4003
- children: /* @__PURE__ */ jsx37("rect", { width: "10", height: "10", x: "3", y: "3", rx: "2" })
4474
+ children: /* @__PURE__ */ jsx40("rect", { width: "10", height: "10", x: "3", y: "3", rx: "2" })
4004
4475
  }
4005
4476
  );
4006
4477
  };
4007
4478
  CircleStopIcon.displayName = "CircleStopIcon";
4008
4479
 
4480
+ // src/ui/composer-attachment.tsx
4481
+ import { forwardRef as forwardRef22 } from "react";
4482
+ import { CircleXIcon } from "lucide-react";
4483
+ import { jsx as jsx41, jsxs as jsxs9 } from "react/jsx-runtime";
4484
+ var ComposerAttachmentRoot = withDefaults("div", {
4485
+ className: "aui-composer-attachment-root"
4486
+ });
4487
+ ComposerAttachmentRoot.displayName = "ComposerAttachmentRoot";
4488
+ var ComposerAttachment2 = () => {
4489
+ const { useAttachment } = useAttachmentContext({ type: "composer" });
4490
+ const attachment = useAttachment((a) => a.attachment);
4491
+ return /* @__PURE__ */ jsxs9(ComposerAttachmentRoot, { children: [
4492
+ ".",
4493
+ attachment.name.split(".").pop(),
4494
+ /* @__PURE__ */ jsx41(ComposerAttachmentRemove, {})
4495
+ ] });
4496
+ };
4497
+ ComposerAttachment2.displayName = "ComposerAttachment";
4498
+ var ComposerAttachmentRemove = forwardRef22((props, ref) => {
4499
+ const {
4500
+ strings: {
4501
+ composer: { removeAttachment: { tooltip = "Remove file" } = {} } = {}
4502
+ } = {}
4503
+ } = useThreadConfig();
4504
+ const { useComposer } = useThreadContext();
4505
+ const { useAttachment } = useAttachmentContext();
4506
+ const handleRemoveAttachment = () => {
4507
+ useComposer.getState().removeAttachment(useAttachment.getState().attachment.id);
4508
+ };
4509
+ return /* @__PURE__ */ jsx41(
4510
+ TooltipIconButton,
4511
+ {
4512
+ tooltip,
4513
+ className: "aui-composer-attachment-remove",
4514
+ side: "top",
4515
+ ...props,
4516
+ onClick: handleRemoveAttachment,
4517
+ ref,
4518
+ children: props.children ?? /* @__PURE__ */ jsx41(CircleXIcon, {})
4519
+ }
4520
+ );
4521
+ });
4522
+ ComposerAttachmentRemove.displayName = "ComposerAttachmentRemove";
4523
+ var exports5 = {
4524
+ Root: ComposerAttachmentRoot,
4525
+ Remove: ComposerAttachmentRemove
4526
+ };
4527
+ var composer_attachment_default = Object.assign(
4528
+ ComposerAttachment2,
4529
+ exports5
4530
+ );
4531
+
4009
4532
  // src/ui/composer.tsx
4010
- import { Fragment as Fragment5, jsx as jsx38, jsxs as jsxs9 } from "react/jsx-runtime";
4533
+ import { Fragment as Fragment5, jsx as jsx42, jsxs as jsxs10 } from "react/jsx-runtime";
4534
+ var useAllowAttachments = (ensureCapability = false) => {
4535
+ const { composer: { allowAttachments = true } = {} } = useThreadConfig();
4536
+ const { useThread } = useThreadContext();
4537
+ const attachmentsSupported = useThread((t) => t.capabilities.attachments);
4538
+ return allowAttachments && (!ensureCapability || attachmentsSupported);
4539
+ };
4011
4540
  var Composer = () => {
4012
- return /* @__PURE__ */ jsxs9(ComposerRoot, { children: [
4013
- /* @__PURE__ */ jsx38(ComposerInput, { autoFocus: true }),
4014
- /* @__PURE__ */ jsx38(ComposerAction, {})
4541
+ const allowAttachments = useAllowAttachments(true);
4542
+ return /* @__PURE__ */ jsxs10(ComposerRoot, { children: [
4543
+ allowAttachments && /* @__PURE__ */ jsx42(ComposerAttachments, {}),
4544
+ allowAttachments && /* @__PURE__ */ jsx42(ComposerAddAttachment, {}),
4545
+ /* @__PURE__ */ jsx42(ComposerInput, { autoFocus: true }),
4546
+ /* @__PURE__ */ jsx42(ComposerAction, {})
4015
4547
  ] });
4016
4548
  };
4017
4549
  Composer.displayName = "Composer";
@@ -4031,10 +4563,47 @@ var ComposerInput = forwardRef23(
4031
4563
  composer: { input: { placeholder = "Write a message..." } = {} } = {}
4032
4564
  } = {}
4033
4565
  } = useThreadConfig();
4034
- return /* @__PURE__ */ jsx38(ComposerInputStyled, { placeholder, ...props, ref });
4566
+ return /* @__PURE__ */ jsx42(ComposerInputStyled, { placeholder, ...props, ref });
4035
4567
  }
4036
4568
  );
4037
4569
  ComposerInput.displayName = "ComposerInput";
4570
+ var ComposerAttachmentsContainer = withDefaults("div", {
4571
+ className: "aui-composer-attachments"
4572
+ });
4573
+ var ComposerAttachments = ({ components }) => {
4574
+ return /* @__PURE__ */ jsx42(ComposerAttachmentsContainer, { children: /* @__PURE__ */ jsx42(
4575
+ composer_exports.Attachments,
4576
+ {
4577
+ components: {
4578
+ ...components,
4579
+ Attachment: components?.Attachment ?? composer_attachment_default
4580
+ }
4581
+ }
4582
+ ) });
4583
+ };
4584
+ var ComposerAttachButton = withDefaults(TooltipIconButton, {
4585
+ variant: "default",
4586
+ className: "aui-composer-attach"
4587
+ });
4588
+ var ComposerAddAttachment = forwardRef23((props, ref) => {
4589
+ const {
4590
+ strings: {
4591
+ composer: { addAttachment: { tooltip = "Attach file" } = {} } = {}
4592
+ } = {}
4593
+ } = useThreadConfig();
4594
+ const allowAttachments = useAllowAttachments();
4595
+ return /* @__PURE__ */ jsx42(composer_exports.AddAttachment, { disabled: !allowAttachments, asChild: true, children: /* @__PURE__ */ jsx42(
4596
+ ComposerAttachButton,
4597
+ {
4598
+ tooltip,
4599
+ variant: "ghost",
4600
+ ...props,
4601
+ ref,
4602
+ children: props.children ?? /* @__PURE__ */ jsx42(PaperclipIcon, {})
4603
+ }
4604
+ ) });
4605
+ });
4606
+ ComposerAddAttachment.displayName = "ComposerAddAttachment";
4038
4607
  var useAllowCancel = () => {
4039
4608
  const { useThread } = useThreadContext();
4040
4609
  const cancelSupported = useThread((t) => t.capabilities.cancel);
@@ -4042,10 +4611,10 @@ var useAllowCancel = () => {
4042
4611
  };
4043
4612
  var ComposerAction = () => {
4044
4613
  const allowCancel = useAllowCancel();
4045
- if (!allowCancel) return /* @__PURE__ */ jsx38(ComposerSend, {});
4046
- return /* @__PURE__ */ jsxs9(Fragment5, { children: [
4047
- /* @__PURE__ */ jsx38(thread_exports.If, { running: false, children: /* @__PURE__ */ jsx38(ComposerSend, {}) }),
4048
- /* @__PURE__ */ jsx38(thread_exports.If, { running: true, children: /* @__PURE__ */ jsx38(ComposerCancel, {}) })
4614
+ if (!allowCancel) return /* @__PURE__ */ jsx42(ComposerSend, {});
4615
+ return /* @__PURE__ */ jsxs10(Fragment5, { children: [
4616
+ /* @__PURE__ */ jsx42(thread_exports.If, { running: false, children: /* @__PURE__ */ jsx42(ComposerSend, {}) }),
4617
+ /* @__PURE__ */ jsx42(thread_exports.If, { running: true, children: /* @__PURE__ */ jsx42(ComposerCancel, {}) })
4049
4618
  ] });
4050
4619
  };
4051
4620
  ComposerAction.displayName = "ComposerAction";
@@ -4057,7 +4626,7 @@ var ComposerSend = forwardRef23((props, ref) => {
4057
4626
  const {
4058
4627
  strings: { composer: { send: { tooltip = "Send" } = {} } = {} } = {}
4059
4628
  } = useThreadConfig();
4060
- return /* @__PURE__ */ jsx38(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx38(ComposerSendButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx38(SendHorizontalIcon, {}) }) });
4629
+ return /* @__PURE__ */ jsx42(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx42(ComposerSendButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx42(SendHorizontalIcon, {}) }) });
4061
4630
  });
4062
4631
  ComposerSend.displayName = "ComposerSend";
4063
4632
  var ComposerCancelButton = withDefaults(TooltipIconButton, {
@@ -4068,28 +4637,30 @@ var ComposerCancel = forwardRef23((props, ref) => {
4068
4637
  const {
4069
4638
  strings: { composer: { cancel: { tooltip = "Cancel" } = {} } = {} } = {}
4070
4639
  } = useThreadConfig();
4071
- return /* @__PURE__ */ jsx38(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx38(ComposerCancelButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx38(CircleStopIcon, {}) }) });
4640
+ return /* @__PURE__ */ jsx42(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx42(ComposerCancelButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx42(CircleStopIcon, {}) }) });
4072
4641
  });
4073
4642
  ComposerCancel.displayName = "ComposerCancel";
4074
- var exports5 = {
4643
+ var exports6 = {
4075
4644
  Root: ComposerRoot,
4076
4645
  Input: ComposerInput,
4077
4646
  Action: ComposerAction,
4078
4647
  Send: ComposerSend,
4079
- Cancel: ComposerCancel
4648
+ Cancel: ComposerCancel,
4649
+ AddAttachment: ComposerAddAttachment,
4650
+ Attachments: ComposerAttachments
4080
4651
  };
4081
- var composer_default = Object.assign(Composer, exports5);
4652
+ var composer_default = Object.assign(Composer, exports6);
4082
4653
 
4083
4654
  // src/ui/thread-welcome.tsx
4084
4655
  import { forwardRef as forwardRef24 } from "react";
4085
- import { jsx as jsx39, jsxs as jsxs10 } from "react/jsx-runtime";
4656
+ import { jsx as jsx43, jsxs as jsxs11 } from "react/jsx-runtime";
4086
4657
  var ThreadWelcome = () => {
4087
- return /* @__PURE__ */ jsxs10(ThreadWelcomeRoot, { children: [
4088
- /* @__PURE__ */ jsxs10(ThreadWelcomeCenter, { children: [
4089
- /* @__PURE__ */ jsx39(ThreadWelcomeAvatar, {}),
4090
- /* @__PURE__ */ jsx39(ThreadWelcomeMessage, {})
4658
+ return /* @__PURE__ */ jsxs11(ThreadWelcomeRoot, { children: [
4659
+ /* @__PURE__ */ jsxs11(ThreadWelcomeCenter, { children: [
4660
+ /* @__PURE__ */ jsx43(ThreadWelcomeAvatar, {}),
4661
+ /* @__PURE__ */ jsx43(ThreadWelcomeMessage, {})
4091
4662
  ] }),
4092
- /* @__PURE__ */ jsx39(ThreadWelcomeSuggestions, {})
4663
+ /* @__PURE__ */ jsx43(ThreadWelcomeSuggestions, {})
4093
4664
  ] });
4094
4665
  };
4095
4666
  ThreadWelcome.displayName = "ThreadWelcome";
@@ -4101,20 +4672,20 @@ var ThreadWelcomeCenter = withDefaults("div", {
4101
4672
  });
4102
4673
  var ThreadWelcomeRoot = forwardRef24(
4103
4674
  (props, ref) => {
4104
- return /* @__PURE__ */ jsx39(thread_exports.Empty, { children: /* @__PURE__ */ jsx39(ThreadWelcomeRootStyled, { ...props, ref }) });
4675
+ return /* @__PURE__ */ jsx43(thread_exports.Empty, { children: /* @__PURE__ */ jsx43(ThreadWelcomeRootStyled, { ...props, ref }) });
4105
4676
  }
4106
4677
  );
4107
4678
  ThreadWelcomeRoot.displayName = "ThreadWelcomeRoot";
4108
4679
  var ThreadWelcomeAvatar = () => {
4109
4680
  const { assistantAvatar: avatar = { fallback: "A" } } = useThreadConfig();
4110
- return /* @__PURE__ */ jsx39(Avatar, { ...avatar });
4681
+ return /* @__PURE__ */ jsx43(Avatar, { ...avatar });
4111
4682
  };
4112
4683
  var ThreadWelcomeMessageStyled = withDefaults("p", {
4113
4684
  className: "aui-thread-welcome-message"
4114
4685
  });
4115
4686
  var ThreadWelcomeMessage = forwardRef24(({ message: messageProp, ...rest }, ref) => {
4116
4687
  const { welcome: { message = "How can I help you today?" } = {} } = useThreadConfig();
4117
- return /* @__PURE__ */ jsx39(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message });
4688
+ return /* @__PURE__ */ jsx43(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message });
4118
4689
  });
4119
4690
  ThreadWelcomeMessage.displayName = "ThreadWelcomeMessage";
4120
4691
  var ThreadWelcomeSuggestionContainer = withDefaults("div", {
@@ -4126,25 +4697,25 @@ var ThreadWelcomeSuggestionStyled = withDefaults(thread_exports.Suggestion, {
4126
4697
  var ThreadWelcomeSuggestion = ({
4127
4698
  suggestion: { text, prompt }
4128
4699
  }) => {
4129
- return /* @__PURE__ */ jsx39(
4700
+ return /* @__PURE__ */ jsx43(
4130
4701
  ThreadWelcomeSuggestionStyled,
4131
4702
  {
4132
4703
  prompt,
4133
4704
  method: "replace",
4134
4705
  autoSend: true,
4135
- children: /* @__PURE__ */ jsx39("span", { className: "aui-thread-welcome-suggestion-text", children: text ?? prompt })
4706
+ children: /* @__PURE__ */ jsx43("span", { className: "aui-thread-welcome-suggestion-text", children: text ?? prompt })
4136
4707
  }
4137
4708
  );
4138
4709
  };
4139
4710
  var ThreadWelcomeSuggestions = () => {
4140
4711
  const { welcome: { suggestions } = {} } = useThreadConfig();
4141
- return /* @__PURE__ */ jsx39(ThreadWelcomeSuggestionContainer, { children: suggestions?.map((suggestion, idx) => {
4712
+ return /* @__PURE__ */ jsx43(ThreadWelcomeSuggestionContainer, { children: suggestions?.map((suggestion, idx) => {
4142
4713
  const key = `${suggestion.prompt}-${idx}`;
4143
- return /* @__PURE__ */ jsx39(ThreadWelcomeSuggestion, { suggestion }, key);
4714
+ return /* @__PURE__ */ jsx43(ThreadWelcomeSuggestion, { suggestion }, key);
4144
4715
  }) });
4145
4716
  };
4146
4717
  ThreadWelcomeSuggestions.displayName = "ThreadWelcomeSuggestions";
4147
- var exports6 = {
4718
+ var exports7 = {
4148
4719
  Root: ThreadWelcomeRoot,
4149
4720
  Center: ThreadWelcomeCenter,
4150
4721
  Avatar: ThreadWelcomeAvatar,
@@ -4152,7 +4723,7 @@ var exports6 = {
4152
4723
  Suggestions: ThreadWelcomeSuggestions,
4153
4724
  Suggestion: ThreadWelcomeSuggestion
4154
4725
  };
4155
- var thread_welcome_default = Object.assign(ThreadWelcome, exports6);
4726
+ var thread_welcome_default = Object.assign(ThreadWelcome, exports7);
4156
4727
 
4157
4728
  // src/ui/user-message.tsx
4158
4729
  import { forwardRef as forwardRef26 } from "react";
@@ -4160,7 +4731,7 @@ import { forwardRef as forwardRef26 } from "react";
4160
4731
  // src/ui/user-action-bar.tsx
4161
4732
  import { forwardRef as forwardRef25 } from "react";
4162
4733
  import { PencilIcon } from "lucide-react";
4163
- import { jsx as jsx40 } from "react/jsx-runtime";
4734
+ import { jsx as jsx44 } from "react/jsx-runtime";
4164
4735
  var useAllowEdit = (ensureCapability = false) => {
4165
4736
  const { userMessage: { allowEdit = true } = {} } = useThreadConfig();
4166
4737
  const { useThread } = useThreadContext();
@@ -4170,7 +4741,7 @@ var useAllowEdit = (ensureCapability = false) => {
4170
4741
  var UserActionBar = () => {
4171
4742
  const allowEdit = useAllowEdit(true);
4172
4743
  if (!allowEdit) return null;
4173
- return /* @__PURE__ */ jsx40(UserActionBarRoot, { hideWhenRunning: true, autohide: "not-last", children: /* @__PURE__ */ jsx40(UserActionBarEdit, {}) });
4744
+ return /* @__PURE__ */ jsx44(UserActionBarRoot, { hideWhenRunning: true, autohide: "not-last", children: /* @__PURE__ */ jsx44(UserActionBarEdit, {}) });
4174
4745
  };
4175
4746
  UserActionBar.displayName = "UserActionBar";
4176
4747
  var UserActionBarRoot = withDefaults(actionBar_exports.Root, {
@@ -4182,23 +4753,46 @@ var UserActionBarEdit = forwardRef25((props, ref) => {
4182
4753
  strings: { userMessage: { edit: { tooltip = "Edit" } = {} } = {} } = {}
4183
4754
  } = useThreadConfig();
4184
4755
  const allowEdit = useAllowEdit();
4185
- if (!allowEdit) return null;
4186
- return /* @__PURE__ */ jsx40(actionBar_exports.Edit, { asChild: true, children: /* @__PURE__ */ jsx40(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx40(PencilIcon, {}) }) });
4756
+ return /* @__PURE__ */ jsx44(actionBar_exports.Edit, { disabled: !allowEdit, asChild: true, children: /* @__PURE__ */ jsx44(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx44(PencilIcon, {}) }) });
4187
4757
  });
4188
4758
  UserActionBarEdit.displayName = "UserActionBarEdit";
4189
- var exports7 = {
4759
+ var exports8 = {
4190
4760
  Root: UserActionBarRoot,
4191
4761
  Edit: UserActionBarEdit
4192
4762
  };
4193
- var user_action_bar_default = Object.assign(UserActionBar, exports7);
4763
+ var user_action_bar_default = Object.assign(UserActionBar, exports8);
4764
+
4765
+ // src/ui/user-message-attachment.tsx
4766
+ import { jsxs as jsxs12 } from "react/jsx-runtime";
4767
+ var UserMessageAttachmentRoot = withDefaults("div", {
4768
+ className: "aui-user-message-attachment-root"
4769
+ });
4770
+ UserMessageAttachmentRoot.displayName = "UserMessageAttachmentRoot";
4771
+ var UserMessageAttachment = () => {
4772
+ const { useAttachment } = useAttachmentContext();
4773
+ const attachment = useAttachment((a) => a.attachment);
4774
+ return /* @__PURE__ */ jsxs12(UserMessageAttachmentRoot, { children: [
4775
+ ".",
4776
+ attachment.name.split(".").pop()
4777
+ ] });
4778
+ };
4779
+ UserMessageAttachment.displayName = "UserMessageAttachment";
4780
+ var exports9 = {
4781
+ Root: UserMessageAttachmentRoot
4782
+ };
4783
+ var user_message_attachment_default = Object.assign(
4784
+ UserMessageAttachment,
4785
+ exports9
4786
+ );
4194
4787
 
4195
4788
  // src/ui/user-message.tsx
4196
- import { jsx as jsx41, jsxs as jsxs11 } from "react/jsx-runtime";
4789
+ import { jsx as jsx45, jsxs as jsxs13 } from "react/jsx-runtime";
4197
4790
  var UserMessage = () => {
4198
- return /* @__PURE__ */ jsxs11(UserMessageRoot, { children: [
4199
- /* @__PURE__ */ jsx41(user_action_bar_default, {}),
4200
- /* @__PURE__ */ jsx41(UserMessageContent, {}),
4201
- /* @__PURE__ */ jsx41(branch_picker_default, {})
4791
+ return /* @__PURE__ */ jsxs13(UserMessageRoot, { children: [
4792
+ /* @__PURE__ */ jsx45(UserMessageAttachments, {}),
4793
+ /* @__PURE__ */ jsx45(user_action_bar_default, {}),
4794
+ /* @__PURE__ */ jsx45(UserMessageContent, {}),
4795
+ /* @__PURE__ */ jsx45(branch_picker_default, {})
4202
4796
  ] });
4203
4797
  };
4204
4798
  UserMessage.displayName = "UserMessage";
@@ -4211,7 +4805,7 @@ var UserMessageContentWrapper = withDefaults("div", {
4211
4805
  });
4212
4806
  var UserMessageContent = forwardRef26(
4213
4807
  ({ components, ...props }, ref) => {
4214
- return /* @__PURE__ */ jsx41(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ jsx41(
4808
+ return /* @__PURE__ */ jsx45(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ jsx45(
4215
4809
  message_exports.Content,
4216
4810
  {
4217
4811
  components: {
@@ -4223,21 +4817,38 @@ var UserMessageContent = forwardRef26(
4223
4817
  }
4224
4818
  );
4225
4819
  UserMessageContent.displayName = "UserMessageContent";
4226
- var exports8 = {
4820
+ var UserMessageAttachmentsContainer = withDefaults("div", {
4821
+ className: "aui-user-message-attachments"
4822
+ });
4823
+ var UserMessageAttachments = ({
4824
+ components
4825
+ }) => {
4826
+ return /* @__PURE__ */ jsx45(message_exports.If, { hasAttachments: true, children: /* @__PURE__ */ jsx45(UserMessageAttachmentsContainer, { children: /* @__PURE__ */ jsx45(
4827
+ message_exports.Attachments,
4828
+ {
4829
+ components: {
4830
+ ...components,
4831
+ Attachment: components?.Attachment ?? user_message_attachment_default
4832
+ }
4833
+ }
4834
+ ) }) });
4835
+ };
4836
+ var exports10 = {
4227
4837
  Root: UserMessageRoot,
4228
- Content: UserMessageContent
4838
+ Content: UserMessageContent,
4839
+ Attachments: UserMessageAttachments
4229
4840
  };
4230
- var user_message_default = Object.assign(UserMessage, exports8);
4841
+ var user_message_default = Object.assign(UserMessage, exports10);
4231
4842
 
4232
4843
  // src/ui/edit-composer.tsx
4233
4844
  import { forwardRef as forwardRef27 } from "react";
4234
- import { jsx as jsx42, jsxs as jsxs12 } from "react/jsx-runtime";
4845
+ import { jsx as jsx46, jsxs as jsxs14 } from "react/jsx-runtime";
4235
4846
  var EditComposer = () => {
4236
- return /* @__PURE__ */ jsxs12(EditComposerRoot, { children: [
4237
- /* @__PURE__ */ jsx42(EditComposerInput, {}),
4238
- /* @__PURE__ */ jsxs12(EditComposerFooter, { children: [
4239
- /* @__PURE__ */ jsx42(EditComposerCancel, {}),
4240
- /* @__PURE__ */ jsx42(EditComposerSend, {})
4847
+ return /* @__PURE__ */ jsxs14(EditComposerRoot, { children: [
4848
+ /* @__PURE__ */ jsx46(EditComposerInput, {}),
4849
+ /* @__PURE__ */ jsxs14(EditComposerFooter, { children: [
4850
+ /* @__PURE__ */ jsx46(EditComposerCancel, {}),
4851
+ /* @__PURE__ */ jsx46(EditComposerSend, {})
4241
4852
  ] })
4242
4853
  ] });
4243
4854
  };
@@ -4261,7 +4872,7 @@ var EditComposerCancel = forwardRef27(
4261
4872
  editComposer: { cancel: { label = "Cancel" } = {} } = {}
4262
4873
  } = {}
4263
4874
  } = useThreadConfig();
4264
- return /* @__PURE__ */ jsx42(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx42(Button, { variant: "ghost", ...props, ref, children: props.children ?? label }) });
4875
+ return /* @__PURE__ */ jsx46(composer_exports.Cancel, { asChild: true, children: /* @__PURE__ */ jsx46(Button, { variant: "ghost", ...props, ref, children: props.children ?? label }) });
4265
4876
  }
4266
4877
  );
4267
4878
  EditComposerCancel.displayName = "EditComposerCancel";
@@ -4270,28 +4881,28 @@ var EditComposerSend = forwardRef27(
4270
4881
  const {
4271
4882
  strings: { editComposer: { send: { label = "Send" } = {} } = {} } = {}
4272
4883
  } = useThreadConfig();
4273
- return /* @__PURE__ */ jsx42(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx42(Button, { ...props, ref, children: props.children ?? label }) });
4884
+ return /* @__PURE__ */ jsx46(composer_exports.Send, { asChild: true, children: /* @__PURE__ */ jsx46(Button, { ...props, ref, children: props.children ?? label }) });
4274
4885
  }
4275
4886
  );
4276
4887
  EditComposerSend.displayName = "EditComposerSend";
4277
- var exports9 = {
4888
+ var exports11 = {
4278
4889
  Root: EditComposerRoot,
4279
4890
  Input: EditComposerInput,
4280
4891
  Footer: EditComposerFooter,
4281
4892
  Cancel: EditComposerCancel,
4282
4893
  Send: EditComposerSend
4283
4894
  };
4284
- var edit_composer_default = Object.assign(EditComposer, exports9);
4895
+ var edit_composer_default = Object.assign(EditComposer, exports11);
4285
4896
 
4286
4897
  // src/ui/thread.tsx
4287
- import { jsx as jsx43, jsxs as jsxs13 } from "react/jsx-runtime";
4898
+ import { jsx as jsx47, jsxs as jsxs15 } from "react/jsx-runtime";
4288
4899
  var Thread = (config) => {
4289
- return /* @__PURE__ */ jsx43(ThreadRoot, { config, children: /* @__PURE__ */ jsxs13(ThreadViewport, { children: [
4290
- /* @__PURE__ */ jsx43(thread_welcome_default, {}),
4291
- /* @__PURE__ */ jsx43(ThreadMessages, {}),
4292
- /* @__PURE__ */ jsxs13(ThreadViewportFooter, { children: [
4293
- /* @__PURE__ */ jsx43(ThreadScrollToBottom, {}),
4294
- /* @__PURE__ */ jsx43(composer_default, {})
4900
+ return /* @__PURE__ */ jsx47(ThreadRoot, { config, children: /* @__PURE__ */ jsxs15(ThreadViewport, { children: [
4901
+ /* @__PURE__ */ jsx47(thread_welcome_default, {}),
4902
+ /* @__PURE__ */ jsx47(ThreadMessages, {}),
4903
+ /* @__PURE__ */ jsxs15(ThreadViewportFooter, { children: [
4904
+ /* @__PURE__ */ jsx47(ThreadScrollToBottom, {}),
4905
+ /* @__PURE__ */ jsx47(composer_default, {})
4295
4906
  ] })
4296
4907
  ] }) });
4297
4908
  };
@@ -4300,7 +4911,7 @@ var ThreadRootStyled = withDefaults(thread_exports.Root, {
4300
4911
  });
4301
4912
  var ThreadRoot = forwardRef28(
4302
4913
  ({ config, ...props }, ref) => {
4303
- return /* @__PURE__ */ jsx43(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx43(ThreadRootStyled, { ...props, ref }) });
4914
+ return /* @__PURE__ */ jsx47(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx47(ThreadRootStyled, { ...props, ref }) });
4304
4915
  }
4305
4916
  );
4306
4917
  ThreadRoot.displayName = "ThreadRoot";
@@ -4314,7 +4925,7 @@ var ThreadViewportFooter = withDefaults("div", {
4314
4925
  ThreadViewportFooter.displayName = "ThreadViewportFooter";
4315
4926
  var SystemMessage = () => null;
4316
4927
  var ThreadMessages = ({ components, ...rest }) => {
4317
- return /* @__PURE__ */ jsx43(
4928
+ return /* @__PURE__ */ jsx47(
4318
4929
  thread_exports.Messages,
4319
4930
  {
4320
4931
  components: {
@@ -4338,33 +4949,33 @@ var ThreadScrollToBottom = forwardRef28((props, ref) => {
4338
4949
  thread: { scrollToBottom: { tooltip = "Scroll to bottom" } = {} } = {}
4339
4950
  } = {}
4340
4951
  } = useThreadConfig();
4341
- return /* @__PURE__ */ jsx43(thread_exports.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx43(ThreadScrollToBottomIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx43(ArrowDownIcon, {}) }) });
4952
+ return /* @__PURE__ */ jsx47(thread_exports.ScrollToBottom, { asChild: true, children: /* @__PURE__ */ jsx47(ThreadScrollToBottomIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsx47(ArrowDownIcon, {}) }) });
4342
4953
  });
4343
4954
  ThreadScrollToBottom.displayName = "ThreadScrollToBottom";
4344
- var exports10 = {
4955
+ var exports12 = {
4345
4956
  Root: ThreadRoot,
4346
4957
  Viewport: ThreadViewport,
4347
4958
  Messages: ThreadMessages,
4348
4959
  ScrollToBottom: ThreadScrollToBottom,
4349
4960
  ViewportFooter: ThreadViewportFooter
4350
4961
  };
4351
- var thread_default = Object.assign(Thread, exports10);
4962
+ var thread_default = Object.assign(Thread, exports12);
4352
4963
 
4353
4964
  // src/ui/assistant-modal.tsx
4354
- import { Fragment as Fragment6, jsx as jsx44, jsxs as jsxs14 } from "react/jsx-runtime";
4965
+ import { Fragment as Fragment6, jsx as jsx48, jsxs as jsxs16 } from "react/jsx-runtime";
4355
4966
  var AssistantModal = (config) => {
4356
- return /* @__PURE__ */ jsxs14(AssistantModalRoot, { config, children: [
4357
- /* @__PURE__ */ jsx44(AssistantModalTrigger, {}),
4358
- /* @__PURE__ */ jsx44(AssistantModalContent, { children: /* @__PURE__ */ jsx44(thread_default, {}) })
4967
+ return /* @__PURE__ */ jsxs16(AssistantModalRoot, { config, children: [
4968
+ /* @__PURE__ */ jsx48(AssistantModalTrigger, {}),
4969
+ /* @__PURE__ */ jsx48(AssistantModalContent, { children: /* @__PURE__ */ jsx48(thread_default, {}) })
4359
4970
  ] });
4360
4971
  };
4361
4972
  AssistantModal.displayName = "AssistantModal";
4362
4973
  var AssistantModalRoot = ({ config, ...props }) => {
4363
- return /* @__PURE__ */ jsx44(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx44(assistantModal_exports.Root, { ...props }) });
4974
+ return /* @__PURE__ */ jsx48(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx48(assistantModal_exports.Root, { ...props }) });
4364
4975
  };
4365
4976
  AssistantModalRoot.displayName = "AssistantModalRoot";
4366
4977
  var AssistantModalTrigger = forwardRef29((props, ref) => {
4367
- return /* @__PURE__ */ jsx44(AssistantModalAnchor, { children: /* @__PURE__ */ jsx44(assistantModal_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx44(AssistantModalButton, { ...props, ref }) }) });
4978
+ return /* @__PURE__ */ jsx48(AssistantModalAnchor, { children: /* @__PURE__ */ jsx48(assistantModal_exports.Trigger, { asChild: true, children: /* @__PURE__ */ jsx48(AssistantModalButton, { ...props, ref }) }) });
4368
4979
  });
4369
4980
  AssistantModalTrigger.displayName = "AssistantModalTrigger";
4370
4981
  var AssistantModalAnchor = withDefaults(assistantModal_exports.Anchor, {
@@ -4389,7 +5000,7 @@ var AssistantModalButton = forwardRef29(({ "data-state": state, ...rest }, ref)
4389
5000
  } = {}
4390
5001
  } = useThreadConfig();
4391
5002
  const tooltip = state === "open" ? openTooltip : closedTooltip;
4392
- return /* @__PURE__ */ jsx44(
5003
+ return /* @__PURE__ */ jsx48(
4393
5004
  ModalButtonStyled,
4394
5005
  {
4395
5006
  side: "left",
@@ -4397,15 +5008,15 @@ var AssistantModalButton = forwardRef29(({ "data-state": state, ...rest }, ref)
4397
5008
  "data-state": state,
4398
5009
  ...rest,
4399
5010
  ref,
4400
- children: rest.children ?? /* @__PURE__ */ jsxs14(Fragment6, { children: [
4401
- /* @__PURE__ */ jsx44(
5011
+ children: rest.children ?? /* @__PURE__ */ jsxs16(Fragment6, { children: [
5012
+ /* @__PURE__ */ jsx48(
4402
5013
  BotIcon,
4403
5014
  {
4404
5015
  "data-state": state,
4405
5016
  className: "aui-modal-button-closed-icon"
4406
5017
  }
4407
5018
  ),
4408
- /* @__PURE__ */ jsx44(
5019
+ /* @__PURE__ */ jsx48(
4409
5020
  ChevronDownIcon,
4410
5021
  {
4411
5022
  "data-state": state,
@@ -4422,14 +5033,14 @@ var AssistantModalContent = withDefaults(assistantModal_exports.Content, {
4422
5033
  sideOffset: 16
4423
5034
  });
4424
5035
  AssistantModalContent.displayName = "AssistantModalContent";
4425
- var exports11 = {
5036
+ var exports13 = {
4426
5037
  Root: AssistantModalRoot,
4427
5038
  Trigger: AssistantModalTrigger,
4428
5039
  Content: AssistantModalContent,
4429
5040
  Button: AssistantModalButton,
4430
5041
  Anchor: AssistantModalAnchor
4431
5042
  };
4432
- var assistant_modal_default = Object.assign(AssistantModal, exports11);
5043
+ var assistant_modal_default = Object.assign(AssistantModal, exports13);
4433
5044
  export {
4434
5045
  actionBar_exports as ActionBarPrimitive,
4435
5046
  assistant_action_bar_default as AssistantActionBar,
@@ -4440,7 +5051,9 @@ export {
4440
5051
  branch_picker_default as BranchPicker,
4441
5052
  branchPicker_exports as BranchPickerPrimitive,
4442
5053
  composer_default as Composer,
5054
+ composer_attachment_default as ComposerAttachment,
4443
5055
  composer_exports as ComposerPrimitive,
5056
+ CompositeAttachmentAdapter,
4444
5057
  content_part_default as ContentPart,
4445
5058
  contentPart_exports as ContentPartPrimitive,
4446
5059
  EdgeChatAdapter,
@@ -4448,12 +5061,15 @@ export {
4448
5061
  ExternalStoreRuntime,
4449
5062
  internal_exports as INTERNAL,
4450
5063
  message_exports as MessagePrimitive,
5064
+ SimpleImageAttachmentAdapter,
5065
+ SimpleTextAttachmentAdapter,
4451
5066
  thread_default as Thread,
4452
5067
  ThreadConfigProvider,
4453
5068
  thread_exports as ThreadPrimitive,
4454
5069
  thread_welcome_default as ThreadWelcome,
4455
5070
  user_action_bar_default as UserActionBar,
4456
5071
  user_message_default as UserMessage,
5072
+ user_message_attachment_default as UserMessageAttachment,
4457
5073
  WebSpeechSynthesisAdapter,
4458
5074
  fromCoreMessage,
4459
5075
  fromCoreMessages,
@@ -4482,6 +5098,7 @@ export {
4482
5098
  useBranchPickerNext,
4483
5099
  useBranchPickerNumber,
4484
5100
  useBranchPickerPrevious,
5101
+ useComposerAddAttachment,
4485
5102
  useComposerCancel,
4486
5103
  useComposerContext,
4487
5104
  useComposerIf,