@assistant-ui/react 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -91,7 +91,7 @@ var useActionBarEdit = () => {
91
91
  // src/primitive-hooks/actionBar/useActionBarReload.tsx
92
92
  import { useCallback as useCallback3 } from "react";
93
93
  var useActionBarReload = () => {
94
- const { useThread, useThreadActions, useViewport } = useThreadContext();
94
+ const { useThread, useThreadActions, useComposer, useViewport } = useThreadContext();
95
95
  const { useMessage } = useMessageContext();
96
96
  const disabled = useCombinedStore(
97
97
  [useThread, useMessage],
@@ -101,7 +101,8 @@ var useActionBarReload = () => {
101
101
  const { parentId } = useMessage.getState();
102
102
  useThreadActions.getState().startRun(parentId);
103
103
  useViewport.getState().scrollToBottom();
104
- }, [useThreadActions, useMessage, useViewport]);
104
+ useComposer.getState().focus();
105
+ }, [useThreadActions, useComposer, useViewport, useMessage]);
105
106
  if (disabled) return null;
106
107
  return callback;
107
108
  };
@@ -180,12 +181,16 @@ var useComposerIf = (props) => {
180
181
  // src/primitive-hooks/composer/useComposerSend.tsx
181
182
  import { useCallback as useCallback7 } from "react";
182
183
  var useComposerSend = () => {
184
+ const { useViewport, useComposer: useNewComposer } = useThreadContext();
183
185
  const { useComposer } = useComposerContext();
184
186
  const disabled = useComposer((c) => !c.isEditing || c.value.length === 0);
185
187
  const callback = useCallback7(() => {
186
- const { send } = useComposer.getState();
187
- send();
188
- }, [useComposer]);
188
+ const composerState = useComposer.getState();
189
+ if (!composerState.isEditing) return;
190
+ composerState.send();
191
+ useViewport.getState().scrollToBottom();
192
+ useNewComposer.getState().focus();
193
+ }, [useNewComposer, useComposer, useViewport]);
189
194
  if (disabled) return null;
190
195
  return callback;
191
196
  };
@@ -277,12 +282,12 @@ var useThreadEmpty = () => {
277
282
  // src/primitive-hooks/thread/useThreadScrollToBottom.tsx
278
283
  import { useCallback as useCallback8 } from "react";
279
284
  var useThreadScrollToBottom = () => {
280
- const { useViewport } = useThreadContext();
285
+ const { useComposer, useViewport } = useThreadContext();
281
286
  const isAtBottom = useViewport((s) => s.isAtBottom);
282
287
  const handleScrollToBottom = useCallback8(() => {
283
- const { scrollToBottom } = useViewport.getState();
284
- scrollToBottom();
285
- }, [useViewport]);
288
+ useViewport.getState().scrollToBottom();
289
+ useComposer.getState().focus();
290
+ }, [useViewport, useComposer]);
286
291
  if (isAtBottom) return null;
287
292
  return handleScrollToBottom;
288
293
  };
