@assistant-ui/react 0.1.10 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  ActionBarPrimitive: () => actionBar_exports,
34
+ AssistantModalPrimitive: () => assistantModal_exports,
34
35
  AssistantRuntimeProvider: () => AssistantRuntimeProvider,
35
36
  BranchPickerPrimitive: () => branchPicker_exports,
36
37
  ComposerPrimitive: () => composer_exports,
@@ -167,7 +168,7 @@ var useThreadContext = () => {
167
168
 
168
169
  // src/primitive-hooks/actionBar/useActionBarReload.tsx
169
170
  var useActionBarReload = () => {
170
- const { useThread, useThreadActions, useViewport } = useThreadContext();
171
+ const { useThread, useThreadActions, useComposer, useViewport } = useThreadContext();
171
172
  const { useMessage } = useMessageContext();
172
173
  const disabled = useCombinedStore(
173
174
  [useThread, useMessage],
@@ -177,7 +178,8 @@ var useActionBarReload = () => {
177
178
  const { parentId } = useMessage.getState();
178
179
  useThreadActions.getState().startRun(parentId);
179
180
  useViewport.getState().scrollToBottom();
180
- }, [useThreadActions, useMessage, useViewport]);
181
+ useComposer.getState().focus();
182
+ }, [useThreadActions, useComposer, useViewport, useMessage]);
181
183
  if (disabled) return null;
182
184
  return callback;
183
185
  };
@@ -300,12 +302,16 @@ var useComposerIf = (props) => {
300
302
  // src/primitive-hooks/composer/useComposerSend.tsx
301
303
  var import_react14 = require("react");
302
304
  var useComposerSend = () => {
305
+ const { useViewport, useComposer: useNewComposer } = useThreadContext();
303
306
  const { useComposer } = useComposerContext();
304
307
  const disabled = useComposer((c) => !c.isEditing || c.value.length === 0);
305
308
  const callback = (0, import_react14.useCallback)(() => {
306
- const { send } = useComposer.getState();
307
- send();
308
- }, [useComposer]);
309
+ const composerState = useComposer.getState();
310
+ if (!composerState.isEditing) return;
311
+ composerState.send();
312
+ useViewport.getState().scrollToBottom();
313
+ useNewComposer.getState().focus();
314
+ }, [useNewComposer, useComposer, useViewport]);
309
315
  if (disabled) return null;
310
316
  return callback;
311
317
  };
@@ -397,12 +403,12 @@ var useThreadEmpty = () => {
397
403
  // src/primitive-hooks/thread/useThreadScrollToBottom.tsx
398
404
  var import_react15 = require("react");
399
405
  var useThreadScrollToBottom = () => {
400
- const { useViewport } = useThreadContext();
406
+ const { useComposer, useViewport } = useThreadContext();
401
407
  const isAtBottom = useViewport((s) => s.isAtBottom);
402
408
  const handleScrollToBottom = (0, import_react15.useCallback)(() => {
403
- const { scrollToBottom } = useViewport.getState();
404
- scrollToBottom();
405
- }, [useViewport]);
409
+ useViewport.getState().scrollToBottom();
410
+ useComposer.getState().focus();
411
+ }, [useViewport, useComposer]);
406
412
  if (isAtBottom) return null;
407
413
  return handleScrollToBottom;
408
414
  };
@@ -427,502 +433,242 @@ var useThreadSuggestion = ({
427
433
  return callback;
428
434
  };
429
435
 
430
- // src/primitives/thread/index.ts
431
- var thread_exports = {};
432
- __export(thread_exports, {
433
- Empty: () => ThreadEmpty,
434
- If: () => ThreadIf,
435
- Messages: () => ThreadMessages,
436
- Root: () => ThreadRoot,
437
- ScrollToBottom: () => ThreadScrollToBottom,
438
- Suggestion: () => ThreadSuggestion,
439
- Viewport: () => ThreadViewport
436
+ // src/primitives/actionBar/index.ts
437
+ var actionBar_exports = {};
438
+ __export(actionBar_exports, {
439
+ Copy: () => ActionBarCopy,
440
+ Edit: () => ActionBarEdit,
441
+ Reload: () => ActionBarReload,
442
+ Root: () => ActionBarRoot
440
443
  });
441
444
 
442
- // src/primitives/thread/ThreadRoot.tsx
445
+ // src/primitives/actionBar/ActionBarRoot.tsx
443
446
  var import_react_primitive = require("@radix-ui/react-primitive");
444
447
  var import_react17 = require("react");
445
448
  var import_jsx_runtime = require("react/jsx-runtime");
446
- var ThreadRoot = (0, import_react17.forwardRef)(
447
- (props, ref) => {
448
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_primitive.Primitive.div, { ...props, ref });
449
- }
450
- );
451
- ThreadRoot.displayName = "ThreadRoot";
452
-
453
- // src/primitives/thread/ThreadIf.tsx
454
- var ThreadIf = ({ children, ...query }) => {
455
- const result = useThreadIf(query);
456
- return result ? children : null;
457
- };
458
-
459
- // src/primitives/thread/ThreadEmpty.tsx
460
- var import_jsx_runtime2 = require("react/jsx-runtime");
461
- var ThreadEmpty = ({ children }) => {
462
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThreadIf, { empty: true, children });
449
+ var useActionBarFloatStatus = ({
450
+ hideWhenRunning,
451
+ autohide,
452
+ autohideFloat
453
+ }) => {
454
+ const { useThread } = useThreadContext();
455
+ const { useMessage, useMessageUtils } = useMessageContext();
456
+ return useCombinedStore(
457
+ [useThread, useMessage, useMessageUtils],
458
+ (t, m, mu) => {
459
+ if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
460
+ const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
461
+ if (!autohideEnabled) return "normal" /* Normal */;
462
+ if (!mu.isHovering) return "hidden" /* Hidden */;
463
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
464
+ return "floating" /* Floating */;
465
+ return "normal" /* Normal */;
466
+ }
467
+ );
463
468
  };
469
+ var ActionBarRoot = (0, import_react17.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
470
+ const hideAndfloatStatus = useActionBarFloatStatus({
471
+ hideWhenRunning,
472
+ autohide,
473
+ autohideFloat
474
+ });
475
+ if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
476
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
477
+ import_react_primitive.Primitive.div,
478
+ {
479
+ ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
480
+ ...rest,
481
+ ref
482
+ }
483
+ );
484
+ });
485
+ ActionBarRoot.displayName = "ActionBarRoot";
464
486
 
465
- // src/primitives/thread/ThreadViewport.tsx
487
+ // src/utils/createActionButton.tsx
466
488
  var import_primitive = require("@radix-ui/primitive");
467
- var import_react_compose_refs = require("@radix-ui/react-compose-refs");
468
489
  var import_react_primitive2 = require("@radix-ui/react-primitive");
469
- var import_react20 = require("react");
470
-
471
- // src/utils/hooks/useOnResizeContent.tsx
472
- var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
473
490
  var import_react18 = require("react");
