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