@assistant-ui/react 0.1.9 → 0.1.11

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
@@ -9,9 +9,9 @@ import {
9
9
  useContentPartContext,
10
10
  useMessageContext,
11
11
  useThreadContext
12
- } from "./chunk-7O2URLFI.mjs";
12
+ } from "./chunk-KUACYNLE.mjs";
13
13
 
14
- // src/actions/useCopyMessage.tsx
14
+ // src/primitive-hooks/actionBar/useActionBarCopy.tsx
15
15
  import { useCallback } from "react";
16
16
 
17
17
  // src/utils/combined/useCombinedStore.ts
@@ -48,38 +48,56 @@ var getMessageText = (message) => {
48
48
  return textParts.map((part) => part.text).join("\n\n");
49
49
  };
50
50
 
51
- // src/actions/useCopyMessage.tsx
52
- var useCopyMessage = ({ copiedDuration = 3e3 }) => {
53
- const { useMessage, useMessageUtils, useComposer } = useMessageContext();
51
+ // src/primitive-hooks/actionBar/useActionBarCopy.tsx
52
+ var useActionBarCopy = ({
53
+ copiedDuration = 3e3
54
+ } = {}) => {
55
+ const { useMessage, useMessageUtils, useEditComposer } = useMessageContext();
54
56
  const hasCopyableContent = useCombinedStore(
55
- [useMessage, useComposer],
57
+ [useMessage, useEditComposer],
56
58
  (m, c) => {
57
- return c.isEditing || m.message.content.some((c2) => c2.type === "text");
59
+ return !c.isEditing && m.message.content.some((c2) => c2.type === "text");
58
60
  }
59
61
  );
60
62
  const callback = useCallback(() => {
61
63
  const { message } = useMessage.getState();
62
64
  const { setIsCopied } = useMessageUtils.getState();
63
- const { isEditing, value: composerValue } = useComposer.getState();
65
+ const { isEditing, value: composerValue } = useEditComposer.getState();
64
66
  const valueToCopy = isEditing ? composerValue : getMessageText(message);
65
67
  navigator.clipboard.writeText(valueToCopy);
66
68
  setIsCopied(true);
67
69
  setTimeout(() => setIsCopied(false), copiedDuration);
68
- }, [useMessage, useMessageUtils, useComposer, copiedDuration]);
70
+ }, [useMessage, useMessageUtils, useEditComposer, copiedDuration]);
69
71
  if (!hasCopyableContent) return null;
70
72
  return callback;
71
73
  };
72
74
 
73
- // src/actions/useReloadMessage.tsx
75
+ // src/primitive-hooks/actionBar/useActionBarEdit.tsx
74
76
  import { useCallback as useCallback2 } from "react";