474
- var useOnResizeContent = (ref, callback) => {
475
- const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
476
- (0, import_react18.useEffect)(() => {
477
- const el = ref.current;
478
- if (!el) return;
479
- const resizeObserver = new ResizeObserver(() => {
480
- callbackRef();
481
- });
482
- const mutationObserver = new MutationObserver((mutations) => {
483
- for (const mutation of mutations) {
484
- for (const node of mutation.addedNodes) {
485
- if (node instanceof Element) {
486
- resizeObserver.observe(node);
487
- }
488
- }
489
- for (const node of mutation.removedNodes) {
490
- if (node instanceof Element) {
491
- resizeObserver.unobserve(node);
492
- }
493
- }
491
+ var import_jsx_runtime2 = require("react/jsx-runtime");
492
+ var createActionButton = (displayName, useActionButton) => {
493
+ const ActionButton = (0, import_react18.forwardRef)((props, forwardedRef) => {
494
+ const callback = useActionButton(props);
495
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
496
+ import_react_primitive2.Primitive.button,
497
+ {
498
+ type: "button",
499
+ disabled: !callback,
500
+ ...props,
501
+ ref: forwardedRef,
502
+ onClick: (0, import_primitive.composeEventHandlers)(props.onClick, () => {
503
+ callback?.();
504
+ })
494
505
  }
495
- callbackRef();
496
- });
497
- resizeObserver.observe(el);
498
- mutationObserver.observe(el, { childList: true });
499
- for (const child of el.children) {
500
- resizeObserver.observe(child);
501
- }
502
- return () => {
503
- resizeObserver.disconnect();
504
- mutationObserver.disconnect();
505
- };
506
- }, [ref, callbackRef]);
506
+ );
507
+ });
508
+ ActionButton.displayName = displayName;
509
+ return ActionButton;
507
510
  };
508
511
 
509
- // src/utils/hooks/useOnScrollToBottom.tsx
510
- var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
512
+ // src/primitives/actionBar/ActionBarCopy.tsx
513
+ var ActionBarCopy = createActionButton(
514
+ "ActionBarCopy",
515
+ useActionBarCopy
516
+ );
517
+
518
+ // src/primitives/actionBar/ActionBarReload.tsx
519
+ var ActionBarReload = createActionButton(
520
+ "ActionBarReload",
521
+ useActionBarReload
522
+ );
523
+
524
+ // src/primitives/actionBar/ActionBarEdit.tsx
525
+ var ActionBarEdit = createActionButton(
526
+ "ActionBarEdit",
527
+ useActionBarEdit
528
+ );
529
+
530
+ // src/primitives/assistantModal/index.ts
531
+ var assistantModal_exports = {};
532
+ __export(assistantModal_exports, {
533
+ Content: () => AssistantModalContent,
534
+ Root: () => AssistantModalRoot,
535
+ Trigger: () => AssistantModalTrigger
536
+ });
537
+
538
+ // src/primitives/assistantModal/AssistantModalRoot.tsx
539
+ var import_react20 = require("react");
540
+ var PopoverPrimitive = __toESM(require("@radix-ui/react-popover"));
541
+ var import_primitive2 = require("@radix-ui/primitive");
542
+
543
+ // src/utils/hooks/useOnComposerFocus.tsx
544
+ var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
511
545
  var import_react19 = require("react");
512
- var useOnScrollToBottom = (callback) => {
513
- const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
514
- const { useViewport } = useThreadContext();
546
+ var useOnComposerFocus = (callback) => {
547
+ const callbackRef = (0, import_react_use_callback_ref.useCallbackRef)(callback);
548
+ const { useComposer } = useThreadContext();
515
549
  (0, import_react19.useEffect)(() => {
516
- return useViewport.getState().onScrollToBottom(() => {
550
+ return useComposer.getState().onFocus(() => {
517
551
  callbackRef();
518
552
  });
519
- }, [useViewport, callbackRef]);
553
+ }, [useComposer, callbackRef]);
520
554
  };
521
555
 
522
- // src/primitives/thread/ThreadViewport.tsx
556
+ // src/primitives/assistantModal/AssistantModalRoot.tsx
523
557
  var import_jsx_runtime3 = require("react/jsx-runtime");
524
- var ThreadViewport = (0, import_react20.forwardRef)(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
525
- const messagesEndRef = (0, import_react20.useRef)(null);
526
- const divRef = (0, import_react20.useRef)(null);
527
- const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, divRef);
528
- const { useViewport } = useThreadContext();
529
- const firstRenderRef = (0, import_react20.useRef)(true);
530
- const isScrollingToBottomRef = (0, import_react20.useRef)(false);
531
- const lastScrollTop = (0, import_react20.useRef)(0);
532
- const scrollToBottom = () => {
533
- const div = messagesEndRef.current;
534
- if (!div || !autoScroll) return;
535
- const behavior = firstRenderRef.current ? "instant" : "auto";
536
- firstRenderRef.current = false;
537
- isScrollingToBottomRef.current = true;
538
- div.scrollIntoView({ behavior });
539
- };
540
- useOnResizeContent(divRef, () => {
541
- if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom) {
542
- handleScroll();
543
- } else {
544
- scrollToBottom();
545
- }
546
- });
547
- useOnScrollToBottom(() => {
548
- scrollToBottom();
558
+ var usePopoverScope = PopoverPrimitive.createPopoverScope();
559
+ var useAssistantModalOpenState = (defaultOpen = false) => {
560
+ const state = (0, import_react20.useState)(defaultOpen);
561
+ const [, setOpen] = state;
562
+ useOnComposerFocus(() => {
563
+ setOpen(true);
549
564
  });
550
- const handleScroll = () => {
551
- const div = divRef.current;
552
- if (!div) return;
553
- const isAtBottom = useViewport.getState().isAtBottom;
554
- const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
555
- if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
556
- } else if (newIsAtBottom !== isAtBottom) {
557
- isScrollingToBottomRef.current = false;
558
- useViewport.setState({
559
- isAtBottom: newIsAtBottom
560
- });
561
- }
562
- lastScrollTop.current = div.scrollTop;
563
- };
564
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
565
- import_react_primitive2.Primitive.div,
565
+ return state;
566
+ };
567
+ var AssistantModalRoot = ({
568
+ __scopeAssistantModal,
569
+ defaultOpen,
570
+ open,
571
+ onOpenChange,
572
+ ...rest
573
+ }) => {
574
+ const scope = usePopoverScope(__scopeAssistantModal);
575
+ const [modalOpen, setOpen] = useAssistantModalOpenState(defaultOpen);
576
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
577
+ PopoverPrimitive.Root,
566
578
  {
567
- ...rest,
568
- onScroll: (0, import_primitive.composeEventHandlers)(onScroll, handleScroll),
569
- ref,
570
- children: [
571
- children,
572
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: messagesEndRef })
573
- ]
579
+ ...scope,
580
+ open: open === void 0 ? modalOpen : open,
581
+ onOpenChange: (0, import_primitive2.composeEventHandlers)(onOpenChange, setOpen),
582
+ ...rest
574
583
  }
575
584
  );
576
- });
577
- ThreadViewport.displayName = "ThreadViewport";
578
-
579
- // src/primitives/thread/ThreadMessages.tsx
580
- var import_react22 = require("react");
585
+ };
586
+ AssistantModalRoot.displayName = "AssistantModalRoot";
581
587
 
582
- // src/context/providers/MessageProvider.tsx
588
+ // src/primitives/assistantModal/AssistantModalTrigger.tsx
583
589
  var import_react21 = require("react");
584
- var import_zustand3 = require("zustand");
585
-
586
- // src/context/stores/EditComposer.ts
587
- var import_zustand = require("zustand");
590
+ var PopoverPrimitive2 = __toESM(require("@radix-ui/react-popover"));
591
+ var import_jsx_runtime4 = require("react/jsx-runtime");
592
+ var AssistantModalTrigger = (0, import_react21.forwardRef)(
593
+ ({ __scopeAssistantModal, ...rest }, ref) => {
594
+ const scope = usePopoverScope(__scopeAssistantModal);
595
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PopoverPrimitive2.Trigger, { ...scope, ...rest, ref });
596
+ }
597
+ );
598
+ AssistantModalTrigger.displayName = "AssistantModalTrigger";
588
599
 
589
- // src/context/stores/BaseComposer.ts
590
- var makeBaseComposer = (set) => ({
591
- value: "",
592
- setValue: (value) => {
593
- set({ value });
600
+ // src/primitives/assistantModal/AssistantModalContent.tsx
601
+ var import_react22 = require("react");
602
+ var PopoverPrimitive3 = __toESM(require("@radix-ui/react-popover"));
603
+ var import_primitive3 = require("@radix-ui/primitive");
604
+ var import_jsx_runtime5 = require("react/jsx-runtime");
605
+ var AssistantModalContent = (0, import_react22.forwardRef)(
606
+ ({
607
+ __scopeAssistantModal,
608
+ side,
609
+ align,
610
+ onInteractOutside,
611
+ dissmissOnInteractOutside = false,
612
+ ...props
613
+ }, forwardedRef) => {
614
+ const scope = usePopoverScope(__scopeAssistantModal);
615
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PopoverPrimitive3.Portal, { ...scope, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
616
+ PopoverPrimitive3.Content,
617
+ {
618
+ ...scope,
619
+ ...props,
620
+ ref: forwardedRef,
621
+ side: side ?? "top",
622
+ align: align ?? "end",
623
+ onInteractOutside: (0, import_primitive3.composeEventHandlers)(
624
+ onInteractOutside,
625
+ dissmissOnInteractOutside ? void 0 : (e) => e.preventDefault()
626
+ )
627
+ }
628
+ ) });
594
629
  }
630
+ );
631
+ AssistantModalContent.displayName = "AssistantModalContent";
632
+
633
+ // src/primitives/branchPicker/index.ts
634
+ var branchPicker_exports = {};
635
+ __export(branchPicker_exports, {
636
+ Count: () => BranchPickerCount,
637
+ Next: () => BranchPickerNext,
638
+ Number: () => BranchPickerNumber,
639
+ Previous: () => BranchPickerPrevious,
640
+ Root: () => BranchPickerRoot
595
641
  });
596
642
 
597
- // src/context/stores/EditComposer.ts
598
- var makeEditComposerStore = ({
599
- onEdit,
600
- onSend
601
- }) => (0, import_zustand.create)()((set, get, store) => ({
602
- ...makeBaseComposer(set, get, store),
603
- isEditing: false,
604
- edit: () => {
605
- const value = onEdit();
606
- set({ isEditing: true, value });
607
- },
608
- send: () => {
609
- const value = get().value;
610
- set({ isEditing: false });
611
- onSend(value);
612
- },
613
- cancel: () => {
614
- if (!get().isEditing) return false;
615
- set({ isEditing: false });
616
- return true;
617
- }
618
- }));
643
+ // src/primitives/branchPicker/BranchPickerNext.tsx
644
+ var BranchPickerNext = createActionButton(
645
+ "BranchPickerNext",
646
+ useBranchPickerNext
647
+ );
619
648
 
620
- // src/context/stores/MessageUtils.ts
621
- var import_zustand2 = require("zustand");
622
- var makeMessageUtilsStore = () => (0, import_zustand2.create)((set) => ({
623
- inProgressIndicator: null,
624
- setInProgressIndicator: (value) => {
625
- set({ inProgressIndicator: value });
626
- },
627
- isCopied: false,
628
- setIsCopied: (value) => {
629
- set({ isCopied: value });
630
- },
631
- isHovering: false,
632
- setIsHovering: (value) => {
633
- set({ isHovering: value });
634
- }
635
- }));
649
+ // src/primitives/branchPicker/BranchPickerPrevious.tsx
650
+ var BranchPickerPrevious = createActionButton(
651
+ "BranchPickerPrevious",
652
+ useBranchPickerPrevious
653
+ );
636
654
 
637
- // src/context/providers/MessageProvider.tsx
638
- var import_jsx_runtime4 = require("react/jsx-runtime");
639
- var getIsLast = (thread, message) => {
640
- return thread.messages[thread.messages.length - 1]?.id === message.id;
655
+ // src/primitives/branchPicker/BranchPickerCount.tsx
656
+ var import_jsx_runtime6 = require("react/jsx-runtime");
657
+ var BranchPickerCount = () => {
658
+ const branchCount = useBranchPickerCount();
659
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: branchCount });
641
660
  };