@@ -307,225 +312,862 @@ var useThreadSuggestion = ({
307
312
  return callback;
308
313
  };
309
314
 
310
- // src/primitives/thread/index.ts
311
- var thread_exports = {};
312
- __export(thread_exports, {
313
- Empty: () => ThreadEmpty,
314
- If: () => ThreadIf,
315
- Messages: () => ThreadMessages,
316
- Root: () => ThreadRoot,
317
- ScrollToBottom: () => ThreadScrollToBottom,
318
- Suggestion: () => ThreadSuggestion,
319
- Viewport: () => ThreadViewport
315
+ // src/primitives/actionBar/index.ts
316
+ var actionBar_exports = {};
317
+ __export(actionBar_exports, {
318
+ Copy: () => ActionBarCopy,
319
+ Edit: () => ActionBarEdit,
320
+ Reload: () => ActionBarReload,
321
+ Root: () => ActionBarRoot
320
322
  });
321
323
 
322
- // src/primitives/thread/ThreadRoot.tsx
324
+ // src/primitives/actionBar/ActionBarRoot.tsx
323
325
  import { Primitive } from "@radix-ui/react-primitive";
324
326
  import { forwardRef } from "react";
325
327
  import { jsx } from "react/jsx-runtime";
326
- var ThreadRoot = forwardRef(
327
- (props, ref) => {
328
- return /* @__PURE__ */ jsx(Primitive.div, { ...props, ref });
329
- }
330
- );
331
- ThreadRoot.displayName = "ThreadRoot";
332
-
333
- // src/primitives/thread/ThreadIf.tsx
334
- var ThreadIf = ({ children, ...query }) => {
335
- const result = useThreadIf(query);
336
- return result ? children : null;
328
+ var useActionBarFloatStatus = ({
329
+ hideWhenRunning,
330
+ autohide,
331
+ autohideFloat
332
+ }) => {
333
+ const { useThread } = useThreadContext();
334
+ const { useMessage, useMessageUtils } = useMessageContext();
335
+ return useCombinedStore(
336
+ [useThread, useMessage, useMessageUtils],
337
+ (t, m, mu) => {
338
+ if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
339
+ const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
340
+ if (!autohideEnabled) return "normal" /* Normal */;
341
+ if (!mu.isHovering) return "hidden" /* Hidden */;
342
+ if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
343
+ return "floating" /* Floating */;
344
+ return "normal" /* Normal */;
345
+ }
346
+ );
337
347
  };
348
+ var ActionBarRoot = forwardRef(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
349
+ const hideAndfloatStatus = useActionBarFloatStatus({
350
+ hideWhenRunning,
351
+ autohide,
352
+ autohideFloat
353
+ });
354
+ if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
355
+ return /* @__PURE__ */ jsx(
356
+ Primitive.div,
357
+ {
358
+ ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
359
+ ...rest,
360
+ ref
361
+ }
362
+ );
363
+ });
364
+ ActionBarRoot.displayName = "ActionBarRoot";
338
365
 
339
- // src/primitives/thread/ThreadEmpty.tsx
366
+ // src/utils/createActionButton.tsx
367
+ import { composeEventHandlers } from "@radix-ui/primitive";
368
+ import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
369
+ import { forwardRef as forwardRef2 } from "react";
340
370
  import { jsx as jsx2 } from "react/jsx-runtime";
341
- var ThreadEmpty = ({ children }) => {
342
- return /* @__PURE__ */ jsx2(ThreadIf, { empty: true, children });
371
+ var createActionButton = (displayName, useActionButton) => {
372
+ const ActionButton = forwardRef2((props, forwardedRef) => {
373
+ const callback = useActionButton(props);
374
+ return /* @__PURE__ */ jsx2(
375
+ Primitive2.button,
376
+ {
377
+ type: "button",
378
+ disabled: !callback,
379
+ ...props,
380
+ ref: forwardedRef,
381
+ onClick: composeEventHandlers(props.onClick, () => {
382
+ callback?.();
383
+ })
384
+ }
385
+ );
386
+ });
387
+ ActionButton.displayName = displayName;
388
+ return ActionButton;
343
389
  };
344
390
 
345
- // src/primitives/thread/ThreadViewport.tsx
346
- import { composeEventHandlers } from "@radix-ui/primitive";
347
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
348
- import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
349
- import {
350
- forwardRef as forwardRef2,
351
- useRef
352
- } from "react";
391
+ // src/primitives/actionBar/ActionBarCopy.tsx
392
+ var ActionBarCopy = createActionButton(
393
+ "ActionBarCopy",
394
+ useActionBarCopy
395
+ );
353
396
 
354
- // src/utils/hooks/useOnResizeContent.tsx
397
+ // src/primitives/actionBar/ActionBarReload.tsx
398
+ var ActionBarReload = createActionButton(
399
+ "ActionBarReload",
400
+ useActionBarReload
401
+ );
402
+
403
+ // src/primitives/actionBar/ActionBarEdit.tsx
404
+ var ActionBarEdit = createActionButton(
405
+ "ActionBarEdit",
406
+ useActionBarEdit
407
+ );
408
+
409
+ // src/primitives/assistantModal/index.ts
410
+ var assistantModal_exports = {};
411
+ __export(assistantModal_exports, {
412
+ Content: () => AssistantModalContent,
413
+ Root: () => AssistantModalRoot,
414
+ Trigger: () => AssistantModalTrigger
415
+ });
416
+
417
+ // src/primitives/assistantModal/AssistantModalRoot.tsx
418
+ import { useState } from "react";
419
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
420
+ import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
421
+
422
+ // src/utils/hooks/useOnComposerFocus.tsx
355
423
  import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
356
424
  import { useEffect } from "react";
357
- var useOnResizeContent = (ref, callback) => {
425
+ var useOnComposerFocus = (callback) => {
358
426
  const callbackRef = useCallbackRef(callback);
427
+ const { useComposer } = useThreadContext();
359
428
  useEffect(() => {
360
- const el = ref.current;
361
- if (!el) return;
362
- const resizeObserver = new ResizeObserver(() => {
363
- callbackRef();
364
- });
365
- const mutationObserver = new MutationObserver((mutations) => {
366
- for (const mutation of mutations) {
367
- for (const node of mutation.addedNodes) {
368
- if (node instanceof Element) {
369
- resizeObserver.observe(node);
370
- }
371
- }
372
- for (const node of mutation.removedNodes) {
373
- if (node instanceof Element) {
374
- resizeObserver.unobserve(node);
375
- }
376
- }
377
- }
378
- callbackRef();
379
- });
380
- resizeObserver.observe(el);
381
- mutationObserver.observe(el, { childList: true });
382
- for (const child of el.children) {
383
- resizeObserver.observe(child);
384
- }
385
- return () => {
386
- resizeObserver.disconnect();
387
- mutationObserver.disconnect();
388
- };
389
- }, [ref, callbackRef]);
390
- };
391
-
392
- // src/utils/hooks/useOnScrollToBottom.tsx
393
- import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
394
- import { useEffect as useEffect2 } from "react";
395
- var useOnScrollToBottom = (callback) => {
396
- const callbackRef = useCallbackRef2(callback);
397
- const { useViewport } = useThreadContext();
398
- useEffect2(() => {
399
- return useViewport.getState().onScrollToBottom(() => {
429
+ return useComposer.getState().onFocus(() => {
400
430
  callbackRef();
401
431
  });
402
- }, [useViewport, callbackRef]);
432
+ }, [useComposer, callbackRef]);
403
433
  };
404
434
 
405
- // src/primitives/thread/ThreadViewport.tsx
406
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
407
- var ThreadViewport = forwardRef2(({ autoScroll = true, onScroll, children, ...rest }, forwardedRef) => {
408
- const messagesEndRef = useRef(null);
409
- const divRef = useRef(null);
410
- const ref = useComposedRefs(forwardedRef, divRef);
411
- const { useViewport } = useThreadContext();
412
- const firstRenderRef = useRef(true);
413
- const isScrollingToBottomRef = useRef(false);
414
- const lastScrollTop = useRef(0);
415
- const scrollToBottom = () => {
416
- const div = messagesEndRef.current;
417
- if (!div || !autoScroll) return;
418
- const behavior = firstRenderRef.current ? "instant" : "auto";
419
- firstRenderRef.current = false;
420
- isScrollingToBottomRef.current = true;
421
- div.scrollIntoView({ behavior });
422
- };
423
- useOnResizeContent(divRef, () => {
424
- if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom) {
425
- handleScroll();
426
- } else {
427
- scrollToBottom();
428
- }
435
+ // src/primitives/assistantModal/AssistantModalRoot.tsx
436
+ import { jsx as jsx3 } from "react/jsx-runtime";
437
+ var usePopoverScope = PopoverPrimitive.createPopoverScope();
438
+ var useAssistantModalOpenState = (defaultOpen = false) => {
439
+ const state = useState(defaultOpen);
440
+ const [, setOpen] = state;
441
+ useOnComposerFocus(() => {
442
+ setOpen(true);
429
443
  });
430
- useOnScrollToBottom(() => {
431
- scrollToBottom();
432
- });
433
- const handleScroll = () => {
434
- const div = divRef.current;
435
- if (!div) return;
436
- const isAtBottom = useViewport.getState().isAtBottom;
437
- const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
438
- if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
439
- } else if (newIsAtBottom !== isAtBottom) {
440
- isScrollingToBottomRef.current = false;
441
- useViewport.setState({
442
- isAtBottom: newIsAtBottom
443
- });
444
- }
445
- lastScrollTop.current = div.scrollTop;
446
- };
447
- return /* @__PURE__ */ jsxs(
448
- Primitive2.div,
444
+ return state;
445
+ };
446
+ var AssistantModalRoot = ({
447
+ __scopeAssistantModal,
448
+ defaultOpen,
449
+ open,
450
+ onOpenChange,
451
+ ...rest
452
+ }) => {
453
+ const scope = usePopoverScope(__scopeAssistantModal);
454
+ const [modalOpen, setOpen] = useAssistantModalOpenState(defaultOpen);
455
+ return /* @__PURE__ */ jsx3(
456
+ PopoverPrimitive.Root,
449
457
  {
450
- ...rest,
451
- onScroll: composeEventHandlers(onScroll, handleScroll),
452
- ref,
453
- children: [
454
- children,
455
- /* @__PURE__ */ jsx3("div", { ref: messagesEndRef })
456
- ]
458
+ ...scope,
459
+ open: open === void 0 ? modalOpen : open,
460
+ onOpenChange: composeEventHandlers2(onOpenChange, setOpen),
461
+ ...rest
457
462
  }
458
463
  );
459
- });
460
- ThreadViewport.displayName = "ThreadViewport";
461
-
462
- // src/primitives/thread/ThreadMessages.tsx
463
- import { memo } from "react";
464
-
465
- // src/context/providers/MessageProvider.tsx
466
- import { useEffect as useEffect3, useState } from "react";
467
- import { create as create3 } from "zustand";
464
+ };
465
+ AssistantModalRoot.displayName = "AssistantModalRoot";
468
466
 
469
- // src/context/stores/EditComposer.ts
470
- import { create } from "zustand";
467
+ // src/primitives/assistantModal/AssistantModalTrigger.tsx
468
+ import { forwardRef as forwardRef3 } from "react";
469
+ import * as PopoverPrimitive2 from "@radix-ui/react-popover";
470
+ import { jsx as jsx4 } from "react/jsx-runtime";
471
+ var AssistantModalTrigger = forwardRef3(
472
+ ({ __scopeAssistantModal, ...rest }, ref) => {
473
+ const scope = usePopoverScope(__scopeAssistantModal);
474
+ return /* @__PURE__ */ jsx4(PopoverPrimitive2.Trigger, { ...scope, ...rest, ref });
475
+ }
476
+ );
477
+ AssistantModalTrigger.displayName = "AssistantModalTrigger";
471
478
 
472
- // src/context/stores/BaseComposer.ts
473
- var makeBaseComposer = (set) => ({
474
- value: "",
475
- setValue: (value) => {
476
- set({ value });
479
+ // src/primitives/assistantModal/AssistantModalContent.tsx
480
+ import { forwardRef as forwardRef4 } from "react";
481
+ import * as PopoverPrimitive3 from "@radix-ui/react-popover";
482
+ import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
483
+ import { jsx as jsx5 } from "react/jsx-runtime";
484
+ var AssistantModalContent = forwardRef4(
485
+ ({
486
+ __scopeAssistantModal,
487
+ side,
488
+ align,
489
+ onInteractOutside,
490
+ dissmissOnInteractOutside = false,
491
+ ...props
492
+ }, forwardedRef) => {
493
+ const scope = usePopoverScope(__scopeAssistantModal);
494
+ return /* @__PURE__ */ jsx5(PopoverPrimitive3.Portal, { ...scope, children: /* @__PURE__ */ jsx5(
495
+ PopoverPrimitive3.Content,
496
+ {
497
+ ...scope,
498
+ ...props,
499
+ ref: forwardedRef,
500
+ side: side ?? "top",
501
+ align: align ?? "end",
502
+ onInteractOutside: composeEventHandlers3(
503
+ onInteractOutside,
504
+ dissmissOnInteractOutside ? void 0 : (e) => e.preventDefault()
505
+ )
506
+ }
507
+ ) });
477
508
  }
509
+ );
510
+ AssistantModalContent.displayName = "AssistantModalContent";
511
+
512
+ // src/primitives/branchPicker/index.ts
513
+ var branchPicker_exports = {};
514
+ __export(branchPicker_exports, {
515
+ Count: () => BranchPickerCount,
516
+ Next: () => BranchPickerNext,
517
+ Number: () => BranchPickerNumber,
518
+ Previous: () => BranchPickerPrevious,
519
+ Root: () => BranchPickerRoot
478
520
  });
479
521
 
480
- // src/context/stores/EditComposer.ts
481
- var makeEditComposerStore = ({
482
- onEdit,
483
- onSend
484
- }) => create()((set, get, store) => ({
485
- ...makeBaseComposer(set, get, store),
486
- isEditing: false,
487
- edit: () => {
488
- const value = onEdit();
489
- set({ isEditing: true, value });
490
- },
491
- send: () => {
492
- const value = get().value;
493
- set({ isEditing: false });
494
- onSend(value);
495
- },
496
- cancel: () => {
497
- if (!get().isEditing) return false;
498
- set({ isEditing: false });
499
- return true;
500
- }
501
- }));
522
+ // src/primitives/branchPicker/BranchPickerNext.tsx
523
+ var BranchPickerNext = createActionButton(
524
+ "BranchPickerNext",
525
+ useBranchPickerNext
526
+ );
502
527
 
503
- // src/context/stores/MessageUtils.ts
504
- import { create as create2 } from "zustand";
505
- var makeMessageUtilsStore = () => create2((set) => ({
506
- inProgressIndicator: null,
507
- setInProgressIndicator: (value) => {
508
- set({ inProgressIndicator: value });
509
- },
510
- isCopied: false,
511
- setIsCopied: (value) => {
512
- set({ isCopied: value });
513
- },
514
- isHovering: false,
515
- setIsHovering: (value) => {
516
- set({ isHovering: value });
517
- }
518
- }));
528
+ // src/primitives/branchPicker/BranchPickerPrevious.tsx
529
+ var BranchPickerPrevious = createActionButton(
530
+ "BranchPickerPrevious",
531
+ useBranchPickerPrevious
532
+ );
519
533
 
520
- // src/context/providers/MessageProvider.tsx
521
- import { jsx as jsx4 } from "react/jsx-runtime";
522
- var getIsLast = (thread, message) => {
523
- return thread.messages[thread.messages.length - 1]?.id === message.id;
534
+ // src/primitives/branchPicker/BranchPickerCount.tsx
535
+ import { Fragment, jsx as jsx6 } from "react/jsx-runtime";
536
+ var BranchPickerCount = () => {
537
+ const branchCount = useBranchPickerCount();
538
+ return /* @__PURE__ */ jsx6(Fragment, { children: branchCount });
524
539
  };
525
- var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
526
- const parentId = thread.messages[messageIndex - 1]?.id ?? null;
527
- const message = thread.messages[messageIndex];
528
- if (!message) return;
540
+
541
+ // src/primitives/branchPicker/BranchPickerNumber.tsx
542
+ import { Fragment as Fragment2, jsx as jsx7 } from "react/jsx-runtime";
543
+ var BranchPickerNumber = () => {
544
+ const branchNumber = useBranchPickerNumber();
545
+ return /* @__PURE__ */ jsx7(Fragment2, { children: branchNumber });
546
+ };
547
+
548
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
549
+ import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
550
+ import { forwardRef as forwardRef8 } from "react";
551
+
552
+ // src/primitives/message/index.ts
553
+ var message_exports = {};
554
+ __export(message_exports, {
555
+ Content: () => MessageContent,
556
+ If: () => MessageIf,
557
+ InProgress: () => MessageInProgress,
558
+ Root: () => MessageRoot
559
+ });
560
+
561
+ // src/primitives/message/MessageRoot.tsx
562
+ import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
563
+ import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
564
+ import { forwardRef as forwardRef5 } from "react";
565
+ import { jsx as jsx8 } from "react/jsx-runtime";
566
+ var MessageRoot = forwardRef5(
567
+ ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
568
+ const { useMessageUtils } = useMessageContext();
569
+ const setIsHovering = useMessageUtils((s) => s.setIsHovering);
570
+ const handleMouseEnter = () => {
571
+ setIsHovering(true);
572
+ };
573
+ const handleMouseLeave = () => {
574
+ setIsHovering(false);
575
+ };
576
+ return /* @__PURE__ */ jsx8(
577
+ Primitive3.div,
578
+ {
579
+ ...rest,
580
+ ref,
581
+ onMouseEnter: composeEventHandlers4(onMouseEnter, handleMouseEnter),
582
+ onMouseLeave: composeEventHandlers4(onMouseLeave, handleMouseLeave)
583
+ }
584
+ );
585
+ }
586
+ );
587
+ MessageRoot.displayName = "MessageRoot";
588
+
589
+ // src/primitives/message/MessageIf.tsx
590
+ var MessageIf = ({ children, ...query }) => {
591
+ const result = useMessageIf(query);
592
+ return result ? children : null;
593
+ };
594
+
595
+ // src/primitives/message/MessageContent.tsx
596
+ import { memo } from "react";
597
+
598
+ // src/context/providers/ContentPartProvider.tsx
599
+ import { useEffect as useEffect2, useState as useState2 } from "react";
600
+ import { create } from "zustand";
601
+ import { jsx as jsx9 } from "react/jsx-runtime";
602
+ var syncContentPart = ({ message }, useContentPart, partIndex) => {
603
+ const part = message.content[partIndex];
604
+ if (!part) return;
605
+ const messageStatus = message.role === "assistant" ? message.status : "done";
606
+ const status = partIndex === message.content.length - 1 ? messageStatus : "done";
607
+ const currentState = useContentPart.getState();
608
+ if (currentState.part === part && currentState.status === status) return;
609
+ useContentPart.setState(
610
+ Object.freeze({
611
+ part,
612
+ status
613
+ })
614
+ );
615
+ };
616
+ var useContentPartContext2 = (partIndex) => {
617
+ const { useMessage } = useMessageContext();
618
+ const [context] = useState2(() => {
619
+ const useContentPart = create(
620
+ () => ({})
621
+ );
622
+ syncContentPart(useMessage.getState(), useContentPart, partIndex);
623
+ return { useContentPart };
624
+ });
625
+ useEffect2(() => {
626
+ syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
627
+ return useMessage.subscribe((message) => {
628
+ syncContentPart(message, context.useContentPart, partIndex);
629
+ });
630
+ }, [context, useMessage, partIndex]);
631
+ return context;
632
+ };
633
+ var ContentPartProvider = ({
634
+ partIndex,
635
+ children
636
+ }) => {
637
+ const context = useContentPartContext2(partIndex);
638
+ return /* @__PURE__ */ jsx9(ContentPartContext.Provider, { value: context, children });
639
+ };
640
+
641
+ // src/primitives/contentPart/ContentPartDisplay.tsx
642
+ var ContentPartDisplay = () => {
643
+ const display = useContentPartDisplay();
644
+ return display ?? null;
645
+ };
646
+
647
+ // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
648
+ var ContentPartInProgressIndicator = () => {
649
+ const indicator = useContentPartInProgressIndicator();
650
+ return indicator;
651
+ };
652
+
653
+ // src/primitives/contentPart/ContentPartText.tsx
654
+ import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
655
+ import { forwardRef as forwardRef6 } from "react";
656
+ import { jsx as jsx10 } from "react/jsx-runtime";
657
+ var ContentPartText = forwardRef6((props, forwardedRef) => {
658
+ const text = useContentPartText();
659
+ return /* @__PURE__ */ jsx10(Primitive4.span, { ...props, ref: forwardedRef, children: text });
660
+ });
661
+ ContentPartText.displayName = "ContentPartText";
662
+
663
+ // src/primitives/message/MessageContent.tsx
664
+ import { Fragment as Fragment3, jsx as jsx11, jsxs } from "react/jsx-runtime";
665
+ var defaultComponents = {
666
+ Text: () => /* @__PURE__ */ jsxs(Fragment3, { children: [
667
+ /* @__PURE__ */ jsx11(ContentPartText, {}),
668
+ /* @__PURE__ */ jsx11(ContentPartInProgressIndicator, {})
669
+ ] }),
670
+ Image: () => null,
671
+ UI: () => /* @__PURE__ */ jsx11(ContentPartDisplay, {}),
672
+ tools: {
673
+ Fallback: (props) => {
674
+ const { useToolUIs } = useAssistantContext();
675
+ const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
676
+ if (!Render) return null;
677
+ return /* @__PURE__ */ jsx11(Render, { ...props });
678
+ }
679
+ }
680
+ };
681
+ var MessageContentPartComponent = ({
682
+ components: {
683
+ Text = defaultComponents.Text,
684
+ Image = defaultComponents.Image,
685
+ UI = defaultComponents.UI,
686
+ tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
687
+ } = {}
688
+ }) => {
689
+ const { useThreadActions } = useThreadContext();
690
+ const addToolResult = useThreadActions((t) => t.addToolResult);
691
+ const { useContentPart } = useContentPartContext();
692
+ const { part, status } = useContentPart();
693
+ const type = part.type;
694
+ switch (type) {
695
+ case "text":
696
+ return /* @__PURE__ */ jsx11(Text, { part, status });
697
+ case "image":
698
+ return /* @__PURE__ */ jsx11(Image, { part, status });
699
+ case "ui":
700
+ return /* @__PURE__ */ jsx11(UI, { part, status });
701
+ case "tool-call": {
702
+ const Tool = by_name[part.toolName] || Fallback;
703
+ const addResult = (result) => addToolResult(part.toolCallId, result);
704
+ return /* @__PURE__ */ jsx11(Tool, { part, status, addResult });
705
+ }
706
+ default:
707
+ throw new Error(`Unknown content part type: ${type}`);
708
+ }
709
+ };
710
+ var MessageContentPartImpl = ({
711
+ partIndex,
712
+ components
713
+ }) => {
714
+ return /* @__PURE__ */ jsx11(ContentPartProvider, { partIndex, children: /* @__PURE__ */ jsx11(MessageContentPartComponent, { components }) });
715
+ };
716
+ var MessageContentPart = memo(
717
+ MessageContentPartImpl,
718
+ (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
719
+ );
720
+ var MessageContent = ({ components }) => {
721
+ const { useMessage } = useMessageContext();
722
+ const contentLength = useMessage((s) => s.message.content.length);
723
+ return new Array(contentLength).fill(null).map((_, idx) => {
724
+ const partIndex = idx;
725
+ return /* @__PURE__ */ jsx11(
726
+ MessageContentPart,
727
+ {
728
+ partIndex,
729
+ components
730
+ },
731
+ partIndex
732
+ );
733
+ });
734
+ };
735
+
736
+ // src/primitives/message/MessageInProgress.tsx
737
+ import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
738
+ import {
739
+ forwardRef as forwardRef7,
740
+ useMemo as useMemo2
741
+ } from "react";
742
+ import { jsx as jsx12 } from "react/jsx-runtime";
743
+ var MessageInProgress = forwardRef7((props, ref) => {
744
+ const { useMessageUtils } = useMessageContext();
745
+ useMemo2(() => {
746
+ useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ jsx12(Primitive5.span, { ...props, ref }));
747
+ }, [useMessageUtils, props, ref]);
748
+ return null;
749
+ });
750
+ MessageInProgress.displayName = "MessageInProgress";
751
+
752
+ // src/primitives/branchPicker/BranchPickerRoot.tsx
753
+ import { jsx as jsx13 } from "react/jsx-runtime";
754
+ var BranchPickerRoot = forwardRef8(({ hideWhenSingleBranch, ...rest }, ref) => {
755
+ return /* @__PURE__ */ jsx13(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx13(Primitive6.div, { ...rest, ref }) });
756
+ });
757
+ BranchPickerRoot.displayName = "BranchPickerRoot";
758
+
759
+ // src/primitives/composer/index.ts
760
+ var composer_exports = {};
761
+ __export(composer_exports, {
762
+ Cancel: () => ComposerCancel,
763
+ If: () => ComposerIf,
764
+ Input: () => ComposerInput,
765
+ Root: () => ComposerRoot,
766
+ Send: () => ComposerSend
767
+ });
768
+
769
+ // src/primitives/composer/ComposerRoot.tsx
770
+ import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
771
+ import { Primitive as Primitive7 } from "@radix-ui/react-primitive";
772
+ import {
773
+ forwardRef as forwardRef9
774
+ } from "react";
775
+ import { jsx as jsx14 } from "react/jsx-runtime";
776
+ var ComposerRoot = forwardRef9(
777
+ ({ onSubmit, ...rest }, forwardedRef) => {
778
+ const send = useComposerSend();
779
+ const handleSubmit = (e) => {
780
+ if (!send) return;
781
+ e.preventDefault();
782
+ send();
783
+ };
784
+ return /* @__PURE__ */ jsx14(
785
+ Primitive7.form,
786
+ {
787
+ ...rest,
788
+ ref: forwardedRef,
789
+ onSubmit: composeEventHandlers5(onSubmit, handleSubmit)
790
+ }
791
+ );
792
+ }
793
+ );
794
+ ComposerRoot.displayName = "ComposerRoot";
795
+
796
+ // src/primitives/composer/ComposerInput.tsx
797
+ import { composeEventHandlers as composeEventHandlers6 } from "@radix-ui/primitive";
798
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
799
+ import { Slot } from "@radix-ui/react-slot";
800
+ import {
801
+ forwardRef as forwardRef10,
802
+ useCallback as useCallback10,
803
+ useEffect as useEffect3,
804
+ useRef
805
+ } from "react";
806
+ import TextareaAutosize from "react-textarea-autosize";
807
+ import { useEscapeKeydown } from "@radix-ui/react-use-escape-keydown";
808
+ import { jsx as jsx15 } from "react/jsx-runtime";
809
+ var ComposerInput = forwardRef10(
810
+ ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
811
+ const { useThread } = useThreadContext();
812
+ const { useComposer, type } = useComposerContext();
813
+ const value = useComposer((c) => {
814
+ if (!c.isEditing) return "";
815
+ return c.value;
816
+ });
817
+ const Component = asChild ? Slot : TextareaAutosize;
818
+ const textareaRef = useRef(null);
819
+ const ref = useComposedRefs(forwardedRef, textareaRef);
820
+ useEscapeKeydown((e) => {
821
+ const composer = useComposer.getState();
822
+ if (composer.cancel()) {
823
+ e.preventDefault();
824
+ }
825
+ });
826
+ const handleKeyPress = (e) => {
827
+ if (disabled) return;
828
+ if (e.key === "Enter" && e.shiftKey === false) {
829
+ const isRunning = useThread.getState().isRunning;
830
+ if (!isRunning) {
831
+ e.preventDefault();
832
+ textareaRef.current?.closest("form")?.requestSubmit();
833
+ }
834
+ }
835
+ };
836
+ const autoFocusEnabled = autoFocus && !disabled;
837
+ const focus = useCallback10(() => {
838
+ const textarea = textareaRef.current;
839
+ if (!textarea || !autoFocusEnabled) return;
840
+ textarea.focus({ preventScroll: true });
841
+ textarea.setSelectionRange(
842
+ textareaRef.current.value.length,
843
+ textareaRef.current.value.length
844
+ );
845
+ }, [autoFocusEnabled]);
846
+ useEffect3(() => focus(), [focus]);
847
+ useOnComposerFocus(() => {
848
+ if (type === "new") {
849
+ focus();
850
+ }
851
+ });
852
+ return /* @__PURE__ */ jsx15(
853
+ Component,
854
+ {
855
+ value,
856
+ ...rest,
857
+ ref,
858
+ disabled,
859
+ onChange: composeEventHandlers6(onChange, (e) => {
860
+ const composerState = useComposer.getState();
861
+ if (!composerState.isEditing) return;
862
+ return composerState.setValue(e.target.value);
863
+ }),
864
+ onKeyDown: composeEventHandlers6(onKeyDown, handleKeyPress)
865
+ }
866
+ );
867
+ }
868
+ );
869
+ ComposerInput.displayName = "ComposerInput";
870
+
871
+ // src/primitives/composer/ComposerSend.tsx
872
+ import { forwardRef as forwardRef11 } from "react";
873
+ import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
874
+ import { jsx as jsx16 } from "react/jsx-runtime";
875
+ var ComposerSend = forwardRef11(
876
+ ({ disabled, ...rest }, ref) => {
877
+ const { useComposer } = useComposerContext();
878
+ const hasValue = useComposer((c) => c.isEditing && c.value.length > 0);
879
+ return /* @__PURE__ */ jsx16(
880
+ Primitive8.button,
881
+ {
882
+ type: "submit",
883
+ ...rest,
884
+ ref,
885
+ disabled: disabled || !hasValue
886
+ }
887
+ );
888
+ }
889
+ );
890
+ ComposerSend.displayName = "ComposerSend";
891
+
892
+ // src/primitives/composer/ComposerCancel.tsx
893
+ var ComposerCancel = createActionButton(
894
+ "ComposerCancel",
895
+ useComposerCancel
896
+ );
897
+
898
+ // src/primitives/composer/ComposerIf.tsx
899
+ var ComposerIf = ({ children, ...query }) => {
900
+ const result = useComposerIf(query);
901
+ return result ? children : null;
902
+ };
903
+
904
+ // src/primitives/contentPart/index.ts
905
+ var contentPart_exports = {};
906
+ __export(contentPart_exports, {
907
+ Display: () => ContentPartDisplay,
908
+ Image: () => ContentPartImage,
909
+ InProgressIndicator: () => ContentPartInProgressIndicator,
910
+ Text: () => ContentPartText
911
+ });
912
+
913
+ // src/primitives/contentPart/ContentPartImage.tsx
914
+ import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
915
+ import { forwardRef as forwardRef12 } from "react";
916
+ import { jsx as jsx17 } from "react/jsx-runtime";
917
+ var ContentPartImage = forwardRef12((props, forwardedRef) => {
918
+ const image = useContentPartImage();
919
+ return /* @__PURE__ */ jsx17(Primitive9.img, { src: image, ...props, ref: forwardedRef });
920
+ });
921
+ ContentPartImage.displayName = "ContentPartImage";
922
+
923
+ // src/primitives/thread/index.ts
924
+ var thread_exports = {};
925
+ __export(thread_exports, {
926
+ Empty: () => ThreadEmpty,
927
+ If: () => ThreadIf,
928
+ Messages: () => ThreadMessages,
929
+ Root: () => ThreadRoot,
930
+ ScrollToBottom: () => ThreadScrollToBottom,
931
+ Suggestion: () => ThreadSuggestion,
932
+ Viewport: () => ThreadViewport
933
+ });
934
+
935
+ // src/primitives/thread/ThreadRoot.tsx
936
+ import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
937
+ import { forwardRef as forwardRef13 } from "react";
938
+ import { jsx as jsx18 } from "react/jsx-runtime";
939
+ var ThreadRoot = forwardRef13(
940
+ (props, ref) => {
941
+ return /* @__PURE__ */ jsx18(Primitive10.div, { ...props, ref });
942
+ }
943
+ );
944
+ ThreadRoot.displayName = "ThreadRoot";
945
+
946
+ // src/primitives/thread/ThreadEmpty.tsx
947
+ var ThreadEmpty = ({ children }) => {
948
+ const empty = useThreadEmpty();
949
+ return empty ? children : null;
950
+ };
951
+
952
+ // src/primitives/thread/ThreadIf.tsx
953
+ var ThreadIf = ({ children, ...query }) => {
954
+ const result = useThreadIf(query);
955
+ return result ? children : null;
956
+ };
957
+
958
+ // src/primitives/thread/ThreadViewport.tsx
959
+ import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
960
+ import { Primitive as Primitive11 } from "@radix-ui/react-primitive";
961
+ import { forwardRef as forwardRef14 } from "react";
962
+
963
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
964
+ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
965
+ import { useRef as useRef3 } from "react";
966
+
967
+ // src/utils/hooks/useOnResizeContent.tsx
968
+ import { useCallbackRef as useCallbackRef2 } from "@radix-ui/react-use-callback-ref";
969
+ import { useCallback as useCallback12 } from "react";
970
+
971
+ // src/utils/hooks/useManagedRef.ts
972
+ import { useCallback as useCallback11, useRef as useRef2 } from "react";
973
+ var useManagedRef = (callback) => {
974
+ const cleanupRef = useRef2();
975
+ const ref = useCallback11(
976
+ (el) => {
977
+ if (cleanupRef.current) {
978
+ cleanupRef.current();
979
+ }
980
+ if (el) {
981
+ cleanupRef.current = callback(el);
982
+ }
983
+ },
984
+ [callback]
985
+ );
986
+ return ref;
987
+ };
988
+
989
+ // src/utils/hooks/useOnResizeContent.tsx
990
+ var useOnResizeContent = (callback) => {
991
+ const callbackRef = useCallbackRef2(callback);
992
+ const refCallback = useCallback12(
993
+ (el) => {
994
+ const resizeObserver = new ResizeObserver(() => {
995
+ callbackRef();
996
+ });
997
+ const mutationObserver = new MutationObserver((mutations) => {
998
+ for (const mutation of mutations) {
999
+ for (const node of mutation.addedNodes) {
1000
+ if (node instanceof Element) {
1001
+ resizeObserver.observe(node);
1002
+ }
1003
+ }
1004
+ for (const node of mutation.removedNodes) {
1005
+ if (node instanceof Element) {
1006
+ resizeObserver.unobserve(node);
1007
+ }
1008
+ }
1009
+ }
1010
+ callbackRef();
1011
+ });
1012
+ resizeObserver.observe(el);
1013
+ mutationObserver.observe(el, { childList: true });
1014
+ for (const child of el.children) {
1015
+ resizeObserver.observe(child);
1016
+ }
1017
+ return () => {
1018
+ resizeObserver.disconnect();
1019
+ mutationObserver.disconnect();
1020
+ };
1021
+ },
1022
+ [callbackRef]
1023
+ );
1024
+ return useManagedRef(refCallback);
1025
+ };
1026
+
1027
+ // src/utils/hooks/useOnScrollToBottom.tsx
1028
+ import { useCallbackRef as useCallbackRef3 } from "@radix-ui/react-use-callback-ref";
1029
+ import { useEffect as useEffect4 } from "react";
1030
+ var useOnScrollToBottom = (callback) => {
1031
+ const callbackRef = useCallbackRef3(callback);
1032
+ const { useViewport } = useThreadContext();
1033
+ useEffect4(() => {
1034
+ return useViewport.getState().onScrollToBottom(() => {
1035
+ callbackRef();
1036
+ });
1037
+ }, [useViewport, callbackRef]);
1038
+ };
1039
+
1040
+ // src/primitive-hooks/thread/useThreadViewportAutoScroll.tsx
1041
+ var useThreadViewportAutoScroll = ({
1042
+ autoScroll = true
1043
+ }) => {
1044
+ const divRef = useRef3(null);
1045
+ const { useViewport } = useThreadContext();
1046
+ const firstRenderRef = useRef3(true);
1047
+ const lastScrollTop = useRef3(0);
1048
+ const isScrollingToBottomRef = useRef3(false);
1049
+ const scrollToBottom = () => {
1050
+ const div = divRef.current;
1051
+ if (!div || !autoScroll) return;
1052
+ const behavior = firstRenderRef.current ? "instant" : "auto";
1053
+ firstRenderRef.current = false;
1054
+ isScrollingToBottomRef.current = true;
1055
+ div.scrollTo({ top: div.scrollHeight, behavior });
1056
+ };
1057
+ const handleScroll = () => {
1058
+ const div = divRef.current;
1059
+ if (!div) return;
1060
+ const isAtBottom = useViewport.getState().isAtBottom;
1061
+ const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight;
1062
+ if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) {
1063
+ } else {
1064
+ isScrollingToBottomRef.current = newIsAtBottom;
1065
+ if (newIsAtBottom !== isAtBottom) {
1066
+ useViewport.setState({
1067
+ isAtBottom: newIsAtBottom
1068
+ });
1069
+ }
1070
+ }
1071
+ lastScrollTop.current = div.scrollTop;
1072
+ };
1073
+ const resizeRef = useOnResizeContent(() => {
1074
+ if (!isScrollingToBottomRef.current && !useViewport.getState().isAtBottom && !firstRenderRef.current) {
1075
+ handleScroll();
1076
+ } else {
1077
+ scrollToBottom();
1078
+ }
1079
+ });
1080
+ const scrollRef = useManagedRef((el) => {
1081
+ el.addEventListener("scroll", handleScroll);
1082
+ return () => {
1083
+ el.removeEventListener("scroll", handleScroll);
1084
+ };
1085
+ });
1086
+ const autoScrollRef = useComposedRefs2(resizeRef, scrollRef, divRef);
1087
+ useOnScrollToBottom(() => {
1088
+ scrollToBottom();
1089
+ });
1090
+ return autoScrollRef;
1091
+ };
1092
+
1093
+ // src/primitives/thread/ThreadViewport.tsx
1094
+ import { jsx as jsx19 } from "react/jsx-runtime";
1095
+ var ThreadViewport = forwardRef14(({ autoScroll, onScroll, children, ...rest }, forwardedRef) => {
1096
+ const autoScrollRef = useThreadViewportAutoScroll({
1097
+ autoScroll
1098
+ });
1099
+ const ref = useComposedRefs3(forwardedRef, autoScrollRef);
1100
+ return /* @__PURE__ */ jsx19(Primitive11.div, { ...rest, ref, children });
1101
+ });
1102
+ ThreadViewport.displayName = "ThreadViewport";
1103
+
1104
+ // src/primitives/thread/ThreadMessages.tsx
1105
+ import { memo as memo2 } from "react";
1106
+
1107
+ // src/context/providers/MessageProvider.tsx
1108
+ import { useEffect as useEffect5, useState as useState3 } from "react";
1109
+ import { create as create4 } from "zustand";
1110
+
1111
+ // src/context/stores/EditComposer.ts
1112
+ import { create as create2 } from "zustand";
1113
+
1114
+ // src/context/stores/BaseComposer.ts
1115
+ var makeBaseComposer = (set) => ({
1116
+ value: "",
1117
+ setValue: (value) => {
1118
+ set({ value });
1119
+ }
1120
+ });
1121
+
1122
+ // src/context/stores/EditComposer.ts
1123
+ var makeEditComposerStore = ({
1124
+ onEdit,
1125
+ onSend
1126
+ }) => create2()((set, get, store) => ({
1127
+ ...makeBaseComposer(set, get, store),
1128
+ isEditing: false,
1129
+ edit: () => {
1130
+ const value = onEdit();
1131
+ set({ isEditing: true, value });
1132
+ },
1133
+ send: () => {
1134
+ const value = get().value;
1135
+ set({ isEditing: false });
1136
+ onSend(value);
1137
+ },
1138
+ cancel: () => {
1139
+ if (!get().isEditing) return false;
1140
+ set({ isEditing: false });
1141
+ return true;
1142
+ }
1143
+ }));
1144
+
1145
+ // src/context/stores/MessageUtils.ts
1146
+ import { create as create3 } from "zustand";
1147
+ var makeMessageUtilsStore = () => create3((set) => ({
1148
+ inProgressIndicator: null,
1149
+ setInProgressIndicator: (value) => {
1150
+ set({ inProgressIndicator: value });
1151
+ },
1152
+ isCopied: false,
1153
+ setIsCopied: (value) => {
1154
+ set({ isCopied: value });
1155
+ },
1156
+ isHovering: false,
1157
+ setIsHovering: (value) => {
1158
+ set({ isHovering: value });
1159
+ }
1160
+ }));
1161
+
1162
+ // src/context/providers/MessageProvider.tsx
1163
+ import { jsx as jsx20 } from "react/jsx-runtime";
1164
+ var getIsLast = (thread, message) => {
1165
+ return thread.messages[thread.messages.length - 1]?.id === message.id;
1166
+ };
1167
+ var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
1168
+ const parentId = thread.messages[messageIndex - 1]?.id ?? null;
1169
+ const message = thread.messages[messageIndex];
1170
+ if (!message) return;
529
1171
  const isLast = getIsLast(thread, message);
530
1172
  const branches = getBranches(message.id);
531
1173
  const currentState = useMessage.getState();
@@ -540,8 +1182,8 @@ var syncMessage = (thread, getBranches, useMessage, messageIndex) => {
540
1182
  };
541
1183
  var useMessageContext2 = (messageIndex) => {
542
1184
  const { useThread, useThreadActions } = useThreadContext();
543
- const [context] = useState(() => {
544
- const useMessage = create3(() => ({}));
1185
+ const [context] = useState3(() => {
1186
+ const useMessage = create4(() => ({}));
545
1187
  const useMessageUtils = makeMessageUtilsStore();
546
1188
  const useEditComposer = makeEditComposerStore({
547
1189
  onEdit: () => {
@@ -564,6 +1206,7 @@ var useMessageContext2 = (messageIndex) => {
564
1206
  );
565
1207
  useThreadActions.getState().append({
566
1208
  parentId,
1209
+ role: "user",
567
1210
  content: [{ type: "text", text }, ...nonTextParts]
568
1211
  });
569
1212
  }
@@ -576,7 +1219,7 @@ var useMessageContext2 = (messageIndex) => {
576
1219
  );
577
1220
  return { useMessage, useMessageUtils, useEditComposer };
578
1221
  });
579
- useEffect3(() => {
1222
+ useEffect5(() => {
580
1223
  return useThread.subscribe((thread) => {
581
1224
  syncMessage(
582
1225
  thread,
@@ -585,565 +1228,74 @@ var useMessageContext2 = (messageIndex) => {
585
1228
  messageIndex
586
1229
  );
587
1230
  });
588
- }, [useThread, useThreadActions, context, messageIndex]);
589
- return context;
590
- };
591
- var MessageProvider = ({
592
- messageIndex,
593
- children
594
- }) => {
595
- const context = useMessageContext2(messageIndex);
596
- return /* @__PURE__ */ jsx4(MessageContext.Provider, { value: context, children });
597
- };
598
-
599
- // src/primitives/composer/ComposerIf.tsx
600
- var ComposerIf = ({ children, ...query }) => {
601
- const result = useComposerIf(query);
602
- return result ? children : null;
603
- };
604
-
605
- // src/primitives/message/MessageIf.tsx
606
- var MessageIf = ({ children, ...query }) => {
607
- const result = useMessageIf(query);
608
- return result ? children : null;
609
- };
610
-
611
- // src/primitives/thread/ThreadMessages.tsx
612
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
613
- var getComponents = (components) => {
614
- return {
615
- EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
616
- UserMessage: components.UserMessage ?? components.Message,
617
- AssistantMessage: components.AssistantMessage ?? components.Message
618
- };
619
- };
620
- var ThreadMessageImpl = ({
621
- messageIndex,
622
- components
623
- }) => {
624
- const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
625
- return /* @__PURE__ */ jsxs2(MessageProvider, { messageIndex, children: [
626
- /* @__PURE__ */ jsxs2(MessageIf, { user: true, children: [
627
- /* @__PURE__ */ jsx5(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx5(UserMessage, {}) }),
628
- /* @__PURE__ */ jsx5(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx5(EditComposer, {}) })
629
- ] }),
630
- /* @__PURE__ */ jsx5(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx5(AssistantMessage, {}) })
631
- ] });
632
- };
633
- var ThreadMessage = memo(
634
- ThreadMessageImpl,
635
- (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
636
- );
637
- var ThreadMessages = ({ components }) => {
638
- const { useThread } = useThreadContext();
639
- const messagesLength = useThread((t) => t.messages.length);
640
- if (messagesLength === 0) return null;
641
- return new Array(messagesLength).fill(null).map((_, idx) => {
642
- const messageIndex = idx;
643
- return /* @__PURE__ */ jsx5(
644
- ThreadMessage,
645
- {
646
- messageIndex,
647
- components
648
- },
649
- messageIndex
650
- );
651
- });
652
- };
653
-
654
- // src/utils/createActionButton.tsx
655
- import { composeEventHandlers as composeEventHandlers2 } from "@radix-ui/primitive";
656
- import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
657
- import { forwardRef as forwardRef3 } from "react";
658
- import { jsx as jsx6 } from "react/jsx-runtime";
659
- var createActionButton = (displayName, useActionButton) => {
660
- const ActionButton = forwardRef3((props, forwardedRef) => {
661
- const callback = useActionButton(props);
662
- return /* @__PURE__ */ jsx6(
663
- Primitive3.button,
664
- {
665
- type: "button",
666
- disabled: !callback,
667
- ...props,
668
- ref: forwardedRef,
669
- onClick: composeEventHandlers2(props.onClick, () => {
670
- callback?.();
671
- })
672
- }
673
- );
674
- });
675
- ActionButton.displayName = displayName;
676
- return ActionButton;
677
- };
678
-
679
- // src/primitives/thread/ThreadScrollToBottom.tsx
680
- var ThreadScrollToBottom = createActionButton(
681
- "ThreadScrollToBottom",
682
- useThreadScrollToBottom
683
- );
684
-
685
- // src/primitives/thread/ThreadSuggestion.tsx
686
- var ThreadSuggestion = createActionButton(
687
- "ThreadSuggestion",
688
- useThreadSuggestion
689
- );
690
-
691
- // src/primitives/composer/index.ts
692
- var composer_exports = {};
693
- __export(composer_exports, {
694
- Cancel: () => ComposerCancel,
695
- If: () => ComposerIf,
696
- Input: () => ComposerInput,
697
- Root: () => ComposerRoot,
698
- Send: () => ComposerSend
699
- });
700
-
701
- // src/primitives/composer/ComposerRoot.tsx
702
- import { composeEventHandlers as composeEventHandlers3 } from "@radix-ui/primitive";
703
- import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
704
- import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
705
- import {
706
- forwardRef as forwardRef4,
707
- useRef as useRef2
708
- } from "react";
709
- import { jsx as jsx7 } from "react/jsx-runtime";
710
- var ComposerRoot = forwardRef4(
711
- ({ onSubmit, ...rest }, forwardedRef) => {
712
- const { useViewport } = useThreadContext();
713
- const { useComposer } = useComposerContext();
714
- const formRef = useRef2(null);
715
- const ref = useComposedRefs2(forwardedRef, formRef);
716
- const handleSubmit = (e) => {
717
- const composerState = useComposer.getState();
718
- if (!composerState.isEditing) return;
719
- e.preventDefault();
720
- composerState.send();
721
- useViewport.getState().scrollToBottom();
722
- };
723
- return /* @__PURE__ */ jsx7(
724
- Primitive4.form,
725
- {
726
- ...rest,
727
- ref,
728
- onSubmit: composeEventHandlers3(onSubmit, handleSubmit)
729
- }
730
- );
731
- }
732
- );
733
- ComposerRoot.displayName = "ComposerRoot";
734
-
735
- // src/primitives/composer/ComposerInput.tsx
736
- import { composeEventHandlers as composeEventHandlers4 } from "@radix-ui/primitive";
737
- import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
738
- import { Slot } from "@radix-ui/react-slot";
739
- import {
740
- forwardRef as forwardRef5,
741
- useCallback as useCallback10,
742
- useEffect as useEffect4,
743
- useRef as useRef3
744
- } from "react";
745
- import TextareaAutosize from "react-textarea-autosize";
746
- import { jsx as jsx8 } from "react/jsx-runtime";
747
- var ComposerInput = forwardRef5(
748
- ({ autoFocus = false, asChild, disabled, onChange, onKeyDown, ...rest }, forwardedRef) => {
749
- const { useThread } = useThreadContext();
750
- const { useComposer, type } = useComposerContext();
751
- const value = useComposer((c) => {
752
- if (!c.isEditing) return "";
753
- return c.value;
754
- });
755
- const Component = asChild ? Slot : TextareaAutosize;
756
- const textareaRef = useRef3(null);
757
- const ref = useComposedRefs3(forwardedRef, textareaRef);
758
- const handleKeyPress = (e) => {
759
- if (disabled) return;
760
- if (e.key === "Escape") {
761
- const composer = useComposer.getState();
762
- if (composer.cancel()) {
763
- e.preventDefault();
764
- }
765
- } else if (e.key === "Enter" && e.shiftKey === false) {
766
- const isRunning = useThread.getState().isRunning;
767
- if (!isRunning) {
768
- e.preventDefault();
769
- textareaRef.current?.closest("form")?.requestSubmit();
770
- }
771
- }
772
- };
773
- const autoFocusEnabled = autoFocus && !disabled;
774
- const focus = useCallback10(() => {
775
- const textarea = textareaRef.current;
776
- if (!textarea || !autoFocusEnabled) return;
777
- textarea.focus();
778
- textarea.setSelectionRange(
779
- textareaRef.current.value.length,
780
- textareaRef.current.value.length
781
- );
782
- }, [autoFocusEnabled]);
783
- useEffect4(() => focus(), [focus]);
784
- useOnScrollToBottom(() => {
785
- if (type === "new") {
786
- focus();
787
- }
788
- });
789
- return /* @__PURE__ */ jsx8(
790
- Component,
791
- {
792
- value,
793
- ...rest,
794
- ref,
795
- autoFocus,
796
- disabled,
797
- onChange: composeEventHandlers4(onChange, (e) => {
798
- const composerState = useComposer.getState();
799
- if (!composerState.isEditing) return;
800
- return composerState.setValue(e.target.value);
801
- }),
802
- onKeyDown: composeEventHandlers4(onKeyDown, handleKeyPress)
803
- }
804
- );
805
- }
806
- );
807
- ComposerInput.displayName = "ComposerInput";
808
-
809
- // src/primitives/composer/ComposerSend.tsx
810
- var ComposerSend = createActionButton("ComposerSend", useComposerSend);
811
-
812
- // src/primitives/composer/ComposerCancel.tsx
813
- var ComposerCancel = createActionButton(
814
- "ComposerCancel",
815
- useComposerCancel
816
- );
817
-
818
- // src/primitives/message/index.ts
819
- var message_exports = {};
820
- __export(message_exports, {
821
- Content: () => MessageContent,
822
- If: () => MessageIf,
823
- InProgress: () => MessageInProgress,
824
- Root: () => MessageRoot
825
- });
826
-
827
- // src/primitives/message/MessageRoot.tsx
828
- import { composeEventHandlers as composeEventHandlers5 } from "@radix-ui/primitive";
829
- import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
830
- import { forwardRef as forwardRef6 } from "react";
831
- import { jsx as jsx9 } from "react/jsx-runtime";
832
- var MessageRoot = forwardRef6(
833
- ({ onMouseEnter, onMouseLeave, ...rest }, ref) => {
834
- const { useMessageUtils } = useMessageContext();
835
- const setIsHovering = useMessageUtils((s) => s.setIsHovering);
836
- const handleMouseEnter = () => {
837
- setIsHovering(true);
838
- };
839
- const handleMouseLeave = () => {
840
- setIsHovering(false);
841
- };
842
- return /* @__PURE__ */ jsx9(
843
- Primitive5.div,
844
- {
845
- ...rest,
846
- ref,
847
- onMouseEnter: composeEventHandlers5(onMouseEnter, handleMouseEnter),
848
- onMouseLeave: composeEventHandlers5(onMouseLeave, handleMouseLeave)
849
- }
850
- );
851
- }
852
- );
853
- MessageRoot.displayName = "MessageRoot";
854
-
855
- // src/primitives/message/MessageContent.tsx
856
- import { memo as memo2 } from "react";
857
-
858
- // src/context/providers/ContentPartProvider.tsx
859
- import { useEffect as useEffect5, useState as useState2 } from "react";
860
- import { create as create4 } from "zustand";
861
- import { jsx as jsx10 } from "react/jsx-runtime";
862
- var syncContentPart = ({ message }, useContentPart, partIndex) => {
863
- const part = message.content[partIndex];
864
- if (!part) return;
865
- const messageStatus = message.role === "assistant" ? message.status : "done";
866
- const status = partIndex === message.content.length - 1 ? messageStatus : "done";
867
- const currentState = useContentPart.getState();
868
- if (currentState.part === part && currentState.status === status) return;
869
- useContentPart.setState(
870
- Object.freeze({
871
- part,
872
- status
873
- })
874
- );
875
- };
876
- var useContentPartContext2 = (partIndex) => {
877
- const { useMessage } = useMessageContext();
878
- const [context] = useState2(() => {
879
- const useContentPart = create4(
880
- () => ({})
881
- );
882
- syncContentPart(useMessage.getState(), useContentPart, partIndex);
883
- return { useContentPart };
884
- });
885
- useEffect5(() => {
886
- syncContentPart(useMessage.getState(), context.useContentPart, partIndex);
887
- return useMessage.subscribe((message) => {
888
- syncContentPart(message, context.useContentPart, partIndex);
889
- });
890
- }, [context, useMessage, partIndex]);
1231
+ }, [useThread, useThreadActions, context, messageIndex]);
891
1232
  return context;
892
1233
  };
893
- var ContentPartProvider = ({
894
- partIndex,
1234
+ var MessageProvider = ({
1235
+ messageIndex,
895
1236
  children
896
1237
  }) => {
897
- const context = useContentPartContext2(partIndex);
898
- return /* @__PURE__ */ jsx10(ContentPartContext.Provider, { value: context, children });
899
- };
900
-
901
- // src/primitives/contentPart/ContentPartDisplay.tsx
902
- var ContentPartDisplay = () => {
903
- const display = useContentPartDisplay();
904
- return display ?? null;
905
- };
906
-
907
- // src/primitives/contentPart/ContentPartInProgressIndicator.tsx
908
- var ContentPartInProgressIndicator = () => {
909
- const indicator = useContentPartInProgressIndicator();
910
- return indicator;
1238
+ const context = useMessageContext2(messageIndex);
1239
+ return /* @__PURE__ */ jsx20(MessageContext.Provider, { value: context, children });
911
1240
  };
912
1241
 
913
- // src/primitives/contentPart/ContentPartText.tsx
914
- import { Primitive as Primitive6 } from "@radix-ui/react-primitive";
915
- import { forwardRef as forwardRef7 } from "react";
916
- import { jsx as jsx11 } from "react/jsx-runtime";
917
- var ContentPartText = forwardRef7((props, forwardedRef) => {
918
- const text = useContentPartText();
919
- return /* @__PURE__ */ jsx11(Primitive6.span, { ...props, ref: forwardedRef, children: text });
920
- });
921
- ContentPartText.displayName = "ContentPartText";
922
-
923
- // src/primitives/message/MessageContent.tsx
924
- import { Fragment, jsx as jsx12, jsxs as jsxs3 } from "react/jsx-runtime";
925
- var defaultComponents = {
926
- Text: () => /* @__PURE__ */ jsxs3(Fragment, { children: [
927
- /* @__PURE__ */ jsx12(ContentPartText, {}),
928
- /* @__PURE__ */ jsx12(ContentPartInProgressIndicator, {})
929
- ] }),
930
- Image: () => null,
931
- UI: () => /* @__PURE__ */ jsx12(ContentPartDisplay, {}),
932
- tools: {
933
- Fallback: (props) => {
934
- const { useToolUIs } = useAssistantContext();
935
- const Render = useToolUIs((s) => s.getToolUI(props.part.toolName));
936
- if (!Render) return null;
937
- return /* @__PURE__ */ jsx12(Render, { ...props });
938
- }
939
- }
940
- };
941
- var MessageContentPartComponent = ({
942
- components: {
943
- Text = defaultComponents.Text,
944
- Image = defaultComponents.Image,
945
- UI = defaultComponents.UI,
946
- tools: { by_name = {}, Fallback = defaultComponents.tools.Fallback } = {}
947
- } = {}
948
- }) => {
949
- const { useThreadActions } = useThreadContext();
950
- const addToolResult = useThreadActions((t) => t.addToolResult);
951
- const { useContentPart } = useContentPartContext();
952
- const { part, status } = useContentPart();
953
- const type = part.type;
954
- switch (type) {
955
- case "text":
956
- return /* @__PURE__ */ jsx12(Text, { part, status });
957
- case "image":
958
- return /* @__PURE__ */ jsx12(Image, { part, status });
959
- case "ui":
960
- return /* @__PURE__ */ jsx12(UI, { part, status });
961
- case "tool-call": {
962
- const Tool = by_name[part.toolName] || Fallback;
963
- const addResult = (result) => addToolResult(part.toolCallId, result);
964
- return /* @__PURE__ */ jsx12(Tool, { part, status, addResult });
965
- }
966
- default:
967
- throw new Error(`Unknown content part type: ${type}`);
968
- }
1242
+ // src/primitives/thread/ThreadMessages.tsx
1243
+ import { jsx as jsx21, jsxs as jsxs2 } from "react/jsx-runtime";
1244
+ var getComponents = (components) => {
1245
+ return {
1246
+ EditComposer: components.EditComposer ?? components.UserMessage ?? components.Message,
1247
+ UserMessage: components.UserMessage ?? components.Message,
1248
+ AssistantMessage: components.AssistantMessage ?? components.Message
1249
+ };
969
1250
  };
970
- var MessageContentPartImpl = ({
971
- partIndex,
1251
+ var ThreadMessageImpl = ({
1252
+ messageIndex,
972
1253
  components
973
1254
  }) => {
974
- return /* @__PURE__ */ jsx12(ContentPartProvider, { partIndex, children: /* @__PURE__ */ jsx12(MessageContentPartComponent, { components }) });
1255
+ const { UserMessage, EditComposer, AssistantMessage } = getComponents(components);
1256
+ return /* @__PURE__ */ jsxs2(MessageProvider, { messageIndex, children: [
1257
+ /* @__PURE__ */ jsxs2(MessageIf, { user: true, children: [
1258
+ /* @__PURE__ */ jsx21(ComposerIf, { editing: false, children: /* @__PURE__ */ jsx21(UserMessage, {}) }),
1259
+ /* @__PURE__ */ jsx21(ComposerIf, { editing: true, children: /* @__PURE__ */ jsx21(EditComposer, {}) })
1260
+ ] }),
1261
+ /* @__PURE__ */ jsx21(MessageIf, { assistant: true, children: /* @__PURE__ */ jsx21(AssistantMessage, {}) })
1262
+ ] });
975
1263
  };
976
- var MessageContentPart = memo2(
977
- MessageContentPartImpl,
978
- (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
1264
+ var ThreadMessage = memo2(
1265
+ ThreadMessageImpl,
1266
+ (prev, next) => prev.messageIndex === next.messageIndex && prev.components.UserMessage === next.components.UserMessage && prev.components.EditComposer === next.components.EditComposer && prev.components.AssistantMessage === next.components.AssistantMessage
979
1267
  );
980
- var MessageContent = ({ components }) => {
981
- const { useMessage } = useMessageContext();
982
- const contentLength = useMessage((s) => s.message.content.length);
983
- return new Array(contentLength).fill(null).map((_, idx) => {
984
- const partIndex = idx;
985
- return /* @__PURE__ */ jsx12(
986
- MessageContentPart,
1268
+ var ThreadMessages = ({ components }) => {
1269
+ const { useThread } = useThreadContext();
1270
+ const messagesLength = useThread((t) => t.messages.length);
1271
+ if (messagesLength === 0) return null;
1272
+ return new Array(messagesLength).fill(null).map((_, idx) => {
1273
+ const messageIndex = idx;
1274
+ return /* @__PURE__ */ jsx21(
1275
+ ThreadMessage,
987
1276
  {
988
- partIndex,
1277
+ messageIndex,
989
1278
  components
990
1279
  },
991
- partIndex
1280
+ messageIndex
992
1281
  );
993
1282
  });
994
1283
  };
995
1284
 
996
- // src/primitives/message/MessageInProgress.tsx
997
- import { Primitive as Primitive7 } from "@radix-ui/react-primitive";
998
- import {
999
- forwardRef as forwardRef8,
1000
- useMemo as useMemo2
1001
- } from "react";
1002
- import { jsx as jsx13 } from "react/jsx-runtime";
1003
- var MessageInProgress = forwardRef8((props, ref) => {
1004
- const { useMessageUtils } = useMessageContext();
1005
- useMemo2(() => {
1006
- useMessageUtils.getState().setInProgressIndicator(/* @__PURE__ */ jsx13(Primitive7.span, { ...props, ref }));
1007
- }, [useMessageUtils, props, ref]);
1008
- return null;
1009
- });
1010
- MessageInProgress.displayName = "MessageInProgress";
1011
-
1012
- // src/primitives/branchPicker/index.ts
1013
- var branchPicker_exports = {};
1014
- __export(branchPicker_exports, {
1015
- Count: () => BranchPickerCount,
1016
- Next: () => BranchPickerNext,
1017
- Number: () => BranchPickerNumber,
1018
- Previous: () => BranchPickerPrevious,
1019
- Root: () => BranchPickerRoot
1020
- });
1021
-
1022
- // src/primitives/branchPicker/BranchPickerNext.tsx
1023
- var BranchPickerNext = createActionButton(
1024
- "BranchPickerNext",
1025
- useBranchPickerNext
1026
- );
1027
-
1028
- // src/primitives/branchPicker/BranchPickerPrevious.tsx
1029
- var BranchPickerPrevious = createActionButton(
1030
- "BranchPickerPrevious",
1031
- useBranchPickerPrevious
1032
- );
1033
-
1034
- // src/primitives/branchPicker/BranchPickerCount.tsx
1035
- import { Fragment as Fragment2, jsx as jsx14 } from "react/jsx-runtime";
1036
- var BranchPickerCount = () => {
1037
- const branchCount = useBranchPickerCount();
1038
- return /* @__PURE__ */ jsx14(Fragment2, { children: branchCount });
1039
- };
1040
-
1041
- // src/primitives/branchPicker/BranchPickerNumber.tsx
1042
- import { Fragment as Fragment3, jsx as jsx15 } from "react/jsx-runtime";
1043
- var BranchPickerNumber = () => {
1044
- const branchNumber = useBranchPickerNumber();
1045
- return /* @__PURE__ */ jsx15(Fragment3, { children: branchNumber });
1046
- };
1047
-
1048
- // src/primitives/branchPicker/BranchPickerRoot.tsx
1049
- import { Primitive as Primitive8 } from "@radix-ui/react-primitive";
1050
- import { forwardRef as forwardRef9 } from "react";
1051
- import { jsx as jsx16 } from "react/jsx-runtime";
1052
- var BranchPickerRoot = forwardRef9(({ hideWhenSingleBranch, ...rest }, ref) => {
1053
- return /* @__PURE__ */ jsx16(MessageIf, { hasBranches: hideWhenSingleBranch ? true : void 0, children: /* @__PURE__ */ jsx16(Primitive8.div, { ...rest, ref }) });
1054
- });
1055
- BranchPickerRoot.displayName = "BranchPickerRoot";
1056
-
1057
- // src/primitives/actionBar/index.ts
1058
- var actionBar_exports = {};
1059
- __export(actionBar_exports, {
1060
- Copy: () => ActionBarCopy,
1061
- Edit: () => ActionBarEdit,
1062
- Reload: () => ActionBarReload,
1063
- Root: () => ActionBarRoot
1064
- });
1065
-
1066
- // src/primitives/actionBar/ActionBarRoot.tsx
1067
- import { Primitive as Primitive9 } from "@radix-ui/react-primitive";
1068
- import { forwardRef as forwardRef10 } from "react";
1069
- import { jsx as jsx17 } from "react/jsx-runtime";
1070
- var useActionBarFloatStatus = ({
1071
- hideWhenRunning,
1072
- autohide,
1073
- autohideFloat
1074
- }) => {
1075
- const { useThread } = useThreadContext();
1076
- const { useMessage, useMessageUtils } = useMessageContext();
1077
- return useCombinedStore(
1078
- [useThread, useMessage, useMessageUtils],
1079
- (t, m, mu) => {
1080
- if (hideWhenRunning && t.isRunning) return "hidden" /* Hidden */;
1081
- const autohideEnabled = autohide === "always" || autohide === "not-last" && !m.isLast;
1082
- if (!autohideEnabled) return "normal" /* Normal */;
1083
- if (!mu.isHovering) return "hidden" /* Hidden */;
1084
- if (autohideFloat === "always" || autohideFloat === "single-branch" && m.branches.length <= 1)
1085
- return "floating" /* Floating */;
1086
- return "normal" /* Normal */;
1087
- }
1088
- );
1089
- };
1090
- var ActionBarRoot = forwardRef10(({ hideWhenRunning, autohide, autohideFloat, ...rest }, ref) => {
1091
- const hideAndfloatStatus = useActionBarFloatStatus({
1092
- hideWhenRunning,
1093
- autohide,
1094
- autohideFloat
1095
- });
1096
- if (hideAndfloatStatus === "hidden" /* Hidden */) return null;
1097
- return /* @__PURE__ */ jsx17(
1098
- Primitive9.div,
1099
- {
1100
- ...hideAndfloatStatus === "floating" /* Floating */ ? { "data-floating": "true" } : null,
1101
- ...rest,
1102
- ref
1103
- }
1104
- );
1105
- });
1106
- ActionBarRoot.displayName = "ActionBarRoot";
1107
-
1108
- // src/primitives/actionBar/ActionBarCopy.tsx
1109
- var ActionBarCopy = createActionButton(
1110
- "ActionBarCopy",
1111
- useActionBarCopy
1112
- );
1113
-
1114
- // src/primitives/actionBar/ActionBarReload.tsx
1115
- var ActionBarReload = createActionButton(
1116
- "ActionBarReload",
1117
- useActionBarReload
1285
+ // src/primitives/thread/ThreadScrollToBottom.tsx
1286
+ var ThreadScrollToBottom = createActionButton(
1287
+ "ThreadScrollToBottom",
1288
+ useThreadScrollToBottom
1118
1289
  );
1119
1290
 
1120
- // src/primitives/actionBar/ActionBarEdit.tsx
1121
- var ActionBarEdit = createActionButton(
1122
- "ActionBarEdit",
1123
- useActionBarEdit
1291
+ // src/primitives/thread/ThreadSuggestion.tsx
1292
+ var ThreadSuggestion = createActionButton(
1293
+ "ThreadSuggestion",
1294
+ useThreadSuggestion
1124
1295
  );
1125
1296
 
1126
- // src/primitives/contentPart/index.ts
1127
- var contentPart_exports = {};
1128
- __export(contentPart_exports, {
1129
- Display: () => ContentPartDisplay,
1130
- Image: () => ContentPartImage,
1131
- InProgressIndicator: () => ContentPartInProgressIndicator,
1132
- Text: () => ContentPartText
1133
- });
1134
-
1135
- // src/primitives/contentPart/ContentPartImage.tsx
1136
- import { Primitive as Primitive10 } from "@radix-ui/react-primitive";
1137
- import { forwardRef as forwardRef11 } from "react";
1138
- import { jsx as jsx18 } from "react/jsx-runtime";
1139
- var ContentPartImage = forwardRef11((props, forwardedRef) => {
1140
- const image = useContentPartImage();
1141
- return /* @__PURE__ */ jsx18(Primitive10.img, { src: image, ...props, ref: forwardedRef });
1142
- });
1143
- ContentPartImage.displayName = "ContentPartImage";
1144
-
1145
1297
  // src/runtime/local/useLocalRuntime.tsx
1146
- import { useInsertionEffect, useState as useState3 } from "react";
1298
+ import { useInsertionEffect, useState as useState4 } from "react";
1147
1299
 
1148
1300
  // src/utils/ModelConfigTypes.ts
1149
1301
  var mergeModelConfigs = (configSet) => {
@@ -1429,7 +1581,7 @@ var LocalRuntime = class {
1429
1581
 
1430
1582
  // src/runtime/local/useLocalRuntime.tsx
1431
1583
  var useLocalRuntime = (adapter) => {
1432
- const [runtime] = useState3(() => new LocalRuntime(adapter));
1584
+ const [runtime] = useState4(() => new LocalRuntime(adapter));
1433
1585
  useInsertionEffect(() => {
1434
1586
  runtime.adapter = adapter;
1435
1587
  });
@@ -1440,7 +1592,7 @@ var useLocalRuntime = (adapter) => {
1440
1592
  import { memo as memo3 } from "react";
1441
1593
 
1442
1594
  // src/context/providers/AssistantProvider.tsx
1443
- import { useEffect as useEffect7, useInsertionEffect as useInsertionEffect3, useRef as useRef5, useState as useState5 } from "react";
1595
+ import { useEffect as useEffect7, useInsertionEffect as useInsertionEffect3, useRef as useRef5, useState as useState6 } from "react";
1444
1596
 
1445
1597
  // src/context/stores/AssistantModelConfig.ts
1446
1598
  import { create as create5 } from "zustand";
@@ -1505,30 +1657,45 @@ var makeAssistantToolUIsStore = () => create6((set) => {
1505
1657
  });
1506
1658
 
1507
1659
  // src/context/providers/ThreadProvider.tsx
1508
- import { useEffect as useEffect6, useInsertionEffect as useInsertionEffect2, useRef as useRef4, useState as useState4 } from "react";
1660
+ import { useEffect as useEffect6, useInsertionEffect as useInsertionEffect2, useRef as useRef4, useState as useState5 } from "react";
1509
1661
 
1510
1662
  // src/context/stores/Composer.ts
1511
1663
  import { create as create7 } from "zustand";
1512
- var makeComposerStore = (useThread, useThreadActions) => create7()((set, get, store) => {
1513
- return {
1514
- ...makeBaseComposer(set, get, store),
1515
- isEditing: true,
1516
- send: () => {
1517
- const { setValue, value } = get();
1518
- setValue("");
1519
- useThreadActions.getState().append({
1520
- parentId: useThread.getState().messages.at(-1)?.id ?? null,
1521
- content: [{ type: "text", text: value }]
1522
- });
1523
- },
1524
- cancel: () => {
1525
- const thread = useThread.getState();
1526
- if (!thread.isRunning) return false;
1527
- useThreadActions.getState().cancelRun();
1528
- return true;
1529
- }
1530
- };
1531
- });
1664
+ var makeComposerStore = (useThread, useThreadActions) => {
1665
+ const focusListeners = /* @__PURE__ */ new Set();
1666
+ return create7()((set, get, store) => {
1667
+ return {
1668
+ ...makeBaseComposer(set, get, store),
1669
+ isEditing: true,
1670
+ send: () => {
1671
+ const { setValue, value } = get();
1672
+ setValue("");
1673
+ useThreadActions.getState().append({
1674
+ parentId: useThread.getState().messages.at(-1)?.id ?? null,
1675
+ role: "user",
1676
+ content: [{ type: "text", text: value }]
1677
+ });
1678
+ },
1679
+ cancel: () => {
1680
+ const thread = useThread.getState();
1681
+ if (!thread.isRunning) return false;
1682
+ useThreadActions.getState().cancelRun();
1683
+ return true;
1684
+ },
1685
+ focus: () => {
1686
+ for (const listener of focusListeners) {
1687
+ listener();
1688
+ }
1689
+ },
1690
+ onFocus: (listener) => {
1691
+ focusListeners.add(listener);
1692
+ return () => {
1693
+ focusListeners.delete(listener);
1694
+ };
1695
+ }
1696
+ };
1697
+ });
1698
+ };
1532
1699
 
1533
1700
  // src/context/stores/Thread.ts
1534
1701
  import { create as create8 } from "zustand";
@@ -1575,7 +1742,7 @@ var makeThreadActionStore = (runtimeRef) => {
1575
1742
  };
1576
1743
 
1577
1744
  // src/context/providers/ThreadProvider.tsx
1578
- import { jsx as jsx19, jsxs as jsxs4 } from "react/jsx-runtime";
1745
+ import { jsx as jsx22, jsxs as jsxs3 } from "react/jsx-runtime";
1579
1746
  var ThreadProvider = ({
1580
1747
  children,
1581
1748
  runtime
@@ -1584,7 +1751,7 @@ var ThreadProvider = ({
1584
1751
  useInsertionEffect2(() => {
1585
1752
  runtimeRef.current = runtime;
1586
1753
  });
1587
- const [context] = useState4(() => {
1754
+ const [context] = useState5(() => {
1588
1755
  const useThread = makeThreadStore(runtimeRef);
1589
1756
  const useThreadActions = makeThreadActionStore(runtimeRef);
1590
1757
  const useViewport = makeThreadViewportStore();
@@ -1610,20 +1777,20 @@ var ThreadProvider = ({
1610
1777
  return runtime.subscribe(onRuntimeUpdate);
1611
1778
  }, [context, runtime]);
1612
1779
  const RuntimeSynchronizer = runtime.unstable_synchronizer;
1613
- return /* @__PURE__ */ jsxs4(ThreadContext.Provider, { value: context, children: [
1614
- RuntimeSynchronizer && /* @__PURE__ */ jsx19(RuntimeSynchronizer, {}),
1780
+ return /* @__PURE__ */ jsxs3(ThreadContext.Provider, { value: context, children: [
1781
+ RuntimeSynchronizer && /* @__PURE__ */ jsx22(RuntimeSynchronizer, {}),
1615
1782
  children
1616
1783
  ] });
1617
1784
  };
1618
1785
 
1619
1786
  // src/context/providers/AssistantProvider.tsx
1620
- import { jsx as jsx20 } from "react/jsx-runtime";
1787
+ import { jsx as jsx23 } from "react/jsx-runtime";
1621
1788
  var AssistantProvider = ({ children, runtime }) => {
1622
1789
  const runtimeRef = useRef5(runtime);
1623
1790
  useInsertionEffect3(() => {
1624
1791
  runtimeRef.current = runtime;
1625
1792
  });
1626
- const [context] = useState5(() => {
1793
+ const [context] = useState6(() => {
1627
1794
  const useModelConfig = makeAssistantModelConfigStore();
1628
1795
  const useToolUIs = makeAssistantToolUIsStore();
1629
1796
  return { useModelConfig, useToolUIs };
@@ -1632,13 +1799,13 @@ var AssistantProvider = ({ children, runtime }) => {
1632
1799
  useEffect7(() => {
1633
1800
  return runtime.registerModelConfigProvider(getModelCOnfig);
1634
1801
  }, [runtime, getModelCOnfig]);
1635
- return /* @__PURE__ */ jsx20(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx20(ThreadProvider, { runtime, children }) });
1802
+ return /* @__PURE__ */ jsx23(AssistantContext.Provider, { value: context, children: /* @__PURE__ */ jsx23(ThreadProvider, { runtime, children }) });
1636
1803
  };
1637
1804
 
1638
1805
  // src/context/providers/AssistantRuntimeProvider.tsx
1639
- import { jsx as jsx21 } from "react/jsx-runtime";
1806
+ import { jsx as jsx24 } from "react/jsx-runtime";
1640
1807
  var AssistantRuntimeProviderImpl = ({ children, runtime }) => {
1641
- return /* @__PURE__ */ jsx21(AssistantProvider, { runtime, children });
1808
+ return /* @__PURE__ */ jsx24(AssistantProvider, { runtime, children });
1642
1809
  };
1643
1810
  var AssistantRuntimeProvider = memo3(AssistantRuntimeProviderImpl);
1644
1811
 
@@ -1650,6 +1817,7 @@ __export(internal_exports, {
1650
1817
  });
1651
1818
  export {
1652
1819
  actionBar_exports as ActionBarPrimitive,
1820
+ assistantModal_exports as AssistantModalPrimitive,
1653
1821
  AssistantRuntimeProvider,
1654
1822
  branchPicker_exports as BranchPickerPrimitive,
1655
1823
  composer_exports as ComposerPrimitive,