75
- var useReloadMessage = () => {
77
+ var useActionBarEdit = () => {
78
+ const { useMessage, useEditComposer } = useMessageContext();
79
+ const disabled = useCombinedStore(
80
+ [useMessage, useEditComposer],
81
+ (m, c) => m.message.role !== "user" || c.isEditing
82
+ );
83
+ const callback = useCallback2(() => {
84
+ const { edit } = useEditComposer.getState();
85
+ edit();
86
+ }, [useEditComposer]);
87
+ if (disabled) return null;
88
+ return callback;
89
+ };
90
+
91
+ // src/primitive-hooks/actionBar/useActionBarReload.tsx
92
+ import { useCallback as useCallback3 } from "react";
93
+ var useActionBarReload = () => {
76
94
  const { useThread, useThreadActions, useViewport } = useThreadContext();
77
95
  const { useMessage } = useMessageContext();
78
96
  const disabled = useCombinedStore(
79
97
  [useThread, useMessage],
80
98
  (t, m) => t.isRunning || m.message.role !== "assistant"
81
99
  );
82
- const callback = useCallback2(() => {
100
+ const callback = useCallback3(() => {
83
101
  const { parentId } = useMessage.getState();
84
102
  useThreadActions.getState().startRun(parentId);
85
103
  useViewport.getState().scrollToBottom();
@@ -88,29 +106,20 @@ var useReloadMessage = () => {
88
106
  return callback;
89
107
  };
90
108
 
91
- // src/actions/useBeginMessageEdit.tsx
92
- import { useCallback as useCallback3 } from "react";
93
- var useBeginMessageEdit = () => {
94
- const { useMessage, useComposer } = useMessageContext();
95
- const disabled = useCombinedStore(
96
- [useMessage, useComposer],
97
- (m, c) => m.message.role !== "user" || c.isEditing
98
- );
99
- const callback = useCallback3(() => {
100
- const { edit } = useComposer.getState();
101
- edit();
102
- }, [useComposer]);
103
- if (disabled) return null;
104
- return callback;
109
+ // src/primitive-hooks/branchPicker/useBranchPickerCount.tsx
110
+ var useBranchPickerCount = () => {
111
+ const { useMessage } = useMessageContext();
112
+ const branchCount = useMessage((s) => s.branches.length);
113
+ return branchCount;
105
114
  };
106
115
 
107
- // src/actions/useGoToNextBranch.tsx
116
+ // src/primitive-hooks/branchPicker/useBranchPickerNext.tsx
108
117
  import { useCallback as useCallback4 } from "react";
109
- var useGoToNextBranch = () => {
118
+ var useBranchPickerNext = () => {
110
119
  const { useThreadActions } = useThreadContext();
111
- const { useMessage, useComposer } = useMessageContext();
120
+ const { useMessage, useEditComposer } = useMessageContext();
112
121
  const disabled = useCombinedStore(
113
- [useMessage, useComposer],
122
+ [useMessage, useEditComposer],
114
123
  (m, c) => c.isEditing || m.branches.indexOf(m.message.id) + 1 >= m.branches.length
115
124
  );
116
125
  const callback = useCallback4(() => {
@@ -121,13 +130,20 @@ var useGoToNextBranch = () => {
121
130
  return callback;
122
131
  };
123
132
 
124
- // src/actions/useGoToPreviousBranch.tsx
133
+ // src/primitive-hooks/branchPicker/useBranchPickerNumber.tsx
134
+ var useBranchPickerNumber = () => {
135
+ const { useMessage } = useMessageContext();
136
+ const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
137
+ return branchIdx + 1;
138
+ };
139
+
140
+ // src/primitive-hooks/branchPicker/useBranchPickerPrevious.tsx
125
141
  import { useCallback as useCallback5 } from "react";
126
- var useGoToPreviousBranch = () => {
142
+ var useBranchPickerPrevious = () => {
127
143
  const { useThreadActions } = useThreadContext();
128
- const { useMessage, useComposer } = useMessageContext();
144
+ const { useMessage, useEditComposer } = useMessageContext();
129
145
  const disabled = useCombinedStore(
130
- [useMessage, useComposer],
146
+ [useMessage, useEditComposer],
131
147
  (m, c) => c.isEditing || m.branches.indexOf(m.message.id) <= 0
132
148
  );
133
149
  const callback = useCallback5(() => {
@@ -138,6 +154,162 @@ var useGoToPreviousBranch = () => {
138
154
  return callback;
139
155
  };
140
156
 
157
+ // src/primitive-hooks/composer/useComposerCancel.tsx
158
+ import { useCallback as useCallback6 } from "react";
159
+ var useComposerCancel = () => {
160
+ const { useComposer } = useComposerContext();
161
+ const disabled = useComposer((c) => !c.isEditing);
162
+ const callback = useCallback6(() => {
163
+ const { cancel } = useComposer.getState();
164
+ cancel();
165
+ }, [useComposer]);
166
+ if (disabled) return null;
167
+ return callback;
168
+ };
169
+
170
+ // src/primitive-hooks/composer/useComposerIf.tsx
171
+ var useComposerIf = (props) => {
172
+ const { useComposer } = useComposerContext();
173
+ return useComposer((composer) => {
174
+ if (props.editing === true && !composer.isEditing) return false;
175
+ if (props.editing === false && composer.isEditing) return false;
176
+ return true;
177
+ });
178
+ };
179
+
180
+ // src/primitive-hooks/composer/useComposerSend.tsx
181
+ import { useCallback as useCallback7 } from "react";
182
+ var useComposerSend = () => {
183
+ const { useViewport } = useThreadContext();
184
+ const { useComposer } = useComposerContext();
185
+ const disabled = useComposer((c) => !c.isEditing || c.value.length === 0);
186
+ const callback = useCallback7(() => {
187
+ const composerState = useComposer.getState();
188
+ if (!composerState.isEditing) return;
189
+ composerState.send();
190
+ useViewport.getState().scrollToBottom();
191
+ }, [useComposer, useViewport]);
192
+ if (disabled) return null;
193
+ return callback;
194
+ };
195
+
196
+ // src/primitive-hooks/contentPart/useContentPartDisplay.tsx
197
+ var useContentPartDisplay = () => {
198
+ const { useContentPart } = useContentPartContext();
199
+ const display = useContentPart((c) => {
200
+ if (c.part.type !== "ui")
201
+ throw new Error(
202
+ "This component can only be used inside ui content parts."
203
+ );
204
+ return c.part.display;
205
+ });
206
+ return display;
207
+ };
208
+
209
+ // src/primitive-hooks/contentPart/useContentPartImage.tsx
210
+ var useContentPartImage = () => {
211
+ const { useContentPart } = useContentPartContext();
212
+ const image = useContentPart((c) => {
213
+ if (c.part.type !== "image")
214
+ throw new Error(
215
+ "ContentPartImage can only be used inside image content parts."
216
+ );
217
+ return c.part.image;
218
+ });
219
+ return image;
220
+ };
221
+
222
+ // src/primitive-hooks/contentPart/useContentPartInProgressIndicator.tsx
223
+ var useContentPartInProgressIndicator = () => {
224
+ const { useMessageUtils } = useMessageContext();
225
+ const { useContentPart } = useContentPartContext();
226
+ const indicator = useCombinedStore(
227
+ [useMessageUtils, useContentPart],
228
+ (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
229
+ );
230
+ return indicator;
231
+ };
232
+
233
+ // src/primitive-hooks/contentPart/useContentPartText.tsx
234
+ var useContentPartText = () => {
235
+ const { useContentPart } = useContentPartContext();
236
+ const text = useContentPart((c) => {
237
+ if (c.part.type !== "text")
238
+ throw new Error(
239
+ "ContentPartText can only be used inside text content parts."
240
+ );
241
+ return c.part.text;
242
+ });
243
+ return text;
244
+ };
245
+
246
+ // src/primitive-hooks/message/useMessageIf.tsx
247
+ var useMessageIf = (props) => {
248
+ const { useMessage, useMessageUtils } = useMessageContext();
249
+ return useCombinedStore(
250
+ [useMessage, useMessageUtils],
251
+ ({ message, branches, isLast }, { isCopied, isHovering }) => {
252
+ if (props.hasBranches === true && branches.length < 2) return false;
253
+ if (props.user && message.role !== "user") return false;
254
+ if (props.assistant && message.role !== "assistant") return false;
255
+ if (props.lastOrHover === true && !isHovering && !isLast) return false;
256
+ if (props.copied === true && !isCopied) return false;
257
+ if (props.copied === false && isCopied) return false;
258
+ return true;
259
+ }
260
+ );
261
+ };
262
+
263
+ // src/primitive-hooks/thread/useThreadIf.tsx
264
+ var useThreadIf = (props) => {
265
+ const { useThread } = useThreadContext();
266
+ return useThread((thread) => {
267
+ if (props.empty === true && thread.messages.length !== 0) return false;
268
+ if (props.empty === false && thread.messages.length === 0) return false;
269
+ if (props.running === true && !thread.isRunning) return false;
270
+ if (props.running === false && thread.isRunning) return false;
271
+ return true;
272
+ });
273
+ };
274
+
275
+ // src/primitive-hooks/thread/useThreadEmpty.tsx
276
+ var useThreadEmpty = () => {
277
+ return useThreadIf({ empty: true });
278
+ };
279
+
280
+ // src/primitive-hooks/thread/useThreadScrollToBottom.tsx
281
+ import { useCallback as useCallback8 } from "react";
282
+ var useThreadScrollToBottom = () => {
283
+ const { useViewport } = useThreadContext();
284
+ const isAtBottom = useViewport((s) => s.isAtBottom);
285
+ const handleScrollToBottom = useCallback8(() => {
286
+ const { scrollToBottom } = useViewport.getState();
287
+ scrollToBottom();
288
+ }, [useViewport]);
289
+ if (isAtBottom) return null;
290
+ return handleScrollToBottom;
291
+ };
292
+
293
+ // src/primitive-hooks/thread/useThreadSuggestion.tsx
294
+ import { useCallback as useCallback9 } from "react";
295
+ var useThreadSuggestion = ({
296
+ prompt,
297
+ autoSend
298
+ }) => {
299
+ const { useThread, useComposer } = useThreadContext();
300
+ const disabled = useThread((t) => t.isRunning);
301
+ const callback = useCallback9(() => {
302
+ const thread = useThread.getState();
303
+ const composer = useComposer.getState();
304
+ composer.setValue(prompt);
305
+ if (autoSend && !thread.isRunning) {
306
+ composer.send();
307
+ }
308
+ }, [useThread, useComposer, prompt, autoSend]);
309
+ if (disabled) return null;
310
+ return callback;
311
+ };
312
+
141
313
  // src/primitives/thread/index.ts
142
314
  var thread_exports = {};
143
315
  __export(thread_exports, {
@@ -161,142 +333,161 @@ var ThreadRoot = forwardRef(
161
333
  );
162
334
  ThreadRoot.displayName = "ThreadRoot";
163
335
 
164
- // src/primitives/thread/ThreadIf.tsx
165
- var useThreadIf = (props) => {
166
- const { useThread } = useThreadContext();
167
- return useThread((thread) => {
168
- if (props.empty === true && thread.messages.length !== 0) return false;
169
- if (props.empty === false && thread.messages.length === 0) return false;
170
- if (props.running === true && !thread.isRunning) return false;
171
- if (props.running === false && thread.isRunning) return false;
172
- return true;
173
- });
336
+ // src/primitives/thread/ThreadEmpty.tsx
337
+ var ThreadEmpty = ({ children }) => {
338
+ const empty = useThreadEmpty();
339
+ return empty ? children : null;
174
340
  };
341
+
342
+ // src/primitives/thread/ThreadIf.tsx
175
343
  var ThreadIf = ({ children, ...query }) => {
176
344
  const result = useThreadIf(query);
177
345
  return result ? children : null;
178
346
  };
179
347
 
180
- // src/primitives/thread/ThreadEmpty.tsx
181
- import { jsx as jsx2 } from "react/jsx-runtime";
182
- var ThreadEmpty = ({ children }) => {
183
- return /* @__PURE__ */ jsx2(ThreadIf, { empty: true, children });
184
- };
185
-
186
348
  // src/primitives/thread/ThreadViewport.tsx
187
- import { composeEventHandlers } from "@radix-ui/primitive";
188
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
349
+ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
189
350
  import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
190
- import {
191
- forwardRef as forwardRef2,
192
- useRef
193
- } from "react";
351
+ import { forwardRef as forwardRef2 } from "react";
352
+
353
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
354
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
355
+ import { useRef as useRef2 } from "react";
194
356
 
195
357
  // src/utils/hooks/useOnResizeContent.tsx
196
358
  import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
197
- import { useEffect } from "react";
198
- var useOnResizeContent = (ref, callback) => {
359
+ import { useCallback as useCallback11 } from "react";
360
+
361
+ // src/utils/hooks/useManagedRef.ts
362
+ import { useCallback as useCallback10, useRef } from "react";
363
+ var useManagedRef = (callback) => {
364
+ const cleanupRef = useRef();
365
+ const ref = useCallback10(
366
+ (el) => {
367
+ if (cleanupRef.current) {
368
+ cleanupRef.current();
369
+ }
370
+ if (el) {
371
+ cleanupRef.current = callback(el);
372
+ }
373
+ },
374
+ [callback]
375
+ );
376
+ return ref;
377
+ };
378
+
379
+ // src/utils/hooks/useOnResizeContent.tsx
380
+ var useOnResizeContent = (callback) => {
199
381
  const callbackRef = useCallbackRef(callback);
200
- const el = ref.current;
201
- useEffect(() => {
202
- if (!el) return;
203
- const resizeObserver = new ResizeObserver(() => {
204
- callbackRef();
205
- });
206
- const mutationObserver = new MutationObserver((mutations) => {
207
- for (const mutation of mutations) {
208
- for (const node of mutation.addedNodes) {
209
- if (node instanceof Element) {
210
- resizeObserver.observe(node);
382
+ const refCallback = useCallback11(
383
+ (el) => {
384
+ const resizeObserver = new ResizeObserver(() => {
385
+ callbackRef();
386
+ });
387
+ const mutationObserver = new MutationObserver((mutations) => {
388
+ for (const mutation of mutations) {
389
+ for (const node of mutation.addedNodes) {
390
+ if (node instanceof Element) {
391
+ resizeObserver.observe(node);
392
+ }
211
393
  }
212
- }
213
- for (const node of mutation.removedNodes) {
214
- if (node instanceof Element) {
215
- resizeObserver.unobserve(node);
394
+ for (const node of mutation.removedNodes) {
395
+ if (node instanceof Element) {
396
+ resizeObserver.unobserve(node);
397
+ }
216
398
  }
217
399
  }
400
+ callbackRef();
401
+ });
402
+ resizeObserver.observe(el);
403
+ mutationObserver.observe(el, { childList: true });
404
+ for (const child of el.children) {
405
+ resizeObserver.observe(child);
218
406
  }
219
- callbackRef();
220
- });
221
- resizeObserver.observe(el);
222
- mutationObserver.observe(el, { childList: true });
223
- for (const child of el.children) {
224
- resizeObserver.observe(child);
225
- }
226
- return () => {
227
- resizeObserver.disconnect();
228
- mutationObserver.disconnect();
229
- };
230
- }, [el, callbackRef]);
407
+ return () => {
408
+ resizeObserver.disconnect();
409
+ mutationObserver.disconnect();
410
+ };
411
+ },
412
+ [callbackRef]
413
+ );
414
+ return useManagedRef(refCallback);
231
415
  };
232
416
 
233
417
  // src/utils/hooks/useOnScrollToBottom.tsx
234
418
  import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
235
- import { useEffect as useEffect2 } from "react";
419
+ import { useEffect } from "react";
236
420
  var useOnScrollToBottom = (callback) => {
237
421
  const callbackRef = useCallbackRef2(callback);
238
422
  const { useViewport } = useThreadContext();
239
- useEffect2(() => {
423
+ useEffect(() => {
240
424
  return useViewport.getState().onScrollToBottom(() => {
241
425
  callbackRef();
242
426
  });
243
427
  }, [useViewport, callbackRef]);
244
428
  };
245
429
 
246
- // src/primitives/thread/ThreadViewport.tsx
247
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
248
- var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
249
- const messagesEndRef = useRef(null);
250
- const divRef = useRef(null);
251
- const ref = useComposedRefs(forwardedRef, divRef);
430
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
431
+ var useThreadViewportAutoScroll = ({
432
+ autoScroll = true
433
+ }) => {
434
+ const divRef = useRef2(null);
252
435
  const { useViewport } = useThreadContext();
253
- const firstRenderRef = useRef(true);
254
- const isScrollingToBottomRef = useRef(false);
255
- const lastScrollTop = useRef(0);
436
+ const firstRenderRef = useRef2(true);
437
+ const lastScrollTop = useRef2(0);
438
+ const isScrollingToBottomRef = useRef2(false);
256
439
  const scrollToBottom = () => {
257
- const div = messagesEndRef.current;
440
+ const div = divRef.current;
258
441
  if (!div || !autoScroll) return;
259
442
  const behavior = firstRenderRef.current ? "instant" : "auto";
260
443
  firstRenderRef.current = false;
261
444
  isScrollingToBottomRef.current = true;
262
- div.scrollIntoView({ behavior });
445
+ div.scrollTo({ top: div.scrollHeight, behavior });
263
446
  };
264
- useOnResizeContent(divRef, () => {
265
- if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom) {
266
- handleScroll();
267
- } else {
268
- scrollToBottom();
269
- }
270
- });
271
- useOnScrollToBottom(() => {
272
- scrollToBottom();
273
- });
274
447
  const handleScroll = () => {
275
448
  const div = divRef.current;
276
449
  if (!div) return;
277
450
  const isAtBottom = useViewport.getState().isAtBottom;
278
451
  const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
279
452
  if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
280
- } else if (newIsAtBottom !== isAtBottom) {
281
- isScrollingToBottomRef.current = false;
282
- useViewport.setState({
283
- isAtBottom: newIsAtBottom
284
- });
453
+ } else {
454
+ isScrollingToBottomRef.current = newIsAtBottom;
455
+ if (newIsAtBottom !== isAtBottom) {
456
+ useViewport.setState({
457
+ isAtBottom: newIsAtBottom
458
+ });
459
+ }
285
460
  }
286
461
  lastScrollTop.current = div.scrollTop;
287
462
  };
288
- return /* @__PURE__ */ jsxs(
289
- Primitive2.div,
290
- {
291
- ...rest,
292
- onScroll: composeEventHandlers(onScroll, handleScroll),
293
- ref,
294
- children: [
295
- children,
296
- /* @__PURE__ */ jsx3("div", { ref: messagesEndRef })
297
- ]
463
+ const resizeRef = useOnResizeContent(() => {
464
+ if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom && !firstRenderRef.current) {
465
+ handleScroll();
466
+ } else {
467
+ scrollToBottom();
298
468
  }
299
- );
469
+ });
470
+ const scrollRef = useManagedRef((el) => {
471
+ el.addEventListener("scroll", handleScroll);
472
+ return () => {
473
+ el.removeEventListener("scroll", handleScroll);
474
+ };
475
+ });
476
+ const autoScrollRef = useComposedRefs(resizeRef, scrollRef, divRef);
477
+ useOnScrollToBottom(() => {
478
+ scrollToBottom();
479
+ });
480
+ return autoScrollRef;
481
+ };
482
+
483
+ // src/primitives/thread/ThreadViewport.tsx
484
+ import { jsx as jsx2 } from "react/jsx-runtime";
485
+ var ThreadViewport = forwardRef2(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
486
+ const autoScrollRef = useThreadViewportAutoScroll({
487
+ autoScroll
488
+ });
489
+ const ref = useComposedRefs2(forwardedRef, autoScrollRef);
490
+ return /* @__PURE__ */ jsx2(Primitive2.div, { ...rest, ref, children });
300
491
  });
301
492
  ThreadViewport.displayName = "ThreadViewport";
302
493
 
@@ -304,10 +495,10 @@ ThreadViewport.displayName = "ThreadViewport";
304
495
  import { memo } from "react";
305
496
 
306
497
  // src/context/providers/MessageProvider.tsx
307
- import { useEffect as useEffect3, useState } from "react";
498
+ import { useEffect as useEffect2, useState } from "react";
308
499
  import { create as create3 } from "zustand";
309
500
 
310
- // src/context/stores/MessageComposer.ts
501
+ // src/context/stores/EditComposer.ts
311
502
  import { create } from "zustand";
312
503
 
313
504
  // src/context/stores/BaseComposer.ts
@@ -318,7 +509,7 @@ var makeBaseComposer = (set) => ({
318
509
  }
319
510
  });
320
511
 
321
- // src/context/stores/MessageComposer.ts
512
+ // src/context/stores/EditComposer.ts
322
513
  var makeEditComposerStore = ({
323
514
  onEdit,
324
515
  onSend
@@ -359,7 +550,7 @@ var makeMessageUtilsStore = () => create2((set) => ({
359
550
  }));
360
551
 
361
552
  // src/context/providers/MessageProvider.tsx
362
- import { jsx as jsx4 } from "react/jsx-runtime";
553
+ import { jsx as jsx3 } from "react/jsx-runtime";
363
554
  var getIsLast = (thread, message) => {
364
555
  return thread.messages[thread.messages.length - 1]?.id === message.id;
365
556
  };
@@ -384,7 +575,7 @@ var useMessageContext2 = (messageIndex) => {
384
575
  const [context] = useState(() => {
385
576
  const useMessage = create3(() => ({}));
386
577
  const useMessageUtils = makeMessageUtilsStore();
387
- const useComposer = makeEditComposerStore({
578
+ const useEditComposer = makeEditComposerStore({
388
579
  onEdit: () => {
389
580
  const message = useMessage.getState().message;
390
581
  if (message.role !== "user")
@@ -405,6 +596,7 @@ var useMessageContext2 = (messageIndex) => {
405
596
  );
406
597
  useThreadActions.getState().append({
407
598
  parentId,
599
+ role: "user",
408
600
  content: [{ type: "text", text }, ...nonTextParts]
409
601
  });
410
602
  }
@@ -415,9 +607,9 @@ var useMessageContext2 = (messageIndex) => {
415
607
  useMessage,
416
608
  messageIndex
417
609
  );
418
- return { useMessage, useMessageUtils, useComposer };
610
+ return { useMessage, useMessageUtils, useEditComposer };
419
611
  });
420
- useEffect3(() => {
612
+ useEffect2(() => {
421
613
  return useThread.subscribe((thread) => {
422
614
  syncMessage(
423
615
  thread,
@@ -434,46 +626,23 @@ var MessageProvider = ({
434
626
  children
435
627
  }) => {
436
628
  const context = useMessageContext2(messageIndex);
437
- return /* @__PURE__ */ jsx4(MessageContext.Provider, { value: context, children });
629
+ return /* @__PURE__ */ jsx3(MessageContext.Provider, { value: context, children });
438
630
  };
439
631
 
440
632
  // src/primitives/composer/ComposerIf.tsx
441
- var useComposerIf = (props) => {
442
- const { useComposer } = useComposerContext();
443
- return useComposer((composer) => {
444
- if (props.editing === true && !composer.isEditing) return false;
445
- if (props.editing === false && composer.isEditing) return false;
446
- return true;
447
- });
448
- };
449
633
  var ComposerIf = ({ children, ...query }) => {
450
634
  const result = useComposerIf(query);
451
635
  return result ? children : null;
452
636
  };
453
637
 
454
638
  // src/primitives/message/MessageIf.tsx
455
- var useMessageIf = (props) => {
456
- const { useMessage, useMessageUtils } = useMessageContext();
457
- return useCombinedStore(
458
- [useMessage, useMessageUtils],
459
- ({ message, branches, isLast }, { isCopied, isHovering }) => {
460
- if (props.hasBranches === true && branches.length < 2) return false;
461
- if (props.user && message.role !== "user") return false;
462
- if (props.assistant && message.role !== "assistant") return false;
463
- if (props.lastOrHover === true && !isHovering && !isLast) return false;
464
- if (props.copied === true && !isCopied) return false;
465
- if (props.copied === false && isCopied) return false;
466
- return true;
467
- }
468
- );
469
- };
470
639
  var MessageIf = ({ children, ...query }) => {
471
640
  const result = useMessageIf(query);
472
641
  return result ? children : null;
473
642
  };
474
643
 
475
644
  // src/primitives/thread/ThreadMessages.tsx
476
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
645
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
477
646
  var getComponents = (components) => {
478
647
  return {
479
648
  EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
@@ -486,12 +655,12 @@ var ThreadMessageImpl = ({
486
655
  components
487
656
  }) => {
488
657
  const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
489
- return /* @__PURE__ */ jsxs2(MessageProvider, { messageIndex, children: [
490
- /* @__PURE__ */ jsxs2(MessageIf, { user: true, children: [
491
- /* @__PURE__ */ jsx5(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx5(UserMessage, {}) }),
492
- /* @__PURE__ */ jsx5(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx5(EditComposer, {}) })
658
+ return /* @__PURE__ */ jsxs(MessageProvider, { messageIndex, children: [
659
+ /* @__PURE__ */ jsxs(MessageIf, { user: true, children: [
660
+ /* @__PURE__ */ jsx4(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx4(UserMessage, {}) }),
661
+ /* @__PURE__ */ jsx4(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx4(EditComposer, {}) })
493
662
  ] }),
494
- /* @__PURE__ */ jsx5(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx5(AssistantMessage, {}) })
663
+ /* @__PURE__ */ jsx4(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx4(AssistantMessage, {}) })
495
664
  ] });
496
665
  };
497
666
  var ThreadMessage = memo(
@@ -504,7 +673,7 @@ var ThreadMessages = ({ components }) => {
504
673
  if (messagesLength === 0) return null;
505
674
  return new Array(messagesLength).fill(null).map((_, idx) => {
506
675
  const messageIndex = idx;
507
- return /* @__PURE__ */ jsx5(
676
+ return /* @__PURE__ */ jsx4(
508
677
  ThreadMessage,
509
678
  {
510
679
  messageIndex,
@@ -515,56 +684,42 @@ var ThreadMessages = ({ components }) => {
515
684
  });
516
685
  };
517
686
 
518
- // src/primitives/thread/ThreadScrollToBottom.tsx
519
- import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
687
+ // src/utils/createActionButton.tsx
688
+ import { composeEventHandlers } from "@radix-ui/primitive";
520
689
  import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
521
690
  import { forwardRef as forwardRef3 } from "react";
522
- import { jsx as jsx6 } from "react/jsx-runtime";
523
- var ThreadScrollToBottom = forwardRef3(({ onClick, ...rest }, ref) => {
524
- const { useViewport } = useThreadContext();
525
- const isAtBottom = useViewport((s) => s.isAtBottom);
526
- const handleScrollToBottom = () => {
527
- useViewport.getState().scrollToBottom();
528
- };
529
- return /* @__PURE__ */ jsx6(
530
- Primitive3.button,
531
- {
532
- ...rest,
533
- disabled: isAtBottom,
534
- ref,
535
- onClick: composeEventHandlers2(onClick, handleScrollToBottom)
536
- }
537
- );
538
- });
539
- ThreadScrollToBottom.displayName = "ThreadScrollToBottom";
691
+ import { jsx as jsx5 } from "react/jsx-runtime";
692
+ var createActionButton = (displayName, useActionButton) => {
693
+ const ActionButton = forwardRef3((props, forwardedRef) => {
694
+ const callback = useActionButton(props);
695
+ return /* @__PURE__ */ jsx5(
696
+ Primitive3.button,
697
+ {
698
+ type: "button",
699
+ disabled: !callback,
700
+ ...props,
701
+ ref: forwardedRef,
702
+ onClick: composeEventHandlers(props.onClick, () => {
703
+ callback?.();
704
+ })
705
+ }
706
+ );
707
+ });
708
+ ActionButton.displayName = displayName;
709
+ return ActionButton;
710
+ };
711
+
712
+ // src/primitives/thread/ThreadScrollToBottom.tsx
713
+ var ThreadScrollToBottom = createActionButton(
714
+ "ThreadScrollToBottom",
715
+ useThreadScrollToBottom
716
+ );
540
717
 
541
718
  // src/primitives/thread/ThreadSuggestion.tsx
542
- import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
543
- import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
544
- import { forwardRef as forwardRef4 } from "react";
545
- import { jsx as jsx7 } from "react/jsx-runtime";
546
- var ThreadSuggestion = forwardRef4(({ onClick, prompt, method, autoSend: send, ...rest }, ref) => {
547
- const { useThread, useComposer } = useThreadContext();
548
- const isDisabled = useThread((t) => t.isRunning);
549
- const handleApplySuggestion = () => {
550
- const thread = useThread.getState();
551
- const composer = useComposer.getState();
552
- composer.setValue(prompt);
553
- if (send && !thread.isRunning) {
554
- composer.send();
555
- }
556
- };
557
- return /* @__PURE__ */ jsx7(
558
- Primitive4.button,
559
- {
560
- ...rest,
561
- disabled: isDisabled,
562
- ref,
563
- onClick: composeEventHandlers3(onClick, handleApplySuggestion)
564
- }
565
- );
566
- });
567
- ThreadSuggestion.displayName = "ThreadSuggestion";
719
+ var ThreadSuggestion = createActionButton(
720
+ "ThreadSuggestion",
721
+ useThreadSuggestion
722
+ );
568
723
 
569
724
  // src/primitives/composer/index.ts
570
725
  var composer_exports = {};
@@ -577,33 +732,26 @@ __export(composer_exports, {
577
732
  });
578
733
 
579
734
  // src/primitives/composer/ComposerRoot.tsx
580
- import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
581
- import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
582
- import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
735
+ import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
736
+ import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
583
737
  import {
584
- forwardRef as forwardRef5,
585
- useRef as useRef2
738
+ forwardRef as forwardRef4
586
739
  } from "react";
587
- import { jsx as jsx8 } from "react/jsx-runtime";
588
- var ComposerRoot = forwardRef5(
740
+ import { jsx as jsx6 } from "react/jsx-runtime";
741
+ var ComposerRoot = forwardRef4(
589
742
  ({ onSubmit, ...rest }, forwardedRef) => {
590
- const { useViewport } = useThreadContext();
591
- const { useComposer } = useComposerContext();
592
- const formRef = useRef2(null);
593
- const ref = useComposedRefs2(forwardedRef, formRef);
743
+ const send = useComposerSend();
594
744
  const handleSubmit = (e) => {
595
- const composerState = useComposer.getState();
596
- if (!composerState.isEditing) return;
745
+ if (!send) return;
597
746
  e.preventDefault();
598
- composerState.send();
599
- useViewport.getState().scrollToBottom();
747
+ send();
600
748
  };
601
- return /* @__PURE__ */ jsx8(
602
- Primitive5.form,
749
+ return /* @__PURE__ */ jsx6(
750
+ Primitive4.form,
603
751
  {
604
752
  ...rest,
605
- ref,
606
- onSubmit: composeEventHandlers4(onSubmit, handleSubmit)
753
+ ref: forwardedRef,
754
+ onSubmit: composeEventHandlers2(onSubmit, handleSubmit)
607
755
  }
608
756
  );
609
757
  }
@@ -611,18 +759,19 @@ var ComposerRoot = forwardRef5(
611
759
  ComposerRoot.displayName = "ComposerRoot";
612
760
 
613
761
  // src/primitives/composer/ComposerInput.tsx
614
- import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
762
+ import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
615
763
  import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
616
764
  import { Slot } from "@radix-ui/react-slot";
617
765
  import {
618
- forwardRef as forwardRef6,
619
- useCallback as useCallback6,
620
- useEffect as useEffect4,
766
+ forwardRef as forwardRef5,
767
+ useCallback as useCallback12,
768
+ useEffect as useEffect3,
621
769
  useRef as useRef3
622
770
  } from "react";
623
771
  import TextareaAutosize from "react-textarea-autosize";
624
- import { jsx as jsx9 } from "react/jsx-runtime";
625
- var ComposerInput = forwardRef6(
772
+ import { useEscapeKeydown } from "@radix-ui/react-use-escape-keydown";
773
+ import { jsx as jsx7 } from "react/jsx-runtime";
774
+ var ComposerInput = forwardRef5(
626
775
  ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
627
776
  const { useThread } = useThreadContext();
628
777
  const { useComposer, type } = useComposerContext();
@@ -633,14 +782,15 @@ var ComposerInput = forwardRef6(
633
782
  const Component = asChild ? Slot : TextareaAutosize;
634
783
  const textareaRef = useRef3(null);
635
784
  const ref = useComposedRefs3(forwardedRef, textareaRef);
785
+ useEscapeKeydown((e) => {
786
+ const composer = useComposer.getState();
787
+ if (composer.cancel()) {
788
+ e.preventDefault();
789
+ }
790
+ });
636
791
  const handleKeyPress = (e) => {
637
792
  if (disabled) return;
638
- if (e.key === "Escape") {
639
- const composer = useComposer.getState();
640
- if (composer.cancel()) {
641
- e.preventDefault();
642
- }
643
- } else if (e.key === "Enter" && e.shiftKey === false) {
793
+ if (e.key === "Enter" && e.shiftKey === false) {
644
794
  const isRunning = useThread.getState().isRunning;
645
795
  if (!isRunning) {
646
796
  e.preventDefault();
@@ -649,23 +799,22 @@ var ComposerInput = forwardRef6(
649
799
  }
650
800
  };
651
801
  const autoFocusEnabled = autoFocus && !disabled;
652
- const focus = useCallback6(() => {
802
+ const focus = useCallback12(() => {
653
803
  const textarea = textareaRef.current;
654
804
  if (!textarea || !autoFocusEnabled) return;
655
- console.log("focus");
656
805
  textarea.focus();
657
806
  textarea.setSelectionRange(
658
807
  textareaRef.current.value.length,
659
808
  textareaRef.current.value.length
660
809
  );
661
810
  }, [autoFocusEnabled]);
662
- useEffect4(() => focus(), [focus]);
811
+ useEffect3(() => focus(), [focus]);
663
812
  useOnScrollToBottom(() => {
664
813
  if (type === "new") {
665
814
  focus();
666
815
  }
667
816
  });
668
- return /* @__PURE__ */ jsx9(
817
+ return /* @__PURE__ */ jsx7(
669
818
  Component,
670
819
  {
671
820
  value,
@@ -673,12 +822,12 @@ var ComposerInput = forwardRef6(
673
822
  ref,
674
823
  autoFocus,
675
824
  disabled,
676
- onChange: composeEventHandlers5(onChange, (e) => {
825
+ onChange: composeEventHandlers3(onChange, (e) => {
677
826
  const composerState = useComposer.getState();
678
827
  if (!composerState.isEditing) return;
679
828
  return composerState.setValue(e.target.value);
680
829
  }),
681
- onKeyDown: composeEventHandlers5(onKeyDown, handleKeyPress)
830
+ onKeyDown: composeEventHandlers3(onKeyDown, handleKeyPress)
682
831
  }
683
832
  );
684
833
  }
@@ -686,15 +835,15 @@ var ComposerInput = forwardRef6(
686
835
  ComposerInput.displayName = "ComposerInput";
687
836
 
688
837
  // src/primitives/composer/ComposerSend.tsx
689
- import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
690
- import { forwardRef as forwardRef7 } from "react";
691
- import { jsx as jsx10 } from "react/jsx-runtime";
692
- var ComposerSend = forwardRef7(
838
+ import { forwardRef as forwardRef6 } from "react";
839
+ import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
840
+ import { jsx as jsx8 } from "react/jsx-runtime";
841
+ var ComposerSend = forwardRef6(
693
842
  ({ disabled, ...rest }, ref) => {
694
843
  const { useComposer } = useComposerContext();
695
844
  const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
696
- return /* @__PURE__ */ jsx10(
697
- Primitive6.button,
845
+ return /* @__PURE__ */ jsx8(
846
+ Primitive5.button,
698
847
  {
699
848
  type: "submit",
700
849
  ...rest,
@@ -707,26 +856,10 @@ var ComposerSend = forwardRef7(
707
856
  ComposerSend.displayName = "ComposerSend";
708
857
 
709
858
  // src/primitives/composer/ComposerCancel.tsx
710
- import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
711
- import { Primitive as Primitive7 } from "@radix-ui/react-primitive";
712
- import { forwardRef as forwardRef8 } from "react";
713
- import { jsx as jsx11 } from "react/jsx-runtime";
714
- var ComposerCancel = forwardRef8(({ onClick, ...rest }, ref) => {
715
- const { useComposer } = useComposerContext();
716
- const handleCancel = () => {
717
- useComposer.getState().cancel();
718
- };
719
- return /* @__PURE__ */ jsx11(
720
- Primitive7.button,
721
- {
722
- type: "button",
723
- ...rest,
724
- ref,
725
- onClick: composeEventHandlers6(onClick, handleCancel)
726
- }
727
- );
728
- });
729
- ComposerCancel.displayName = "ComposerCancel";
859
+ var ComposerCancel = createActionButton(
860
+ "ComposerCancel",
861
+ useComposerCancel
862
+ );
730
863
 
731
864
  // src/primitives/message/index.ts
732
865
  var message_exports = {};
@@ -738,11 +871,11 @@ __export(message_exports, {
738
871
  });
739
872
 
740
873
  // src/primitives/message/MessageRoot.tsx
741
- import { composeEventHandlers as composeEventHandlers7 } from "@radix-ui/primitive";
742
- import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
743
- import { forwardRef as forwardRef9 } from "react";
744
- import { jsx as jsx12 } from "react/jsx-runtime";
745
- var MessageRoot = forwardRef9(
874
+ import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
875
+ import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
876
+ import { forwardRef as forwardRef7 } from "react";
877
+ import { jsx as jsx9 } from "react/jsx-runtime";
878
+ var MessageRoot = forwardRef7(
746
879
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
747
880
  const { useMessageUtils } = useMessageContext();
748
881
  const setIsHovering = useMessageUtils((s) => s.setIsHovering);
@@ -752,13 +885,13 @@ var MessageRoot = forwardRef9(
752
885
  const handleMouseLeave = () => {
753
886
  setIsHovering(false);
754
887
  };
755
- return /* @__PURE__ */ jsx12(
756
- Primitive8.div,
888
+ return /* @__PURE__ */ jsx9(
889
+ Primitive6.div,
757
890
  {
758
891
  ...rest,
759
892
  ref,
760
- onMouseEnter: composeEventHandlers7(onMouseEnter, handleMouseEnter),
761
- onMouseLeave: composeEventHandlers7(onMouseLeave, handleMouseLeave)
893
+ onMouseEnter: composeEventHandlers4(onMouseEnter, handleMouseEnter),
894
+ onMouseLeave: composeEventHandlers4(onMouseLeave, handleMouseLeave)
762
895
  }
763
896
  );
764
897
  }
@@ -769,9 +902,9 @@ MessageRoot.displayName = "MessageRoot";
769
902
  import { memo as memo2 } from "react";
770
903
 
771
904
  // src/context/providers/ContentPartProvider.tsx
772
- import { useEffect as useEffect5, useState as useState2 } from "react";
905
+ import { useEffect as useEffect4, useState as useState2 } from "react";
773
906
  import { create as create4 } from "zustand";
774
- import { jsx as jsx13 } from "react/jsx-runtime";
907
+ import { jsx as jsx10 } from "react/jsx-runtime";
775
908
  var syncContentPart = ({ message }, useContentPart, partIndex) => {
776
909
  const part = message.content[partIndex];
777
910
  if (!part) return;
@@ -795,7 +928,7 @@ var useContentPartContext2 = (partIndex) => {
795
928
  syncContentPart(useMessage.getState(), useContentPart, partIndex);
796
929
  return { useContentPart };
797
930
  });
798
- useEffect5(() => {
931
+ useEffect4(() => {
799
932
  syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
800
933
  return useMessage.subscribe((message) => {
801
934
  syncContentPart(message, context.useContentPart, partIndex);
@@ -808,65 +941,46 @@ var ContentPartProvider = ({
808
941
  children
809
942
  }) => {
810
943
  const context = useContentPartContext2(partIndex);
811
- return /* @__PURE__ */ jsx13(ContentPartContext.Provider, { value: context, children });
944
+ return /* @__PURE__ */ jsx10(ContentPartContext.Provider, { value: context, children });
812
945
  };
813
946
 
814
947
  // src/primitives/contentPart/ContentPartDisplay.tsx
815
948
  var ContentPartDisplay = () => {
816
- const { useContentPart } = useContentPartContext();
817
- const display = useContentPart((c) => {
818
- if (c.part.type !== "ui")
819
- throw new Error(
820
- "ContentPartDisplay can only be used inside ui content parts."
821
- );
822
- return c.part.display;
823
- });
949
+ const display = useContentPartDisplay();
824
950
  return display ?? null;
825
951
  };
826
952
 
827
953
  // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
828
954
  var ContentPartInProgressIndicator = () => {
829
- const { useMessageUtils } = useMessageContext();
830
- const { useContentPart } = useContentPartContext();
831
- const indicator = useCombinedStore(
832
- [useMessageUtils, useContentPart],
833
- (m, c) => c.status === "in_progress" ? m.inProgressIndicator : null
834
- );
955
+ const indicator = useContentPartInProgressIndicator();
835
956
  return indicator;
836
957
  };
837
958
 
838
959
  // src/primitives/contentPart/ContentPartText.tsx
839
- import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
840
- import { forwardRef as forwardRef10 } from "react";
841
- import { jsx as jsx14 } from "react/jsx-runtime";
842
- var ContentPartText = forwardRef10((props, forwardedRef) => {
843
- const { useContentPart } = useContentPartContext();
844
- const text = useContentPart((c) => {
845
- if (c.part.type !== "text")
846
- throw new Error(
847
- "ContentPartText can only be used inside text content parts."
848
- );
849
- return c.part.text;
850
- });
851
- return /* @__PURE__ */ jsx14(Primitive9.span, { ...props, ref: forwardedRef, children: text });
960
+ import { Primitive as Primitive7 } from "@radix-ui/react-primitive";
961
+ import { forwardRef as forwardRef8 } from "react";
962
+ import { jsx as jsx11 } from "react/jsx-runtime";
963
+ var ContentPartText = forwardRef8((props, forwardedRef) => {
964
+ const text = useContentPartText();
965
+ return /* @__PURE__ */ jsx11(Primitive7.span, { ...props, ref: forwardedRef, children: text });
852
966
  });
853
967
  ContentPartText.displayName = "ContentPartText";
854
968
 
855
969
  // src/primitives/message/MessageContent.tsx
856
- import { Fragment, jsx as jsx15, jsxs as jsxs3 } from "react/jsx-runtime";
970
+ import { Fragment, jsx as jsx12, jsxs as jsxs2 } from "react/jsx-runtime";
857
971
  var defaultComponents = {
858
- Text: () => /* @__PURE__ */ jsxs3(Fragment, { children: [
859
- /* @__PURE__ */ jsx15(ContentPartText, {}),
860
- /* @__PURE__ */ jsx15(ContentPartInProgressIndicator, {})
972
+ Text: () => /* @__PURE__ */ jsxs2(Fragment, { children: [
973
+ /* @__PURE__ */ jsx12(ContentPartText, {}),
974
+ /* @__PURE__ */ jsx12(ContentPartInProgressIndicator, {})
861
975
  ] }),
862
976
  Image: () => null,
863
- UI: () => /* @__PURE__ */ jsx15(ContentPartDisplay, {}),
977
+ UI: () => /* @__PURE__ */ jsx12(ContentPartDisplay, {}),
864
978
  tools: {
865
979
  Fallback: (props) => {
866
980
  const { useToolUIs } = useAssistantContext();
867
981
  const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
868
982
  if (!Render) return null;
869
- return /* @__PURE__ */ jsx15(Render, { ...props });
983
+ return /* @__PURE__ */ jsx12(Render, { ...props });
870
984
  }
871
985
  }
872
986
  };
@@ -885,15 +999,15 @@ var MessageContentPartComponent = ({
885
999
  const type = part.type;
886
1000
  switch (type) {
887
1001
  case "text":
888
- return /* @__PURE__ */ jsx15(Text, { part, status });
1002
+ return /* @__PURE__ */ jsx12(Text, { part, status });
889
1003
  case "image":
890
- return /* @__PURE__ */ jsx15(Image, { part, status });
1004
+ return /* @__PURE__ */ jsx12(Image, { part, status });
891
1005
  case "ui":
892
- return /* @__PURE__ */ jsx15(UI, { part, status });
1006
+ return /* @__PURE__ */ jsx12(UI, { part, status });
893
1007
  case "tool-call": {
894
1008
  const Tool = by_name[part.toolName] || Fallback;
895
1009
  const addResult = (result) => addToolResult(part.toolCallId, result);
896
- return /* @__PURE__ */ jsx15(Tool, { part, status, addResult });
1010
+ return /* @__PURE__ */ jsx12(Tool, { part, status, addResult });
897
1011
  }
898
1012
  default:
899
1013
  throw new Error(`Unknown content part type: ${type}`);
@@ -903,7 +1017,7 @@ var MessageContentPartImpl = ({
903
1017
  partIndex,
904
1018
  components
905
1019
  }) => {
906
- return /* @__PURE__ */ jsx15(ContentPartProvider, { partIndex, children: /* @__PURE__ */ jsx15(MessageContentPartComponent, { components }) });
1020
+ return /* @__PURE__ */ jsx12(ContentPartProvider, { partIndex, children: /* @__PURE__ */ jsx12(MessageContentPartComponent, { components }) });
907
1021
  };
908
1022
  var MessageContentPart = memo2(
909
1023
  MessageContentPartImpl,
@@ -914,7 +1028,7 @@ var MessageContent = ({ components }) => {
914
1028
  const contentLength = useMessage((s) => s.message.content.length);
915
1029
  return new Array(contentLength).fill(null).map((_, idx) => {
916
1030
  const partIndex = idx;
917
- return /* @__PURE__ */ jsx15(
1031
+ return /* @__PURE__ */ jsx12(
918
1032
  MessageContentPart,
919
1033
  {
920
1034
  partIndex,
@@ -926,16 +1040,16 @@ var MessageContent = ({ components }) => {
926
1040
  };
927
1041
 
928
1042
  // src/primitives/message/MessageInProgress.tsx
929
- import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
1043
+ import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
930
1044
  import {
931
- forwardRef as forwardRef11,
1045
+ forwardRef as forwardRef9,
932
1046
  useMemo as useMemo2
933
1047
  } from "react";
934
- import { jsx as jsx16 } from "react/jsx-runtime";
935
- var MessageInProgress = forwardRef11((props, ref) => {
1048
+ import { jsx as jsx13 } from "react/jsx-runtime";
1049
+ var MessageInProgress = forwardRef9((props, ref) => {
936
1050
  const { useMessageUtils } = useMessageContext();
937
1051
  useMemo2(() => {
938
- useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ jsx16(Primitive10.span, { ...props, ref }));
1052
+ useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ jsx13(Primitive8.span, { ...props, ref }));
939
1053
  }, [useMessageUtils, props, ref]);
940
1054
  return null;
941
1055
  });
@@ -951,57 +1065,38 @@ __export(branchPicker_exports, {
951
1065
  Root: () => BranchPickerRoot
952
1066
  });
953
1067
 
954
- // src/utils/createActionButton.tsx
955
- import { composeEventHandlers as composeEventHandlers8 } from "@radix-ui/primitive";
956
- import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
957
- import { forwardRef as forwardRef12 } from "react";
958
- import { jsx as jsx17 } from "react/jsx-runtime";
959
- var createActionButton = (useActionButton) => {
960
- const ActionButton = forwardRef12((props, forwardedRef) => {
961
- const onClick = useActionButton(props);
962
- return /* @__PURE__ */ jsx17(
963
- Primitive11.button,
964
- {
965
- type: "button",
966
- disabled: !onClick,
967
- ...props,
968
- ref: forwardedRef,
969
- onClick: composeEventHandlers8(props.onClick, onClick ?? void 0)
970
- }
971
- );
972
- });
973
- ActionButton.displayName = "ActionButton";
974
- return ActionButton;
975
- };
976
-
977
1068
  // src/primitives/branchPicker/BranchPickerNext.tsx
978
- var BranchPickerNext = createActionButton(useGoToNextBranch);
1069
+ var BranchPickerNext = createActionButton(
1070
+ "BranchPickerNext",
1071
+ useBranchPickerNext
1072
+ );
979
1073
 
980
1074
  // src/primitives/branchPicker/BranchPickerPrevious.tsx
981
- var BranchPickerPrevious = createActionButton(useGoToPreviousBranch);
1075
+ var BranchPickerPrevious = createActionButton(
1076
+ "BranchPickerPrevious",
1077
+ useBranchPickerPrevious
1078
+ );
982
1079
 
983
1080
  // src/primitives/branchPicker/BranchPickerCount.tsx
984
- import { Fragment as Fragment2, jsx as jsx18 } from "react/jsx-runtime";
1081
+ import { Fragment as Fragment2, jsx as jsx14 } from "react/jsx-runtime";
985
1082
  var BranchPickerCount = () => {
986
- const { useMessage } = useMessageContext();
987
- const branchCount = useMessage((s) => s.branches.length);
988
- return /* @__PURE__ */ jsx18(Fragment2, { children: branchCount });
1083
+ const branchCount = useBranchPickerCount();
1084
+ return /* @__PURE__ */ jsx14(Fragment2, { children: branchCount });
989
1085
  };
990
1086
 
991
1087
  // src/primitives/branchPicker/BranchPickerNumber.tsx
992
- import { Fragment as Fragment3, jsx as jsx19 } from "react/jsx-runtime";
1088
+ import { Fragment as Fragment3, jsx as jsx15 } from "react/jsx-runtime";
993
1089
  var BranchPickerNumber = () => {
994
- const { useMessage } = useMessageContext();
995
- const branchIdx = useMessage((s) => s.branches.indexOf(s.message.id));
996
- return /* @__PURE__ */ jsx19(Fragment3, { children: branchIdx + 1 });
1090
+ const branchNumber = useBranchPickerNumber();
1091
+ return /* @__PURE__ */ jsx15(Fragment3, { children: branchNumber });
997
1092
  };
998
1093
 
999
1094
  // src/primitives/branchPicker/BranchPickerRoot.tsx
1000
- import { Primitive as Primitive12 } from "@radix-ui/react-primitive";
1001
- import { forwardRef as forwardRef13 } from "react";
1002
- import { jsx as jsx20 } from "react/jsx-runtime";
1003
- var BranchPickerRoot = forwardRef13(({ hideWhenSingleBranch, ...rest }, ref) => {
1004
- return /* @__PURE__ */ jsx20(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx20(Primitive12.div, { ...rest, ref }) });
1095
+ import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
1096
+ import { forwardRef as forwardRef10 } from "react";
1097
+ import { jsx as jsx16 } from "react/jsx-runtime";
1098
+ var BranchPickerRoot = forwardRef10(({ hideWhenSingleBranch, ...rest }, ref) => {
1099
+ return /* @__PURE__ */ jsx16(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx16(Primitive9.div, { ...rest, ref }) });
1005
1100
  });
1006
1101
  BranchPickerRoot.displayName = "BranchPickerRoot";
1007
1102
 
@@ -1015,13 +1110,17 @@ __export(actionBar_exports, {
1015
1110
  });
1016
1111
 
1017
1112
  // src/primitives/actionBar/ActionBarRoot.tsx
1018
- import { Primitive as Primitive13 } from "@radix-ui/react-primitive";
1019
- import { forwardRef as forwardRef14 } from "react";
1020
- import { jsx as jsx21 } from "react/jsx-runtime";
1021
- var ActionBarRoot = forwardRef14(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1113
+ import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
1114
+ import { forwardRef as forwardRef11 } from "react";
1115
+ import { jsx as jsx17 } from "react/jsx-runtime";
1116
+ var useActionBarFloatStatus = ({
1117
+ hideWhenRunning,
1118
+ autohide,
1119
+ autohideFloat
1120
+ }) => {
1022
1121
  const { useThread } = useThreadContext();
1023
1122
  const { useMessage, useMessageUtils } = useMessageContext();
1024
- const hideAndfloatStatus = useCombinedStore(
1123
+ return useCombinedStore(
1025
1124
  [useThread, useMessage, useMessageUtils],
1026
1125
  (t, m, mu) => {
1027
1126
  if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
@@ -1033,9 +1132,16 @@ var ActionBarRoot = forwardRef14(({ hideWhenRunning, autohide, autohideFloat, ..
1033
1132
  return "normal" /* Normal */;
1034
1133
  }
1035
1134
  );
1135
+ };
1136
+ var ActionBarRoot = forwardRef11(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1137
+ const hideAndfloatStatus = useActionBarFloatStatus({
1138
+ hideWhenRunning,
1139
+ autohide,
1140
+ autohideFloat
1141
+ });
1036
1142
  if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
1037
- return /* @__PURE__ */ jsx21(
1038
- Primitive13.div,
1143
+ return /* @__PURE__ */ jsx17(
1144
+ Primitive10.div,
1039
1145
  {
1040
1146
  ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
1041
1147
  ...rest,
@@ -1046,13 +1152,22 @@ var ActionBarRoot = forwardRef14(({ hideWhenRunning, autohide, autohideFloat, ..
1046
1152
  ActionBarRoot.displayName = "ActionBarRoot";
1047
1153
 
1048
1154
  // src/primitives/actionBar/ActionBarCopy.tsx
1049
- var ActionBarCopy = createActionButton(useCopyMessage);
1155
+ var ActionBarCopy = createActionButton(
1156
+ "ActionBarCopy",
1157
+ useActionBarCopy
1158
+ );
1050
1159
 
1051
1160
  // src/primitives/actionBar/ActionBarReload.tsx
1052
- var ActionBarReload = createActionButton(useReloadMessage);
1161
+ var ActionBarReload = createActionButton(
1162
+ "ActionBarReload",
1163
+ useActionBarReload
1164
+ );
1053
1165
 
1054
1166
  // src/primitives/actionBar/ActionBarEdit.tsx
1055
- var ActionBarEdit = createActionButton(useBeginMessageEdit);
1167
+ var ActionBarEdit = createActionButton(
1168
+ "ActionBarEdit",
1169
+ useActionBarEdit
1170
+ );
1056
1171
 
1057
1172
  // src/primitives/contentPart/index.ts
1058
1173
  var contentPart_exports = {};
@@ -1064,19 +1179,12 @@ __export(contentPart_exports, {
1064
1179
  });
1065
1180
 
1066
1181
  // src/primitives/contentPart/ContentPartImage.tsx
1067
- import { Primitive as Primitive14 } from "@radix-ui/react-primitive";
1068
- import { forwardRef as forwardRef15 } from "react";
1069
- import { jsx as jsx22 } from "react/jsx-runtime";
1070
- var ContentPartImage = forwardRef15((props, forwardedRef) => {
1071
- const { useContentPart } = useContentPartContext();
1072
- const image = useContentPart((c) => {
1073
- if (c.part.type !== "image")
1074
- throw new Error(
1075
- "ContentPartImage can only be used inside image content parts."
1076
- );
1077
- return c.part.image;
1078
- });
1079
- return /* @__PURE__ */ jsx22(Primitive14.img, { src: image, ...props, ref: forwardedRef });
1182
+ import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
1183
+ import { forwardRef as forwardRef12 } from "react";
1184
+ import { jsx as jsx18 } from "react/jsx-runtime";
1185
+ var ContentPartImage = forwardRef12((props, forwardedRef) => {
1186
+ const image = useContentPartImage();
1187
+ return /* @__PURE__ */ jsx18(Primitive11.img, { src: image, ...props, ref: forwardedRef });
1080
1188
  });
1081
1189
  ContentPartImage.displayName = "ContentPartImage";
1082
1190
 
@@ -1378,7 +1486,7 @@ var useLocalRuntime = (adapter) => {
1378
1486
  import { memo as memo3 } from "react";
1379
1487
 
1380
1488
  // src/context/providers/AssistantProvider.tsx
1381
- import { useEffect as useEffect7, useInsertionEffect as useInsertionEffect3, useRef as useRef5, useState as useState5 } from "react";
1489
+ import { useEffect as useEffect6, useInsertionEffect as useInsertionEffect3, useRef as useRef5, useState as useState5 } from "react";
1382
1490
 
1383
1491
  // src/context/stores/AssistantModelConfig.ts
1384
1492
  import { create as create5 } from "zustand";
@@ -1443,7 +1551,7 @@ var makeAssistantToolUIsStore = () => create6((set) => {
1443
1551
  });
1444
1552
 
1445
1553
  // src/context/providers/ThreadProvider.tsx
1446
- import { useEffect as useEffect6, useInsertionEffect as useInsertionEffect2, useRef as useRef4, useState as useState4 } from "react";
1554
+ import { useEffect as useEffect5, useInsertionEffect as useInsertionEffect2, useRef as useRef4, useState as useState4 } from "react";
1447
1555
 
1448
1556
  // src/context/stores/Composer.ts
1449
1557
  import { create as create7 } from "zustand";
@@ -1456,6 +1564,7 @@ var makeComposerStore = (useThread, useThreadActions) => create7()((set, get, st
1456
1564
  setValue("");
1457
1565
  useThreadActions.getState().append({
1458
1566
  parentId: useThread.getState().messages.at(-1)?.id ?? null,
1567
+ role: "user",
1459
1568
  content: [{ type: "text", text: value }]
1460
1569
  });
1461
1570
  },
@@ -1513,7 +1622,7 @@ var makeThreadActionStore = (runtimeRef) => {
1513
1622
  };
1514
1623
 
1515
1624
  // src/context/providers/ThreadProvider.tsx
1516
- import { jsx as jsx23, jsxs as jsxs4 } from "react/jsx-runtime";
1625
+ import { jsx as jsx19, jsxs as jsxs3 } from "react/jsx-runtime";
1517
1626
  var ThreadProvider = ({
1518
1627
  children,
1519
1628
  runtime
@@ -1534,7 +1643,7 @@ var ThreadProvider = ({
1534
1643
  useViewport
1535
1644
  };
1536
1645
  });
1537
- useEffect6(() => {
1646
+ useEffect5(() => {
1538
1647
  const onRuntimeUpdate = () => {
1539
1648
  context.useThread.setState(
1540
1649
  Object.freeze({
@@ -1548,14 +1657,14 @@ var ThreadProvider = ({
1548
1657
  return runtime.subscribe(onRuntimeUpdate);
1549
1658
  }, [context, runtime]);
1550
1659
  const RuntimeSynchronizer = runtime.unstable_synchronizer;
1551
- return /* @__PURE__ */ jsxs4(ThreadContext.Provider, { value: context, children: [
1552
- RuntimeSynchronizer && /* @__PURE__ */ jsx23(RuntimeSynchronizer, {}),
1660
+ return /* @__PURE__ */ jsxs3(ThreadContext.Provider, { value: context, children: [
1661
+ RuntimeSynchronizer && /* @__PURE__ */ jsx19(RuntimeSynchronizer, {}),
1553
1662
  children
1554
1663
  ] });
1555
1664
  };
1556
1665
 
1557
1666
  // src/context/providers/AssistantProvider.tsx
1558
- import { jsx as jsx24 } from "react/jsx-runtime";
1667
+ import { jsx as jsx20 } from "react/jsx-runtime";
1559
1668
  var AssistantProvider = ({ children, runtime }) => {
1560
1669
  const runtimeRef = useRef5(runtime);
1561
1670
  useInsertionEffect3(() => {
@@ -1567,16 +1676,16 @@ var AssistantProvider = ({ children, runtime }) => {
1567
1676
  return { useModelConfig, useToolUIs };
1568
1677
  });
1569
1678
  const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
1570
- useEffect7(() => {
1679
+ useEffect6(() => {
1571
1680
  return runtime.registerModelConfigProvider(getModelCOnfig);
1572
1681
  }, [runtime, getModelCOnfig]);
1573
- return /* @__PURE__ */ jsx24(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx24(ThreadProvider, { runtime, children }) });
1682
+ return /* @__PURE__ */ jsx20(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx20(ThreadProvider, { runtime, children }) });
1574
1683
  };
1575
1684
 
1576
1685
  // src/context/providers/AssistantRuntimeProvider.tsx
1577
- import { jsx as jsx25 } from "react/jsx-runtime";
1686
+ import { jsx as jsx21 } from "react/jsx-runtime";
1578
1687
  var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1579
- return /* @__PURE__ */ jsx25(AssistantProvider, { runtime, children });
1688
+ return /* @__PURE__ */ jsx21(AssistantProvider, { runtime, children });
1580
1689
  };
1581
1690
  var AssistantRuntimeProvider = memo3(AssistantRuntimeProviderImpl);
1582
1691
 
@@ -1595,11 +1704,25 @@ export {
1595
1704
  internal_exports as INTERNAL,
1596
1705
  message_exports as MessagePrimitive,
1597
1706
  thread_exports as ThreadPrimitive,
1598
- useBeginMessageEdit,
1599
- useCopyMessage,
1600
- useGoToNextBranch,
1601
- useGoToPreviousBranch,
1707
+ useActionBarCopy,
1708
+ useActionBarEdit,
1709
+ useActionBarReload,
1710
+ useBranchPickerCount,
1711
+ useBranchPickerNext,
1712
+ useBranchPickerNumber,
1713
+ useBranchPickerPrevious,
1714
+ useComposerCancel,
1715
+ useComposerIf,
1716
+ useComposerSend,
1717
+ useContentPartDisplay,
1718
+ useContentPartImage,
1719
+ useContentPartInProgressIndicator,
1720
+ useContentPartText,
1602
1721
  useLocalRuntime,
1603
- useReloadMessage
1722
+ useMessageIf,
1723
+ useThreadEmpty,
1724
+ useThreadIf,
1725
+ useThreadScrollToBottom,
1726
+ useThreadSuggestion
1604
1727
  };
1605
1728
  //# sourceMappingURL=index.mjs.map