642
- var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
643
- const parentId = thread.messages[messageIndex - 1]?.id ?? null;
644
- const message = thread.messages[messageIndex];
645
- if (!message) return;
646
- const isLast = getIsLast(thread, message);
647
- const branches = getBranches(message.id);
648
- const currentState = useMessage.getState();
649
- if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
650
- return;
651
- useMessage.setState({
652
- message,
653
- parentId,
654
- branches,
655
- isLast
656
- });
657
- };
658
- var useMessageContext2 = (messageIndex) => {
659
- const { useThread, useThreadActions } = useThreadContext();
660
- const [context] = (0, import_react21.useState)(() => {
661
- const useMessage = (0, import_zustand3.create)(() => ({}));
662
- const useMessageUtils = makeMessageUtilsStore();
663
- const useEditComposer = makeEditComposerStore({
664
- onEdit: () => {
665
- const message = useMessage.getState().message;
666
- if (message.role !== "user")
667
- throw new Error(
668
- "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
669
- );
670
- const text = getMessageText(message);
671
- return text;
672
- },
673
- onSend: (text) => {
674
- const { message, parentId } = useMessage.getState();
675
- if (message.role !== "user")
676
- throw new Error(
677
- "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
678
- );
679
- const nonTextParts = message.content.filter(
680
- (part) => part.type !== "text" && part.type !== "ui"
681
- );
682
- useThreadActions.getState().append({
683
- parentId,
684
- content: [{ type: "text", text }, ...nonTextParts]
685
- });
686
- }
687
- });
688
- syncMessage(
689
- useThread.getState(),
690
- useThreadActions.getState().getBranches,
691
- useMessage,
692
- messageIndex
693
- );
694
- return { useMessage, useMessageUtils, useEditComposer };
695
- });
696
- (0, import_react21.useEffect)(() => {
697
- return useThread.subscribe((thread) => {
698
- syncMessage(
699
- thread,
700
- useThreadActions.getState().getBranches,
701
- context.useMessage,
702
- messageIndex
703
- );
704
- });
705
- }, [useThread, useThreadActions, context, messageIndex]);
706
- return context;
707
- };
708
- var MessageProvider = ({
709
- messageIndex,
710
- children
711
- }) => {
712
- const context = useMessageContext2(messageIndex);
713
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MessageContext.Provider, { value: context, children });
714
- };
715
-
716
- // src/primitives/composer/ComposerIf.tsx
717
- var ComposerIf = ({ children, ...query }) => {
718
- const result = useComposerIf(query);
719
- return result ? children : null;
720
- };
721
-
722
- // src/primitives/message/MessageIf.tsx
723
- var MessageIf = ({ children, ...query }) => {
724
- const result = useMessageIf(query);
725
- return result ? children : null;
726
- };
727
-
728
- // src/primitives/thread/ThreadMessages.tsx
729
- var import_jsx_runtime5 = require("react/jsx-runtime");
730
- var getComponents = (components) => {
731
- return {
732
- EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
733
- UserMessage: components.UserMessage ?? components.Message,
734
- AssistantMessage: components.AssistantMessage ?? components.Message
735
- };
736
- };
737
- var ThreadMessageImpl = ({
738
- messageIndex,
739
- components
740
- }) => {
741
- const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
742
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageProvider, { messageIndex, children: [
743
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageIf, { user: true, children: [
744
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(UserMessage, {}) }),
745
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EditComposer, {}) })
746
- ] }),
747
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AssistantMessage, {}) })
748
- ] });
749
- };
750
- var ThreadMessage = (0, import_react22.memo)(
751
- ThreadMessageImpl,
752
- (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
753
- );
754
- var ThreadMessages = ({ components }) => {
755
- const { useThread } = useThreadContext();
756
- const messagesLength = useThread((t) => t.messages.length);
757
- if (messagesLength === 0) return null;
758
- return new Array(messagesLength).fill(null).map((_, idx) => {
759
- const messageIndex = idx;
760
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
761
- ThreadMessage,
762
- {
763
- messageIndex,
764
- components
765
- },
766
- messageIndex
767
- );
768
- });
769
- };
770
-
771
- // src/utils/createActionButton.tsx
772
- var import_primitive2 = require("@radix-ui/primitive");
773
- var import_react_primitive3 = require("@radix-ui/react-primitive");
774
- var import_react23 = require("react");
775
- var import_jsx_runtime6 = require("react/jsx-runtime");
776
- var createActionButton = (displayName, useActionButton) => {
777
- const ActionButton = (0, import_react23.forwardRef)((props, forwardedRef) => {
778
- const callback = useActionButton(props);
779
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
780
- import_react_primitive3.Primitive.button,
781
- {
782
- type: "button",
783
- disabled: !callback,
784
- ...props,
785
- ref: forwardedRef,
786
- onClick: (0, import_primitive2.composeEventHandlers)(props.onClick, () => {
787
- callback?.();
788
- })
789
- }
790
- );
791
- });
792
- ActionButton.displayName = displayName;
793
- return ActionButton;
794
- };
795
-
796
- // src/primitives/thread/ThreadScrollToBottom.tsx
797
- var ThreadScrollToBottom = createActionButton(
798
- "ThreadScrollToBottom",
799
- useThreadScrollToBottom
800
- );
801
-
802
- // src/primitives/thread/ThreadSuggestion.tsx
803
- var ThreadSuggestion = createActionButton(
804
- "ThreadSuggestion",
805
- useThreadSuggestion
806
- );
807
-
808
- // src/primitives/composer/index.ts
809
- var composer_exports = {};
810
- __export(composer_exports, {
811
- Cancel: () => ComposerCancel,
812
- If: () => ComposerIf,
813
- Input: () => ComposerInput,
814
- Root: () => ComposerRoot,
815
- Send: () => ComposerSend
816
- });
817
661
 
818
- // src/primitives/composer/ComposerRoot.tsx
819
- var import_primitive3 = require("@radix-ui/primitive");
820
- var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
821
- var import_react_primitive4 = require("@radix-ui/react-primitive");
822
- var import_react24 = require("react");
662
+ // src/primitives/branchPicker/BranchPickerNumber.tsx
823
663
  var import_jsx_runtime7 = require("react/jsx-runtime");
824
- var ComposerRoot = (0, import_react24.forwardRef)(
825
- ({ onSubmit, ...rest }, forwardedRef) => {
826
- const { useViewport } = useThreadContext();
827
- const { useComposer } = useComposerContext();
828
- const formRef = (0, import_react24.useRef)(null);
829
- const ref = (0, import_react_compose_refs2.useComposedRefs)(forwardedRef, formRef);
830
- const handleSubmit = (e) => {
831
- const composerState = useComposer.getState();
832
- if (!composerState.isEditing) return;
833
- e.preventDefault();
834
- composerState.send();
835
- useViewport.getState().scrollToBottom();
836
- };
837
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
838
- import_react_primitive4.Primitive.form,
839
- {
840
- ...rest,
841
- ref,
842
- onSubmit: (0, import_primitive3.composeEventHandlers)(onSubmit, handleSubmit)
843
- }
844
- );
845
- }
846
- );
847
- ComposerRoot.displayName = "ComposerRoot";
848
-
849
- // src/primitives/composer/ComposerInput.tsx
850
- var import_primitive4 = require("@radix-ui/primitive");
851
- var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
852
- var import_react_slot = require("@radix-ui/react-slot");
853
- var import_react25 = require("react");
854
- var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
855
- var import_jsx_runtime8 = require("react/jsx-runtime");
856
- var ComposerInput = (0, import_react25.forwardRef)(
857
- ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
858
- const { useThread } = useThreadContext();
859
- const { useComposer, type } = useComposerContext();
860
- const value = useComposer((c) => {
861
- if (!c.isEditing) return "";
862
- return c.value;
863
- });
864
- const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize.default;
865
- const textareaRef = (0, import_react25.useRef)(null);
866
- const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, textareaRef);
867
- const handleKeyPress = (e) => {
868
- if (disabled) return;
869
- if (e.key === "Escape") {
870
- const composer = useComposer.getState();
871
- if (composer.cancel()) {
872
- e.preventDefault();
873
- }
874
- } else if (e.key === "Enter" && e.shiftKey === false) {
875
- const isRunning = useThread.getState().isRunning;
876
- if (!isRunning) {
877
- e.preventDefault();
878
- textareaRef.current?.closest("form")?.requestSubmit();
879
- }
880
- }
881
- };
882
- const autoFocusEnabled = autoFocus && !disabled;
883
- const focus = (0, import_react25.useCallback)(() => {
884
- const textarea = textareaRef.current;
885
- if (!textarea || !autoFocusEnabled) return;
886
- textarea.focus();
887
- textarea.setSelectionRange(
888
- textareaRef.current.value.length,
889
- textareaRef.current.value.length
890
- );
891
- }, [autoFocusEnabled]);
892
- (0, import_react25.useEffect)(() => focus(), [focus]);
893
- useOnScrollToBottom(() => {
894
- if (type === "new") {
895
- focus();
896
- }
897
- });
898
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
899
- Component,
900
- {
901
- value,
902
- ...rest,
903
- ref,
904
- autoFocus,
905
- disabled,
906
- onChange: (0, import_primitive4.composeEventHandlers)(onChange, (e) => {
907
- const composerState = useComposer.getState();
908
- if (!composerState.isEditing) return;
909
- return composerState.setValue(e.target.value);
910
- }),
911
- onKeyDown: (0, import_primitive4.composeEventHandlers)(onKeyDown, handleKeyPress)
912
- }
913
- );
914
- }
915
- );
916
- ComposerInput.displayName = "ComposerInput";
917
-
918
- // src/primitives/composer/ComposerSend.tsx
919
- var ComposerSend = createActionButton("ComposerSend", useComposerSend);
664
+ var BranchPickerNumber = () => {
665
+ const branchNumber = useBranchPickerNumber();
666
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: branchNumber });
667
+ };
920
668
 
