@assistant-ui/mcp-docs-server 0.1.14 → 0.1.16
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/.docs/organized/code-examples/store-example.md +628 -0
- package/.docs/organized/code-examples/with-ag-ui.md +792 -178
- package/.docs/organized/code-examples/with-ai-sdk-v5.md +762 -209
- package/.docs/organized/code-examples/with-assistant-transport.md +707 -254
- package/.docs/organized/code-examples/with-cloud.md +848 -202
- package/.docs/organized/code-examples/with-custom-thread-list.md +1855 -0
- package/.docs/organized/code-examples/with-external-store.md +788 -172
- package/.docs/organized/code-examples/with-ffmpeg.md +796 -196
- package/.docs/organized/code-examples/with-langgraph.md +864 -230
- package/.docs/organized/code-examples/with-parent-id-grouping.md +785 -255
- package/.docs/organized/code-examples/with-react-hook-form.md +804 -226
- package/.docs/organized/code-examples/with-tanstack.md +1574 -0
- package/.docs/raw/blog/2024-07-29-hello/index.mdx +2 -3
- package/.docs/raw/docs/api-reference/overview.mdx +6 -6
- package/.docs/raw/docs/api-reference/primitives/ActionBar.mdx +85 -4
- package/.docs/raw/docs/api-reference/primitives/AssistantIf.mdx +200 -0
- package/.docs/raw/docs/api-reference/primitives/Composer.mdx +0 -20
- package/.docs/raw/docs/api-reference/primitives/Message.mdx +0 -45
- package/.docs/raw/docs/api-reference/primitives/Thread.mdx +0 -50
- package/.docs/raw/docs/cli.mdx +396 -0
- package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +2 -3
- package/.docs/raw/docs/cloud/persistence/langgraph.mdx +2 -3
- package/.docs/raw/docs/devtools.mdx +2 -3
- package/.docs/raw/docs/getting-started.mdx +37 -1109
- package/.docs/raw/docs/guides/Attachments.mdx +3 -25
- package/.docs/raw/docs/guides/Branching.mdx +1 -1
- package/.docs/raw/docs/guides/Speech.mdx +1 -1
- package/.docs/raw/docs/guides/ToolUI.mdx +1 -1
- package/.docs/raw/docs/legacy/styled/AssistantModal.mdx +2 -3
- package/.docs/raw/docs/legacy/styled/Decomposition.mdx +6 -5
- package/.docs/raw/docs/legacy/styled/Markdown.mdx +2 -3
- package/.docs/raw/docs/legacy/styled/Thread.mdx +2 -3
- package/.docs/raw/docs/react-compatibility.mdx +2 -5
- package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +3 -4
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +3 -6
- package/.docs/raw/docs/runtimes/assistant-transport.mdx +891 -0
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +2 -3
- package/.docs/raw/docs/runtimes/custom/local.mdx +11 -41
- package/.docs/raw/docs/runtimes/data-stream.mdx +15 -11
- package/.docs/raw/docs/runtimes/langgraph/index.mdx +4 -4
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +2 -3
- package/.docs/raw/docs/runtimes/langserve.mdx +2 -3
- package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +2 -3
- package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +2 -3
- package/.docs/raw/docs/ui/AssistantModal.mdx +3 -25
- package/.docs/raw/docs/ui/AssistantSidebar.mdx +2 -24
- package/.docs/raw/docs/ui/Attachment.mdx +3 -25
- package/.docs/raw/docs/ui/Markdown.mdx +2 -24
- package/.docs/raw/docs/ui/Mermaid.mdx +2 -24
- package/.docs/raw/docs/ui/Reasoning.mdx +2 -24
- package/.docs/raw/docs/ui/Scrollbar.mdx +4 -6
- package/.docs/raw/docs/ui/SyntaxHighlighting.mdx +3 -47
- package/.docs/raw/docs/ui/Thread.mdx +38 -53
- package/.docs/raw/docs/ui/ThreadList.mdx +4 -47
- package/.docs/raw/docs/ui/ToolFallback.mdx +2 -24
- package/package.json +15 -8
|
@@ -421,6 +421,247 @@ export default function Home() {
|
|
|
421
421
|
|
|
422
422
|
```
|
|
423
423
|
|
|
424
|
+
## components/assistant-ui/attachment.tsx
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
"use client";
|
|
428
|
+
|
|
429
|
+
import { PropsWithChildren, useEffect, useState, type FC } from "react";
|
|
430
|
+
import Image from "next/image";
|
|
431
|
+
import { XIcon, PlusIcon, FileText } from "lucide-react";
|
|
432
|
+
import {
|
|
433
|
+
AttachmentPrimitive,
|
|
434
|
+
ComposerPrimitive,
|
|
435
|
+
MessagePrimitive,
|
|
436
|
+
useAssistantState,
|
|
437
|
+
useAssistantApi,
|
|
438
|
+
} from "@assistant-ui/react";
|
|
439
|
+
import { useShallow } from "zustand/shallow";
|
|
440
|
+
import {
|
|
441
|
+
Tooltip,
|
|
442
|
+
TooltipContent,
|
|
443
|
+
TooltipTrigger,
|
|
444
|
+
} from "@/components/ui/tooltip";
|
|
445
|
+
import {
|
|
446
|
+
Dialog,
|
|
447
|
+
DialogTitle,
|
|
448
|
+
DialogContent,
|
|
449
|
+
DialogTrigger,
|
|
450
|
+
} from "@/components/ui/dialog";
|
|
451
|
+
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
|
452
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
453
|
+
import { cn } from "@/lib/utils";
|
|
454
|
+
|
|
455
|
+
const useFileSrc = (file: File | undefined) => {
|
|
456
|
+
const [src, setSrc] = useState<string | undefined>(undefined);
|
|
457
|
+
|
|
458
|
+
useEffect(() => {
|
|
459
|
+
if (!file) {
|
|
460
|
+
setSrc(undefined);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const objectUrl = URL.createObjectURL(file);
|
|
465
|
+
setSrc(objectUrl);
|
|
466
|
+
|
|
467
|
+
return () => {
|
|
468
|
+
URL.revokeObjectURL(objectUrl);
|
|
469
|
+
};
|
|
470
|
+
}, [file]);
|
|
471
|
+
|
|
472
|
+
return src;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const useAttachmentSrc = () => {
|
|
476
|
+
const { file, src } = useAssistantState(
|
|
477
|
+
useShallow(({ attachment }): { file?: File; src?: string } => {
|
|
478
|
+
if (attachment.type !== "image") return {};
|
|
479
|
+
if (attachment.file) return { file: attachment.file };
|
|
480
|
+
const src = attachment.content?.filter((c) => c.type === "image")[0]
|
|
481
|
+
?.image;
|
|
482
|
+
if (!src) return {};
|
|
483
|
+
return { src };
|
|
484
|
+
}),
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
return useFileSrc(file) ?? src;
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
type AttachmentPreviewProps = {
|
|
491
|
+
src: string;
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
const AttachmentPreview: FC<AttachmentPreviewProps> = ({ src }) => {
|
|
495
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
496
|
+
return (
|
|
497
|
+
<Image
|
|
498
|
+
src={src}
|
|
499
|
+
alt="Image Preview"
|
|
500
|
+
width={1}
|
|
501
|
+
height={1}
|
|
502
|
+
className={
|
|
503
|
+
isLoaded
|
|
504
|
+
? "aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain"
|
|
505
|
+
: "aui-attachment-preview-image-loading hidden"
|
|
506
|
+
}
|
|
507
|
+
onLoadingComplete={() => setIsLoaded(true)}
|
|
508
|
+
priority={false}
|
|
509
|
+
/>
|
|
510
|
+
);
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
|
|
514
|
+
const src = useAttachmentSrc();
|
|
515
|
+
|
|
516
|
+
if (!src) return children;
|
|
517
|
+
|
|
518
|
+
return (
|
|
519
|
+
<Dialog>
|
|
520
|
+
<DialogTrigger
|
|
521
|
+
className="aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50"
|
|
522
|
+
asChild
|
|
523
|
+
>
|
|
524
|
+
{children}
|
|
525
|
+
</DialogTrigger>
|
|
526
|
+
<DialogContent className="aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:ring-0! [&_svg]:text-background [&>button]:hover:[&_svg]:text-destructive">
|
|
527
|
+
<DialogTitle className="aui-sr-only sr-only">
|
|
528
|
+
Image Attachment Preview
|
|
529
|
+
</DialogTitle>
|
|
530
|
+
<div className="aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background">
|
|
531
|
+
<AttachmentPreview src={src} />
|
|
532
|
+
</div>
|
|
533
|
+
</DialogContent>
|
|
534
|
+
</Dialog>
|
|
535
|
+
);
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
const AttachmentThumb: FC = () => {
|
|
539
|
+
const isImage = useAssistantState(
|
|
540
|
+
({ attachment }) => attachment.type === "image",
|
|
541
|
+
);
|
|
542
|
+
const src = useAttachmentSrc();
|
|
543
|
+
|
|
544
|
+
return (
|
|
545
|
+
<Avatar className="aui-attachment-tile-avatar h-full w-full rounded-none">
|
|
546
|
+
<AvatarImage
|
|
547
|
+
src={src}
|
|
548
|
+
alt="Attachment preview"
|
|
549
|
+
className="aui-attachment-tile-image object-cover"
|
|
550
|
+
/>
|
|
551
|
+
<AvatarFallback delayMs={isImage ? 200 : 0}>
|
|
552
|
+
<FileText className="aui-attachment-tile-fallback-icon size-8 text-muted-foreground" />
|
|
553
|
+
</AvatarFallback>
|
|
554
|
+
</Avatar>
|
|
555
|
+
);
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
const AttachmentUI: FC = () => {
|
|
559
|
+
const api = useAssistantApi();
|
|
560
|
+
const isComposer = api.attachment.source === "composer";
|
|
561
|
+
|
|
562
|
+
const isImage = useAssistantState(
|
|
563
|
+
({ attachment }) => attachment.type === "image",
|
|
564
|
+
);
|
|
565
|
+
const typeLabel = useAssistantState(({ attachment }) => {
|
|
566
|
+
const type = attachment.type;
|
|
567
|
+
switch (type) {
|
|
568
|
+
case "image":
|
|
569
|
+
return "Image";
|
|
570
|
+
case "document":
|
|
571
|
+
return "Document";
|
|
572
|
+
case "file":
|
|
573
|
+
return "File";
|
|
574
|
+
default:
|
|
575
|
+
const _exhaustiveCheck: never = type;
|
|
576
|
+
throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
return (
|
|
581
|
+
<Tooltip>
|
|
582
|
+
<AttachmentPrimitive.Root
|
|
583
|
+
className={cn(
|
|
584
|
+
"aui-attachment-root relative",
|
|
585
|
+
isImage &&
|
|
586
|
+
"aui-attachment-root-composer only:[&>#attachment-tile]:size-24",
|
|
587
|
+
)}
|
|
588
|
+
>
|
|
589
|
+
<AttachmentPreviewDialog>
|
|
590
|
+
<TooltipTrigger asChild>
|
|
591
|
+
<div
|
|
592
|
+
className={cn(
|
|
593
|
+
"aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
|
|
594
|
+
isComposer &&
|
|
595
|
+
"aui-attachment-tile-composer border-foreground/20",
|
|
596
|
+
)}
|
|
597
|
+
role="button"
|
|
598
|
+
id="attachment-tile"
|
|
599
|
+
aria-label={`${typeLabel} attachment`}
|
|
600
|
+
>
|
|
601
|
+
<AttachmentThumb />
|
|
602
|
+
</div>
|
|
603
|
+
</TooltipTrigger>
|
|
604
|
+
</AttachmentPreviewDialog>
|
|
605
|
+
{isComposer && <AttachmentRemove />}
|
|
606
|
+
</AttachmentPrimitive.Root>
|
|
607
|
+
<TooltipContent side="top">
|
|
608
|
+
<AttachmentPrimitive.Name />
|
|
609
|
+
</TooltipContent>
|
|
610
|
+
</Tooltip>
|
|
611
|
+
);
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
const AttachmentRemove: FC = () => {
|
|
615
|
+
return (
|
|
616
|
+
<AttachmentPrimitive.Remove asChild>
|
|
617
|
+
<TooltipIconButton
|
|
618
|
+
tooltip="Remove file"
|
|
619
|
+
className="aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white text-muted-foreground opacity-100 shadow-sm hover:bg-white! [&_svg]:text-black hover:[&_svg]:text-destructive"
|
|
620
|
+
side="top"
|
|
621
|
+
>
|
|
622
|
+
<XIcon className="aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" />
|
|
623
|
+
</TooltipIconButton>
|
|
624
|
+
</AttachmentPrimitive.Remove>
|
|
625
|
+
);
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
export const UserMessageAttachments: FC = () => {
|
|
629
|
+
return (
|
|
630
|
+
<div className="aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2">
|
|
631
|
+
<MessagePrimitive.Attachments components={{ Attachment: AttachmentUI }} />
|
|
632
|
+
</div>
|
|
633
|
+
);
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
export const ComposerAttachments: FC = () => {
|
|
637
|
+
return (
|
|
638
|
+
<div className="aui-composer-attachments mb-2 flex w-full flex-row items-center gap-2 overflow-x-auto px-1.5 pt-0.5 pb-1 empty:hidden">
|
|
639
|
+
<ComposerPrimitive.Attachments
|
|
640
|
+
components={{ Attachment: AttachmentUI }}
|
|
641
|
+
/>
|
|
642
|
+
</div>
|
|
643
|
+
);
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
export const ComposerAddAttachment: FC = () => {
|
|
647
|
+
return (
|
|
648
|
+
<ComposerPrimitive.AddAttachment asChild>
|
|
649
|
+
<TooltipIconButton
|
|
650
|
+
tooltip="Add Attachment"
|
|
651
|
+
side="bottom"
|
|
652
|
+
variant="ghost"
|
|
653
|
+
size="icon"
|
|
654
|
+
className="aui-composer-add-attachment size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30"
|
|
655
|
+
aria-label="Add Attachment"
|
|
656
|
+
>
|
|
657
|
+
<PlusIcon className="aui-attachment-add-icon size-5 stroke-[1.5px]" />
|
|
658
|
+
</TooltipIconButton>
|
|
659
|
+
</ComposerPrimitive.AddAttachment>
|
|
660
|
+
);
|
|
661
|
+
};
|
|
662
|
+
|
|
663
|
+
```
|
|
664
|
+
|
|
424
665
|
## components/assistant-ui/markdown-text.tsx
|
|
425
666
|
|
|
426
667
|
```tsx
|
|
@@ -429,13 +670,13 @@ export default function Home() {
|
|
|
429
670
|
import "@assistant-ui/react-markdown/styles/dot.css";
|
|
430
671
|
|
|
431
672
|
import {
|
|
432
|
-
CodeHeaderProps,
|
|
673
|
+
type CodeHeaderProps,
|
|
433
674
|
MarkdownTextPrimitive,
|
|
434
675
|
unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,
|
|
435
676
|
useIsMarkdownCodeBlock,
|
|
436
677
|
} from "@assistant-ui/react-markdown";
|
|
437
678
|
import remarkGfm from "remark-gfm";
|
|
438
|
-
import { FC, memo, useState } from "react";
|
|
679
|
+
import { type FC, memo, useState } from "react";
|
|
439
680
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
440
681
|
|
|
441
682
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
@@ -461,8 +702,10 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
|
|
|
461
702
|
};
|
|
462
703
|
|
|
463
704
|
return (
|
|
464
|
-
<div className="flex items-center justify-between gap-4 rounded-t-lg bg-
|
|
465
|
-
<span className="lowercase [&>span]:text-xs">
|
|
705
|
+
<div className="aui-code-header-root mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-muted-foreground/15 px-4 py-2 font-semibold text-foreground text-sm dark:bg-muted-foreground/20">
|
|
706
|
+
<span className="aui-code-header-language lowercase [&>span]:text-xs">
|
|
707
|
+
{language}
|
|
708
|
+
</span>
|
|
466
709
|
<TooltipIconButton tooltip="Copy" onClick={onCopy}>
|
|
467
710
|
{!isCopied && <CopyIcon />}
|
|
468
711
|
{isCopied && <CheckIcon />}
|
|
@@ -494,7 +737,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
494
737
|
h1: ({ className, ...props }) => (
|
|
495
738
|
<h1
|
|
496
739
|
className={cn(
|
|
497
|
-
"mb-8 scroll-m-20 text-4xl
|
|
740
|
+
"aui-md-h1 mb-8 scroll-m-20 font-extrabold text-4xl tracking-tight last:mb-0",
|
|
498
741
|
className,
|
|
499
742
|
)}
|
|
500
743
|
{...props}
|
|
@@ -503,7 +746,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
503
746
|
h2: ({ className, ...props }) => (
|
|
504
747
|
<h2
|
|
505
748
|
className={cn(
|
|
506
|
-
"mt-8 mb-4 scroll-m-20 text-3xl
|
|
749
|
+
"aui-md-h2 mt-8 mb-4 scroll-m-20 font-semibold text-3xl tracking-tight first:mt-0 last:mb-0",
|
|
507
750
|
className,
|
|
508
751
|
)}
|
|
509
752
|
{...props}
|
|
@@ -512,7 +755,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
512
755
|
h3: ({ className, ...props }) => (
|
|
513
756
|
<h3
|
|
514
757
|
className={cn(
|
|
515
|
-
"mt-6 mb-4 scroll-m-20 text-2xl
|
|
758
|
+
"aui-md-h3 mt-6 mb-4 scroll-m-20 font-semibold text-2xl tracking-tight first:mt-0 last:mb-0",
|
|
516
759
|
className,
|
|
517
760
|
)}
|
|
518
761
|
{...props}
|
|
@@ -521,7 +764,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
521
764
|
h4: ({ className, ...props }) => (
|
|
522
765
|
<h4
|
|
523
766
|
className={cn(
|
|
524
|
-
"mt-6 mb-4 scroll-m-20 text-xl
|
|
767
|
+
"aui-md-h4 mt-6 mb-4 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0",
|
|
525
768
|
className,
|
|
526
769
|
)}
|
|
527
770
|
{...props}
|
|
@@ -530,7 +773,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
530
773
|
h5: ({ className, ...props }) => (
|
|
531
774
|
<h5
|
|
532
775
|
className={cn(
|
|
533
|
-
"my-4 text-lg
|
|
776
|
+
"aui-md-h5 my-4 font-semibold text-lg first:mt-0 last:mb-0",
|
|
534
777
|
className,
|
|
535
778
|
)}
|
|
536
779
|
{...props}
|
|
@@ -538,20 +781,26 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
538
781
|
),
|
|
539
782
|
h6: ({ className, ...props }) => (
|
|
540
783
|
<h6
|
|
541
|
-
className={cn(
|
|
784
|
+
className={cn(
|
|
785
|
+
"aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0",
|
|
786
|
+
className,
|
|
787
|
+
)}
|
|
542
788
|
{...props}
|
|
543
789
|
/>
|
|
544
790
|
),
|
|
545
791
|
p: ({ className, ...props }) => (
|
|
546
792
|
<p
|
|
547
|
-
className={cn(
|
|
793
|
+
className={cn(
|
|
794
|
+
"aui-md-p mt-5 mb-5 leading-7 first:mt-0 last:mb-0",
|
|
795
|
+
className,
|
|
796
|
+
)}
|
|
548
797
|
{...props}
|
|
549
798
|
/>
|
|
550
799
|
),
|
|
551
800
|
a: ({ className, ...props }) => (
|
|
552
801
|
<a
|
|
553
802
|
className={cn(
|
|
554
|
-
"
|
|
803
|
+
"aui-md-a font-medium text-primary underline underline-offset-4",
|
|
555
804
|
className,
|
|
556
805
|
)}
|
|
557
806
|
{...props}
|
|
@@ -559,29 +808,29 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
559
808
|
),
|
|
560
809
|
blockquote: ({ className, ...props }) => (
|
|
561
810
|
<blockquote
|
|
562
|
-
className={cn("border-l-2 pl-6 italic", className)}
|
|
811
|
+
className={cn("aui-md-blockquote border-l-2 pl-6 italic", className)}
|
|
563
812
|
{...props}
|
|
564
813
|
/>
|
|
565
814
|
),
|
|
566
815
|
ul: ({ className, ...props }) => (
|
|
567
816
|
<ul
|
|
568
|
-
className={cn("my-5 ml-6 list-disc [&>li]:mt-2", className)}
|
|
817
|
+
className={cn("aui-md-ul my-5 ml-6 list-disc [&>li]:mt-2", className)}
|
|
569
818
|
{...props}
|
|
570
819
|
/>
|
|
571
820
|
),
|
|
572
821
|
ol: ({ className, ...props }) => (
|
|
573
822
|
<ol
|
|
574
|
-
className={cn("my-5 ml-6 list-decimal [&>li]:mt-2", className)}
|
|
823
|
+
className={cn("aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2", className)}
|
|
575
824
|
{...props}
|
|
576
825
|
/>
|
|
577
826
|
),
|
|
578
827
|
hr: ({ className, ...props }) => (
|
|
579
|
-
<hr className={cn("my-5 border-b", className)} {...props} />
|
|
828
|
+
<hr className={cn("aui-md-hr my-5 border-b", className)} {...props} />
|
|
580
829
|
),
|
|
581
830
|
table: ({ className, ...props }) => (
|
|
582
831
|
<table
|
|
583
832
|
className={cn(
|
|
584
|
-
"my-5 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
833
|
+
"aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
585
834
|
className,
|
|
586
835
|
)}
|
|
587
836
|
{...props}
|
|
@@ -590,7 +839,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
590
839
|
th: ({ className, ...props }) => (
|
|
591
840
|
<th
|
|
592
841
|
className={cn(
|
|
593
|
-
"bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [
|
|
842
|
+
"aui-md-th bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [[align=center]]:text-center [[align=right]]:text-right",
|
|
594
843
|
className,
|
|
595
844
|
)}
|
|
596
845
|
{...props}
|
|
@@ -599,7 +848,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
599
848
|
td: ({ className, ...props }) => (
|
|
600
849
|
<td
|
|
601
850
|
className={cn(
|
|
602
|
-
"border-b border-l px-4 py-2 text-left last:border-r [
|
|
851
|
+
"aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right",
|
|
603
852
|
className,
|
|
604
853
|
)}
|
|
605
854
|
{...props}
|
|
@@ -608,7 +857,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
608
857
|
tr: ({ className, ...props }) => (
|
|
609
858
|
<tr
|
|
610
859
|
className={cn(
|
|
611
|
-
"m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg",
|
|
860
|
+
"aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg",
|
|
612
861
|
className,
|
|
613
862
|
)}
|
|
614
863
|
{...props}
|
|
@@ -616,14 +865,14 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
616
865
|
),
|
|
617
866
|
sup: ({ className, ...props }) => (
|
|
618
867
|
<sup
|
|
619
|
-
className={cn("[&>a]:text-xs [&>a]:no-underline", className)}
|
|
868
|
+
className={cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className)}
|
|
620
869
|
{...props}
|
|
621
870
|
/>
|
|
622
871
|
),
|
|
623
872
|
pre: ({ className, ...props }) => (
|
|
624
873
|
<pre
|
|
625
874
|
className={cn(
|
|
626
|
-
"overflow-x-auto rounded-b-lg bg-black p-4 text-white",
|
|
875
|
+
"aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-black p-4 text-white",
|
|
627
876
|
className,
|
|
628
877
|
)}
|
|
629
878
|
{...props}
|
|
@@ -634,7 +883,8 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
634
883
|
return (
|
|
635
884
|
<code
|
|
636
885
|
className={cn(
|
|
637
|
-
!isCodeBlock &&
|
|
886
|
+
!isCodeBlock &&
|
|
887
|
+
"aui-md-inline-code rounded border bg-muted font-semibold",
|
|
638
888
|
className,
|
|
639
889
|
)}
|
|
640
890
|
{...props}
|
|
@@ -649,60 +899,67 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
649
899
|
## components/assistant-ui/thread.tsx
|
|
650
900
|
|
|
651
901
|
```tsx
|
|
902
|
+
import {
|
|
903
|
+
ComposerAddAttachment,
|
|
904
|
+
ComposerAttachments,
|
|
905
|
+
UserMessageAttachments,
|
|
906
|
+
} from "@/components/assistant-ui/attachment";
|
|
907
|
+
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
908
|
+
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
|
909
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
910
|
+
import { Button } from "@/components/ui/button";
|
|
911
|
+
import { cn } from "@/lib/utils";
|
|
652
912
|
import {
|
|
653
913
|
ActionBarPrimitive,
|
|
914
|
+
AssistantIf,
|
|
654
915
|
BranchPickerPrimitive,
|
|
655
916
|
ComposerPrimitive,
|
|
917
|
+
ErrorPrimitive,
|
|
656
918
|
MessagePrimitive,
|
|
657
919
|
ThreadPrimitive,
|
|
658
920
|
} from "@assistant-ui/react";
|
|
659
|
-
import type { FC, PropsWithChildren } from "react";
|
|
660
921
|
import {
|
|
661
922
|
ArrowDownIcon,
|
|
923
|
+
ArrowUpIcon,
|
|
662
924
|
CheckIcon,
|
|
663
925
|
ChevronLeftIcon,
|
|
664
926
|
ChevronRightIcon,
|
|
665
927
|
CopyIcon,
|
|
928
|
+
DownloadIcon,
|
|
666
929
|
PencilIcon,
|
|
667
930
|
RefreshCwIcon,
|
|
668
|
-
|
|
669
|
-
ChevronDownIcon,
|
|
670
|
-
ChevronUpIcon,
|
|
931
|
+
SquareIcon,
|
|
671
932
|
} from "lucide-react";
|
|
672
|
-
import {
|
|
673
|
-
|
|
674
|
-
import { Button } from "@/components/ui/button";
|
|
675
|
-
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
676
|
-
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
677
|
-
import { useState } from "react";
|
|
933
|
+
import type { FC } from "react";
|
|
678
934
|
|
|
679
935
|
export const Thread: FC = () => {
|
|
680
936
|
return (
|
|
681
937
|
<ThreadPrimitive.Root
|
|
682
|
-
className="
|
|
938
|
+
className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
|
|
683
939
|
style={{
|
|
684
|
-
["--thread-max-width" as string]: "
|
|
940
|
+
["--thread-max-width" as string]: "44rem",
|
|
685
941
|
}}
|
|
686
942
|
>
|
|
687
|
-
<ThreadPrimitive.Viewport
|
|
688
|
-
|
|
943
|
+
<ThreadPrimitive.Viewport
|
|
944
|
+
turnAnchor="top"
|
|
945
|
+
className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
|
|
946
|
+
>
|
|
947
|
+
<AssistantIf condition={({ thread }) => thread.isEmpty}>
|
|
948
|
+
<ThreadWelcome />
|
|
949
|
+
</AssistantIf>
|
|
689
950
|
|
|
690
951
|
<ThreadPrimitive.Messages
|
|
691
952
|
components={{
|
|
692
|
-
UserMessage
|
|
693
|
-
EditComposer
|
|
694
|
-
AssistantMessage
|
|
953
|
+
UserMessage,
|
|
954
|
+
EditComposer,
|
|
955
|
+
AssistantMessage,
|
|
695
956
|
}}
|
|
696
957
|
/>
|
|
697
958
|
|
|
698
|
-
<ThreadPrimitive.
|
|
699
|
-
<div className="min-h-8 flex-grow" />
|
|
700
|
-
</ThreadPrimitive.If>
|
|
701
|
-
|
|
702
|
-
<div className="sticky bottom-0 mt-3 flex w-full max-w-[var(--thread-max-width)] flex-col items-center justify-end rounded-t-lg bg-inherit pb-4">
|
|
959
|
+
<ThreadPrimitive.ViewportFooter className="aui-thread-viewport-footer sticky bottom-0 mx-auto mt-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6">
|
|
703
960
|
<ThreadScrollToBottom />
|
|
704
961
|
<Composer />
|
|
705
|
-
</
|
|
962
|
+
</ThreadPrimitive.ViewportFooter>
|
|
706
963
|
</ThreadPrimitive.Viewport>
|
|
707
964
|
</ThreadPrimitive.Root>
|
|
708
965
|
);
|
|
@@ -714,7 +971,7 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
714
971
|
<TooltipIconButton
|
|
715
972
|
tooltip="Scroll to bottom"
|
|
716
973
|
variant="outline"
|
|
717
|
-
className="
|
|
974
|
+
className="aui-thread-scroll-to-bottom -top-12 absolute z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent"
|
|
718
975
|
>
|
|
719
976
|
<ArrowDownIcon />
|
|
720
977
|
</TooltipIconButton>
|
|
@@ -724,227 +981,150 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
724
981
|
|
|
725
982
|
const ThreadWelcome: FC = () => {
|
|
726
983
|
return (
|
|
727
|
-
<
|
|
728
|
-
<div className="
|
|
729
|
-
<div className="flex
|
|
730
|
-
<
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
984
|
+
<div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
|
|
985
|
+
<div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
|
|
986
|
+
<div className="aui-thread-welcome-message flex size-full flex-col justify-center px-4">
|
|
987
|
+
<h1 className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-2xl duration-200">
|
|
988
|
+
Hello there!
|
|
989
|
+
</h1>
|
|
990
|
+
<p className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in text-muted-foreground text-xl delay-75 duration-200">
|
|
991
|
+
How can I help you today?
|
|
734
992
|
</p>
|
|
735
993
|
</div>
|
|
736
|
-
<ThreadWelcomeSuggestions />
|
|
737
994
|
</div>
|
|
738
|
-
|
|
995
|
+
<ThreadSuggestions />
|
|
996
|
+
</div>
|
|
739
997
|
);
|
|
740
998
|
};
|
|
741
999
|
|
|
742
|
-
const
|
|
1000
|
+
const SUGGESTIONS = [
|
|
1001
|
+
{
|
|
1002
|
+
title: "What's the weather",
|
|
1003
|
+
label: "in San Francisco?",
|
|
1004
|
+
prompt: "What's the weather in San Francisco?",
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
title: "Explain React hooks",
|
|
1008
|
+
label: "like useState and useEffect",
|
|
1009
|
+
prompt: "Explain React hooks like useState and useEffect",
|
|
1010
|
+
},
|
|
1011
|
+
] as const;
|
|
1012
|
+
|
|
1013
|
+
const ThreadSuggestions: FC = () => {
|
|
743
1014
|
return (
|
|
744
|
-
<div className="
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
1015
|
+
<div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
|
|
1016
|
+
{SUGGESTIONS.map((suggestion, index) => (
|
|
1017
|
+
<div
|
|
1018
|
+
key={suggestion.prompt}
|
|
1019
|
+
className="aui-thread-welcome-suggestion-display fade-in slide-in-from-bottom-2 @md:nth-[n+3]:block nth-[n+3]:hidden animate-in fill-mode-both duration-200"
|
|
1020
|
+
style={{ animationDelay: `${100 + index * 50}ms` }}
|
|
1021
|
+
>
|
|
1022
|
+
<ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
|
|
1023
|
+
<Button
|
|
1024
|
+
variant="ghost"
|
|
1025
|
+
className="aui-thread-welcome-suggestion h-auto w-full @md:flex-col flex-wrap items-start justify-start gap-1 rounded-2xl border px-4 py-3 text-left text-sm transition-colors hover:bg-muted"
|
|
1026
|
+
aria-label={suggestion.prompt}
|
|
1027
|
+
>
|
|
1028
|
+
<span className="aui-thread-welcome-suggestion-text-1 font-medium">
|
|
1029
|
+
{suggestion.title}
|
|
1030
|
+
</span>
|
|
1031
|
+
<span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
|
|
1032
|
+
{suggestion.label}
|
|
1033
|
+
</span>
|
|
1034
|
+
</Button>
|
|
1035
|
+
</ThreadPrimitive.Suggestion>
|
|
1036
|
+
</div>
|
|
1037
|
+
))}
|
|
765
1038
|
</div>
|
|
766
1039
|
);
|
|
767
1040
|
};
|
|
768
1041
|
|
|
769
1042
|
const Composer: FC = () => {
|
|
770
1043
|
return (
|
|
771
|
-
<ComposerPrimitive.Root className="
|
|
772
|
-
<ComposerPrimitive.
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
1044
|
+
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
|
|
1045
|
+
<ComposerPrimitive.AttachmentDropzone className="aui-composer-attachment-dropzone flex w-full flex-col rounded-2xl border border-input bg-background px-1 pt-2 outline-none transition-shadow has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-2 has-[textarea:focus-visible]:ring-ring/20 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50">
|
|
1046
|
+
<ComposerAttachments />
|
|
1047
|
+
<ComposerPrimitive.Input
|
|
1048
|
+
placeholder="Send a message..."
|
|
1049
|
+
className="aui-composer-input mb-1 max-h-32 min-h-14 w-full resize-none bg-transparent px-4 pt-2 pb-3 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-0"
|
|
1050
|
+
rows={1}
|
|
1051
|
+
autoFocus
|
|
1052
|
+
aria-label="Message input"
|
|
1053
|
+
/>
|
|
1054
|
+
<ComposerAction />
|
|
1055
|
+
</ComposerPrimitive.AttachmentDropzone>
|
|
779
1056
|
</ComposerPrimitive.Root>
|
|
780
1057
|
);
|
|
781
1058
|
};
|
|
782
1059
|
|
|
783
1060
|
const ComposerAction: FC = () => {
|
|
784
1061
|
return (
|
|
785
|
-
|
|
786
|
-
<
|
|
1062
|
+
<div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
|
|
1063
|
+
<ComposerAddAttachment />
|
|
1064
|
+
|
|
1065
|
+
<AssistantIf condition={({ thread }) => !thread.isRunning}>
|
|
787
1066
|
<ComposerPrimitive.Send asChild>
|
|
788
1067
|
<TooltipIconButton
|
|
789
|
-
tooltip="Send"
|
|
1068
|
+
tooltip="Send message"
|
|
1069
|
+
side="bottom"
|
|
1070
|
+
type="submit"
|
|
790
1071
|
variant="default"
|
|
791
|
-
|
|
1072
|
+
size="icon"
|
|
1073
|
+
className="aui-composer-send size-8 rounded-full"
|
|
1074
|
+
aria-label="Send message"
|
|
792
1075
|
>
|
|
793
|
-
<
|
|
1076
|
+
<ArrowUpIcon className="aui-composer-send-icon size-4" />
|
|
794
1077
|
</TooltipIconButton>
|
|
795
1078
|
</ComposerPrimitive.Send>
|
|
796
|
-
</
|
|
797
|
-
|
|
1079
|
+
</AssistantIf>
|
|
1080
|
+
|
|
1081
|
+
<AssistantIf condition={({ thread }) => thread.isRunning}>
|
|
798
1082
|
<ComposerPrimitive.Cancel asChild>
|
|
799
|
-
<
|
|
800
|
-
|
|
1083
|
+
<Button
|
|
1084
|
+
type="button"
|
|
801
1085
|
variant="default"
|
|
802
|
-
|
|
1086
|
+
size="icon"
|
|
1087
|
+
className="aui-composer-cancel size-8 rounded-full"
|
|
1088
|
+
aria-label="Stop generating"
|
|
803
1089
|
>
|
|
804
|
-
<
|
|
805
|
-
</
|
|
1090
|
+
<SquareIcon className="aui-composer-cancel-icon size-3 fill-current" />
|
|
1091
|
+
</Button>
|
|
806
1092
|
</ComposerPrimitive.Cancel>
|
|
807
|
-
</
|
|
808
|
-
|
|
809
|
-
);
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
const UserMessage: FC = () => {
|
|
813
|
-
return (
|
|
814
|
-
<MessagePrimitive.Root className="grid w-full max-w-[var(--thread-max-width)] auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 py-4 [&:where(>*)]:col-start-2">
|
|
815
|
-
<UserActionBar />
|
|
816
|
-
|
|
817
|
-
<div className="bg-muted text-foreground col-start-2 row-start-2 max-w-[calc(var(--thread-max-width)*0.8)] rounded-3xl px-5 py-2.5 break-words">
|
|
818
|
-
<MessagePrimitive.Parts />
|
|
819
|
-
</div>
|
|
820
|
-
|
|
821
|
-
<BranchPicker className="col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
|
|
822
|
-
</MessagePrimitive.Root>
|
|
823
|
-
);
|
|
824
|
-
};
|
|
825
|
-
|
|
826
|
-
const UserActionBar: FC = () => {
|
|
827
|
-
return (
|
|
828
|
-
<ActionBarPrimitive.Root
|
|
829
|
-
hideWhenRunning
|
|
830
|
-
autohide="not-last"
|
|
831
|
-
className="col-start-1 row-start-2 mt-2.5 mr-3 flex flex-col items-end"
|
|
832
|
-
>
|
|
833
|
-
<ActionBarPrimitive.Edit asChild>
|
|
834
|
-
<TooltipIconButton tooltip="Edit">
|
|
835
|
-
<PencilIcon />
|
|
836
|
-
</TooltipIconButton>
|
|
837
|
-
</ActionBarPrimitive.Edit>
|
|
838
|
-
</ActionBarPrimitive.Root>
|
|
839
|
-
);
|
|
840
|
-
};
|
|
841
|
-
|
|
842
|
-
const EditComposer: FC = () => {
|
|
843
|
-
return (
|
|
844
|
-
<ComposerPrimitive.Root className="bg-muted my-4 flex w-full max-w-[var(--thread-max-width)] flex-col gap-2 rounded-xl">
|
|
845
|
-
<ComposerPrimitive.Input className="text-foreground flex h-8 w-full resize-none bg-transparent p-4 pb-0 outline-none" />
|
|
846
|
-
|
|
847
|
-
<div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
|
|
848
|
-
<ComposerPrimitive.Cancel asChild>
|
|
849
|
-
<Button variant="ghost">Cancel</Button>
|
|
850
|
-
</ComposerPrimitive.Cancel>
|
|
851
|
-
<ComposerPrimitive.Send asChild>
|
|
852
|
-
<Button>Send</Button>
|
|
853
|
-
</ComposerPrimitive.Send>
|
|
854
|
-
</div>
|
|
855
|
-
</ComposerPrimitive.Root>
|
|
1093
|
+
</AssistantIf>
|
|
1094
|
+
</div>
|
|
856
1095
|
);
|
|
857
1096
|
};
|
|
858
1097
|
|
|
859
|
-
|
|
860
|
-
const ParentIdGroup: FC<
|
|
861
|
-
PropsWithChildren<{ groupKey: string | undefined; indices: number[] }>
|
|
862
|
-
> = ({ groupKey, indices, children }) => {
|
|
863
|
-
const [isCollapsed, setIsCollapsed] = useState(false);
|
|
864
|
-
|
|
865
|
-
if (!groupKey) {
|
|
866
|
-
// Ungrouped parts - just render them directly
|
|
867
|
-
return <>{children}</>;
|
|
868
|
-
}
|
|
869
|
-
|
|
1098
|
+
const MessageError: FC = () => {
|
|
870
1099
|
return (
|
|
871
|
-
<
|
|
872
|
-
<
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
<span className="flex items-center gap-2">
|
|
877
|
-
<span className="text-muted-foreground">Research Group:</span>
|
|
878
|
-
<span className="text-foreground">
|
|
879
|
-
{groupKey === "research-climate-causes" && "Climate Change Causes"}
|
|
880
|
-
{groupKey === "research-climate-effects" &&
|
|
881
|
-
"Climate Change Effects"}
|
|
882
|
-
{groupKey === "new-research" && "Recent Research"}
|
|
883
|
-
{![
|
|
884
|
-
"research-climate-causes",
|
|
885
|
-
"research-climate-effects",
|
|
886
|
-
"new-research",
|
|
887
|
-
].includes(groupKey) && groupKey}
|
|
888
|
-
</span>
|
|
889
|
-
<span className="text-muted-foreground text-xs">
|
|
890
|
-
({indices.length} parts)
|
|
891
|
-
</span>
|
|
892
|
-
</span>
|
|
893
|
-
{isCollapsed ? (
|
|
894
|
-
<ChevronDownIcon className="h-4 w-4" />
|
|
895
|
-
) : (
|
|
896
|
-
<ChevronUpIcon className="h-4 w-4" />
|
|
897
|
-
)}
|
|
898
|
-
</button>
|
|
899
|
-
{!isCollapsed && <div className="space-y-2 px-4 py-2">{children}</div>}
|
|
900
|
-
</div>
|
|
1100
|
+
<MessagePrimitive.Error>
|
|
1101
|
+
<ErrorPrimitive.Root className="aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-destructive text-sm dark:bg-destructive/5 dark:text-red-200">
|
|
1102
|
+
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
|
|
1103
|
+
</ErrorPrimitive.Root>
|
|
1104
|
+
</MessagePrimitive.Error>
|
|
901
1105
|
);
|
|
902
1106
|
};
|
|
903
1107
|
|
|
904
1108
|
const AssistantMessage: FC = () => {
|
|
905
1109
|
return (
|
|
906
|
-
<MessagePrimitive.Root
|
|
907
|
-
|
|
908
|
-
|
|
1110
|
+
<MessagePrimitive.Root
|
|
1111
|
+
className="aui-assistant-message-root fade-in slide-in-from-bottom-1 relative mx-auto w-full max-w-(--thread-max-width) animate-in py-3 duration-150"
|
|
1112
|
+
data-role="assistant"
|
|
1113
|
+
>
|
|
1114
|
+
<div className="aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed">
|
|
1115
|
+
<MessagePrimitive.Parts
|
|
909
1116
|
components={{
|
|
910
1117
|
Text: MarkdownText,
|
|
911
|
-
|
|
912
|
-
Source: ({ url, title }) => (
|
|
913
|
-
<div className="text-muted-foreground text-sm">
|
|
914
|
-
<a
|
|
915
|
-
href={url}
|
|
916
|
-
target="_blank"
|
|
917
|
-
rel="noopener noreferrer"
|
|
918
|
-
className="hover:underline"
|
|
919
|
-
>
|
|
920
|
-
📄 {title || url}
|
|
921
|
-
</a>
|
|
922
|
-
</div>
|
|
923
|
-
),
|
|
924
|
-
tools: {
|
|
925
|
-
Fallback: ({ toolName, args, result }) => (
|
|
926
|
-
<div className="bg-muted/40 my-1 rounded-md p-2 text-sm">
|
|
927
|
-
<div className="text-muted-foreground font-medium">
|
|
928
|
-
🔧 {toolName}
|
|
929
|
-
</div>
|
|
930
|
-
<div className="text-muted-foreground mt-1 text-xs">
|
|
931
|
-
<details>
|
|
932
|
-
<summary className="cursor-pointer">View details</summary>
|
|
933
|
-
<pre className="mt-2 overflow-x-auto">
|
|
934
|
-
{JSON.stringify({ args, result }, null, 2)}
|
|
935
|
-
</pre>
|
|
936
|
-
</details>
|
|
937
|
-
</div>
|
|
938
|
-
</div>
|
|
939
|
-
),
|
|
940
|
-
},
|
|
1118
|
+
tools: { Fallback: ToolFallback },
|
|
941
1119
|
}}
|
|
942
1120
|
/>
|
|
1121
|
+
<MessageError />
|
|
943
1122
|
</div>
|
|
944
1123
|
|
|
945
|
-
<
|
|
946
|
-
|
|
947
|
-
|
|
1124
|
+
<div className="aui-assistant-message-footer mt-1 ml-2 flex">
|
|
1125
|
+
<BranchPicker />
|
|
1126
|
+
<AssistantActionBar />
|
|
1127
|
+
</div>
|
|
948
1128
|
</MessagePrimitive.Root>
|
|
949
1129
|
);
|
|
950
1130
|
};
|
|
@@ -955,18 +1135,23 @@ const AssistantActionBar: FC = () => {
|
|
|
955
1135
|
hideWhenRunning
|
|
956
1136
|
autohide="not-last"
|
|
957
1137
|
autohideFloat="single-branch"
|
|
958
|
-
className="
|
|
1138
|
+
className="aui-assistant-action-bar-root -ml-1 col-start-3 row-start-2 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm"
|
|
959
1139
|
>
|
|
960
1140
|
<ActionBarPrimitive.Copy asChild>
|
|
961
1141
|
<TooltipIconButton tooltip="Copy">
|
|
962
|
-
<
|
|
1142
|
+
<AssistantIf condition={({ message }) => message.isCopied}>
|
|
963
1143
|
<CheckIcon />
|
|
964
|
-
</
|
|
965
|
-
<
|
|
1144
|
+
</AssistantIf>
|
|
1145
|
+
<AssistantIf condition={({ message }) => !message.isCopied}>
|
|
966
1146
|
<CopyIcon />
|
|
967
|
-
</
|
|
1147
|
+
</AssistantIf>
|
|
968
1148
|
</TooltipIconButton>
|
|
969
1149
|
</ActionBarPrimitive.Copy>
|
|
1150
|
+
<ActionBarPrimitive.ExportMarkdown asChild>
|
|
1151
|
+
<TooltipIconButton tooltip="Export as Markdown">
|
|
1152
|
+
<DownloadIcon />
|
|
1153
|
+
</TooltipIconButton>
|
|
1154
|
+
</ActionBarPrimitive.ExportMarkdown>
|
|
970
1155
|
<ActionBarPrimitive.Reload asChild>
|
|
971
1156
|
<TooltipIconButton tooltip="Refresh">
|
|
972
1157
|
<RefreshCwIcon />
|
|
@@ -976,6 +1161,67 @@ const AssistantActionBar: FC = () => {
|
|
|
976
1161
|
);
|
|
977
1162
|
};
|
|
978
1163
|
|
|
1164
|
+
const UserMessage: FC = () => {
|
|
1165
|
+
return (
|
|
1166
|
+
<MessagePrimitive.Root
|
|
1167
|
+
className="aui-user-message-root fade-in slide-in-from-bottom-1 mx-auto grid w-full max-w-(--thread-max-width) animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 py-3 duration-150 [&:where(>*)]:col-start-2"
|
|
1168
|
+
data-role="user"
|
|
1169
|
+
>
|
|
1170
|
+
<UserMessageAttachments />
|
|
1171
|
+
|
|
1172
|
+
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
|
|
1173
|
+
<div className="aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground">
|
|
1174
|
+
<MessagePrimitive.Parts />
|
|
1175
|
+
</div>
|
|
1176
|
+
<div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
|
|
1177
|
+
<UserActionBar />
|
|
1178
|
+
</div>
|
|
1179
|
+
</div>
|
|
1180
|
+
|
|
1181
|
+
<BranchPicker className="aui-user-branch-picker -mr-1 col-span-full col-start-1 row-start-3 justify-end" />
|
|
1182
|
+
</MessagePrimitive.Root>
|
|
1183
|
+
);
|
|
1184
|
+
};
|
|
1185
|
+
|
|
1186
|
+
const UserActionBar: FC = () => {
|
|
1187
|
+
return (
|
|
1188
|
+
<ActionBarPrimitive.Root
|
|
1189
|
+
hideWhenRunning
|
|
1190
|
+
autohide="not-last"
|
|
1191
|
+
className="aui-user-action-bar-root flex flex-col items-end"
|
|
1192
|
+
>
|
|
1193
|
+
<ActionBarPrimitive.Edit asChild>
|
|
1194
|
+
<TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
|
|
1195
|
+
<PencilIcon />
|
|
1196
|
+
</TooltipIconButton>
|
|
1197
|
+
</ActionBarPrimitive.Edit>
|
|
1198
|
+
</ActionBarPrimitive.Root>
|
|
1199
|
+
);
|
|
1200
|
+
};
|
|
1201
|
+
|
|
1202
|
+
const EditComposer: FC = () => {
|
|
1203
|
+
return (
|
|
1204
|
+
<MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3">
|
|
1205
|
+
<ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted">
|
|
1206
|
+
<ComposerPrimitive.Input
|
|
1207
|
+
className="aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none"
|
|
1208
|
+
autoFocus
|
|
1209
|
+
/>
|
|
1210
|
+
<div className="aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end">
|
|
1211
|
+
<ComposerPrimitive.Cancel asChild>
|
|
1212
|
+
<Button variant="ghost" size="sm">
|
|
1213
|
+
Cancel
|
|
1214
|
+
</Button>
|
|
1215
|
+
</ComposerPrimitive.Cancel>
|
|
1216
|
+
<ComposerPrimitive.Send asChild>
|
|
1217
|
+
<Button size="sm">Update</Button>
|
|
1218
|
+
</ComposerPrimitive.Send>
|
|
1219
|
+
</div>
|
|
1220
|
+
</ComposerPrimitive.Root>
|
|
1221
|
+
</MessagePrimitive.Root>
|
|
1222
|
+
);
|
|
1223
|
+
};
|
|
1224
|
+
|
|
979
1225
|
const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
980
1226
|
className,
|
|
981
1227
|
...rest
|
|
@@ -984,7 +1230,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
984
1230
|
<BranchPickerPrimitive.Root
|
|
985
1231
|
hideWhenSingleBranch
|
|
986
1232
|
className={cn(
|
|
987
|
-
"
|
|
1233
|
+
"aui-branch-picker-root -ml-2 mr-2 inline-flex items-center text-muted-foreground text-xs",
|
|
988
1234
|
className,
|
|
989
1235
|
)}
|
|
990
1236
|
{...rest}
|
|
@@ -994,7 +1240,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
994
1240
|
<ChevronLeftIcon />
|
|
995
1241
|
</TooltipIconButton>
|
|
996
1242
|
</BranchPickerPrimitive.Previous>
|
|
997
|
-
<span className="font-medium">
|
|
1243
|
+
<span className="aui-branch-picker-state font-medium">
|
|
998
1244
|
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
|
999
1245
|
</span>
|
|
1000
1246
|
<BranchPickerPrimitive.Next asChild>
|
|
@@ -1006,17 +1252,102 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
1006
1252
|
);
|
|
1007
1253
|
};
|
|
1008
1254
|
|
|
1009
|
-
|
|
1255
|
+
```
|
|
1256
|
+
|
|
1257
|
+
## components/assistant-ui/tool-fallback.tsx
|
|
1258
|
+
|
|
1259
|
+
```tsx
|
|
1260
|
+
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
1261
|
+
import {
|
|
1262
|
+
CheckIcon,
|
|
1263
|
+
ChevronDownIcon,
|
|
1264
|
+
ChevronUpIcon,
|
|
1265
|
+
XCircleIcon,
|
|
1266
|
+
} from "lucide-react";
|
|
1267
|
+
import { useState } from "react";
|
|
1268
|
+
import { Button } from "@/components/ui/button";
|
|
1269
|
+
import { cn } from "@/lib/utils";
|
|
1270
|
+
|
|
1271
|
+
export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
1272
|
+
toolName,
|
|
1273
|
+
argsText,
|
|
1274
|
+
result,
|
|
1275
|
+
status,
|
|
1276
|
+
}) => {
|
|
1277
|
+
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
1278
|
+
|
|
1279
|
+
const isCancelled =
|
|
1280
|
+
status?.type === "incomplete" && status.reason === "cancelled";
|
|
1281
|
+
const cancelledReason =
|
|
1282
|
+
isCancelled && status.error
|
|
1283
|
+
? typeof status.error === "string"
|
|
1284
|
+
? status.error
|
|
1285
|
+
: JSON.stringify(status.error)
|
|
1286
|
+
: null;
|
|
1287
|
+
|
|
1010
1288
|
return (
|
|
1011
|
-
<
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
height="16"
|
|
1289
|
+
<div
|
|
1290
|
+
className={cn(
|
|
1291
|
+
"aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3",
|
|
1292
|
+
isCancelled && "border-muted-foreground/30 bg-muted/30",
|
|
1293
|
+
)}
|
|
1017
1294
|
>
|
|
1018
|
-
<
|
|
1019
|
-
|
|
1295
|
+
<div className="aui-tool-fallback-header flex items-center gap-2 px-4">
|
|
1296
|
+
{isCancelled ? (
|
|
1297
|
+
<XCircleIcon className="aui-tool-fallback-icon size-4 text-muted-foreground" />
|
|
1298
|
+
) : (
|
|
1299
|
+
<CheckIcon className="aui-tool-fallback-icon size-4" />
|
|
1300
|
+
)}
|
|
1301
|
+
<p
|
|
1302
|
+
className={cn(
|
|
1303
|
+
"aui-tool-fallback-title grow",
|
|
1304
|
+
isCancelled && "text-muted-foreground line-through",
|
|
1305
|
+
)}
|
|
1306
|
+
>
|
|
1307
|
+
{isCancelled ? "Cancelled tool: " : "Used tool: "}
|
|
1308
|
+
<b>{toolName}</b>
|
|
1309
|
+
</p>
|
|
1310
|
+
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
1311
|
+
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
1312
|
+
</Button>
|
|
1313
|
+
</div>
|
|
1314
|
+
{!isCollapsed && (
|
|
1315
|
+
<div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
|
|
1316
|
+
{cancelledReason && (
|
|
1317
|
+
<div className="aui-tool-fallback-cancelled-root px-4">
|
|
1318
|
+
<p className="aui-tool-fallback-cancelled-header font-semibold text-muted-foreground">
|
|
1319
|
+
Cancelled reason:
|
|
1320
|
+
</p>
|
|
1321
|
+
<p className="aui-tool-fallback-cancelled-reason text-muted-foreground">
|
|
1322
|
+
{cancelledReason}
|
|
1323
|
+
</p>
|
|
1324
|
+
</div>
|
|
1325
|
+
)}
|
|
1326
|
+
<div
|
|
1327
|
+
className={cn(
|
|
1328
|
+
"aui-tool-fallback-args-root px-4",
|
|
1329
|
+
isCancelled && "opacity-60",
|
|
1330
|
+
)}
|
|
1331
|
+
>
|
|
1332
|
+
<pre className="aui-tool-fallback-args-value whitespace-pre-wrap">
|
|
1333
|
+
{argsText}
|
|
1334
|
+
</pre>
|
|
1335
|
+
</div>
|
|
1336
|
+
{!isCancelled && result !== undefined && (
|
|
1337
|
+
<div className="aui-tool-fallback-result-root border-t border-dashed px-4 pt-2">
|
|
1338
|
+
<p className="aui-tool-fallback-result-header font-semibold">
|
|
1339
|
+
Result:
|
|
1340
|
+
</p>
|
|
1341
|
+
<pre className="aui-tool-fallback-result-content whitespace-pre-wrap">
|
|
1342
|
+
{typeof result === "string"
|
|
1343
|
+
? result
|
|
1344
|
+
: JSON.stringify(result, null, 2)}
|
|
1345
|
+
</pre>
|
|
1346
|
+
</div>
|
|
1347
|
+
)}
|
|
1348
|
+
</div>
|
|
1349
|
+
)}
|
|
1350
|
+
</div>
|
|
1020
1351
|
);
|
|
1021
1352
|
};
|
|
1022
1353
|
|
|
@@ -1027,7 +1358,7 @@ const CircleStopIcon = () => {
|
|
|
1027
1358
|
```tsx
|
|
1028
1359
|
"use client";
|
|
1029
1360
|
|
|
1030
|
-
import {
|
|
1361
|
+
import { ComponentPropsWithRef, forwardRef } from "react";
|
|
1031
1362
|
import { Slottable } from "@radix-ui/react-slot";
|
|
1032
1363
|
|
|
1033
1364
|
import {
|
|
@@ -1038,7 +1369,7 @@ import {
|
|
|
1038
1369
|
import { Button } from "@/components/ui/button";
|
|
1039
1370
|
import { cn } from "@/lib/utils";
|
|
1040
1371
|
|
|
1041
|
-
export type TooltipIconButtonProps =
|
|
1372
|
+
export type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
|
|
1042
1373
|
tooltip: string;
|
|
1043
1374
|
side?: "top" | "bottom" | "left" | "right";
|
|
1044
1375
|
};
|
|
@@ -1054,11 +1385,11 @@ export const TooltipIconButton = forwardRef<
|
|
|
1054
1385
|
variant="ghost"
|
|
1055
1386
|
size="icon"
|
|
1056
1387
|
{...rest}
|
|
1057
|
-
className={cn("size-6 p-1", className)}
|
|
1388
|
+
className={cn("aui-button-icon size-6 p-1", className)}
|
|
1058
1389
|
ref={ref}
|
|
1059
1390
|
>
|
|
1060
1391
|
<Slottable>{children}</Slottable>
|
|
1061
|
-
<span className="sr-only">{tooltip}</span>
|
|
1392
|
+
<span className="aui-sr-only sr-only">{tooltip}</span>
|
|
1062
1393
|
</Button>
|
|
1063
1394
|
</TooltipTrigger>
|
|
1064
1395
|
<TooltipContent side={side}>{tooltip}</TooltipContent>
|
|
@@ -1070,6 +1401,62 @@ TooltipIconButton.displayName = "TooltipIconButton";
|
|
|
1070
1401
|
|
|
1071
1402
|
```
|
|
1072
1403
|
|
|
1404
|
+
## components/ui/avatar.tsx
|
|
1405
|
+
|
|
1406
|
+
```tsx
|
|
1407
|
+
"use client";
|
|
1408
|
+
|
|
1409
|
+
import * as React from "react";
|
|
1410
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
1411
|
+
|
|
1412
|
+
import { cn } from "@/lib/utils";
|
|
1413
|
+
|
|
1414
|
+
const Avatar = React.forwardRef<
|
|
1415
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
1416
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
1417
|
+
>(({ className, ...props }, ref) => (
|
|
1418
|
+
<AvatarPrimitive.Root
|
|
1419
|
+
ref={ref}
|
|
1420
|
+
className={cn(
|
|
1421
|
+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
|
1422
|
+
className,
|
|
1423
|
+
)}
|
|
1424
|
+
{...props}
|
|
1425
|
+
/>
|
|
1426
|
+
));
|
|
1427
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
1428
|
+
|
|
1429
|
+
const AvatarImage = React.forwardRef<
|
|
1430
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
1431
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
1432
|
+
>(({ className, ...props }, ref) => (
|
|
1433
|
+
<AvatarPrimitive.Image
|
|
1434
|
+
ref={ref}
|
|
1435
|
+
className={cn("aspect-square h-full w-full", className)}
|
|
1436
|
+
{...props}
|
|
1437
|
+
/>
|
|
1438
|
+
));
|
|
1439
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
1440
|
+
|
|
1441
|
+
const AvatarFallback = React.forwardRef<
|
|
1442
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
1443
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
1444
|
+
>(({ className, ...props }, ref) => (
|
|
1445
|
+
<AvatarPrimitive.Fallback
|
|
1446
|
+
ref={ref}
|
|
1447
|
+
className={cn(
|
|
1448
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
1449
|
+
className,
|
|
1450
|
+
)}
|
|
1451
|
+
{...props}
|
|
1452
|
+
/>
|
|
1453
|
+
));
|
|
1454
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
1455
|
+
|
|
1456
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
1457
|
+
|
|
1458
|
+
```
|
|
1459
|
+
|
|
1073
1460
|
## components/ui/button.tsx
|
|
1074
1461
|
|
|
1075
1462
|
```tsx
|
|
@@ -1082,7 +1469,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|
|
1082
1469
|
import { cn } from "@/lib/utils";
|
|
1083
1470
|
|
|
1084
1471
|
const buttonVariants = cva(
|
|
1085
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm
|
|
1472
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
1086
1473
|
{
|
|
1087
1474
|
variants: {
|
|
1088
1475
|
variant: {
|
|
@@ -1135,6 +1522,147 @@ export { Button, buttonVariants };
|
|
|
1135
1522
|
|
|
1136
1523
|
```
|
|
1137
1524
|
|
|
1525
|
+
## components/ui/dialog.tsx
|
|
1526
|
+
|
|
1527
|
+
```tsx
|
|
1528
|
+
"use client";
|
|
1529
|
+
|
|
1530
|
+
import * as React from "react";
|
|
1531
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
1532
|
+
import { XIcon } from "lucide-react";
|
|
1533
|
+
|
|
1534
|
+
import { cn } from "@/lib/utils";
|
|
1535
|
+
|
|
1536
|
+
function Dialog({
|
|
1537
|
+
...props
|
|
1538
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
1539
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
function DialogTrigger({
|
|
1543
|
+
...props
|
|
1544
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
1545
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
function DialogPortal({
|
|
1549
|
+
...props
|
|
1550
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
1551
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
function DialogClose({
|
|
1555
|
+
...props
|
|
1556
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
1557
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
function DialogOverlay({
|
|
1561
|
+
className,
|
|
1562
|
+
...props
|
|
1563
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
1564
|
+
return (
|
|
1565
|
+
<DialogPrimitive.Overlay
|
|
1566
|
+
data-slot="dialog-overlay"
|
|
1567
|
+
className={cn(
|
|
1568
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80 data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
1569
|
+
className,
|
|
1570
|
+
)}
|
|
1571
|
+
{...props}
|
|
1572
|
+
/>
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
function DialogContent({
|
|
1577
|
+
className,
|
|
1578
|
+
children,
|
|
1579
|
+
...props
|
|
1580
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content>) {
|
|
1581
|
+
return (
|
|
1582
|
+
<DialogPortal data-slot="dialog-portal">
|
|
1583
|
+
<DialogOverlay />
|
|
1584
|
+
<DialogPrimitive.Content
|
|
1585
|
+
data-slot="dialog-content"
|
|
1586
|
+
className={cn(
|
|
1587
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[state=closed]:animate-out data-[state=open]:animate-in sm:max-w-lg",
|
|
1588
|
+
className,
|
|
1589
|
+
)}
|
|
1590
|
+
{...props}
|
|
1591
|
+
>
|
|
1592
|
+
{children}
|
|
1593
|
+
<DialogPrimitive.Close className="absolute top-4 right-4 rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0">
|
|
1594
|
+
<XIcon />
|
|
1595
|
+
<span className="sr-only">Close</span>
|
|
1596
|
+
</DialogPrimitive.Close>
|
|
1597
|
+
</DialogPrimitive.Content>
|
|
1598
|
+
</DialogPortal>
|
|
1599
|
+
);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
1603
|
+
return (
|
|
1604
|
+
<div
|
|
1605
|
+
data-slot="dialog-header"
|
|
1606
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
1607
|
+
{...props}
|
|
1608
|
+
/>
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
1613
|
+
return (
|
|
1614
|
+
<div
|
|
1615
|
+
data-slot="dialog-footer"
|
|
1616
|
+
className={cn(
|
|
1617
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
1618
|
+
className,
|
|
1619
|
+
)}
|
|
1620
|
+
{...props}
|
|
1621
|
+
/>
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
function DialogTitle({
|
|
1626
|
+
className,
|
|
1627
|
+
...props
|
|
1628
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
1629
|
+
return (
|
|
1630
|
+
<DialogPrimitive.Title
|
|
1631
|
+
data-slot="dialog-title"
|
|
1632
|
+
className={cn("font-semibold text-lg leading-none", className)}
|
|
1633
|
+
{...props}
|
|
1634
|
+
/>
|
|
1635
|
+
);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
function DialogDescription({
|
|
1639
|
+
className,
|
|
1640
|
+
...props
|
|
1641
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
1642
|
+
return (
|
|
1643
|
+
<DialogPrimitive.Description
|
|
1644
|
+
data-slot="dialog-description"
|
|
1645
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
1646
|
+
{...props}
|
|
1647
|
+
/>
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
export {
|
|
1652
|
+
Dialog,
|
|
1653
|
+
DialogClose,
|
|
1654
|
+
DialogContent,
|
|
1655
|
+
DialogDescription,
|
|
1656
|
+
DialogFooter,
|
|
1657
|
+
DialogHeader,
|
|
1658
|
+
DialogOverlay,
|
|
1659
|
+
DialogPortal,
|
|
1660
|
+
DialogTitle,
|
|
1661
|
+
DialogTrigger,
|
|
1662
|
+
};
|
|
1663
|
+
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1138
1666
|
## components/ui/tooltip.tsx
|
|
1139
1667
|
|
|
1140
1668
|
```tsx
|
|
@@ -1186,13 +1714,13 @@ function TooltipContent({
|
|
|
1186
1714
|
data-slot="tooltip-content"
|
|
1187
1715
|
sideOffset={sideOffset}
|
|
1188
1716
|
className={cn(
|
|
1189
|
-
"
|
|
1717
|
+
"fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-[--radix-tooltip-content-transform-origin] animate-in text-balance rounded-md bg-primary px-3 py-1.5 text-primary-foreground text-xs data-[state=closed]:animate-out",
|
|
1190
1718
|
className,
|
|
1191
1719
|
)}
|
|
1192
1720
|
{...props}
|
|
1193
1721
|
>
|
|
1194
1722
|
{children}
|
|
1195
|
-
<TooltipPrimitive.Arrow className="
|
|
1723
|
+
<TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" />
|
|
1196
1724
|
</TooltipPrimitive.Content>
|
|
1197
1725
|
</TooltipPrimitive.Portal>
|
|
1198
1726
|
);
|
|
@@ -1237,24 +1765,26 @@ export default nextConfig;
|
|
|
1237
1765
|
"scripts": {
|
|
1238
1766
|
"dev": "next dev --turbo",
|
|
1239
1767
|
"build": "next build",
|
|
1240
|
-
"start": "next start"
|
|
1241
|
-
"lint": "eslint ."
|
|
1768
|
+
"start": "next start"
|
|
1242
1769
|
},
|
|
1243
1770
|
"dependencies": {
|
|
1244
|
-
"@ai-sdk/openai": "^2.0.
|
|
1771
|
+
"@ai-sdk/openai": "^2.0.77",
|
|
1245
1772
|
"@assistant-ui/react": "workspace:*",
|
|
1246
1773
|
"@assistant-ui/react-markdown": "workspace:*",
|
|
1774
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
1775
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
1247
1776
|
"@radix-ui/react-slot": "^1.2.4",
|
|
1248
1777
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
1249
1778
|
"class-variance-authority": "^0.7.1",
|
|
1250
1779
|
"clsx": "^2.1.1",
|
|
1251
|
-
"lucide-react": "^0.
|
|
1252
|
-
"next": "16.0.
|
|
1253
|
-
"react": "19.2.
|
|
1254
|
-
"react-dom": "19.2.
|
|
1780
|
+
"lucide-react": "^0.556.0",
|
|
1781
|
+
"next": "16.0.7",
|
|
1782
|
+
"react": "19.2.1",
|
|
1783
|
+
"react-dom": "19.2.1",
|
|
1255
1784
|
"remark-gfm": "^4.0.1",
|
|
1256
1785
|
"tailwind-merge": "^3.4.0",
|
|
1257
|
-
"tw-animate-css": "^1.4.0"
|
|
1786
|
+
"tw-animate-css": "^1.4.0",
|
|
1787
|
+
"zustand": "^5.0.9"
|
|
1258
1788
|
},
|
|
1259
1789
|
"devDependencies": {
|
|
1260
1790
|
"@assistant-ui/x-buildutils": "workspace:*",
|