@assistant-ui/react 0.5.46 → 0.5.48

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;
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;
1128
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 = () => {
@@ -2400,7 +2633,7 @@ var useComposerSend = () => {
2400
2633
  const { useComposer } = useComposerContext();
2401
2634
  const disabled = useCombinedStore(
2402
2635
  [useThread, useComposer],
2403
- (t, c) => t.isRunning || !c.isEditing || c.text.length === 0
2636
+ (t, c) => t.isRunning || !c.isEditing || c.isEmpty
2404
2637
  );
2405
2638
  const callback = useCallback11(() => {
2406
2639
  const composerState = useComposer.getState();
@@ -2413,6 +2646,30 @@ var useComposerSend = () => {
2413
2646
  return callback;
2414
2647
  };
2415
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
+
2416
2673
  // src/primitive-hooks/contentPart/useContentPartDisplay.tsx
2417
2674
  var useContentPartDisplay = () => {
2418
2675
  const { useContentPart } = useContentPartContext();
@@ -2467,6 +2724,10 @@ var useMessageIf = (props) => {
2467
2724
  if (props.copied === false && isCopied) return false;
2468
2725
  if (props.speaking === true && !isSpeaking) return false;
2469
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;
2470
2731
  return true;
2471
2732
  }
2472
2733
  );
@@ -2495,11 +2756,11 @@ var useThreadEmpty = () => {
2495
2756
  };
2496
2757
 
2497
2758
  // src/primitive-hooks/thread/useThreadScrollToBottom.tsx
2498
- import { useCallback as useCallback12 } from "react";
2759
+ import { useCallback as useCallback13 } from "react";
2499
2760
  var useThreadScrollToBottom = () => {
2500
2761
  const { useComposer, useViewport } = useThreadContext();
2501
2762
  const isAtBottom = useViewport((s) => s.isAtBottom);
2502
- const handleScrollToBottom = useCallback12(() => {
2763
+ const handleScrollToBottom = useCallback13(() => {
2503
2764
  useViewport.getState().scrollToBottom();
2504
2765
  useComposer.getState().focus();
2505
2766
  }, [useViewport, useComposer]);
@@ -2508,7 +2769,7 @@ var useThreadScrollToBottom = () => {
2508
2769
  };
2509
2770
 
2510
2771
  // src/primitive-hooks/thread/useThreadSuggestion.tsx
2511
- import { useCallback as useCallback13 } from "react";
2772
+ import { useCallback as useCallback14 } from "react";
2512
2773
  var useThreadSuggestion = ({
2513
2774
  prompt,
2514
2775
  autoSend
@@ -2516,7 +2777,7 @@ var useThreadSuggestion = ({
2516
2777
  const { useThread, useComposer } = useThreadContext();
2517
2778
  const append = useAppendMessage();
2518
2779
  const disabled = useThread((t) => t.isDisabled);
2519
- const callback = useCallback13(() => {
2780
+ const callback = useCallback14(() => {
2520
2781
  const thread = useThread.getState();
2521
2782
  const composer = useComposer.getState();
2522
2783
  if (autoSend && !thread.isRunning) {
@@ -2844,6 +3105,7 @@ import { forwardRef as forwardRef14 } from "react";
2844
3105
  // src/primitives/message/index.ts
2845
3106
  var message_exports = {};
2846
3107
  __export(message_exports, {
3108
+ Attachments: () => MessagePrimitiveAttachments,
2847
3109
  Content: () => MessagePrimitiveContent,
2848
3110
  If: () => MessagePrimitiveIf,
2849
3111
  InProgress: () => MessagePrimitiveInProgress,
@@ -2854,14 +3116,14 @@ __export(message_exports, {
2854
3116
  import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
2855
3117
  import {
2856
3118
  forwardRef as forwardRef11,
2857
- useCallback as useCallback15
3119
+ useCallback as useCallback16
2858
3120
  } from "react";
2859
3121
 
2860
3122
  // src/utils/hooks/useManagedRef.ts
2861
- import { useCallback as useCallback14, useRef as useRef3 } from "react";
3123
+ import { useCallback as useCallback15, useRef as useRef3 } from "react";
2862
3124
  var useManagedRef = (callback) => {
2863
3125
  const cleanupRef = useRef3();
2864
- const ref = useCallback14(
3126
+ const ref = useCallback15(
2865
3127
  (el) => {
2866
3128
  if (cleanupRef.current) {
2867
3129
  cleanupRef.current();
@@ -2880,7 +3142,7 @@ import { useComposedRefs } from "@radix-ui/react-compose-refs";
2880
3142
  import { jsx as jsx18 } from "react/jsx-runtime";
2881
3143
  var useIsHoveringRef = () => {
2882
3144
  const { useMessageUtils } = useMessageContext();
2883
- const callbackRef = useCallback15(
3145
+ const callbackRef = useCallback16(
2884
3146
  (el) => {
2885
3147
  const setIsHovering = useMessageUtils.getState().setIsHovering;
2886
3148
  const handleMouseEnter = () => {
@@ -2975,7 +3237,7 @@ var useContentPartContext2 = (partIndex) => {
2975
3237
  partIndex
2976
3238
  );
2977
3239
  if (!newState) return;
2978
- context.useContentPart.setState(newState, true);
3240
+ writableStore(context.useContentPart).setState(newState, true);
2979
3241
  };
2980
3242
  syncContentPart(useMessage.getState());
2981
3243
  return useMessage.subscribe(syncContentPart);
@@ -3119,17 +3381,7 @@ var MessagePrimitiveContent = ({
3119
3381
  }) => {
3120
3382
  const { useMessage } = useMessageContext();
3121
3383
  const contentLength = useMessage((s) => s.message.content.length) || 1;
3122
- return new Array(contentLength).fill(null).map((_, idx) => {
3123
- const partIndex = idx;
3124
- return /* @__PURE__ */ jsx22(
3125
- MessageContentPart,
3126
- {
3127
- partIndex,
3128
- components
3129
- },
3130
- partIndex
3131
- );
3132
- });
3384
+ return Array.from({ length: contentLength }, (_, index) => /* @__PURE__ */ jsx22(MessageContentPart, { partIndex: index, components }, index));
3133
3385
  };
3134
3386
  MessagePrimitiveContent.displayName = "MessagePrimitive.Content";
3135
3387
 
@@ -3139,16 +3391,137 @@ var MessagePrimitiveInProgress = () => {
3139
3391
  };
3140
3392
  MessagePrimitiveInProgress.displayName = "MessagePrimitive.InProgress";
3141
3393
 
3142
- // 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";
3143
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";
3144
3515
  var BranchPickerPrimitiveRoot = forwardRef14(({ hideWhenSingleBranch, ...rest }, ref) => {
3145
- 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 }) });
3146
3517
  });
3147
3518
  BranchPickerPrimitiveRoot.displayName = "BranchPickerPrimitive.Root";
3148
3519
 
3149
3520
  // src/primitives/composer/index.ts
3150
3521
  var composer_exports = {};
3151
3522
  __export(composer_exports, {
3523
+ AddAttachment: () => ComposerPrimitiveAddAttachment,
3524
+ Attachments: () => ComposerPrimitiveAttachments,
3152
3525
  Cancel: () => ComposerPrimitiveCancel,
3153
3526
  If: () => ComposerPrimitiveIf,
3154
3527
  Input: () => ComposerPrimitiveInput,
@@ -3162,7 +3535,7 @@ import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
3162
3535
  import {
3163
3536
  forwardRef as forwardRef15
3164
3537
  } from "react";
3165
- import { jsx as jsx24 } from "react/jsx-runtime";
3538
+ import { jsx as jsx26 } from "react/jsx-runtime";
3166
3539
  var ComposerPrimitiveRoot = forwardRef15(({ onSubmit, ...rest }, forwardedRef) => {
3167
3540
  const send = useComposerSend();
3168
3541
  const handleSubmit = (e) => {
@@ -3170,7 +3543,7 @@ var ComposerPrimitiveRoot = forwardRef15(({ onSubmit, ...rest }, forwardedRef) =
3170
3543
  if (!send) return;
3171
3544
  send();
3172
3545
  };
3173
- return /* @__PURE__ */ jsx24(
3546
+ return /* @__PURE__ */ jsx26(
3174
3547
  Primitive8.form,
3175
3548
  {
3176
3549
  ...rest,
@@ -3187,13 +3560,13 @@ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-ref
3187
3560
  import { Slot } from "@radix-ui/react-slot";
3188
3561
  import {
3189
3562
  forwardRef as forwardRef16,
3190
- useCallback as useCallback16,
3191
- useEffect as useEffect10,
3563
+ useCallback as useCallback17,
3564
+ useEffect as useEffect11,
3192
3565
  useRef as useRef4
3193
3566
  } from "react";
3194
3567
  import TextareaAutosize from "react-textarea-autosize";
3195
3568
  import { useEscapeKeydown as useEscapeKeydown2 } from "@radix-ui/react-use-escape-keydown";
3196
- import { jsx as jsx25 } from "react/jsx-runtime";
3569
+ import { jsx as jsx27 } from "react/jsx-runtime";
3197
3570
  var ComposerPrimitiveInput = forwardRef16(
3198
3571
  ({
3199
3572
  autoFocus = false,
@@ -3232,7 +3605,7 @@ var ComposerPrimitiveInput = forwardRef16(
3232
3605
  }
3233
3606
  };
3234
3607
  const autoFocusEnabled = autoFocus && !isDisabled;
3235
- const focus = useCallback16(() => {
3608
+ const focus = useCallback17(() => {
3236
3609
  const textarea = textareaRef.current;
3237
3610
  if (!textarea || !autoFocusEnabled) return;
3238
3611
  textarea.focus({ preventScroll: true });
@@ -3241,13 +3614,13 @@ var ComposerPrimitiveInput = forwardRef16(
3241
3614
  textareaRef.current.value.length
3242
3615
  );
3243
3616
  }, [autoFocusEnabled]);
3244
- useEffect10(() => focus(), [focus]);
3617
+ useEffect11(() => focus(), [focus]);
3245
3618
  useOnComposerFocus(() => {
3246
3619
  if (type === "new") {
3247
3620
  focus();
3248
3621
  }
3249
3622
  });
3250
- return /* @__PURE__ */ jsx25(
3623
+ return /* @__PURE__ */ jsx27(
3251
3624
  Component,
3252
3625
  {
3253
3626
  name: "input",
@@ -3268,23 +3641,10 @@ var ComposerPrimitiveInput = forwardRef16(
3268
3641
  ComposerPrimitiveInput.displayName = "ComposerPrimitive.Input";
3269
3642
 
3270
3643
  // src/primitives/composer/ComposerSend.tsx
3271
- import { forwardRef as forwardRef17 } from "react";
3272
- import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
3273
- import { jsx as jsx26 } from "react/jsx-runtime";
3274
- var ComposerPrimitiveSend = forwardRef17(({ disabled, ...rest }, ref) => {
3275
- const { useComposer } = useComposerContext();
3276
- const hasValue = useComposer((c) => c.isEditing && c.text.length > 0);
3277
- return /* @__PURE__ */ jsx26(
3278
- Primitive9.button,
3279
- {
3280
- type: "submit",
3281
- ...rest,
3282
- ref,
3283
- disabled: disabled || !hasValue
3284
- }
3285
- );
3286
- });
3287
- ComposerPrimitiveSend.displayName = "ComposerPrimitive.Send";
3644
+ var ComposerPrimitiveSend = createActionButton(
3645
+ "ComposerPrimitive.Send",
3646
+ useComposerSend
3647
+ );
3288
3648
 
3289
3649
  // src/primitives/composer/ComposerCancel.tsx
3290
3650
  var ComposerPrimitiveCancel = createActionButton(
@@ -3292,6 +3652,101 @@ var ComposerPrimitiveCancel = createActionButton(
3292
3652
  useComposerCancel
3293
3653
  );
3294
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
+
3295
3750
  // src/primitives/composer/ComposerIf.tsx
3296
3751
  var ComposerPrimitiveIf = ({
3297
3752
  children,
@@ -3324,11 +3779,11 @@ __export(thread_exports, {
3324
3779
  });
3325
3780
 
3326
3781
  // src/primitives/thread/ThreadRoot.tsx
3327
- import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
3328
- import { forwardRef as forwardRef18 } from "react";
3329
- import { jsx as jsx27 } from "react/jsx-runtime";
3330
- var ThreadPrimitiveRoot = forwardRef18((props, ref) => {
3331
- 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 });
3332
3787
  });
3333
3788
  ThreadPrimitiveRoot.displayName = "ThreadPrimitive.Root";
3334
3789
 
@@ -3353,8 +3808,8 @@ ThreadPrimitiveIf.displayName = "ThreadPrimitive.If";
3353
3808
 
3354
3809
  // src/primitives/thread/ThreadViewport.tsx
3355
3810
  import { useComposedRefs as useComposedRefs4 } from "@radix-ui/react-compose-refs";
3356
- import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
3357
- import { forwardRef as forwardRef19 } from "react";
3811
+ import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
3812
+ import { forwardRef as forwardRef18 } from "react";
3358
3813
 
3359
3814
  // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
3360
3815
  import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
@@ -3362,10 +3817,10 @@ import { useRef as useRef5 } from "react";
3362
3817
 
3363
3818
  // src/utils/hooks/useOnResizeContent.tsx
3364
3819
  import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
3365
- import { useCallback as useCallback17 } from "react";
3820
+ import { useCallback as useCallback18 } from "react";
3366
3821
  var useOnResizeContent = (callback) => {
3367
3822
  const callbackRef = useCallbackRef3(callback);
3368
- const refCallback = useCallback17(
3823
+ const refCallback = useCallback18(
3369
3824
  (el) => {
3370
3825
  const resizeObserver = new ResizeObserver(() => {
3371
3826
  callbackRef();
@@ -3402,11 +3857,11 @@ var useOnResizeContent = (callback) => {
3402
3857
 
3403
3858
  // src/utils/hooks/useOnScrollToBottom.tsx
3404
3859
  import { useCallbackRef as useCallbackRef4 } from "@radix-ui/react-use-callback-ref";
3405
- import { useEffect as useEffect11 } from "react";
3860
+ import { useEffect as useEffect13 } from "react";
3406
3861
  var useOnScrollToBottom = (callback) => {
3407
3862
  const callbackRef = useCallbackRef4(callback);
3408
3863
  const { useViewport } = useThreadContext();
3409
- useEffect11(() => {
3864
+ useEffect13(() => {
3410
3865
  return useViewport.getState().onScrollToBottom(() => {
3411
3866
  callbackRef();
3412
3867
  });
@@ -3438,9 +3893,7 @@ var useThreadViewportAutoScroll = ({
3438
3893
  isScrollingToBottomRef.current = false;
3439
3894
  }
3440
3895
  if (newIsAtBottom !== isAtBottom) {
3441
- useViewport.setState({
3442
- isAtBottom: newIsAtBottom
3443
- });
3896
+ writableStore(useViewport).setState({ isAtBottom: newIsAtBottom });
3444
3897
  }
3445
3898
  }
3446
3899
  lastScrollTop.current = div.scrollTop;
@@ -3465,29 +3918,29 @@ var useThreadViewportAutoScroll = ({
3465
3918
  };
3466
3919
 
3467
3920
  // src/primitives/thread/ThreadViewport.tsx
3468
- import { jsx as jsx28 } from "react/jsx-runtime";
3469
- 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) => {
3470
3923
  const autoScrollRef = useThreadViewportAutoScroll({
3471
3924
  autoScroll
3472
3925
  });
3473
3926
  const ref = useComposedRefs4(forwardedRef, autoScrollRef);
3474
- return /* @__PURE__ */ jsx28(Primitive11.div, { ...rest, ref, children });
3927
+ return /* @__PURE__ */ jsx31(Primitive10.div, { ...rest, ref, children });
3475
3928
  });
3476
3929
  ThreadPrimitiveViewport.displayName = "ThreadPrimitive.Viewport";
3477
3930
 
3478
3931
  // src/primitives/thread/ThreadMessages.tsx
3479
- import { memo as memo3 } from "react";
3932
+ import { memo as memo5 } from "react";
3480
3933
 
3481
3934
  // src/context/providers/MessageProvider.tsx
3482
- import { useEffect as useEffect12, useState as useState11 } from "react";
3483
- import { create as create15 } from "zustand";
3935
+ import { useEffect as useEffect14, useState as useState13 } from "react";
3936
+ import { create as create17 } from "zustand";
3484
3937
 
3485
3938
  // src/context/stores/EditComposer.ts
3486
- import { create as create13 } from "zustand";
3939
+ import { create as create15 } from "zustand";
3487
3940
  var makeEditComposerStore = ({
3488
3941
  onEdit,
3489
3942
  onSend
3490
- }) => create13()((set, get) => ({
3943
+ }) => create15()((set, get) => ({
3491
3944
  get value() {
3492
3945
  return get().text;
3493
3946
  },
@@ -3496,13 +3949,19 @@ var makeEditComposerStore = ({
3496
3949
  },
3497
3950
  text: "",
3498
3951
  setText: (text) => {
3499
- set({ text });
3952
+ set({ text, isEmpty: text.trim().length === 0 });
3500
3953
  },
3501
3954
  canCancel: false,
3502
3955
  isEditing: false,
3956
+ isEmpty: true,
3503
3957
  edit: () => {
3504
3958
  const text = onEdit();
3505
- set({ isEditing: true, canCancel: true, text });
3959
+ set({
3960
+ isEditing: true,
3961
+ canCancel: true,
3962
+ isEmpty: text.trim().length === 0,
3963
+ text
3964
+ });
3506
3965
  },
3507
3966
  send: () => {
3508
3967
  const text = get().text;
@@ -3515,8 +3974,8 @@ var makeEditComposerStore = ({
3515
3974
  }));
3516
3975
 
3517
3976
  // src/context/stores/MessageUtils.ts
3518
- import { create as create14 } from "zustand";
3519
- var makeMessageUtilsStore = () => create14((set) => {
3977
+ import { create as create16 } from "zustand";
3978
+ var makeMessageUtilsStore = () => create16((set) => {
3520
3979
  let utterance = null;
3521
3980
  return {
3522
3981
  isCopied: false,
@@ -3542,7 +4001,7 @@ var makeMessageUtilsStore = () => create14((set) => {
3542
4001
  });
3543
4002
 
3544
4003
  // src/context/providers/MessageProvider.tsx
3545
- import { jsx as jsx29 } from "react/jsx-runtime";
4004
+ import { jsx as jsx32 } from "react/jsx-runtime";
3546
4005
  var getIsLast = (messages, message) => {
3547
4006
  return messages[messages.length - 1]?.id === message.id;
3548
4007
  };
@@ -3564,8 +4023,8 @@ var getMessageState = (messages, getBranches, useMessage, messageIndex) => {
3564
4023
  };
3565
4024
  var useMessageContext2 = (messageIndex) => {
3566
4025
  const { useThreadMessages, useThreadActions } = useThreadContext();
3567
- const [context] = useState11(() => {
3568
- const useMessage = create15(
4026
+ const [context] = useState13(() => {
4027
+ const useMessage = create17(
3569
4028
  () => getMessageState(
3570
4029
  useThreadMessages.getState(),
3571
4030
  useThreadActions.getState().getBranches,
@@ -3596,13 +4055,14 @@ var useMessageContext2 = (messageIndex) => {
3596
4055
  useThreadActions.getState().append({
3597
4056
  parentId,
3598
4057
  role: "user",
3599
- content: [{ type: "text", text }, ...nonTextParts]
4058
+ content: [{ type: "text", text }, ...nonTextParts],
4059
+ attachments: message.attachments
3600
4060
  });
3601
4061
  }
3602
4062
  });
3603
4063
  return { useMessage, useMessageUtils, useEditComposer };
3604
4064
  });
3605
- useEffect12(() => {
4065
+ useEffect14(() => {
3606
4066
  const syncMessage = (thread) => {
3607
4067
  const newState = getMessageState(
3608
4068
  thread,
@@ -3611,10 +4071,7 @@ var useMessageContext2 = (messageIndex) => {
3611
4071
  messageIndex
3612
4072
  );
3613
4073
  if (!newState) return;
3614
- context.useMessage.setState(
3615
- newState,
3616
- true
3617
- );
4074
+ writableStore(context.useMessage).setState(newState, true);
3618
4075
  };
3619
4076
  syncMessage(useThreadMessages.getState());
3620
4077
  return useThreadMessages.subscribe(syncMessage);
@@ -3626,11 +4083,11 @@ var MessageProvider = ({
3626
4083
  children
3627
4084
  }) => {
3628
4085
  const context = useMessageContext2(messageIndex);
3629
- return /* @__PURE__ */ jsx29(MessageContext.Provider, { value: context, children });
4086
+ return /* @__PURE__ */ jsx32(MessageContext.Provider, { value: context, children });
3630
4087
  };
3631
4088
 
3632
4089
  // src/primitives/thread/ThreadMessages.tsx
3633
- import { jsx as jsx30, jsxs as jsxs4 } from "react/jsx-runtime";
4090
+ import { jsx as jsx33, jsxs as jsxs4 } from "react/jsx-runtime";
3634
4091
  var DEFAULT_SYSTEM_MESSAGE = () => null;
3635
4092
  var getComponents = (components) => {
3636
4093
  return {
@@ -3647,14 +4104,14 @@ var ThreadMessageImpl = ({
3647
4104
  const { UserMessage: UserMessage2, EditComposer: EditComposer2, AssistantMessage: AssistantMessage2, SystemMessage: SystemMessage2 } = getComponents(components);
3648
4105
  return /* @__PURE__ */ jsxs4(MessageProvider, { messageIndex, children: [
3649
4106
  /* @__PURE__ */ jsxs4(MessagePrimitiveIf, { user: true, children: [
3650
- /* @__PURE__ */ jsx30(ComposerPrimitiveIf, { editing: false, children: /* @__PURE__ */ jsx30(UserMessage2, {}) }),
3651
- /* @__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, {}) })
3652
4109
  ] }),
3653
- /* @__PURE__ */ jsx30(MessagePrimitiveIf, { assistant: true, children: /* @__PURE__ */ jsx30(AssistantMessage2, {}) }),
3654
- /* @__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, {}) })
3655
4112
  ] });
3656
4113
  };
3657
- var ThreadMessage = memo3(
4114
+ var ThreadMessage = memo5(
3658
4115
  ThreadMessageImpl,
3659
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
3660
4117
  );
@@ -3664,20 +4121,10 @@ var ThreadPrimitiveMessagesImpl = ({
3664
4121
  const { useThreadMessages } = useThreadContext();
3665
4122
  const messagesLength = useThreadMessages((t) => t.length);
3666
4123
  if (messagesLength === 0) return null;
3667
- return new Array(messagesLength).fill(null).map((_, idx) => {
3668
- const messageIndex = idx;
3669
- return /* @__PURE__ */ jsx30(
3670
- ThreadMessage,
3671
- {
3672
- messageIndex,
3673
- components
3674
- },
3675
- messageIndex
3676
- );
3677
- });
4124
+ return Array.from({ length: messagesLength }, (_, index) => /* @__PURE__ */ jsx33(ThreadMessage, { messageIndex: index, components }, index));
3678
4125
  };
3679
4126
  ThreadPrimitiveMessagesImpl.displayName = "ThreadPrimitive.Messages";
3680
- var ThreadPrimitiveMessages = memo3(
4127
+ var ThreadPrimitiveMessages = memo5(
3681
4128
  ThreadPrimitiveMessagesImpl,
3682
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
3683
4130
  );
@@ -3697,32 +4144,32 @@ var ThreadPrimitiveSuggestion = createActionButton(
3697
4144
 
3698
4145
  // src/ui/thread-config.tsx
3699
4146
  import {
3700
- createContext as createContext6,
3701
- useContext as useContext6
4147
+ createContext as createContext7,
4148
+ useContext as useContext7
3702
4149
  } from "react";
3703
- import { Fragment as Fragment3, jsx as jsx31 } from "react/jsx-runtime";
3704
- var ThreadConfigContext = createContext6({});
4150
+ import { Fragment as Fragment3, jsx as jsx34 } from "react/jsx-runtime";
4151
+ var ThreadConfigContext = createContext7({});
3705
4152
  var useThreadConfig = () => {
3706
- return useContext6(ThreadConfigContext);
4153
+ return useContext7(ThreadConfigContext);
3707
4154
  };
3708
4155
  var ThreadConfigProvider = ({
3709
4156
  children,
3710
4157
  config
3711
4158
  }) => {
3712
4159
  const assistant = useAssistantContext({ optional: true });
3713
- 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 });
3714
4161
  if (!config?.runtime) return configProvider;
3715
4162
  if (assistant) {
3716
4163
  throw new Error(
3717
4164
  "You provided a runtime to <Thread> while simulataneously using <AssistantRuntimeProvider>. This is not allowed."
3718
4165
  );
3719
4166
  }
3720
- return /* @__PURE__ */ jsx31(AssistantRuntimeProvider, { runtime: config.runtime, children: configProvider });
4167
+ return /* @__PURE__ */ jsx34(AssistantRuntimeProvider, { runtime: config.runtime, children: configProvider });
3721
4168
  };
3722
4169
  ThreadConfigProvider.displayName = "ThreadConfigProvider";
3723
4170
 
3724
4171
  // src/ui/assistant-action-bar.tsx
3725
- import { forwardRef as forwardRef20 } from "react";
4172
+ import { forwardRef as forwardRef19 } from "react";
3726
4173
  import {
3727
4174
  AudioLinesIcon,
3728
4175
  CheckIcon,
@@ -3730,7 +4177,7 @@ import {
3730
4177
  RefreshCwIcon,
3731
4178
  StopCircleIcon
3732
4179
  } from "lucide-react";
3733
- 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";
3734
4181
  var useAllowCopy = (ensureCapability = false) => {
3735
4182
  const { assistantMessage: { allowCopy = true } = {} } = useThreadConfig();
3736
4183
  const { useThread } = useThreadContext();
@@ -3761,9 +4208,9 @@ var AssistantActionBar = () => {
3761
4208
  autohide: "not-last",
3762
4209
  autohideFloat: "single-branch",
3763
4210
  children: [
3764
- allowSpeak && /* @__PURE__ */ jsx32(AssistantActionBarSpeechControl, {}),
3765
- allowCopy && /* @__PURE__ */ jsx32(AssistantActionBarCopy, {}),
3766
- allowReload && /* @__PURE__ */ jsx32(AssistantActionBarReload, {})
4211
+ allowSpeak && /* @__PURE__ */ jsx35(AssistantActionBarSpeechControl, {}),
4212
+ allowCopy && /* @__PURE__ */ jsx35(AssistantActionBarCopy, {}),
4213
+ allowReload && /* @__PURE__ */ jsx35(AssistantActionBarReload, {})
3767
4214
  ]
3768
4215
  }
3769
4216
  );
@@ -3773,36 +4220,35 @@ var AssistantActionBarRoot = withDefaults(actionBar_exports.Root, {
3773
4220
  className: "aui-assistant-action-bar-root"
3774
4221
  });
3775
4222
  AssistantActionBarRoot.displayName = "AssistantActionBarRoot";
3776
- var AssistantActionBarCopy = forwardRef20((props, ref) => {
4223
+ var AssistantActionBarCopy = forwardRef19((props, ref) => {
3777
4224
  const {
3778
4225
  strings: {
3779
4226
  assistantMessage: { copy: { tooltip = "Copy" } = {} } = {}
3780
4227
  } = {}
3781
4228
  } = useThreadConfig();
3782
- return /* @__PURE__ */ jsx32(actionBar_exports.Copy, { asChild: true, children: /* @__PURE__ */ jsx32(TooltipIconButton, { tooltip, ...props, ref, children: props.children ?? /* @__PURE__ */ jsxs5(Fragment4, { children: [
3783
- /* @__PURE__ */ jsx32(message_exports.If, { copied: true, children: /* @__PURE__ */ jsx32(CheckIcon, {}) }),
3784
- /* @__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, {}) })
3785
4232
  ] }) }) });
3786
4233
  });
3787
4234
  AssistantActionBarCopy.displayName = "AssistantActionBarCopy";
3788
4235
  var AssistantActionBarSpeechControl = () => {
3789
4236
  return /* @__PURE__ */ jsxs5(Fragment4, { children: [
3790
- /* @__PURE__ */ jsx32(message_exports.If, { speaking: false, children: /* @__PURE__ */ jsx32(AssistantActionBarSpeak, {}) }),
3791
- /* @__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, {}) })
3792
4239
  ] });
3793
4240
  };
3794
- var AssistantActionBarSpeak = forwardRef20((props, ref) => {
4241
+ var AssistantActionBarSpeak = forwardRef19((props, ref) => {
3795
4242
  const {
3796
4243
  strings: {
3797
4244
  assistantMessage: { speak: { tooltip = "Read aloud" } = {} } = {}
3798
4245
  } = {}
3799
4246
  } = useThreadConfig();
3800
4247
  const allowSpeak = useAllowSpeak();
3801
- if (!allowSpeak) return null;
3802
- 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, {}) }) });
3803
4249
  });
3804
4250
  AssistantActionBarSpeak.displayName = "AssistantActionBarSpeak";
3805
- var AssistantActionBarStopSpeaking = forwardRef20((props, ref) => {
4251
+ var AssistantActionBarStopSpeaking = forwardRef19((props, ref) => {
3806
4252
  const {
3807
4253
  strings: {
3808
4254
  assistantMessage: {
@@ -3811,19 +4257,17 @@ var AssistantActionBarStopSpeaking = forwardRef20((props, ref) => {
3811
4257
  } = {}
3812
4258
  } = useThreadConfig();
3813
4259
  const allowSpeak = useAllowSpeak();
3814
- if (!allowSpeak) return null;
3815
- 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, {}) }) });
3816
4261
  });
3817
4262
  AssistantActionBarStopSpeaking.displayName = "AssistantActionBarStopSpeaking";
3818
- var AssistantActionBarReload = forwardRef20((props, ref) => {
4263
+ var AssistantActionBarReload = forwardRef19((props, ref) => {
3819
4264
  const {
3820
4265
  strings: {
3821
4266
  assistantMessage: { reload: { tooltip = "Refresh" } = {} } = {}
3822
4267
  } = {}
3823
4268
  } = useThreadConfig();
3824
4269
  const allowReload = useAllowReload();
3825
- if (!allowReload) return null;
3826
- 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, {}) }) });
3827
4271
  });
3828
4272
  AssistantActionBarReload.displayName = "AssistantActionBarReload";
3829
4273
  var exports = {
@@ -3840,25 +4284,25 @@ var assistant_action_bar_default = Object.assign(
3840
4284
  );
3841
4285
 
3842
4286
  // src/ui/assistant-message.tsx
3843
- import { forwardRef as forwardRef22 } from "react";
4287
+ import { forwardRef as forwardRef21, useMemo as useMemo5 } from "react";
3844
4288
 
3845
4289
  // src/ui/branch-picker.tsx
3846
- import { forwardRef as forwardRef21 } from "react";
4290
+ import { forwardRef as forwardRef20 } from "react";
3847
4291
  import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
3848
- import { jsx as jsx33, jsxs as jsxs6 } from "react/jsx-runtime";
3849
- var useAllowBranchPicker = () => {
4292
+ import { jsx as jsx36, jsxs as jsxs6 } from "react/jsx-runtime";
4293
+ var useAllowBranchPicker = (ensureCapability = false) => {
3850
4294
  const { branchPicker: { allowBranchPicker = true } = {} } = useThreadConfig();
3851
4295
  const { useThread } = useThreadContext();
3852
4296
  const branchPickerSupported = useThread((t) => t.capabilities.edit);
3853
- return branchPickerSupported && allowBranchPicker;
4297
+ return allowBranchPicker && (!ensureCapability || branchPickerSupported);
3854
4298
  };
3855
4299
  var BranchPicker = () => {
3856
4300
  const allowBranchPicker = useAllowBranchPicker();
3857
4301
  if (!allowBranchPicker) return null;
3858
4302
  return /* @__PURE__ */ jsxs6(BranchPickerRoot, { hideWhenSingleBranch: true, children: [
3859
- /* @__PURE__ */ jsx33(BranchPickerPrevious2, {}),
3860
- /* @__PURE__ */ jsx33(BranchPickerState, {}),
3861
- /* @__PURE__ */ jsx33(BranchPickerNext, {})
4303
+ /* @__PURE__ */ jsx36(BranchPickerPrevious2, {}),
4304
+ /* @__PURE__ */ jsx36(BranchPickerState, {}),
4305
+ /* @__PURE__ */ jsx36(BranchPickerNext, {})
3862
4306
  ] });
3863
4307
  };
3864
4308
  BranchPicker.displayName = "BranchPicker";
@@ -3866,31 +4310,33 @@ var BranchPickerRoot = withDefaults(branchPicker_exports.Root, {
3866
4310
  className: "aui-branch-picker-root"
3867
4311
  });
3868
4312
  BranchPickerRoot.displayName = "BranchPickerRoot";
3869
- var BranchPickerPrevious2 = forwardRef21((props, ref) => {
4313
+ var BranchPickerPrevious2 = forwardRef20((props, ref) => {
3870
4314
  const {
3871
4315
  strings: {
3872
4316
  branchPicker: { previous: { tooltip = "Previous" } = {} } = {}
3873
4317
  } = {}
3874
4318
  } = useThreadConfig();
3875
- 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, {}) }) });
3876
4321
  });
3877
4322
  BranchPickerPrevious2.displayName = "BranchPickerPrevious";
3878
4323
  var BranchPickerStateWrapper = withDefaults("span", {
3879
4324
  className: "aui-branch-picker-state"
3880
4325
  });
3881
- var BranchPickerState = forwardRef21((props, ref) => {
4326
+ var BranchPickerState = forwardRef20((props, ref) => {
3882
4327
  return /* @__PURE__ */ jsxs6(BranchPickerStateWrapper, { ...props, ref, children: [
3883
- /* @__PURE__ */ jsx33(branchPicker_exports.Number, {}),
4328
+ /* @__PURE__ */ jsx36(branchPicker_exports.Number, {}),
3884
4329
  " / ",
3885
- /* @__PURE__ */ jsx33(branchPicker_exports.Count, {})
4330
+ /* @__PURE__ */ jsx36(branchPicker_exports.Count, {})
3886
4331
  ] });
3887
4332
  });
3888
4333
  BranchPickerState.displayName = "BranchPickerState";
3889
- var BranchPickerNext = forwardRef21((props, ref) => {
4334
+ var BranchPickerNext = forwardRef20((props, ref) => {
3890
4335
  const {
3891
4336
  strings: { branchPicker: { next: { tooltip = "Next" } = {} } = {} } = {}
3892
4337
  } = useThreadConfig();
3893
- 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, {}) }) });
3894
4340
  });
3895
4341
  BranchPickerNext.displayName = "BranchPickerNext";
3896
4342
  var exports2 = {
@@ -3902,12 +4348,12 @@ var branch_picker_default = Object.assign(BranchPicker, exports2);
3902
4348
 
3903
4349
  // src/ui/base/avatar.tsx
3904
4350
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
3905
- import { jsx as jsx34, jsxs as jsxs7 } from "react/jsx-runtime";
4351
+ import { jsx as jsx37, jsxs as jsxs7 } from "react/jsx-runtime";
3906
4352
  var Avatar = ({ src, alt, fallback }) => {
3907
4353
  if (src == null && fallback == null) return null;
3908
4354
  return /* @__PURE__ */ jsxs7(AvatarRoot, { children: [
3909
- src != null && /* @__PURE__ */ jsx34(AvatarImage, { src, alt }),
3910
- fallback != null && /* @__PURE__ */ jsx34(AvatarFallback, { children: fallback })
4355
+ src != null && /* @__PURE__ */ jsx37(AvatarImage, { src, alt }),
4356
+ fallback != null && /* @__PURE__ */ jsx37(AvatarFallback, { children: fallback })
3911
4357
  ] });
3912
4358
  };
3913
4359
  Avatar.displayName = "Avatar";
@@ -3926,10 +4372,10 @@ AvatarFallback.displayName = "AvatarFallback";
3926
4372
 
3927
4373
  // src/ui/content-part.tsx
3928
4374
  import classNames2 from "classnames";
3929
- import { jsx as jsx35 } from "react/jsx-runtime";
4375
+ import { jsx as jsx38 } from "react/jsx-runtime";
3930
4376
  var Text = () => {
3931
4377
  const status = useSmoothStatus();
3932
- return /* @__PURE__ */ jsx35(
4378
+ return /* @__PURE__ */ jsx38(
3933
4379
  contentPart_exports.Text,
3934
4380
  {
3935
4381
  className: classNames2(
@@ -3944,19 +4390,19 @@ var exports3 = { Text: withSmoothContextProvider(Text) };
3944
4390
  var content_part_default = exports3;
3945
4391
 
3946
4392
  // src/ui/assistant-message.tsx
3947
- import { jsx as jsx36, jsxs as jsxs8 } from "react/jsx-runtime";
4393
+ import { jsx as jsx39, jsxs as jsxs8 } from "react/jsx-runtime";
3948
4394
  var AssistantMessage = () => {
3949
4395
  return /* @__PURE__ */ jsxs8(AssistantMessageRoot, { children: [
3950
- /* @__PURE__ */ jsx36(AssistantMessageAvatar, {}),
3951
- /* @__PURE__ */ jsx36(AssistantMessageContent, {}),
3952
- /* @__PURE__ */ jsx36(branch_picker_default, {}),
3953
- /* @__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, {})
3954
4400
  ] });
3955
4401
  };
3956
4402
  AssistantMessage.displayName = "AssistantMessage";
3957
4403
  var AssistantMessageAvatar = () => {
3958
4404
  const { assistantAvatar: avatar = { fallback: "A" } } = useThreadConfig();
3959
- return /* @__PURE__ */ jsx36(Avatar, { ...avatar });
4405
+ return /* @__PURE__ */ jsx39(Avatar, { ...avatar });
3960
4406
  };
3961
4407
  var AssistantMessageRoot = withDefaults(message_exports.Root, {
3962
4408
  className: "aui-assistant-message-root"
@@ -3965,23 +4411,28 @@ AssistantMessageRoot.displayName = "AssistantMessageRoot";
3965
4411
  var AssistantMessageContentWrapper = withDefaults("div", {
3966
4412
  className: "aui-assistant-message-content"
3967
4413
  });
3968
- var AssistantMessageContent = forwardRef22(({ components: componentsProp, ...rest }, ref) => {
4414
+ var AssistantMessageContent = forwardRef21(({ components: componentsProp, ...rest }, ref) => {
3969
4415
  const { tools, assistantMessage: { components = {} } = {} } = useThreadConfig();
3970
- return /* @__PURE__ */ jsx36(AssistantMessageContentWrapper, { ...rest, ref, children: /* @__PURE__ */ jsx36(
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(
3971
4430
  message_exports.Content,
3972
4431
  {
3973
4432
  components: {
3974
4433
  ...componentsProp,
3975
4434
  Text: componentsProp?.Text ?? components.Text ?? content_part_default.Text,
3976
- tools: {
3977
- by_name: !tools ? void 0 : Object.fromEntries(
3978
- tools.map((t) => [
3979
- t.unstable_tool.toolName,
3980
- t.unstable_tool.render
3981
- ])
3982
- ),
3983
- Fallback: components.ToolFallback
3984
- }
4435
+ tools: toolsComponents
3985
4436
  }
3986
4437
  }
3987
4438
  ) });
@@ -4007,12 +4458,12 @@ import { ArrowDownIcon } from "lucide-react";
4007
4458
 
4008
4459
  // src/ui/composer.tsx
4009
4460
  import { forwardRef as forwardRef23 } from "react";
4010
- import { SendHorizontalIcon } from "lucide-react";
4461
+ import { PaperclipIcon, SendHorizontalIcon } from "lucide-react";
4011
4462
 
4012
4463
  // src/ui/base/CircleStopIcon.tsx
4013
- import { jsx as jsx37 } from "react/jsx-runtime";
4464
+ import { jsx as jsx40 } from "react/jsx-runtime";
4014
4465
  var CircleStopIcon = () => {
4015
- return /* @__PURE__ */ jsx37(
4466
+ return /* @__PURE__ */ jsx40(
4016
4467
  "svg",
4017
4468
  {
4018
4469
  xmlns: "http://www.w3.org/2000/svg",
@@ -4020,18 +4471,79 @@ var CircleStopIcon = () => {
4020
4471
  fill: "currentColor",
4021
4472
  width: "16",
4022
4473
  height: "16",
4023
- 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" })
4024
4475
  }
4025
4476
  );
4026
4477
  };
4027
4478
  CircleStopIcon.displayName = "CircleStopIcon";
4028
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
+
4029
4532
  // src/ui/composer.tsx
4030
- 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
+ };
4031
4540
  var Composer = () => {
4032
- return /* @__PURE__ */ jsxs9(ComposerRoot, { children: [
4033
- /* @__PURE__ */ jsx38(ComposerInput, { autoFocus: true }),
4034
- /* @__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, {})
4035
4547
  ] });
4036
4548
  };
4037
4549
  Composer.displayName = "Composer";
@@ -4051,10 +4563,47 @@ var ComposerInput = forwardRef23(
4051
4563
  composer: { input: { placeholder = "Write a message..." } = {} } = {}
4052
4564
  } = {}
4053
4565
  } = useThreadConfig();
4054
- return /* @__PURE__ */ jsx38(ComposerInputStyled, { placeholder, ...props, ref });
4566
+ return /* @__PURE__ */ jsx42(ComposerInputStyled, { placeholder, ...props, ref });
4055
4567
  }
4056
4568
  );
4057
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";
4058
4607
  var useAllowCancel = () => {
4059
4608
  const { useThread } = useThreadContext();
4060
4609
  const cancelSupported = useThread((t) => t.capabilities.cancel);
@@ -4062,10 +4611,10 @@ var useAllowCancel = () => {
4062
4611
  };
4063
4612
  var ComposerAction = () => {
4064
4613
  const allowCancel = useAllowCancel();
4065
- if (!allowCancel) return /* @__PURE__ */ jsx38(ComposerSend, {});
4066
- return /* @__PURE__ */ jsxs9(Fragment5, { children: [
4067
- /* @__PURE__ */ jsx38(thread_exports.If, { running: false, children: /* @__PURE__ */ jsx38(ComposerSend, {}) }),
4068
- /* @__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, {}) })
4069
4618
  ] });
4070
4619
  };
4071
4620
  ComposerAction.displayName = "ComposerAction";
@@ -4077,7 +4626,7 @@ var ComposerSend = forwardRef23((props, ref) => {
4077
4626
  const {
4078
4627
  strings: { composer: { send: { tooltip = "Send" } = {} } = {} } = {}
4079
4628
  } = useThreadConfig();
4080
- 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, {}) }) });
4081
4630
  });
4082
4631
  ComposerSend.displayName = "ComposerSend";
4083
4632
  var ComposerCancelButton = withDefaults(TooltipIconButton, {
@@ -4088,28 +4637,30 @@ var ComposerCancel = forwardRef23((props, ref) => {
4088
4637
  const {
4089
4638
  strings: { composer: { cancel: { tooltip = "Cancel" } = {} } = {} } = {}
4090
4639
  } = useThreadConfig();
4091
- 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, {}) }) });
4092
4641
  });
4093
4642
  ComposerCancel.displayName = "ComposerCancel";
4094
- var exports5 = {
4643
+ var exports6 = {
4095
4644
  Root: ComposerRoot,
4096
4645
  Input: ComposerInput,
4097
4646
  Action: ComposerAction,
4098
4647
  Send: ComposerSend,
4099
- Cancel: ComposerCancel
4648
+ Cancel: ComposerCancel,
4649
+ AddAttachment: ComposerAddAttachment,
4650
+ Attachments: ComposerAttachments
4100
4651
  };
4101
- var composer_default = Object.assign(Composer, exports5);
4652
+ var composer_default = Object.assign(Composer, exports6);
4102
4653
 
4103
4654
  // src/ui/thread-welcome.tsx
4104
4655
  import { forwardRef as forwardRef24 } from "react";
4105
- import { jsx as jsx39, jsxs as jsxs10 } from "react/jsx-runtime";
4656
+ import { jsx as jsx43, jsxs as jsxs11 } from "react/jsx-runtime";
4106
4657
  var ThreadWelcome = () => {
4107
- return /* @__PURE__ */ jsxs10(ThreadWelcomeRoot, { children: [
4108
- /* @__PURE__ */ jsxs10(ThreadWelcomeCenter, { children: [
4109
- /* @__PURE__ */ jsx39(ThreadWelcomeAvatar, {}),
4110
- /* @__PURE__ */ jsx39(ThreadWelcomeMessage, {})
4658
+ return /* @__PURE__ */ jsxs11(ThreadWelcomeRoot, { children: [
4659
+ /* @__PURE__ */ jsxs11(ThreadWelcomeCenter, { children: [
4660
+ /* @__PURE__ */ jsx43(ThreadWelcomeAvatar, {}),
4661
+ /* @__PURE__ */ jsx43(ThreadWelcomeMessage, {})
4111
4662
  ] }),
4112
- /* @__PURE__ */ jsx39(ThreadWelcomeSuggestions, {})
4663
+ /* @__PURE__ */ jsx43(ThreadWelcomeSuggestions, {})
4113
4664
  ] });
4114
4665
  };
4115
4666
  ThreadWelcome.displayName = "ThreadWelcome";
@@ -4121,20 +4672,20 @@ var ThreadWelcomeCenter = withDefaults("div", {
4121
4672
  });
4122
4673
  var ThreadWelcomeRoot = forwardRef24(
4123
4674
  (props, ref) => {
4124
- 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 }) });
4125
4676
  }
4126
4677
  );
4127
4678
  ThreadWelcomeRoot.displayName = "ThreadWelcomeRoot";
4128
4679
  var ThreadWelcomeAvatar = () => {
4129
4680
  const { assistantAvatar: avatar = { fallback: "A" } } = useThreadConfig();
4130
- return /* @__PURE__ */ jsx39(Avatar, { ...avatar });
4681
+ return /* @__PURE__ */ jsx43(Avatar, { ...avatar });
4131
4682
  };
4132
4683
  var ThreadWelcomeMessageStyled = withDefaults("p", {
4133
4684
  className: "aui-thread-welcome-message"
4134
4685
  });
4135
4686
  var ThreadWelcomeMessage = forwardRef24(({ message: messageProp, ...rest }, ref) => {
4136
4687
  const { welcome: { message = "How can I help you today?" } = {} } = useThreadConfig();
4137
- return /* @__PURE__ */ jsx39(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message });
4688
+ return /* @__PURE__ */ jsx43(ThreadWelcomeMessageStyled, { ...rest, ref, children: messageProp ?? message });
4138
4689
  });
4139
4690
  ThreadWelcomeMessage.displayName = "ThreadWelcomeMessage";
4140
4691
  var ThreadWelcomeSuggestionContainer = withDefaults("div", {
@@ -4146,25 +4697,25 @@ var ThreadWelcomeSuggestionStyled = withDefaults(thread_exports.Suggestion, {
4146
4697
  var ThreadWelcomeSuggestion = ({
4147
4698
  suggestion: { text, prompt }
4148
4699
  }) => {
4149
- return /* @__PURE__ */ jsx39(
4700
+ return /* @__PURE__ */ jsx43(
4150
4701
  ThreadWelcomeSuggestionStyled,
4151
4702
  {
4152
4703
  prompt,
4153
4704
  method: "replace",
4154
4705
  autoSend: true,
4155
- 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 })
4156
4707
  }
4157
4708
  );
4158
4709
  };
4159
4710
  var ThreadWelcomeSuggestions = () => {
4160
4711
  const { welcome: { suggestions } = {} } = useThreadConfig();
4161
- return /* @__PURE__ */ jsx39(ThreadWelcomeSuggestionContainer, { children: suggestions?.map((suggestion, idx) => {
4712
+ return /* @__PURE__ */ jsx43(ThreadWelcomeSuggestionContainer, { children: suggestions?.map((suggestion, idx) => {
4162
4713
  const key = `${suggestion.prompt}-${idx}`;
4163
- return /* @__PURE__ */ jsx39(ThreadWelcomeSuggestion, { suggestion }, key);
4714
+ return /* @__PURE__ */ jsx43(ThreadWelcomeSuggestion, { suggestion }, key);
4164
4715
  }) });
4165
4716
  };
4166
4717
  ThreadWelcomeSuggestions.displayName = "ThreadWelcomeSuggestions";
4167
- var exports6 = {
4718
+ var exports7 = {
4168
4719
  Root: ThreadWelcomeRoot,
4169
4720
  Center: ThreadWelcomeCenter,
4170
4721
  Avatar: ThreadWelcomeAvatar,
@@ -4172,7 +4723,7 @@ var exports6 = {
4172
4723
  Suggestions: ThreadWelcomeSuggestions,
4173
4724
  Suggestion: ThreadWelcomeSuggestion
4174
4725
  };
4175
- var thread_welcome_default = Object.assign(ThreadWelcome, exports6);
4726
+ var thread_welcome_default = Object.assign(ThreadWelcome, exports7);
4176
4727
 
4177
4728
  // src/ui/user-message.tsx
4178
4729
  import { forwardRef as forwardRef26 } from "react";
@@ -4180,7 +4731,7 @@ import { forwardRef as forwardRef26 } from "react";
4180
4731
  // src/ui/user-action-bar.tsx
4181
4732
  import { forwardRef as forwardRef25 } from "react";
4182
4733
  import { PencilIcon } from "lucide-react";
4183
- import { jsx as jsx40 } from "react/jsx-runtime";
4734
+ import { jsx as jsx44 } from "react/jsx-runtime";
4184
4735
  var useAllowEdit = (ensureCapability = false) => {
4185
4736
  const { userMessage: { allowEdit = true } = {} } = useThreadConfig();
4186
4737
  const { useThread } = useThreadContext();
@@ -4190,7 +4741,7 @@ var useAllowEdit = (ensureCapability = false) => {
4190
4741
  var UserActionBar = () => {
4191
4742
  const allowEdit = useAllowEdit(true);
4192
4743
  if (!allowEdit) return null;
4193
- 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, {}) });
4194
4745
  };
4195
4746
  UserActionBar.displayName = "UserActionBar";
4196
4747
  var UserActionBarRoot = withDefaults(actionBar_exports.Root, {
@@ -4202,23 +4753,46 @@ var UserActionBarEdit = forwardRef25((props, ref) => {
4202
4753
  strings: { userMessage: { edit: { tooltip = "Edit" } = {} } = {} } = {}
4203
4754
  } = useThreadConfig();
4204
4755
  const allowEdit = useAllowEdit();
4205
- if (!allowEdit) return null;
4206
- 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, {}) }) });
4207
4757
  });
4208
4758
  UserActionBarEdit.displayName = "UserActionBarEdit";
4209
- var exports7 = {
4759
+ var exports8 = {
4210
4760
  Root: UserActionBarRoot,
4211
4761
  Edit: UserActionBarEdit
4212
4762
  };
4213
- 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
+ );
4214
4787
 
4215
4788
  // src/ui/user-message.tsx
4216
- import { jsx as jsx41, jsxs as jsxs11 } from "react/jsx-runtime";
4789
+ import { jsx as jsx45, jsxs as jsxs13 } from "react/jsx-runtime";
4217
4790
  var UserMessage = () => {
4218
- return /* @__PURE__ */ jsxs11(UserMessageRoot, { children: [
4219
- /* @__PURE__ */ jsx41(user_action_bar_default, {}),
4220
- /* @__PURE__ */ jsx41(UserMessageContent, {}),
4221
- /* @__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, {})
4222
4796
  ] });
4223
4797
  };
4224
4798
  UserMessage.displayName = "UserMessage";
@@ -4231,7 +4805,7 @@ var UserMessageContentWrapper = withDefaults("div", {
4231
4805
  });
4232
4806
  var UserMessageContent = forwardRef26(
4233
4807
  ({ components, ...props }, ref) => {
4234
- return /* @__PURE__ */ jsx41(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ jsx41(
4808
+ return /* @__PURE__ */ jsx45(UserMessageContentWrapper, { ...props, ref, children: /* @__PURE__ */ jsx45(
4235
4809
  message_exports.Content,
4236
4810
  {
4237
4811
  components: {
@@ -4243,21 +4817,38 @@ var UserMessageContent = forwardRef26(
4243
4817
  }
4244
4818
  );
4245
4819
  UserMessageContent.displayName = "UserMessageContent";
4246
- 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 = {
4247
4837
  Root: UserMessageRoot,
4248
- Content: UserMessageContent
4838
+ Content: UserMessageContent,
4839
+ Attachments: UserMessageAttachments
4249
4840
  };
4250
- var user_message_default = Object.assign(UserMessage, exports8);
4841
+ var user_message_default = Object.assign(UserMessage, exports10);
4251
4842
 
4252
4843
  // src/ui/edit-composer.tsx
4253
4844
  import { forwardRef as forwardRef27 } from "react";
4254
- import { jsx as jsx42, jsxs as jsxs12 } from "react/jsx-runtime";
4845
+ import { jsx as jsx46, jsxs as jsxs14 } from "react/jsx-runtime";
4255
4846
  var EditComposer = () => {
4256
- return /* @__PURE__ */ jsxs12(EditComposerRoot, { children: [
4257
- /* @__PURE__ */ jsx42(EditComposerInput, {}),
4258
- /* @__PURE__ */ jsxs12(EditComposerFooter, { children: [
4259
- /* @__PURE__ */ jsx42(EditComposerCancel, {}),
4260
- /* @__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, {})
4261
4852
  ] })
4262
4853
  ] });
4263
4854
  };
@@ -4281,7 +4872,7 @@ var EditComposerCancel = forwardRef27(
4281
4872
  editComposer: { cancel: { label = "Cancel" } = {} } = {}
4282
4873
  } = {}
4283
4874
  } = useThreadConfig();
4284
- 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 }) });
4285
4876
  }
4286
4877
  );
4287
4878
  EditComposerCancel.displayName = "EditComposerCancel";
@@ -4290,28 +4881,28 @@ var EditComposerSend = forwardRef27(
4290
4881
  const {
4291
4882
  strings: { editComposer: { send: { label = "Send" } = {} } = {} } = {}
4292
4883
  } = useThreadConfig();
4293
- 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 }) });
4294
4885
  }
4295
4886
  );
4296
4887
  EditComposerSend.displayName = "EditComposerSend";
4297
- var exports9 = {
4888
+ var exports11 = {
4298
4889
  Root: EditComposerRoot,
4299
4890
  Input: EditComposerInput,
4300
4891
  Footer: EditComposerFooter,
4301
4892
  Cancel: EditComposerCancel,
4302
4893
  Send: EditComposerSend
4303
4894
  };
4304
- var edit_composer_default = Object.assign(EditComposer, exports9);
4895
+ var edit_composer_default = Object.assign(EditComposer, exports11);
4305
4896
 
4306
4897
  // src/ui/thread.tsx
4307
- import { jsx as jsx43, jsxs as jsxs13 } from "react/jsx-runtime";
4898
+ import { jsx as jsx47, jsxs as jsxs15 } from "react/jsx-runtime";
4308
4899
  var Thread = (config) => {
4309
- return /* @__PURE__ */ jsx43(ThreadRoot, { config, children: /* @__PURE__ */ jsxs13(ThreadViewport, { children: [
4310
- /* @__PURE__ */ jsx43(thread_welcome_default, {}),
4311
- /* @__PURE__ */ jsx43(ThreadMessages, {}),
4312
- /* @__PURE__ */ jsxs13(ThreadViewportFooter, { children: [
4313
- /* @__PURE__ */ jsx43(ThreadScrollToBottom, {}),
4314
- /* @__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, {})
4315
4906
  ] })
4316
4907
  ] }) });
4317
4908
  };
@@ -4320,7 +4911,7 @@ var ThreadRootStyled = withDefaults(thread_exports.Root, {
4320
4911
  });
4321
4912
  var ThreadRoot = forwardRef28(
4322
4913
  ({ config, ...props }, ref) => {
4323
- return /* @__PURE__ */ jsx43(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx43(ThreadRootStyled, { ...props, ref }) });
4914
+ return /* @__PURE__ */ jsx47(ThreadConfigProvider, { config, children: /* @__PURE__ */ jsx47(ThreadRootStyled, { ...props, ref }) });
4324
4915
  }
4325
4916
  );
4326
4917
  ThreadRoot.displayName = "ThreadRoot";
@@ -4334,7 +4925,7 @@ var ThreadViewportFooter = withDefaults("div", {
4334
4925
  ThreadViewportFooter.displayName = "ThreadViewportFooter";
4335
4926
  var SystemMessage = () => null;
4336
4927
  var ThreadMessages = ({ components, ...rest }) => {
4337
- return /* @__PURE__ */ jsx43(
4928
+ return /* @__PURE__ */ jsx47(
4338
4929
  thread_exports.Messages,
4339
4930
  {
4340
4931
  components: {
@@ -4358,33 +4949,33 @@ var ThreadScrollToBottom = forwardRef28((props, ref) => {
4358
4949
  thread: { scrollToBottom: { tooltip = "Scroll to bottom" } = {} } = {}
4359
4950
  } = {}
4360
4951
  } = useThreadConfig();
4361
- 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, {}) }) });
4362
4953
  });
4363
4954
  ThreadScrollToBottom.displayName = "ThreadScrollToBottom";
4364
- var exports10 = {
4955
+ var exports12 = {
4365
4956
  Root: ThreadRoot,
4366
4957
  Viewport: ThreadViewport,
4367
4958
  Messages: ThreadMessages,
4368
4959
  ScrollToBottom: ThreadScrollToBottom,
4369
4960
  ViewportFooter: ThreadViewportFooter
4370
4961
  };
4371
- var thread_default = Object.assign(Thread, exports10);
4962
+ var thread_default = Object.assign(Thread, exports12);
4372
4963
 
4373
4964
  // src/ui/assistant-modal.tsx
4374
- 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";
4375
4966
  var AssistantModal = (config) => {
4376
- return /* @__PURE__ */ jsxs14(AssistantModalRoot, { config, children: [
4377
- /* @__PURE__ */ jsx44(AssistantModalTrigger, {}),
4378
- /* @__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, {}) })
4379
4970
  ] });
4380
4971
  };
4381
4972
  AssistantModal.displayName = "AssistantModal";
4382
4973
  var AssistantModalRoot = ({ config, ...props }) => {
4383
- 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 }) });
4384
4975
  };
4385
4976
  AssistantModalRoot.displayName = "AssistantModalRoot";
4386
4977
  var AssistantModalTrigger = forwardRef29((props, ref) => {
4387
- 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 }) }) });
4388
4979
  });
4389
4980
  AssistantModalTrigger.displayName = "AssistantModalTrigger";
4390
4981
  var AssistantModalAnchor = withDefaults(assistantModal_exports.Anchor, {
@@ -4409,7 +5000,7 @@ var AssistantModalButton = forwardRef29(({ "data-state": state, ...rest }, ref)
4409
5000
  } = {}
4410
5001
  } = useThreadConfig();
4411
5002
  const tooltip = state === "open" ? openTooltip : closedTooltip;
4412
- return /* @__PURE__ */ jsx44(
5003
+ return /* @__PURE__ */ jsx48(
4413
5004
  ModalButtonStyled,
4414
5005
  {
4415
5006
  side: "left",
@@ -4417,15 +5008,15 @@ var AssistantModalButton = forwardRef29(({ "data-state": state, ...rest }, ref)
4417
5008
  "data-state": state,
4418
5009
  ...rest,
4419
5010
  ref,
4420
- children: rest.children ?? /* @__PURE__ */ jsxs14(Fragment6, { children: [
4421
- /* @__PURE__ */ jsx44(
5011
+ children: rest.children ?? /* @__PURE__ */ jsxs16(Fragment6, { children: [
5012
+ /* @__PURE__ */ jsx48(
4422
5013
  BotIcon,
4423
5014
  {
4424
5015
  "data-state": state,
4425
5016
  className: "aui-modal-button-closed-icon"
4426
5017
  }
4427
5018
  ),
4428
- /* @__PURE__ */ jsx44(
5019
+ /* @__PURE__ */ jsx48(
4429
5020
  ChevronDownIcon,
4430
5021
  {
4431
5022
  "data-state": state,
@@ -4442,14 +5033,14 @@ var AssistantModalContent = withDefaults(assistantModal_exports.Content, {
4442
5033
  sideOffset: 16
4443
5034
  });
4444
5035
  AssistantModalContent.displayName = "AssistantModalContent";
4445
- var exports11 = {
5036
+ var exports13 = {
4446
5037
  Root: AssistantModalRoot,
4447
5038
  Trigger: AssistantModalTrigger,
4448
5039
  Content: AssistantModalContent,
4449
5040
  Button: AssistantModalButton,
4450
5041
  Anchor: AssistantModalAnchor
4451
5042
  };
4452
- var assistant_modal_default = Object.assign(AssistantModal, exports11);
5043
+ var assistant_modal_default = Object.assign(AssistantModal, exports13);
4453
5044
  export {
4454
5045
  actionBar_exports as ActionBarPrimitive,
4455
5046
  assistant_action_bar_default as AssistantActionBar,
@@ -4460,7 +5051,9 @@ export {
4460
5051
  branch_picker_default as BranchPicker,
4461
5052
  branchPicker_exports as BranchPickerPrimitive,
4462
5053
  composer_default as Composer,
5054
+ composer_attachment_default as ComposerAttachment,
4463
5055
  composer_exports as ComposerPrimitive,
5056
+ CompositeAttachmentAdapter,
4464
5057
  content_part_default as ContentPart,
4465
5058
  contentPart_exports as ContentPartPrimitive,
4466
5059
  EdgeChatAdapter,
@@ -4468,12 +5061,15 @@ export {
4468
5061
  ExternalStoreRuntime,
4469
5062
  internal_exports as INTERNAL,
4470
5063
  message_exports as MessagePrimitive,
5064
+ SimpleImageAttachmentAdapter,
5065
+ SimpleTextAttachmentAdapter,
4471
5066
  thread_default as Thread,
4472
5067
  ThreadConfigProvider,
4473
5068
  thread_exports as ThreadPrimitive,
4474
5069
  thread_welcome_default as ThreadWelcome,
4475
5070
  user_action_bar_default as UserActionBar,
4476
5071
  user_message_default as UserMessage,
5072
+ user_message_attachment_default as UserMessageAttachment,
4477
5073
  WebSpeechSynthesisAdapter,
4478
5074
  fromCoreMessage,
4479
5075
  fromCoreMessages,
@@ -4502,6 +5098,7 @@ export {
4502
5098
  useBranchPickerNext,
4503
5099
  useBranchPickerNumber,
4504
5100
  useBranchPickerPrevious,
5101
+ useComposerAddAttachment,
4505
5102
  useComposerCancel,
4506
5103
  useComposerContext,
4507
5104
  useComposerIf,