921
- // src/primitives/composer/ComposerCancel.tsx
922
- var ComposerCancel = createActionButton(
923
- "ComposerCancel",
924
- useComposerCancel
925
- );
669
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
670
+ var import_react_primitive6 = require("@radix-ui/react-primitive");
671
+ var import_react28 = require("react");
926
672
 
927
673
  // src/primitives/message/index.ts
928
674
  var message_exports = {};
@@ -934,11 +680,11 @@ __export(message_exports, {
934
680
  });
935
681
 
936
682
  // src/primitives/message/MessageRoot.tsx
937
- var import_primitive5 = require("@radix-ui/primitive");
938
- var import_react_primitive5 = require("@radix-ui/react-primitive");
939
- var import_react26 = require("react");
940
- var import_jsx_runtime9 = require("react/jsx-runtime");
941
- var MessageRoot = (0, import_react26.forwardRef)(
683
+ var import_primitive4 = require("@radix-ui/primitive");
684
+ var import_react_primitive3 = require("@radix-ui/react-primitive");
685
+ var import_react23 = require("react");
686
+ var import_jsx_runtime8 = require("react/jsx-runtime");
687
+ var MessageRoot = (0, import_react23.forwardRef)(
942
688
  ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
943
689
  const { useMessageUtils } = useMessageContext();
944
690
  const setIsHovering = useMessageUtils((s) => s.setIsHovering);
@@ -948,26 +694,32 @@ var MessageRoot = (0, import_react26.forwardRef)(
948
694
  const handleMouseLeave = () => {
949
695
  setIsHovering(false);
950
696
  };
951
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
952
- import_react_primitive5.Primitive.div,
697
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
698
+ import_react_primitive3.Primitive.div,
953
699
  {
954
700
  ...rest,
955
701
  ref,
956
- onMouseEnter: (0, import_primitive5.composeEventHandlers)(onMouseEnter, handleMouseEnter),
957
- onMouseLeave: (0, import_primitive5.composeEventHandlers)(onMouseLeave, handleMouseLeave)
702
+ onMouseEnter: (0, import_primitive4.composeEventHandlers)(onMouseEnter, handleMouseEnter),
703
+ onMouseLeave: (0, import_primitive4.composeEventHandlers)(onMouseLeave, handleMouseLeave)
958
704
  }
959
705
  );
960
706
  }
961
707
  );
962
708
  MessageRoot.displayName = "MessageRoot";
963
709
 
964
- // src/primitives/message/MessageContent.tsx
965
- var import_react29 = require("react");
710
+ // src/primitives/message/MessageIf.tsx
711
+ var MessageIf = ({ children, ...query }) => {
712
+ const result = useMessageIf(query);
713
+ return result ? children : null;
714
+ };
715
+
716
+ // src/primitives/message/MessageContent.tsx
717
+ var import_react26 = require("react");
966
718
 
967
719
  // src/context/providers/ContentPartProvider.tsx
968
- var import_react27 = require("react");
969
- var import_zustand4 = require("zustand");
970
- var import_jsx_runtime10 = require("react/jsx-runtime");
720
+ var import_react24 = require("react");
721
+ var import_zustand = require("zustand");
722
+ var import_jsx_runtime9 = require("react/jsx-runtime");
971
723
  var syncContentPart = ({ message }, useContentPart, partIndex) => {
972
724
  const part = message.content[partIndex];
973
725
  if (!part) return;
@@ -984,14 +736,14 @@ var syncContentPart = ({ message }, useContentPart, partIndex) => {
984
736
  };
985
737
  var useContentPartContext2 = (partIndex) => {
986
738
  const { useMessage } = useMessageContext();
987
- const [context] = (0, import_react27.useState)(() => {
988
- const useContentPart = (0, import_zustand4.create)(
739
+ const [context] = (0, import_react24.useState)(() => {
740
+ const useContentPart = (0, import_zustand.create)(
989
741
  () => ({})
990
742
  );
991
743
  syncContentPart(useMessage.getState(), useContentPart, partIndex);
992
744
  return { useContentPart };
993
745
  });
994
- (0, import_react27.useEffect)(() => {
746
+ (0, import_react24.useEffect)(() => {
995
747
  syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
996
748
  return useMessage.subscribe((message) => {
997
749
  syncContentPart(message, context.useContentPart, partIndex);
@@ -1004,7 +756,7 @@ var ContentPartProvider = ({
1004
756
  children
1005
757
  }) => {
1006
758
  const context = useContentPartContext2(partIndex);
1007
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ContentPartContext.Provider, { value: context, children });
759
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ContentPartContext.Provider, { value: context, children });
1008
760
  };
1009
761
 
1010
762
  // src/primitives/contentPart/ContentPartDisplay.tsx
@@ -1012,244 +764,649 @@ var ContentPartDisplay = () => {
1012
764
  const display = useContentPartDisplay();
1013
765
  return display ?? null;
1014
766
  };
1015
-
1016
- // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
1017
- var ContentPartInProgressIndicator = () => {
1018
- const indicator = useContentPartInProgressIndicator();
1019
- return indicator;
767
+
768
+ // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
769
+ var ContentPartInProgressIndicator = () => {
770
+ const indicator = useContentPartInProgressIndicator();
771
+ return indicator;
772
+ };
773
+
774
+ // src/primitives/contentPart/ContentPartText.tsx
775
+ var import_react_primitive4 = require("@radix-ui/react-primitive");
776
+ var import_react25 = require("react");
777
+ var import_jsx_runtime10 = require("react/jsx-runtime");
778
+ var ContentPartText = (0, import_react25.forwardRef)((props, forwardedRef) => {
779
+ const text = useContentPartText();
780
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react_primitive4.Primitive.span, { ...props, ref: forwardedRef, children: text });
781
+ });
782
+ ContentPartText.displayName = "ContentPartText";
783
+
784
+ // src/primitives/message/MessageContent.tsx
785
+ var import_jsx_runtime11 = require("react/jsx-runtime");
786
+ var defaultComponents = {
787
+ Text: () => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
788
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ContentPartText, {}),
789
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ContentPartInProgressIndicator, {})
790
+ ] }),
791
+ Image: () => null,
792
+ UI: () => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ContentPartDisplay, {}),
793
+ tools: {
794
+ Fallback: (props) => {
795
+ const { useToolUIs } = useAssistantContext();
796
+ const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
797
+ if (!Render) return null;
798
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Render, { ...props });
799
+ }
800
+ }
801
+ };
802
+ var MessageContentPartComponent = ({
803
+ components: {
804
+ Text = defaultComponents.Text,
805
+ Image = defaultComponents.Image,
806
+ UI = defaultComponents.UI,
807
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
808
+ } = {}
809
+ }) => {
810
+ const { useThreadActions } = useThreadContext();
811
+ const addToolResult = useThreadActions((t) => t.addToolResult);
812
+ const { useContentPart } = useContentPartContext();
813
+ const { part, status } = useContentPart();
814
+ const type = part.type;
815
+ switch (type) {
816
+ case "text":
817
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { part, status });
818
+ case "image":
819
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Image, { part, status });
820
+ case "ui":
821
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(UI, { part, status });
822
+ case "tool-call": {
823
+ const Tool = by_name[part.toolName] || Fallback;
824
+ const addResult = (result) => addToolResult(part.toolCallId, result);
825
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Tool, { part, status, addResult });
826
+ }
827
+ default:
828
+ throw new Error(`Unknown content part type: ${type}`);
829
+ }
830
+ };
831
+ var MessageContentPartImpl = ({
832
+ partIndex,
833
+ components
834
+ }) => {
835
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ContentPartProvider, { partIndex, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MessageContentPartComponent, { components }) });
836
+ };
837
+ var MessageContentPart = (0, import_react26.memo)(
838
+ MessageContentPartImpl,
839
+ (prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Image === next.components?.Image && prev.components?.UI === next.components?.UI && prev.components?.tools === next.components?.tools
840
+ );
841
+ var MessageContent = ({ components }) => {
842
+ const { useMessage } = useMessageContext();
843
+ const contentLength = useMessage((s) => s.message.content.length);
844
+ return new Array(contentLength).fill(null).map((_, idx) => {
845
+ const partIndex = idx;
846
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
847
+ MessageContentPart,
848
+ {
849
+ partIndex,
850
+ components
851
+ },
852
+ partIndex
853
+ );
854
+ });
855
+ };
856
+
857
+ // src/primitives/message/MessageInProgress.tsx
858
+ var import_react_primitive5 = require("@radix-ui/react-primitive");
859
+ var import_react27 = require("react");
860
+ var import_jsx_runtime12 = require("react/jsx-runtime");
861
+ var MessageInProgress = (0, import_react27.forwardRef)((props, ref) => {
862
+ const { useMessageUtils } = useMessageContext();
863
+ (0, import_react27.useMemo)(() => {
864
+ useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_primitive5.Primitive.span, { ...props, ref }));
865
+ }, [useMessageUtils, props, ref]);
866
+ return null;
867
+ });
868
+ MessageInProgress.displayName = "MessageInProgress";
869
+
870
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
871
+ var import_jsx_runtime13 = require("react/jsx-runtime");
872
+ var BranchPickerRoot = (0, import_react28.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
873
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_primitive6.Primitive.div, { ...rest, ref }) });
874
+ });
875
+ BranchPickerRoot.displayName = "BranchPickerRoot";
876
+
877
+ // src/primitives/composer/index.ts
878
+ var composer_exports = {};
879
+ __export(composer_exports, {
880
+ Cancel: () => ComposerCancel,
881
+ If: () => ComposerIf,
882
+ Input: () => ComposerInput,
883
+ Root: () => ComposerRoot,
884
+ Send: () => ComposerSend
885
+ });
886
+
887
+ // src/primitives/composer/ComposerRoot.tsx
888
+ var import_primitive5 = require("@radix-ui/primitive");
889
+ var import_react_primitive7 = require("@radix-ui/react-primitive");
890
+ var import_react29 = require("react");
891
+ var import_jsx_runtime14 = require("react/jsx-runtime");
892
+ var ComposerRoot = (0, import_react29.forwardRef)(
893
+ ({ onSubmit, ...rest }, forwardedRef) => {
894
+ const send = useComposerSend();
895
+ const handleSubmit = (e) => {
896
+ if (!send) return;
897
+ e.preventDefault();
898
+ send();
899
+ };
900
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
901
+ import_react_primitive7.Primitive.form,
902
+ {
903
+ ...rest,
904
+ ref: forwardedRef,
905
+ onSubmit: (0, import_primitive5.composeEventHandlers)(onSubmit, handleSubmit)
906
+ }
907
+ );
908
+ }
909
+ );
910
+ ComposerRoot.displayName = "ComposerRoot";
911
+
912
+ // src/primitives/composer/ComposerInput.tsx
913
+ var import_primitive6 = require("@radix-ui/primitive");
914
+ var import_react_compose_refs = require("@radix-ui/react-compose-refs");
915
+ var import_react_slot = require("@radix-ui/react-slot");
916
+ var import_react30 = require("react");
917
+ var import_react_textarea_autosize = __toESM(require("react-textarea-autosize"));
918
+ var import_react_use_escape_keydown = require("@radix-ui/react-use-escape-keydown");
919
+ var import_jsx_runtime15 = require("react/jsx-runtime");
920
+ var ComposerInput = (0, import_react30.forwardRef)(
921
+ ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
922
+ const { useThread } = useThreadContext();
923
+ const { useComposer, type } = useComposerContext();
924
+ const value = useComposer((c) => {
925
+ if (!c.isEditing) return "";
926
+ return c.value;
927
+ });
928
+ const Component = asChild ? import_react_slot.Slot : import_react_textarea_autosize.default;
929
+ const textareaRef = (0, import_react30.useRef)(null);
930
+ const ref = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, textareaRef);
931
+ (0, import_react_use_escape_keydown.useEscapeKeydown)((e) => {
932
+ const composer = useComposer.getState();
933
+ if (composer.cancel()) {
934
+ e.preventDefault();
935
+ }
936
+ });
937
+ const handleKeyPress = (e) => {
938
+ if (disabled) return;
939
+ if (e.key === "Enter" && e.shiftKey === false) {
940
+ const isRunning = useThread.getState().isRunning;
941
+ if (!isRunning) {
942
+ e.preventDefault();
943
+ textareaRef.current?.closest("form")?.requestSubmit();
944
+ }
945
+ }
946
+ };
947
+ const autoFocusEnabled = autoFocus && !disabled;
948
+ const focus = (0, import_react30.useCallback)(() => {
949
+ const textarea = textareaRef.current;
950
+ if (!textarea || !autoFocusEnabled) return;
951
+ textarea.focus({ preventScroll: true });
952
+ textarea.setSelectionRange(
953
+ textareaRef.current.value.length,
954
+ textareaRef.current.value.length
955
+ );
956
+ }, [autoFocusEnabled]);
957
+ (0, import_react30.useEffect)(() => focus(), [focus]);
958
+ useOnComposerFocus(() => {
959
+ if (type === "new") {
960
+ focus();
961
+ }
962
+ });
963
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
964
+ Component,
965
+ {
966
+ value,
967
+ ...rest,
968
+ ref,
969
+ disabled,
970
+ onChange: (0, import_primitive6.composeEventHandlers)(onChange, (e) => {
971
+ const composerState = useComposer.getState();
972
+ if (!composerState.isEditing) return;
973
+ return composerState.setValue(e.target.value);
974
+ }),
975
+ onKeyDown: (0, import_primitive6.composeEventHandlers)(onKeyDown, handleKeyPress)
976
+ }
977
+ );
978
+ }
979
+ );
980
+ ComposerInput.displayName = "ComposerInput";
981
+
982
+ // src/primitives/composer/ComposerSend.tsx
983
+ var import_react31 = require("react");
984
+ var import_react_primitive8 = require("@radix-ui/react-primitive");
985
+ var import_jsx_runtime16 = require("react/jsx-runtime");
986
+ var ComposerSend = (0, import_react31.forwardRef)(
987
+ ({ disabled, ...rest }, ref) => {
988
+ const { useComposer } = useComposerContext();
989
+ const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
990
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
991
+ import_react_primitive8.Primitive.button,
992
+ {
993
+ type: "submit",
994
+ ...rest,
995
+ ref,
996
+ disabled: disabled || !hasValue
997
+ }
998
+ );
999
+ }
1000
+ );
1001
+ ComposerSend.displayName = "ComposerSend";
1002
+
1003
+ // src/primitives/composer/ComposerCancel.tsx
1004
+ var ComposerCancel = createActionButton(
1005
+ "ComposerCancel",
1006
+ useComposerCancel
1007
+ );
1008
+
1009
+ // src/primitives/composer/ComposerIf.tsx
1010
+ var ComposerIf = ({ children, ...query }) => {
1011
+ const result = useComposerIf(query);
1012
+ return result ? children : null;
1013
+ };
1014
+
1015
+ // src/primitives/contentPart/index.ts
1016
+ var contentPart_exports = {};
1017
+ __export(contentPart_exports, {
1018
+ Display: () => ContentPartDisplay,
1019
+ Image: () => ContentPartImage,
1020
+ InProgressIndicator: () => ContentPartInProgressIndicator,
1021
+ Text: () => ContentPartText
1022
+ });
1023
+
1024
+ // src/primitives/contentPart/ContentPartImage.tsx
1025
+ var import_react_primitive9 = require("@radix-ui/react-primitive");
1026
+ var import_react32 = require("react");
1027
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1028
+ var ContentPartImage = (0, import_react32.forwardRef)((props, forwardedRef) => {
1029
+ const image = useContentPartImage();
1030
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react_primitive9.Primitive.img, { src: image, ...props, ref: forwardedRef });
1031
+ });
1032
+ ContentPartImage.displayName = "ContentPartImage";
1033
+
1034
+ // src/primitives/thread/index.ts
1035
+ var thread_exports = {};
1036
+ __export(thread_exports, {
1037
+ Empty: () => ThreadEmpty,
1038
+ If: () => ThreadIf,
1039
+ Messages: () => ThreadMessages,
1040
+ Root: () => ThreadRoot,
1041
+ ScrollToBottom: () => ThreadScrollToBottom,
1042
+ Suggestion: () => ThreadSuggestion,
1043
+ Viewport: () => ThreadViewport
1044
+ });
1045
+
1046
+ // src/primitives/thread/ThreadRoot.tsx
1047
+ var import_react_primitive10 = require("@radix-ui/react-primitive");
1048
+ var import_react33 = require("react");
1049
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1050
+ var ThreadRoot = (0, import_react33.forwardRef)(
1051
+ (props, ref) => {
1052
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_primitive10.Primitive.div, { ...props, ref });
1053
+ }
1054
+ );
1055
+ ThreadRoot.displayName = "ThreadRoot";
1056
+
1057
+ // src/primitives/thread/ThreadEmpty.tsx
1058
+ var ThreadEmpty = ({ children }) => {
1059
+ const empty = useThreadEmpty();
1060
+ return empty ? children : null;
1061
+ };
1062
+
1063
+ // src/primitives/thread/ThreadIf.tsx
1064
+ var ThreadIf = ({ children, ...query }) => {
1065
+ const result = useThreadIf(query);
1066
+ return result ? children : null;
1067
+ };
1068
+
1069
+ // src/primitives/thread/ThreadViewport.tsx
1070
+ var import_react_compose_refs3 = require("@radix-ui/react-compose-refs");
1071
+ var import_react_primitive11 = require("@radix-ui/react-primitive");
1072
+ var import_react38 = require("react");
1073
+
1074
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
1075
+ var import_react_compose_refs2 = require("@radix-ui/react-compose-refs");
1076
+ var import_react37 = require("react");
1077
+
1078
+ // src/utils/hooks/useOnResizeContent.tsx
1079
+ var import_react_use_callback_ref2 = require("@radix-ui/react-use-callback-ref");
1080
+ var import_react35 = require("react");
1081
+
1082
+ // src/utils/hooks/useManagedRef.ts
1083
+ var import_react34 = require("react");
1084
+ var useManagedRef = (callback) => {
1085
+ const cleanupRef = (0, import_react34.useRef)();
1086
+ const ref = (0, import_react34.useCallback)(
1087
+ (el) => {
1088
+ if (cleanupRef.current) {
1089
+ cleanupRef.current();
1090
+ }
1091
+ if (el) {
1092
+ cleanupRef.current = callback(el);
1093
+ }
1094
+ },
1095
+ [callback]
1096
+ );
1097
+ return ref;
1098
+ };
1099
+
1100
+ // src/utils/hooks/useOnResizeContent.tsx
1101
+ var useOnResizeContent = (callback) => {
1102
+ const callbackRef = (0, import_react_use_callback_ref2.useCallbackRef)(callback);
1103
+ const refCallback = (0, import_react35.useCallback)(
1104
+ (el) => {
1105
+ const resizeObserver = new ResizeObserver(() => {
1106
+ callbackRef();
1107
+ });
1108
+ const mutationObserver = new MutationObserver((mutations) => {
1109
+ for (const mutation of mutations) {
1110
+ for (const node of mutation.addedNodes) {
1111
+ if (node instanceof Element) {
1112
+ resizeObserver.observe(node);
1113
+ }
1114
+ }
1115
+ for (const node of mutation.removedNodes) {
1116
+ if (node instanceof Element) {
1117
+ resizeObserver.unobserve(node);
1118
+ }
1119
+ }
1120
+ }
1121
+ callbackRef();
1122
+ });
1123
+ resizeObserver.observe(el);
1124
+ mutationObserver.observe(el, { childList: true });
1125
+ for (const child of el.children) {
1126
+ resizeObserver.observe(child);
1127
+ }
1128
+ return () => {
1129
+ resizeObserver.disconnect();
1130
+ mutationObserver.disconnect();
1131
+ };
1132
+ },
1133
+ [callbackRef]
1134
+ );
1135
+ return useManagedRef(refCallback);
1136
+ };
1137
+
1138
+ // src/utils/hooks/useOnScrollToBottom.tsx
1139
+ var import_react_use_callback_ref3 = require("@radix-ui/react-use-callback-ref");
1140
+ var import_react36 = require("react");
1141
+ var useOnScrollToBottom = (callback) => {
1142
+ const callbackRef = (0, import_react_use_callback_ref3.useCallbackRef)(callback);
1143
+ const { useViewport } = useThreadContext();
1144
+ (0, import_react36.useEffect)(() => {
1145
+ return useViewport.getState().onScrollToBottom(() => {
1146
+ callbackRef();
1147
+ });
1148
+ }, [useViewport, callbackRef]);
1149
+ };
1150
+
1151
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
1152
+ var useThreadViewportAutoScroll = ({
1153
+ autoScroll = true
1154
+ }) => {
1155
+ const divRef = (0, import_react37.useRef)(null);
1156
+ const { useViewport } = useThreadContext();
1157
+ const firstRenderRef = (0, import_react37.useRef)(true);
1158
+ const lastScrollTop = (0, import_react37.useRef)(0);
1159
+ const isScrollingToBottomRef = (0, import_react37.useRef)(false);
1160
+ const scrollToBottom = () => {
1161
+ const div = divRef.current;
1162
+ if (!div || !autoScroll) return;
1163
+ const behavior = firstRenderRef.current ? "instant" : "auto";
1164
+ firstRenderRef.current = false;
1165
+ isScrollingToBottomRef.current = true;
1166
+ div.scrollTo({ top: div.scrollHeight, behavior });
1167
+ };
1168
+ const handleScroll = () => {
1169
+ const div = divRef.current;
1170
+ if (!div) return;
1171
+ const isAtBottom = useViewport.getState().isAtBottom;
1172
+ const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
1173
+ if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
1174
+ } else {
1175
+ isScrollingToBottomRef.current = newIsAtBottom;
1176
+ if (newIsAtBottom !== isAtBottom) {
1177
+ useViewport.setState({
1178
+ isAtBottom: newIsAtBottom
1179
+ });
1180
+ }
1181
+ }
1182
+ lastScrollTop.current = div.scrollTop;
1183
+ };
1184
+ const resizeRef = useOnResizeContent(() => {
1185
+ if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom && !firstRenderRef.current) {
1186
+ handleScroll();
1187
+ } else {
1188
+ scrollToBottom();
1189
+ }
1190
+ });
1191
+ const scrollRef = useManagedRef((el) => {
1192
+ el.addEventListener("scroll", handleScroll);
1193
+ return () => {
1194
+ el.removeEventListener("scroll", handleScroll);
1195
+ };
1196
+ });
1197
+ const autoScrollRef = (0, import_react_compose_refs2.useComposedRefs)(resizeRef, scrollRef, divRef);
1198
+ useOnScrollToBottom(() => {
1199
+ scrollToBottom();
1200
+ });
1201
+ return autoScrollRef;
1202
+ };
1203
+
1204
+ // src/primitives/thread/ThreadViewport.tsx
1205
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1206
+ var ThreadViewport = (0, import_react38.forwardRef)(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
1207
+ const autoScrollRef = useThreadViewportAutoScroll({
1208
+ autoScroll
1209
+ });
1210
+ const ref = (0, import_react_compose_refs3.useComposedRefs)(forwardedRef, autoScrollRef);
1211
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react_primitive11.Primitive.div, { ...rest, ref, children });
1212
+ });
1213
+ ThreadViewport.displayName = "ThreadViewport";
1214
+
1215
+ // src/primitives/thread/ThreadMessages.tsx
1216
+ var import_react40 = require("react");
1217
+
1218
+ // src/context/providers/MessageProvider.tsx
1219
+ var import_react39 = require("react");
1220
+ var import_zustand4 = require("zustand");
1221
+
1222
+ // src/context/stores/EditComposer.ts
1223
+ var import_zustand2 = require("zustand");
1224
+
1225
+ // src/context/stores/BaseComposer.ts
1226
+ var makeBaseComposer = (set) => ({
1227
+ value: "",
1228
+ setValue: (value) => {
1229
+ set({ value });
1230
+ }
1231
+ });
1232
+
1233
+ // src/context/stores/EditComposer.ts
1234
+ var makeEditComposerStore = ({
1235
+ onEdit,
1236
+ onSend
1237
+ }) => (0, import_zustand2.create)()((set, get, store) => ({
1238
+ ...makeBaseComposer(set, get, store),
1239
+ isEditing: false,
1240
+ edit: () => {
1241
+ const value = onEdit();
1242
+ set({ isEditing: true, value });
1243
+ },
1244
+ send: () => {
1245
+ const value = get().value;
1246
+ set({ isEditing: false });
1247
+ onSend(value);
1248
+ },
1249
+ cancel: () => {
1250
+ if (!get().isEditing) return false;
1251
+ set({ isEditing: false });
1252
+ return true;
1253
+ }
1254
+ }));
1255
+
1256
+ // src/context/stores/MessageUtils.ts
1257
+ var import_zustand3 = require("zustand");
1258
+ var makeMessageUtilsStore = () => (0, import_zustand3.create)((set) => ({
1259
+ inProgressIndicator: null,
1260
+ setInProgressIndicator: (value) => {
1261
+ set({ inProgressIndicator: value });
1262
+ },
1263
+ isCopied: false,
1264
+ setIsCopied: (value) => {
1265
+ set({ isCopied: value });
1266
+ },
1267
+ isHovering: false,
1268
+ setIsHovering: (value) => {
1269
+ set({ isHovering: value });
1270
+ }
1271
+ }));
1272
+
1273
+ // src/context/providers/MessageProvider.tsx
1274
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1275
+ var getIsLast = (thread, message) => {
1276
+ return thread.messages[thread.messages.length - 1]?.id === message.id;
1277
+ };
1278
+ var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
1279
+ const parentId = thread.messages[messageIndex - 1]?.id ?? null;
1280
+ const message = thread.messages[messageIndex];
1281
+ if (!message) return;
1282
+ const isLast = getIsLast(thread, message);
1283
+ const branches = getBranches(message.id);
1284
+ const currentState = useMessage.getState();
1285
+ if (currentState.message === message && currentState.parentId === parentId && currentState.branches === branches && currentState.isLast === isLast)
1286
+ return;
1287
+ useMessage.setState({
1288
+ message,
1289
+ parentId,
1290
+ branches,
1291
+ isLast
1292
+ });
1293
+ };
1294
+ var useMessageContext2 = (messageIndex) => {
1295
+ const { useThread, useThreadActions } = useThreadContext();
1296
+ const [context] = (0, import_react39.useState)(() => {
1297
+ const useMessage = (0, import_zustand4.create)(() => ({}));
1298
+ const useMessageUtils = makeMessageUtilsStore();
1299
+ const useEditComposer = makeEditComposerStore({
1300
+ onEdit: () => {
1301
+ const message = useMessage.getState().message;
1302
+ if (message.role !== "user")
1303
+ throw new Error(
1304
+ "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
1305
+ );
1306
+ const text = getMessageText(message);
1307
+ return text;
1308
+ },
1309
+ onSend: (text) => {
1310
+ const { message, parentId } = useMessage.getState();
1311
+ if (message.role !== "user")
1312
+ throw new Error(
1313
+ "Tried to edit a non-user message. Editing is only supported for user messages. This is likely an internal bug in assistant-ui."
1314
+ );
1315
+ const nonTextParts = message.content.filter(
1316
+ (part) => part.type !== "text" && part.type !== "ui"
1317
+ );
1318
+ useThreadActions.getState().append({
1319
+ parentId,
1320
+ role: "user",
1321
+ content: [{ type: "text", text }, ...nonTextParts]
1322
+ });
1323
+ }
1324
+ });
1325
+ syncMessage(
1326
+ useThread.getState(),
1327
+ useThreadActions.getState().getBranches,
1328
+ useMessage,
1329
+ messageIndex
1330
+ );
1331
+ return { useMessage, useMessageUtils, useEditComposer };
1332
+ });
1333
+ (0, import_react39.useEffect)(() => {
1334
+ return useThread.subscribe((thread) => {
1335
+ syncMessage(
1336
+ thread,
1337
+ useThreadActions.getState().getBranches,
1338
+ context.useMessage,
1339
+ messageIndex
1340
+ );
1341
+ });
1342
+ }, [useThread, useThreadActions, context, messageIndex]);
1343
+ return context;
1344
+ };
1345
+ var MessageProvider = ({
1346
+ messageIndex,
1347
+ children
1348
+ }) => {
1349
+ const context = useMessageContext2(messageIndex);
1350
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(MessageContext.Provider, { value: context, children });
1020
1351
  };
1021
1352
 
1022
- // src/primitives/contentPart/ContentPartText.tsx
1023
- var import_react_primitive6 = require("@radix-ui/react-primitive");
1024
- var import_react28 = require("react");
1025
- var import_jsx_runtime11 = require("react/jsx-runtime");
1026
- var ContentPartText = (0, import_react28.forwardRef)((props, forwardedRef) => {
1027
- const text = useContentPartText();
1028
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_react_primitive6.Primitive.span, { ...props, ref: forwardedRef, children: text });
1029
- });
1030
- ContentPartText.displayName = "ContentPartText";
1031
-
1032
- // src/primitives/message/MessageContent.tsx
1033
- var import_jsx_runtime12 = require("react/jsx-runtime");
1034
- var defaultComponents = {
1035
- Text: () => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1036
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartText, {}),
1037
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartInProgressIndicator, {})
1038
- ] }),
1039
- Image: () => null,
1040
- UI: () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartDisplay, {}),
1041
- tools: {
1042
- Fallback: (props) => {
1043
- const { useToolUIs } = useAssistantContext();
1044
- const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
1045
- if (!Render) return null;
1046
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Render, { ...props });
1047
- }
1048
- }
1049
- };
1050
- var MessageContentPartComponent = ({
1051
- components: {
1052
- Text = defaultComponents.Text,
1053
- Image = defaultComponents.Image,
1054
- UI = defaultComponents.UI,
1055
- tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
1056
- } = {}
1057
- }) => {
1058
- const { useThreadActions } = useThreadContext();
1059
- const addToolResult = useThreadActions((t) => t.addToolResult);
1060
- const { useContentPart } = useContentPartContext();
1061
- const { part, status } = useContentPart();
1062
- const type = part.type;
1063
- switch (type) {
1064
- case "text":
1065
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { part, status });
1066
- case "image":
1067
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Image, { part, status });
1068
- case "ui":
1069
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(UI, { part, status });
1070
- case "tool-call": {
1071
- const Tool = by_name[part.toolName] || Fallback;
1072
- const addResult = (result) => addToolResult(part.toolCallId, result);
1073
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Tool, { part, status, addResult });
1074
- }
1075
- default:
1076
- throw new Error(`Unknown content part type: ${type}`);
1077
- }
1353
+ // src/primitives/thread/ThreadMessages.tsx
1354
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1355
+ var getComponents = (components) => {
1356
+ return {
1357
+ EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
1358
+ UserMessage: components.UserMessage ?? components.Message,
1359
+ AssistantMessage: components.AssistantMessage ?? components.Message
1360
+ };
1078
1361
  };
1079
- var MessageContentPartImpl = ({
1080
- partIndex,
1362
+ var ThreadMessageImpl = ({
1363
+ messageIndex,
1081
1364
  components
1082
1365
  }) => {
1083
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ContentPartProvider, { partIndex, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MessageContentPartComponent, { components }) });
1366
+ const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
1367
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(MessageProvider, { messageIndex, children: [
1368
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(MessageIf, { user: true, children: [
1369
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ComposerIf, { editing: false, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(UserMessage, {}) }),
1370
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ComposerIf, { editing: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EditComposer, {}) })
1371
+ ] }),
1372
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MessageIf, { assistant: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantMessage, {}) })
1373
+ ] });
1084
1374
  };
1085
- var MessageContentPart = (0, import_react29.memo)(
1086
- MessageContentPartImpl,
1087
- (prev, next) => prev.partIndex === next.partIndex && prev.components?.Text === next.components?.Text && prev.components?.Image === next.components?.Image && prev.components?.UI === next.components?.UI && prev.components?.tools === next.components?.tools
1375
+ var ThreadMessage = (0, import_react40.memo)(
1376
+ ThreadMessageImpl,
1377
+ (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
1088
1378
  );
1089
- var MessageContent = ({ components }) => {
1090
- const { useMessage } = useMessageContext();
1091
- const contentLength = useMessage((s) => s.message.content.length);
1092
- return new Array(contentLength).fill(null).map((_, idx) => {
1093
- const partIndex = idx;
1094
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1095
- MessageContentPart,
1379
+ var ThreadMessages = ({ components }) => {
1380
+ const { useThread } = useThreadContext();
1381
+ const messagesLength = useThread((t) => t.messages.length);
1382
+ if (messagesLength === 0) return null;
1383
+ return new Array(messagesLength).fill(null).map((_, idx) => {
1384
+ const messageIndex = idx;
1385
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1386
+ ThreadMessage,
1096
1387
  {
1097
- partIndex,
1388
+ messageIndex,
1098
1389
  components
1099
1390
  },
1100
- partIndex
1391
+ messageIndex
1101
1392
  );
1102
1393
  });
1103
1394
  };
1104
1395
 
1105
- // src/primitives/message/MessageInProgress.tsx
1106
- var import_react_primitive7 = require("@radix-ui/react-primitive");
1107
- var import_react30 = require("react");
1108
- var import_jsx_runtime13 = require("react/jsx-runtime");
1109
- var MessageInProgress = (0, import_react30.forwardRef)((props, ref) => {
1110
- const { useMessageUtils } = useMessageContext();
1111
- (0, import_react30.useMemo)(() => {
1112
- useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_react_primitive7.Primitive.span, { ...props, ref }));
1113
- }, [useMessageUtils, props, ref]);
1114
- return null;
1115
- });
1116
- MessageInProgress.displayName = "MessageInProgress";
1117
-
1118
- // src/primitives/branchPicker/index.ts
1119
- var branchPicker_exports = {};
1120
- __export(branchPicker_exports, {
1121
- Count: () => BranchPickerCount,
1122
- Next: () => BranchPickerNext,
1123
- Number: () => BranchPickerNumber,
1124
- Previous: () => BranchPickerPrevious,
1125
- Root: () => BranchPickerRoot
1126
- });
1127
-
1128
- // src/primitives/branchPicker/BranchPickerNext.tsx
1129
- var BranchPickerNext = createActionButton(
1130
- "BranchPickerNext",
1131
- useBranchPickerNext
1132
- );
1133
-
1134
- // src/primitives/branchPicker/BranchPickerPrevious.tsx
1135
- var BranchPickerPrevious = createActionButton(
1136
- "BranchPickerPrevious",
1137
- useBranchPickerPrevious
1138
- );
1139
-
1140
- // src/primitives/branchPicker/BranchPickerCount.tsx
1141
- var import_jsx_runtime14 = require("react/jsx-runtime");
1142
- var BranchPickerCount = () => {
1143
- const branchCount = useBranchPickerCount();
1144
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, { children: branchCount });
1145
- };
1146
-
1147
- // src/primitives/branchPicker/BranchPickerNumber.tsx
1148
- var import_jsx_runtime15 = require("react/jsx-runtime");
1149
- var BranchPickerNumber = () => {
1150
- const branchNumber = useBranchPickerNumber();
1151
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_jsx_runtime15.Fragment, { children: branchNumber });
1152
- };
1153
-
1154
- // src/primitives/branchPicker/BranchPickerRoot.tsx
1155
- var import_react_primitive8 = require("@radix-ui/react-primitive");
1156
- var import_react31 = require("react");
1157
- var import_jsx_runtime16 = require("react/jsx-runtime");
1158
- var BranchPickerRoot = (0, import_react31.forwardRef)(({ hideWhenSingleBranch, ...rest }, ref) => {
1159
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react_primitive8.Primitive.div, { ...rest, ref }) });
1160
- });
1161
- BranchPickerRoot.displayName = "BranchPickerRoot";
1162
-
1163
- // src/primitives/actionBar/index.ts
1164
- var actionBar_exports = {};
1165
- __export(actionBar_exports, {
1166
- Copy: () => ActionBarCopy,
1167
- Edit: () => ActionBarEdit,
1168
- Reload: () => ActionBarReload,
1169
- Root: () => ActionBarRoot
1170
- });
1171
-
1172
- // src/primitives/actionBar/ActionBarRoot.tsx
1173
- var import_react_primitive9 = require("@radix-ui/react-primitive");
1174
- var import_react32 = require("react");
1175
- var import_jsx_runtime17 = require("react/jsx-runtime");
1176
- var useActionBarFloatStatus = ({
1177
- hideWhenRunning,
1178
- autohide,
1179
- autohideFloat
1180
- }) => {
1181
- const { useThread } = useThreadContext();
1182
- const { useMessage, useMessageUtils } = useMessageContext();
1183
- return useCombinedStore(
1184
- [useThread, useMessage, useMessageUtils],
1185
- (t, m, mu) => {
1186
- if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
1187
- const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
1188
- if (!autohideEnabled) return "normal" /* Normal */;
1189
- if (!mu.isHovering) return "hidden" /* Hidden */;
1190
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
1191
- return "floating" /* Floating */;
1192
- return "normal" /* Normal */;
1193
- }
1194
- );
1195
- };
1196
- var ActionBarRoot = (0, import_react32.forwardRef)(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1197
- const hideAndfloatStatus = useActionBarFloatStatus({
1198
- hideWhenRunning,
1199
- autohide,
1200
- autohideFloat
1201
- });
1202
- if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
1203
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1204
- import_react_primitive9.Primitive.div,
1205
- {
1206
- ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
1207
- ...rest,
1208
- ref
1209
- }
1210
- );
1211
- });
1212
- ActionBarRoot.displayName = "ActionBarRoot";
1213
-
1214
- // src/primitives/actionBar/ActionBarCopy.tsx
1215
- var ActionBarCopy = createActionButton(
1216
- "ActionBarCopy",
1217
- useActionBarCopy
1218
- );
1219
-
1220
- // src/primitives/actionBar/ActionBarReload.tsx
1221
- var ActionBarReload = createActionButton(
1222
- "ActionBarReload",
1223
- useActionBarReload
1396
+ // src/primitives/thread/ThreadScrollToBottom.tsx
1397
+ var ThreadScrollToBottom = createActionButton(
1398
+ "ThreadScrollToBottom",
1399
+ useThreadScrollToBottom
1224
1400
  );
1225
1401
 
1226
- // src/primitives/actionBar/ActionBarEdit.tsx
1227
- var ActionBarEdit = createActionButton(
1228
- "ActionBarEdit",
1229
- useActionBarEdit
1402
+ // src/primitives/thread/ThreadSuggestion.tsx
1403
+ var ThreadSuggestion = createActionButton(
1404
+ "ThreadSuggestion",
1405
+ useThreadSuggestion
1230
1406
  );
1231
1407
 
1232
- // src/primitives/contentPart/index.ts
1233
- var contentPart_exports = {};
1234
- __export(contentPart_exports, {
1235
- Display: () => ContentPartDisplay,
1236
- Image: () => ContentPartImage,
1237
- InProgressIndicator: () => ContentPartInProgressIndicator,
1238
- Text: () => ContentPartText
1239
- });
1240
-
1241
- // src/primitives/contentPart/ContentPartImage.tsx
1242
- var import_react_primitive10 = require("@radix-ui/react-primitive");
1243
- var import_react33 = require("react");
1244
- var import_jsx_runtime18 = require("react/jsx-runtime");
1245
- var ContentPartImage = (0, import_react33.forwardRef)((props, forwardedRef) => {
1246
- const image = useContentPartImage();
1247
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react_primitive10.Primitive.img, { src: image, ...props, ref: forwardedRef });
1248
- });
1249
- ContentPartImage.displayName = "ContentPartImage";
1250
-
1251
1408
  // src/runtime/local/useLocalRuntime.tsx
1252
- var import_react34 = require("react");
1409
+ var import_react41 = require("react");
1253
1410
 
1254
1411
  // src/utils/ModelConfigTypes.ts
1255
1412
  var mergeModelConfigs = (configSet) => {
@@ -1535,18 +1692,18 @@ var LocalRuntime = class {
1535
1692
 
1536
1693
  // src/runtime/local/useLocalRuntime.tsx
1537
1694
  var useLocalRuntime = (adapter) => {
1538
- const [runtime] = (0, import_react34.useState)(() => new LocalRuntime(adapter));
1539
- (0, import_react34.useInsertionEffect)(() => {
1695
+ const [runtime] = (0, import_react41.useState)(() => new LocalRuntime(adapter));
1696
+ (0, import_react41.useInsertionEffect)(() => {
1540
1697
  runtime.adapter = adapter;
1541
1698
  });
1542
1699
  return runtime;
1543
1700
  };
1544
1701
 
1545
1702
  // src/context/providers/AssistantRuntimeProvider.tsx
1546
- var import_react37 = require("react");
1703
+ var import_react44 = require("react");
1547
1704
 
1548
1705
  // src/context/providers/AssistantProvider.tsx
1549
- var import_react36 = require("react");
1706
+ var import_react43 = require("react");
1550
1707
 
1551
1708
  // src/context/stores/AssistantModelConfig.ts
1552
1709
  var import_zustand5 = require("zustand");
@@ -1611,30 +1768,45 @@ var makeAssistantToolUIsStore = () => (0, import_zustand6.create)((set) => {
1611
1768
  });
1612
1769
 
1613
1770
  // src/context/providers/ThreadProvider.tsx
1614
- var import_react35 = require("react");
1771
+ var import_react42 = require("react");
1615
1772
 
1616
1773
  // src/context/stores/Composer.ts
1617
1774
  var import_zustand7 = require("zustand");
1618
- var makeComposerStore = (useThread, useThreadActions) => (0, import_zustand7.create)()((set, get, store) => {
1619
- return {
1620
- ...makeBaseComposer(set, get, store),
1621
- isEditing: true,
1622
- send: () => {
1623
- const { setValue, value } = get();
1624
- setValue("");
1625
- useThreadActions.getState().append({
1626
- parentId: useThread.getState().messages.at(-1)?.id ?? null,
1627
- content: [{ type: "text", text: value }]
1628
- });
1629
- },
1630
- cancel: () => {
1631
- const thread = useThread.getState();
1632
- if (!thread.isRunning) return false;
1633
- useThreadActions.getState().cancelRun();
1634
- return true;
1635
- }
1636
- };
1637
- });
1775
+ var makeComposerStore = (useThread, useThreadActions) => {
1776
+ const focusListeners = /* @__PURE__ */ new Set();
1777
+ return (0, import_zustand7.create)()((set, get, store) => {
1778
+ return {
1779
+ ...makeBaseComposer(set, get, store),
1780
+ isEditing: true,
1781
+ send: () => {
1782
+ const { setValue, value } = get();
1783
+ setValue("");
1784
+ useThreadActions.getState().append({
1785
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
1786
+ role: "user",
1787
+ content: [{ type: "text", text: value }]
1788
+ });
1789
+ },
1790
+ cancel: () => {
1791
+ const thread = useThread.getState();
1792
+ if (!thread.isRunning) return false;
1793
+ useThreadActions.getState().cancelRun();
1794
+ return true;
1795
+ },
1796
+ focus: () => {
1797
+ for (const listener of focusListeners) {
1798
+ listener();
1799
+ }
1800
+ },
1801
+ onFocus: (listener) => {
1802
+ focusListeners.add(listener);
1803
+ return () => {
1804
+ focusListeners.delete(listener);
1805
+ };
1806
+ }
1807
+ };
1808
+ });
1809
+ };
1638
1810
 
1639
1811
  // src/context/stores/Thread.ts
1640
1812
  var import_zustand8 = require("zustand");
@@ -1681,16 +1853,16 @@ var makeThreadActionStore = (runtimeRef) => {
1681
1853
  };
1682
1854
 
1683
1855
  // src/context/providers/ThreadProvider.tsx
1684
- var import_jsx_runtime19 = require("react/jsx-runtime");
1856
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1685
1857
  var ThreadProvider = ({
1686
1858
  children,
1687
1859
  runtime
1688
1860
  }) => {
1689
- const runtimeRef = (0, import_react35.useRef)(runtime);
1690
- (0, import_react35.useInsertionEffect)(() => {
1861
+ const runtimeRef = (0, import_react42.useRef)(runtime);
1862
+ (0, import_react42.useInsertionEffect)(() => {
1691
1863
  runtimeRef.current = runtime;
1692
1864
  });
1693
- const [context] = (0, import_react35.useState)(() => {
1865
+ const [context] = (0, import_react42.useState)(() => {
1694
1866
  const useThread = makeThreadStore(runtimeRef);
1695
1867
  const useThreadActions = makeThreadActionStore(runtimeRef);
1696
1868
  const useViewport = makeThreadViewportStore();
@@ -1702,7 +1874,7 @@ var ThreadProvider = ({
1702
1874
  useViewport
1703
1875
  };
1704
1876
  });
1705
- (0, import_react35.useEffect)(() => {
1877
+ (0, import_react42.useEffect)(() => {
1706
1878
  const onRuntimeUpdate = () => {
1707
1879
  context.useThread.setState(
1708
1880
  Object.freeze({
@@ -1716,37 +1888,37 @@ var ThreadProvider = ({
1716
1888
  return runtime.subscribe(onRuntimeUpdate);
1717
1889
  }, [context, runtime]);
1718
1890
  const RuntimeSynchronizer = runtime.unstable_synchronizer;
1719
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(ThreadContext.Provider, { value: context, children: [
1720
- RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(RuntimeSynchronizer, {}),
1891
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(ThreadContext.Provider, { value: context, children: [
1892
+ RuntimeSynchronizer && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(RuntimeSynchronizer, {}),
1721
1893
  children
1722
1894
  ] });
1723
1895
  };
1724
1896
 
1725
1897
  // src/context/providers/AssistantProvider.tsx
1726
- var import_jsx_runtime20 = require("react/jsx-runtime");
1898
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1727
1899
  var AssistantProvider = ({ children, runtime }) => {
1728
- const runtimeRef = (0, import_react36.useRef)(runtime);
1729
- (0, import_react36.useInsertionEffect)(() => {
1900
+ const runtimeRef = (0, import_react43.useRef)(runtime);
1901
+ (0, import_react43.useInsertionEffect)(() => {
1730
1902
  runtimeRef.current = runtime;
1731
1903
  });
1732
- const [context] = (0, import_react36.useState)(() => {
1904
+ const [context] = (0, import_react43.useState)(() => {
1733
1905
  const useModelConfig = makeAssistantModelConfigStore();
1734
1906
  const useToolUIs = makeAssistantToolUIsStore();
1735
1907
  return { useModelConfig, useToolUIs };
1736
1908
  });
1737
1909
  const getModelCOnfig = context.useModelConfig((c) => c.getModelConfig);
1738
- (0, import_react36.useEffect)(() => {
1910
+ (0, import_react43.useEffect)(() => {
1739
1911
  return runtime.registerModelConfigProvider(getModelCOnfig);
1740
1912
  }, [runtime, getModelCOnfig]);
1741
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ThreadProvider, { runtime, children }) });
1913
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThreadProvider, { runtime, children }) });
1742
1914
  };
1743
1915
 
1744
1916
  // src/context/providers/AssistantRuntimeProvider.tsx
1745
- var import_jsx_runtime21 = require("react/jsx-runtime");
1917
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1746
1918
  var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1747
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(AssistantProvider, { runtime, children });
1919
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(AssistantProvider, { runtime, children });
1748
1920
  };
1749
- var AssistantRuntimeProvider = (0, import_react37.memo)(AssistantRuntimeProviderImpl);
1921
+ var AssistantRuntimeProvider = (0, import_react44.memo)(AssistantRuntimeProviderImpl);
1750
1922
 
1751
1923
  // src/internal.ts
1752
1924
  var internal_exports = {};
@@ -1757,6 +1929,7 @@ __export(internal_exports, {
1757
1929
  // Annotate the CommonJS export names for ESM import in node:
1758
1930
  0 && (module.exports = {
1759
1931
  ActionBarPrimitive,
1932
+ AssistantModalPrimitive,
1760
1933
  AssistantRuntimeProvider,
1761
1934
  BranchPickerPrimitive,
1762
1935
  ComposerPrimitive,