@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
|
@@ -312,7 +312,7 @@ const FfmpegTool: FC<{ file: File }> = ({ file }) => {
|
|
|
312
312
|
load();
|
|
313
313
|
}, []);
|
|
314
314
|
|
|
315
|
-
useAssistantInstructions(
|
|
315
|
+
useAssistantInstructions(`The user has attached a file: ${file.name}`);
|
|
316
316
|
|
|
317
317
|
useAssistantTool({
|
|
318
318
|
toolName: "run_ffmpeg",
|
|
@@ -357,7 +357,7 @@ const FfmpegTool: FC<{ file: File }> = ({ file }) => {
|
|
|
357
357
|
hint:
|
|
358
358
|
code === 0
|
|
359
359
|
? "note: a download button is appearing in the chat for the user"
|
|
360
|
-
:
|
|
360
|
+
: `some error happened, logs: ${logs.join("\n")}`,
|
|
361
361
|
};
|
|
362
362
|
},
|
|
363
363
|
render: function RenderFfmpeg({
|
|
@@ -391,7 +391,7 @@ const FfmpegTool: FC<{ file: File }> = ({ file }) => {
|
|
|
391
391
|
)}
|
|
392
392
|
<p>Running ffmpeg</p>
|
|
393
393
|
</div>
|
|
394
|
-
<pre className="
|
|
394
|
+
<pre className="overflow-y-scroll font-sm">
|
|
395
395
|
ffmpeg {command?.join(" ")}
|
|
396
396
|
</pre>
|
|
397
397
|
</div>
|
|
@@ -426,11 +426,10 @@ export default function Home() {
|
|
|
426
426
|
setLastFile(lastAttachment.file!);
|
|
427
427
|
}, [attachments]);
|
|
428
428
|
|
|
429
|
-
console.log(lastFile);
|
|
430
429
|
return (
|
|
431
430
|
<div className="flex h-full flex-col">
|
|
432
431
|
<div className="border-b">
|
|
433
|
-
<p className="my-4 ml-8 text-xl
|
|
432
|
+
<p className="my-4 ml-8 font-bold text-xl">
|
|
434
433
|
ConvertGPT (built with{" "}
|
|
435
434
|
<a
|
|
436
435
|
href="https://github.com/assistant-ui/assistant-ui"
|
|
@@ -472,6 +471,247 @@ export default function Home() {
|
|
|
472
471
|
|
|
473
472
|
```
|
|
474
473
|
|
|
474
|
+
## components/assistant-ui/attachment.tsx
|
|
475
|
+
|
|
476
|
+
```tsx
|
|
477
|
+
"use client";
|
|
478
|
+
|
|
479
|
+
import { PropsWithChildren, useEffect, useState, type FC } from "react";
|
|
480
|
+
import Image from "next/image";
|
|
481
|
+
import { XIcon, PlusIcon, FileText } from "lucide-react";
|
|
482
|
+
import {
|
|
483
|
+
AttachmentPrimitive,
|
|
484
|
+
ComposerPrimitive,
|
|
485
|
+
MessagePrimitive,
|
|
486
|
+
useAssistantState,
|
|
487
|
+
useAssistantApi,
|
|
488
|
+
} from "@assistant-ui/react";
|
|
489
|
+
import { useShallow } from "zustand/shallow";
|
|
490
|
+
import {
|
|
491
|
+
Tooltip,
|
|
492
|
+
TooltipContent,
|
|
493
|
+
TooltipTrigger,
|
|
494
|
+
} from "@/components/ui/tooltip";
|
|
495
|
+
import {
|
|
496
|
+
Dialog,
|
|
497
|
+
DialogTitle,
|
|
498
|
+
DialogContent,
|
|
499
|
+
DialogTrigger,
|
|
500
|
+
} from "@/components/ui/dialog";
|
|
501
|
+
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
|
502
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
503
|
+
import { cn } from "@/lib/utils";
|
|
504
|
+
|
|
505
|
+
const useFileSrc = (file: File | undefined) => {
|
|
506
|
+
const [src, setSrc] = useState<string | undefined>(undefined);
|
|
507
|
+
|
|
508
|
+
useEffect(() => {
|
|
509
|
+
if (!file) {
|
|
510
|
+
setSrc(undefined);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const objectUrl = URL.createObjectURL(file);
|
|
515
|
+
setSrc(objectUrl);
|
|
516
|
+
|
|
517
|
+
return () => {
|
|
518
|
+
URL.revokeObjectURL(objectUrl);
|
|
519
|
+
};
|
|
520
|
+
}, [file]);
|
|
521
|
+
|
|
522
|
+
return src;
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
const useAttachmentSrc = () => {
|
|
526
|
+
const { file, src } = useAssistantState(
|
|
527
|
+
useShallow(({ attachment }): { file?: File; src?: string } => {
|
|
528
|
+
if (attachment.type !== "image") return {};
|
|
529
|
+
if (attachment.file) return { file: attachment.file };
|
|
530
|
+
const src = attachment.content?.filter((c) => c.type === "image")[0]
|
|
531
|
+
?.image;
|
|
532
|
+
if (!src) return {};
|
|
533
|
+
return { src };
|
|
534
|
+
}),
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
return useFileSrc(file) ?? src;
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
type AttachmentPreviewProps = {
|
|
541
|
+
src: string;
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
const AttachmentPreview: FC<AttachmentPreviewProps> = ({ src }) => {
|
|
545
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
546
|
+
return (
|
|
547
|
+
<Image
|
|
548
|
+
src={src}
|
|
549
|
+
alt="Image Preview"
|
|
550
|
+
width={1}
|
|
551
|
+
height={1}
|
|
552
|
+
className={
|
|
553
|
+
isLoaded
|
|
554
|
+
? "aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain"
|
|
555
|
+
: "aui-attachment-preview-image-loading hidden"
|
|
556
|
+
}
|
|
557
|
+
onLoadingComplete={() => setIsLoaded(true)}
|
|
558
|
+
priority={false}
|
|
559
|
+
/>
|
|
560
|
+
);
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
|
|
564
|
+
const src = useAttachmentSrc();
|
|
565
|
+
|
|
566
|
+
if (!src) return children;
|
|
567
|
+
|
|
568
|
+
return (
|
|
569
|
+
<Dialog>
|
|
570
|
+
<DialogTrigger
|
|
571
|
+
className="aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50"
|
|
572
|
+
asChild
|
|
573
|
+
>
|
|
574
|
+
{children}
|
|
575
|
+
</DialogTrigger>
|
|
576
|
+
<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">
|
|
577
|
+
<DialogTitle className="aui-sr-only sr-only">
|
|
578
|
+
Image Attachment Preview
|
|
579
|
+
</DialogTitle>
|
|
580
|
+
<div className="aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background">
|
|
581
|
+
<AttachmentPreview src={src} />
|
|
582
|
+
</div>
|
|
583
|
+
</DialogContent>
|
|
584
|
+
</Dialog>
|
|
585
|
+
);
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
const AttachmentThumb: FC = () => {
|
|
589
|
+
const isImage = useAssistantState(
|
|
590
|
+
({ attachment }) => attachment.type === "image",
|
|
591
|
+
);
|
|
592
|
+
const src = useAttachmentSrc();
|
|
593
|
+
|
|
594
|
+
return (
|
|
595
|
+
<Avatar className="aui-attachment-tile-avatar h-full w-full rounded-none">
|
|
596
|
+
<AvatarImage
|
|
597
|
+
src={src}
|
|
598
|
+
alt="Attachment preview"
|
|
599
|
+
className="aui-attachment-tile-image object-cover"
|
|
600
|
+
/>
|
|
601
|
+
<AvatarFallback delayMs={isImage ? 200 : 0}>
|
|
602
|
+
<FileText className="aui-attachment-tile-fallback-icon size-8 text-muted-foreground" />
|
|
603
|
+
</AvatarFallback>
|
|
604
|
+
</Avatar>
|
|
605
|
+
);
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
const AttachmentUI: FC = () => {
|
|
609
|
+
const api = useAssistantApi();
|
|
610
|
+
const isComposer = api.attachment.source === "composer";
|
|
611
|
+
|
|
612
|
+
const isImage = useAssistantState(
|
|
613
|
+
({ attachment }) => attachment.type === "image",
|
|
614
|
+
);
|
|
615
|
+
const typeLabel = useAssistantState(({ attachment }) => {
|
|
616
|
+
const type = attachment.type;
|
|
617
|
+
switch (type) {
|
|
618
|
+
case "image":
|
|
619
|
+
return "Image";
|
|
620
|
+
case "document":
|
|
621
|
+
return "Document";
|
|
622
|
+
case "file":
|
|
623
|
+
return "File";
|
|
624
|
+
default:
|
|
625
|
+
const _exhaustiveCheck: never = type;
|
|
626
|
+
throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
return (
|
|
631
|
+
<Tooltip>
|
|
632
|
+
<AttachmentPrimitive.Root
|
|
633
|
+
className={cn(
|
|
634
|
+
"aui-attachment-root relative",
|
|
635
|
+
isImage &&
|
|
636
|
+
"aui-attachment-root-composer only:[&>#attachment-tile]:size-24",
|
|
637
|
+
)}
|
|
638
|
+
>
|
|
639
|
+
<AttachmentPreviewDialog>
|
|
640
|
+
<TooltipTrigger asChild>
|
|
641
|
+
<div
|
|
642
|
+
className={cn(
|
|
643
|
+
"aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
|
|
644
|
+
isComposer &&
|
|
645
|
+
"aui-attachment-tile-composer border-foreground/20",
|
|
646
|
+
)}
|
|
647
|
+
role="button"
|
|
648
|
+
id="attachment-tile"
|
|
649
|
+
aria-label={`${typeLabel} attachment`}
|
|
650
|
+
>
|
|
651
|
+
<AttachmentThumb />
|
|
652
|
+
</div>
|
|
653
|
+
</TooltipTrigger>
|
|
654
|
+
</AttachmentPreviewDialog>
|
|
655
|
+
{isComposer && <AttachmentRemove />}
|
|
656
|
+
</AttachmentPrimitive.Root>
|
|
657
|
+
<TooltipContent side="top">
|
|
658
|
+
<AttachmentPrimitive.Name />
|
|
659
|
+
</TooltipContent>
|
|
660
|
+
</Tooltip>
|
|
661
|
+
);
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
const AttachmentRemove: FC = () => {
|
|
665
|
+
return (
|
|
666
|
+
<AttachmentPrimitive.Remove asChild>
|
|
667
|
+
<TooltipIconButton
|
|
668
|
+
tooltip="Remove file"
|
|
669
|
+
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"
|
|
670
|
+
side="top"
|
|
671
|
+
>
|
|
672
|
+
<XIcon className="aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" />
|
|
673
|
+
</TooltipIconButton>
|
|
674
|
+
</AttachmentPrimitive.Remove>
|
|
675
|
+
);
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
export const UserMessageAttachments: FC = () => {
|
|
679
|
+
return (
|
|
680
|
+
<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">
|
|
681
|
+
<MessagePrimitive.Attachments components={{ Attachment: AttachmentUI }} />
|
|
682
|
+
</div>
|
|
683
|
+
);
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
export const ComposerAttachments: FC = () => {
|
|
687
|
+
return (
|
|
688
|
+
<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">
|
|
689
|
+
<ComposerPrimitive.Attachments
|
|
690
|
+
components={{ Attachment: AttachmentUI }}
|
|
691
|
+
/>
|
|
692
|
+
</div>
|
|
693
|
+
);
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
export const ComposerAddAttachment: FC = () => {
|
|
697
|
+
return (
|
|
698
|
+
<ComposerPrimitive.AddAttachment asChild>
|
|
699
|
+
<TooltipIconButton
|
|
700
|
+
tooltip="Add Attachment"
|
|
701
|
+
side="bottom"
|
|
702
|
+
variant="ghost"
|
|
703
|
+
size="icon"
|
|
704
|
+
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"
|
|
705
|
+
aria-label="Add Attachment"
|
|
706
|
+
>
|
|
707
|
+
<PlusIcon className="aui-attachment-add-icon size-5 stroke-[1.5px]" />
|
|
708
|
+
</TooltipIconButton>
|
|
709
|
+
</ComposerPrimitive.AddAttachment>
|
|
710
|
+
);
|
|
711
|
+
};
|
|
712
|
+
|
|
713
|
+
```
|
|
714
|
+
|
|
475
715
|
## components/assistant-ui/markdown-text.tsx
|
|
476
716
|
|
|
477
717
|
```tsx
|
|
@@ -480,13 +720,13 @@ export default function Home() {
|
|
|
480
720
|
import "@assistant-ui/react-markdown/styles/dot.css";
|
|
481
721
|
|
|
482
722
|
import {
|
|
483
|
-
CodeHeaderProps,
|
|
723
|
+
type CodeHeaderProps,
|
|
484
724
|
MarkdownTextPrimitive,
|
|
485
725
|
unstable_memoizeMarkdownComponents as memoizeMarkdownComponents,
|
|
486
726
|
useIsMarkdownCodeBlock,
|
|
487
727
|
} from "@assistant-ui/react-markdown";
|
|
488
728
|
import remarkGfm from "remark-gfm";
|
|
489
|
-
import { FC, memo, useState } from "react";
|
|
729
|
+
import { type FC, memo, useState } from "react";
|
|
490
730
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
491
731
|
|
|
492
732
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
@@ -512,8 +752,10 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
|
|
|
512
752
|
};
|
|
513
753
|
|
|
514
754
|
return (
|
|
515
|
-
<div className="flex items-center justify-between gap-4 rounded-t-lg bg-
|
|
516
|
-
<span className="lowercase [&>span]:text-xs">
|
|
755
|
+
<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">
|
|
756
|
+
<span className="aui-code-header-language lowercase [&>span]:text-xs">
|
|
757
|
+
{language}
|
|
758
|
+
</span>
|
|
517
759
|
<TooltipIconButton tooltip="Copy" onClick={onCopy}>
|
|
518
760
|
{!isCopied && <CopyIcon />}
|
|
519
761
|
{isCopied && <CheckIcon />}
|
|
@@ -545,7 +787,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
545
787
|
h1: ({ className, ...props }) => (
|
|
546
788
|
<h1
|
|
547
789
|
className={cn(
|
|
548
|
-
"mb-8 scroll-m-20 text-4xl
|
|
790
|
+
"aui-md-h1 mb-8 scroll-m-20 font-extrabold text-4xl tracking-tight last:mb-0",
|
|
549
791
|
className,
|
|
550
792
|
)}
|
|
551
793
|
{...props}
|
|
@@ -554,7 +796,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
554
796
|
h2: ({ className, ...props }) => (
|
|
555
797
|
<h2
|
|
556
798
|
className={cn(
|
|
557
|
-
"mt-8 mb-4 scroll-m-20 text-3xl
|
|
799
|
+
"aui-md-h2 mt-8 mb-4 scroll-m-20 font-semibold text-3xl tracking-tight first:mt-0 last:mb-0",
|
|
558
800
|
className,
|
|
559
801
|
)}
|
|
560
802
|
{...props}
|
|
@@ -563,7 +805,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
563
805
|
h3: ({ className, ...props }) => (
|
|
564
806
|
<h3
|
|
565
807
|
className={cn(
|
|
566
|
-
"mt-6 mb-4 scroll-m-20 text-2xl
|
|
808
|
+
"aui-md-h3 mt-6 mb-4 scroll-m-20 font-semibold text-2xl tracking-tight first:mt-0 last:mb-0",
|
|
567
809
|
className,
|
|
568
810
|
)}
|
|
569
811
|
{...props}
|
|
@@ -572,7 +814,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
572
814
|
h4: ({ className, ...props }) => (
|
|
573
815
|
<h4
|
|
574
816
|
className={cn(
|
|
575
|
-
"mt-6 mb-4 scroll-m-20 text-xl
|
|
817
|
+
"aui-md-h4 mt-6 mb-4 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0",
|
|
576
818
|
className,
|
|
577
819
|
)}
|
|
578
820
|
{...props}
|
|
@@ -581,7 +823,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
581
823
|
h5: ({ className, ...props }) => (
|
|
582
824
|
<h5
|
|
583
825
|
className={cn(
|
|
584
|
-
"my-4 text-lg
|
|
826
|
+
"aui-md-h5 my-4 font-semibold text-lg first:mt-0 last:mb-0",
|
|
585
827
|
className,
|
|
586
828
|
)}
|
|
587
829
|
{...props}
|
|
@@ -589,20 +831,26 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
589
831
|
),
|
|
590
832
|
h6: ({ className, ...props }) => (
|
|
591
833
|
<h6
|
|
592
|
-
className={cn(
|
|
834
|
+
className={cn(
|
|
835
|
+
"aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0",
|
|
836
|
+
className,
|
|
837
|
+
)}
|
|
593
838
|
{...props}
|
|
594
839
|
/>
|
|
595
840
|
),
|
|
596
841
|
p: ({ className, ...props }) => (
|
|
597
842
|
<p
|
|
598
|
-
className={cn(
|
|
843
|
+
className={cn(
|
|
844
|
+
"aui-md-p mt-5 mb-5 leading-7 first:mt-0 last:mb-0",
|
|
845
|
+
className,
|
|
846
|
+
)}
|
|
599
847
|
{...props}
|
|
600
848
|
/>
|
|
601
849
|
),
|
|
602
850
|
a: ({ className, ...props }) => (
|
|
603
851
|
<a
|
|
604
852
|
className={cn(
|
|
605
|
-
"
|
|
853
|
+
"aui-md-a font-medium text-primary underline underline-offset-4",
|
|
606
854
|
className,
|
|
607
855
|
)}
|
|
608
856
|
{...props}
|
|
@@ -610,29 +858,29 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
610
858
|
),
|
|
611
859
|
blockquote: ({ className, ...props }) => (
|
|
612
860
|
<blockquote
|
|
613
|
-
className={cn("border-l-2 pl-6 italic", className)}
|
|
861
|
+
className={cn("aui-md-blockquote border-l-2 pl-6 italic", className)}
|
|
614
862
|
{...props}
|
|
615
863
|
/>
|
|
616
864
|
),
|
|
617
865
|
ul: ({ className, ...props }) => (
|
|
618
866
|
<ul
|
|
619
|
-
className={cn("my-5 ml-6 list-disc [&>li]:mt-2", className)}
|
|
867
|
+
className={cn("aui-md-ul my-5 ml-6 list-disc [&>li]:mt-2", className)}
|
|
620
868
|
{...props}
|
|
621
869
|
/>
|
|
622
870
|
),
|
|
623
871
|
ol: ({ className, ...props }) => (
|
|
624
872
|
<ol
|
|
625
|
-
className={cn("my-5 ml-6 list-decimal [&>li]:mt-2", className)}
|
|
873
|
+
className={cn("aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2", className)}
|
|
626
874
|
{...props}
|
|
627
875
|
/>
|
|
628
876
|
),
|
|
629
877
|
hr: ({ className, ...props }) => (
|
|
630
|
-
<hr className={cn("my-5 border-b", className)} {...props} />
|
|
878
|
+
<hr className={cn("aui-md-hr my-5 border-b", className)} {...props} />
|
|
631
879
|
),
|
|
632
880
|
table: ({ className, ...props }) => (
|
|
633
881
|
<table
|
|
634
882
|
className={cn(
|
|
635
|
-
"my-5 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
883
|
+
"aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
636
884
|
className,
|
|
637
885
|
)}
|
|
638
886
|
{...props}
|
|
@@ -641,7 +889,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
641
889
|
th: ({ className, ...props }) => (
|
|
642
890
|
<th
|
|
643
891
|
className={cn(
|
|
644
|
-
"bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [
|
|
892
|
+
"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",
|
|
645
893
|
className,
|
|
646
894
|
)}
|
|
647
895
|
{...props}
|
|
@@ -650,7 +898,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
650
898
|
td: ({ className, ...props }) => (
|
|
651
899
|
<td
|
|
652
900
|
className={cn(
|
|
653
|
-
"border-b border-l px-4 py-2 text-left last:border-r [
|
|
901
|
+
"aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right",
|
|
654
902
|
className,
|
|
655
903
|
)}
|
|
656
904
|
{...props}
|
|
@@ -659,7 +907,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
659
907
|
tr: ({ className, ...props }) => (
|
|
660
908
|
<tr
|
|
661
909
|
className={cn(
|
|
662
|
-
"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",
|
|
910
|
+
"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",
|
|
663
911
|
className,
|
|
664
912
|
)}
|
|
665
913
|
{...props}
|
|
@@ -667,14 +915,14 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
667
915
|
),
|
|
668
916
|
sup: ({ className, ...props }) => (
|
|
669
917
|
<sup
|
|
670
|
-
className={cn("[&>a]:text-xs [&>a]:no-underline", className)}
|
|
918
|
+
className={cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className)}
|
|
671
919
|
{...props}
|
|
672
920
|
/>
|
|
673
921
|
),
|
|
674
922
|
pre: ({ className, ...props }) => (
|
|
675
923
|
<pre
|
|
676
924
|
className={cn(
|
|
677
|
-
"overflow-x-auto rounded-b-lg bg-black p-4 text-white",
|
|
925
|
+
"aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-black p-4 text-white",
|
|
678
926
|
className,
|
|
679
927
|
)}
|
|
680
928
|
{...props}
|
|
@@ -685,7 +933,8 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
685
933
|
return (
|
|
686
934
|
<code
|
|
687
935
|
className={cn(
|
|
688
|
-
!isCodeBlock &&
|
|
936
|
+
!isCodeBlock &&
|
|
937
|
+
"aui-md-inline-code rounded border bg-muted font-semibold",
|
|
689
938
|
className,
|
|
690
939
|
)}
|
|
691
940
|
{...props}
|
|
@@ -700,57 +949,67 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
700
949
|
## components/assistant-ui/thread.tsx
|
|
701
950
|
|
|
702
951
|
```tsx
|
|
952
|
+
import {
|
|
953
|
+
ComposerAddAttachment,
|
|
954
|
+
ComposerAttachments,
|
|
955
|
+
UserMessageAttachments,
|
|
956
|
+
} from "@/components/assistant-ui/attachment";
|
|
957
|
+
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
958
|
+
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
|
959
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
960
|
+
import { Button } from "@/components/ui/button";
|
|
961
|
+
import { cn } from "@/lib/utils";
|
|
703
962
|
import {
|
|
704
963
|
ActionBarPrimitive,
|
|
964
|
+
AssistantIf,
|
|
705
965
|
BranchPickerPrimitive,
|
|
706
966
|
ComposerPrimitive,
|
|
967
|
+
ErrorPrimitive,
|
|
707
968
|
MessagePrimitive,
|
|
708
969
|
ThreadPrimitive,
|
|
709
970
|
} from "@assistant-ui/react";
|
|
710
|
-
import type { FC } from "react";
|
|
711
971
|
import {
|
|
712
972
|
ArrowDownIcon,
|
|
973
|
+
ArrowUpIcon,
|
|
713
974
|
CheckIcon,
|
|
714
975
|
ChevronLeftIcon,
|
|
715
976
|
ChevronRightIcon,
|
|
716
977
|
CopyIcon,
|
|
978
|
+
DownloadIcon,
|
|
717
979
|
PencilIcon,
|
|
718
980
|
RefreshCwIcon,
|
|
719
|
-
|
|
981
|
+
SquareIcon,
|
|
720
982
|
} from "lucide-react";
|
|
721
|
-
import {
|
|
722
|
-
|
|
723
|
-
import { Button } from "@/components/ui/button";
|
|
724
|
-
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
725
|
-
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
983
|
+
import type { FC } from "react";
|
|
726
984
|
|
|
727
985
|
export const Thread: FC = () => {
|
|
728
986
|
return (
|
|
729
987
|
<ThreadPrimitive.Root
|
|
730
|
-
className="
|
|
988
|
+
className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
|
|
731
989
|
style={{
|
|
732
|
-
["--thread-max-width" as string]: "
|
|
990
|
+
["--thread-max-width" as string]: "44rem",
|
|
733
991
|
}}
|
|
734
992
|
>
|
|
735
|
-
<ThreadPrimitive.Viewport
|
|
736
|
-
|
|
993
|
+
<ThreadPrimitive.Viewport
|
|
994
|
+
turnAnchor="top"
|
|
995
|
+
className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
|
|
996
|
+
>
|
|
997
|
+
<AssistantIf condition={({ thread }) => thread.isEmpty}>
|
|
998
|
+
<ThreadWelcome />
|
|
999
|
+
</AssistantIf>
|
|
737
1000
|
|
|
738
1001
|
<ThreadPrimitive.Messages
|
|
739
1002
|
components={{
|
|
740
|
-
UserMessage
|
|
741
|
-
EditComposer
|
|
742
|
-
AssistantMessage
|
|
1003
|
+
UserMessage,
|
|
1004
|
+
EditComposer,
|
|
1005
|
+
AssistantMessage,
|
|
743
1006
|
}}
|
|
744
1007
|
/>
|
|
745
1008
|
|
|
746
|
-
<ThreadPrimitive.
|
|
747
|
-
<div className="min-h-8 flex-grow" />
|
|
748
|
-
</ThreadPrimitive.If>
|
|
749
|
-
|
|
750
|
-
<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">
|
|
1009
|
+
<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">
|
|
751
1010
|
<ThreadScrollToBottom />
|
|
752
1011
|
<Composer />
|
|
753
|
-
</
|
|
1012
|
+
</ThreadPrimitive.ViewportFooter>
|
|
754
1013
|
</ThreadPrimitive.Viewport>
|
|
755
1014
|
</ThreadPrimitive.Root>
|
|
756
1015
|
);
|
|
@@ -762,7 +1021,7 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
762
1021
|
<TooltipIconButton
|
|
763
1022
|
tooltip="Scroll to bottom"
|
|
764
1023
|
variant="outline"
|
|
765
|
-
className="
|
|
1024
|
+
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"
|
|
766
1025
|
>
|
|
767
1026
|
<ArrowDownIcon />
|
|
768
1027
|
</TooltipIconButton>
|
|
@@ -772,175 +1031,247 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
772
1031
|
|
|
773
1032
|
const ThreadWelcome: FC = () => {
|
|
774
1033
|
return (
|
|
775
|
-
<
|
|
776
|
-
<div className="
|
|
777
|
-
<div className="flex
|
|
778
|
-
<
|
|
1034
|
+
<div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
|
|
1035
|
+
<div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
|
|
1036
|
+
<div className="aui-thread-welcome-message flex size-full flex-col justify-center px-4">
|
|
1037
|
+
<h1 className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-2xl duration-200">
|
|
1038
|
+
Hello there!
|
|
1039
|
+
</h1>
|
|
1040
|
+
<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">
|
|
1041
|
+
How can I help you today?
|
|
1042
|
+
</p>
|
|
779
1043
|
</div>
|
|
780
|
-
<ThreadWelcomeSuggestions />
|
|
781
1044
|
</div>
|
|
782
|
-
|
|
1045
|
+
<ThreadSuggestions />
|
|
1046
|
+
</div>
|
|
783
1047
|
);
|
|
784
1048
|
};
|
|
785
1049
|
|
|
786
|
-
const
|
|
1050
|
+
const SUGGESTIONS = [
|
|
1051
|
+
{
|
|
1052
|
+
title: "What's the weather",
|
|
1053
|
+
label: "in San Francisco?",
|
|
1054
|
+
prompt: "What's the weather in San Francisco?",
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
title: "Explain React hooks",
|
|
1058
|
+
label: "like useState and useEffect",
|
|
1059
|
+
prompt: "Explain React hooks like useState and useEffect",
|
|
1060
|
+
},
|
|
1061
|
+
] as const;
|
|
1062
|
+
|
|
1063
|
+
const ThreadSuggestions: FC = () => {
|
|
787
1064
|
return (
|
|
788
|
-
<div className="
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
1065
|
+
<div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
|
|
1066
|
+
{SUGGESTIONS.map((suggestion, index) => (
|
|
1067
|
+
<div
|
|
1068
|
+
key={suggestion.prompt}
|
|
1069
|
+
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"
|
|
1070
|
+
style={{ animationDelay: `${100 + index * 50}ms` }}
|
|
1071
|
+
>
|
|
1072
|
+
<ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
|
|
1073
|
+
<Button
|
|
1074
|
+
variant="ghost"
|
|
1075
|
+
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"
|
|
1076
|
+
aria-label={suggestion.prompt}
|
|
1077
|
+
>
|
|
1078
|
+
<span className="aui-thread-welcome-suggestion-text-1 font-medium">
|
|
1079
|
+
{suggestion.title}
|
|
1080
|
+
</span>
|
|
1081
|
+
<span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
|
|
1082
|
+
{suggestion.label}
|
|
1083
|
+
</span>
|
|
1084
|
+
</Button>
|
|
1085
|
+
</ThreadPrimitive.Suggestion>
|
|
1086
|
+
</div>
|
|
1087
|
+
))}
|
|
809
1088
|
</div>
|
|
810
1089
|
);
|
|
811
1090
|
};
|
|
812
1091
|
|
|
813
1092
|
const Composer: FC = () => {
|
|
814
1093
|
return (
|
|
815
|
-
<ComposerPrimitive.Root className="
|
|
816
|
-
<ComposerPrimitive.
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
1094
|
+
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
|
|
1095
|
+
<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">
|
|
1096
|
+
<ComposerAttachments />
|
|
1097
|
+
<ComposerPrimitive.Input
|
|
1098
|
+
placeholder="Send a message..."
|
|
1099
|
+
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"
|
|
1100
|
+
rows={1}
|
|
1101
|
+
autoFocus
|
|
1102
|
+
aria-label="Message input"
|
|
1103
|
+
/>
|
|
1104
|
+
<ComposerAction />
|
|
1105
|
+
</ComposerPrimitive.AttachmentDropzone>
|
|
823
1106
|
</ComposerPrimitive.Root>
|
|
824
1107
|
);
|
|
825
1108
|
};
|
|
826
1109
|
|
|
827
1110
|
const ComposerAction: FC = () => {
|
|
828
1111
|
return (
|
|
829
|
-
|
|
830
|
-
<
|
|
1112
|
+
<div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
|
|
1113
|
+
<ComposerAddAttachment />
|
|
1114
|
+
|
|
1115
|
+
<AssistantIf condition={({ thread }) => !thread.isRunning}>
|
|
831
1116
|
<ComposerPrimitive.Send asChild>
|
|
832
1117
|
<TooltipIconButton
|
|
833
|
-
tooltip="Send"
|
|
1118
|
+
tooltip="Send message"
|
|
1119
|
+
side="bottom"
|
|
1120
|
+
type="submit"
|
|
834
1121
|
variant="default"
|
|
835
|
-
|
|
1122
|
+
size="icon"
|
|
1123
|
+
className="aui-composer-send size-8 rounded-full"
|
|
1124
|
+
aria-label="Send message"
|
|
836
1125
|
>
|
|
837
|
-
<
|
|
1126
|
+
<ArrowUpIcon className="aui-composer-send-icon size-4" />
|
|
838
1127
|
</TooltipIconButton>
|
|
839
1128
|
</ComposerPrimitive.Send>
|
|
840
|
-
</
|
|
841
|
-
|
|
1129
|
+
</AssistantIf>
|
|
1130
|
+
|
|
1131
|
+
<AssistantIf condition={({ thread }) => thread.isRunning}>
|
|
842
1132
|
<ComposerPrimitive.Cancel asChild>
|
|
843
|
-
<
|
|
844
|
-
|
|
1133
|
+
<Button
|
|
1134
|
+
type="button"
|
|
845
1135
|
variant="default"
|
|
846
|
-
|
|
1136
|
+
size="icon"
|
|
1137
|
+
className="aui-composer-cancel size-8 rounded-full"
|
|
1138
|
+
aria-label="Stop generating"
|
|
847
1139
|
>
|
|
848
|
-
<
|
|
849
|
-
</
|
|
1140
|
+
<SquareIcon className="aui-composer-cancel-icon size-3 fill-current" />
|
|
1141
|
+
</Button>
|
|
850
1142
|
</ComposerPrimitive.Cancel>
|
|
851
|
-
</
|
|
852
|
-
|
|
1143
|
+
</AssistantIf>
|
|
1144
|
+
</div>
|
|
853
1145
|
);
|
|
854
1146
|
};
|
|
855
1147
|
|
|
856
|
-
const
|
|
1148
|
+
const MessageError: FC = () => {
|
|
857
1149
|
return (
|
|
858
|
-
<MessagePrimitive.
|
|
859
|
-
<
|
|
1150
|
+
<MessagePrimitive.Error>
|
|
1151
|
+
<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">
|
|
1152
|
+
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
|
|
1153
|
+
</ErrorPrimitive.Root>
|
|
1154
|
+
</MessagePrimitive.Error>
|
|
1155
|
+
);
|
|
1156
|
+
};
|
|
860
1157
|
|
|
861
|
-
|
|
862
|
-
|
|
1158
|
+
const AssistantMessage: FC = () => {
|
|
1159
|
+
return (
|
|
1160
|
+
<MessagePrimitive.Root
|
|
1161
|
+
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"
|
|
1162
|
+
data-role="assistant"
|
|
1163
|
+
>
|
|
1164
|
+
<div className="aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed">
|
|
1165
|
+
<MessagePrimitive.Parts
|
|
1166
|
+
components={{
|
|
1167
|
+
Text: MarkdownText,
|
|
1168
|
+
tools: { Fallback: ToolFallback },
|
|
1169
|
+
}}
|
|
1170
|
+
/>
|
|
1171
|
+
<MessageError />
|
|
863
1172
|
</div>
|
|
864
1173
|
|
|
865
|
-
<
|
|
1174
|
+
<div className="aui-assistant-message-footer mt-1 ml-2 flex">
|
|
1175
|
+
<BranchPicker />
|
|
1176
|
+
<AssistantActionBar />
|
|
1177
|
+
</div>
|
|
866
1178
|
</MessagePrimitive.Root>
|
|
867
1179
|
);
|
|
868
1180
|
};
|
|
869
1181
|
|
|
870
|
-
const
|
|
1182
|
+
const AssistantActionBar: FC = () => {
|
|
871
1183
|
return (
|
|
872
1184
|
<ActionBarPrimitive.Root
|
|
873
1185
|
hideWhenRunning
|
|
874
1186
|
autohide="not-last"
|
|
875
|
-
|
|
1187
|
+
autohideFloat="single-branch"
|
|
1188
|
+
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"
|
|
876
1189
|
>
|
|
877
|
-
<ActionBarPrimitive.
|
|
878
|
-
<TooltipIconButton tooltip="
|
|
879
|
-
<
|
|
1190
|
+
<ActionBarPrimitive.Copy asChild>
|
|
1191
|
+
<TooltipIconButton tooltip="Copy">
|
|
1192
|
+
<AssistantIf condition={({ message }) => message.isCopied}>
|
|
1193
|
+
<CheckIcon />
|
|
1194
|
+
</AssistantIf>
|
|
1195
|
+
<AssistantIf condition={({ message }) => !message.isCopied}>
|
|
1196
|
+
<CopyIcon />
|
|
1197
|
+
</AssistantIf>
|
|
880
1198
|
</TooltipIconButton>
|
|
881
|
-
</ActionBarPrimitive.
|
|
1199
|
+
</ActionBarPrimitive.Copy>
|
|
1200
|
+
<ActionBarPrimitive.ExportMarkdown asChild>
|
|
1201
|
+
<TooltipIconButton tooltip="Export as Markdown">
|
|
1202
|
+
<DownloadIcon />
|
|
1203
|
+
</TooltipIconButton>
|
|
1204
|
+
</ActionBarPrimitive.ExportMarkdown>
|
|
1205
|
+
<ActionBarPrimitive.Reload asChild>
|
|
1206
|
+
<TooltipIconButton tooltip="Refresh">
|
|
1207
|
+
<RefreshCwIcon />
|
|
1208
|
+
</TooltipIconButton>
|
|
1209
|
+
</ActionBarPrimitive.Reload>
|
|
882
1210
|
</ActionBarPrimitive.Root>
|
|
883
1211
|
);
|
|
884
1212
|
};
|
|
885
1213
|
|
|
886
|
-
const
|
|
1214
|
+
const UserMessage: FC = () => {
|
|
887
1215
|
return (
|
|
888
|
-
<
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
<Button variant="ghost">Cancel</Button>
|
|
894
|
-
</ComposerPrimitive.Cancel>
|
|
895
|
-
<ComposerPrimitive.Send asChild>
|
|
896
|
-
<Button>Send</Button>
|
|
897
|
-
</ComposerPrimitive.Send>
|
|
898
|
-
</div>
|
|
899
|
-
</ComposerPrimitive.Root>
|
|
900
|
-
);
|
|
901
|
-
};
|
|
1216
|
+
<MessagePrimitive.Root
|
|
1217
|
+
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"
|
|
1218
|
+
data-role="user"
|
|
1219
|
+
>
|
|
1220
|
+
<UserMessageAttachments />
|
|
902
1221
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
<
|
|
1222
|
+
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
|
|
1223
|
+
<div className="aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground">
|
|
1224
|
+
<MessagePrimitive.Parts />
|
|
1225
|
+
</div>
|
|
1226
|
+
<div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
|
|
1227
|
+
<UserActionBar />
|
|
1228
|
+
</div>
|
|
908
1229
|
</div>
|
|
909
1230
|
|
|
910
|
-
<
|
|
911
|
-
|
|
912
|
-
<BranchPicker className="col-start-2 row-start-2 mr-2 -ml-2" />
|
|
1231
|
+
<BranchPicker className="aui-user-branch-picker -mr-1 col-span-full col-start-1 row-start-3 justify-end" />
|
|
913
1232
|
</MessagePrimitive.Root>
|
|
914
1233
|
);
|
|
915
1234
|
};
|
|
916
1235
|
|
|
917
|
-
const
|
|
1236
|
+
const UserActionBar: FC = () => {
|
|
918
1237
|
return (
|
|
919
1238
|
<ActionBarPrimitive.Root
|
|
920
1239
|
hideWhenRunning
|
|
921
1240
|
autohide="not-last"
|
|
922
|
-
|
|
923
|
-
className="text-muted-foreground data-[floating]:bg-background col-start-3 row-start-2 -ml-1 flex gap-1 data-[floating]:absolute data-[floating]:rounded-md data-[floating]:border data-[floating]:p-1 data-[floating]:shadow-sm"
|
|
1241
|
+
className="aui-user-action-bar-root flex flex-col items-end"
|
|
924
1242
|
>
|
|
925
|
-
<ActionBarPrimitive.
|
|
926
|
-
<TooltipIconButton tooltip="
|
|
927
|
-
<
|
|
928
|
-
<CheckIcon />
|
|
929
|
-
</MessagePrimitive.If>
|
|
930
|
-
<MessagePrimitive.If copied={false}>
|
|
931
|
-
<CopyIcon />
|
|
932
|
-
</MessagePrimitive.If>
|
|
933
|
-
</TooltipIconButton>
|
|
934
|
-
</ActionBarPrimitive.Copy>
|
|
935
|
-
<ActionBarPrimitive.Reload asChild>
|
|
936
|
-
<TooltipIconButton tooltip="Refresh">
|
|
937
|
-
<RefreshCwIcon />
|
|
1243
|
+
<ActionBarPrimitive.Edit asChild>
|
|
1244
|
+
<TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
|
|
1245
|
+
<PencilIcon />
|
|
938
1246
|
</TooltipIconButton>
|
|
939
|
-
</ActionBarPrimitive.
|
|
1247
|
+
</ActionBarPrimitive.Edit>
|
|
940
1248
|
</ActionBarPrimitive.Root>
|
|
941
1249
|
);
|
|
942
1250
|
};
|
|
943
1251
|
|
|
1252
|
+
const EditComposer: FC = () => {
|
|
1253
|
+
return (
|
|
1254
|
+
<MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3">
|
|
1255
|
+
<ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted">
|
|
1256
|
+
<ComposerPrimitive.Input
|
|
1257
|
+
className="aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none"
|
|
1258
|
+
autoFocus
|
|
1259
|
+
/>
|
|
1260
|
+
<div className="aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end">
|
|
1261
|
+
<ComposerPrimitive.Cancel asChild>
|
|
1262
|
+
<Button variant="ghost" size="sm">
|
|
1263
|
+
Cancel
|
|
1264
|
+
</Button>
|
|
1265
|
+
</ComposerPrimitive.Cancel>
|
|
1266
|
+
<ComposerPrimitive.Send asChild>
|
|
1267
|
+
<Button size="sm">Update</Button>
|
|
1268
|
+
</ComposerPrimitive.Send>
|
|
1269
|
+
</div>
|
|
1270
|
+
</ComposerPrimitive.Root>
|
|
1271
|
+
</MessagePrimitive.Root>
|
|
1272
|
+
);
|
|
1273
|
+
};
|
|
1274
|
+
|
|
944
1275
|
const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
945
1276
|
className,
|
|
946
1277
|
...rest
|
|
@@ -949,7 +1280,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
949
1280
|
<BranchPickerPrimitive.Root
|
|
950
1281
|
hideWhenSingleBranch
|
|
951
1282
|
className={cn(
|
|
952
|
-
"
|
|
1283
|
+
"aui-branch-picker-root -ml-2 mr-2 inline-flex items-center text-muted-foreground text-xs",
|
|
953
1284
|
className,
|
|
954
1285
|
)}
|
|
955
1286
|
{...rest}
|
|
@@ -959,7 +1290,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
959
1290
|
<ChevronLeftIcon />
|
|
960
1291
|
</TooltipIconButton>
|
|
961
1292
|
</BranchPickerPrimitive.Previous>
|
|
962
|
-
<span className="font-medium">
|
|
1293
|
+
<span className="aui-branch-picker-state font-medium">
|
|
963
1294
|
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
|
964
1295
|
</span>
|
|
965
1296
|
<BranchPickerPrimitive.Next asChild>
|
|
@@ -971,17 +1302,102 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
971
1302
|
);
|
|
972
1303
|
};
|
|
973
1304
|
|
|
974
|
-
|
|
1305
|
+
```
|
|
1306
|
+
|
|
1307
|
+
## components/assistant-ui/tool-fallback.tsx
|
|
1308
|
+
|
|
1309
|
+
```tsx
|
|
1310
|
+
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
1311
|
+
import {
|
|
1312
|
+
CheckIcon,
|
|
1313
|
+
ChevronDownIcon,
|
|
1314
|
+
ChevronUpIcon,
|
|
1315
|
+
XCircleIcon,
|
|
1316
|
+
} from "lucide-react";
|
|
1317
|
+
import { useState } from "react";
|
|
1318
|
+
import { Button } from "@/components/ui/button";
|
|
1319
|
+
import { cn } from "@/lib/utils";
|
|
1320
|
+
|
|
1321
|
+
export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
1322
|
+
toolName,
|
|
1323
|
+
argsText,
|
|
1324
|
+
result,
|
|
1325
|
+
status,
|
|
1326
|
+
}) => {
|
|
1327
|
+
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
1328
|
+
|
|
1329
|
+
const isCancelled =
|
|
1330
|
+
status?.type === "incomplete" && status.reason === "cancelled";
|
|
1331
|
+
const cancelledReason =
|
|
1332
|
+
isCancelled && status.error
|
|
1333
|
+
? typeof status.error === "string"
|
|
1334
|
+
? status.error
|
|
1335
|
+
: JSON.stringify(status.error)
|
|
1336
|
+
: null;
|
|
1337
|
+
|
|
975
1338
|
return (
|
|
976
|
-
<
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
height="16"
|
|
1339
|
+
<div
|
|
1340
|
+
className={cn(
|
|
1341
|
+
"aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3",
|
|
1342
|
+
isCancelled && "border-muted-foreground/30 bg-muted/30",
|
|
1343
|
+
)}
|
|
982
1344
|
>
|
|
983
|
-
<
|
|
984
|
-
|
|
1345
|
+
<div className="aui-tool-fallback-header flex items-center gap-2 px-4">
|
|
1346
|
+
{isCancelled ? (
|
|
1347
|
+
<XCircleIcon className="aui-tool-fallback-icon size-4 text-muted-foreground" />
|
|
1348
|
+
) : (
|
|
1349
|
+
<CheckIcon className="aui-tool-fallback-icon size-4" />
|
|
1350
|
+
)}
|
|
1351
|
+
<p
|
|
1352
|
+
className={cn(
|
|
1353
|
+
"aui-tool-fallback-title grow",
|
|
1354
|
+
isCancelled && "text-muted-foreground line-through",
|
|
1355
|
+
)}
|
|
1356
|
+
>
|
|
1357
|
+
{isCancelled ? "Cancelled tool: " : "Used tool: "}
|
|
1358
|
+
<b>{toolName}</b>
|
|
1359
|
+
</p>
|
|
1360
|
+
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
1361
|
+
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
1362
|
+
</Button>
|
|
1363
|
+
</div>
|
|
1364
|
+
{!isCollapsed && (
|
|
1365
|
+
<div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
|
|
1366
|
+
{cancelledReason && (
|
|
1367
|
+
<div className="aui-tool-fallback-cancelled-root px-4">
|
|
1368
|
+
<p className="aui-tool-fallback-cancelled-header font-semibold text-muted-foreground">
|
|
1369
|
+
Cancelled reason:
|
|
1370
|
+
</p>
|
|
1371
|
+
<p className="aui-tool-fallback-cancelled-reason text-muted-foreground">
|
|
1372
|
+
{cancelledReason}
|
|
1373
|
+
</p>
|
|
1374
|
+
</div>
|
|
1375
|
+
)}
|
|
1376
|
+
<div
|
|
1377
|
+
className={cn(
|
|
1378
|
+
"aui-tool-fallback-args-root px-4",
|
|
1379
|
+
isCancelled && "opacity-60",
|
|
1380
|
+
)}
|
|
1381
|
+
>
|
|
1382
|
+
<pre className="aui-tool-fallback-args-value whitespace-pre-wrap">
|
|
1383
|
+
{argsText}
|
|
1384
|
+
</pre>
|
|
1385
|
+
</div>
|
|
1386
|
+
{!isCancelled && result !== undefined && (
|
|
1387
|
+
<div className="aui-tool-fallback-result-root border-t border-dashed px-4 pt-2">
|
|
1388
|
+
<p className="aui-tool-fallback-result-header font-semibold">
|
|
1389
|
+
Result:
|
|
1390
|
+
</p>
|
|
1391
|
+
<pre className="aui-tool-fallback-result-content whitespace-pre-wrap">
|
|
1392
|
+
{typeof result === "string"
|
|
1393
|
+
? result
|
|
1394
|
+
: JSON.stringify(result, null, 2)}
|
|
1395
|
+
</pre>
|
|
1396
|
+
</div>
|
|
1397
|
+
)}
|
|
1398
|
+
</div>
|
|
1399
|
+
)}
|
|
1400
|
+
</div>
|
|
985
1401
|
);
|
|
986
1402
|
};
|
|
987
1403
|
|
|
@@ -992,7 +1408,7 @@ const CircleStopIcon = () => {
|
|
|
992
1408
|
```tsx
|
|
993
1409
|
"use client";
|
|
994
1410
|
|
|
995
|
-
import {
|
|
1411
|
+
import { ComponentPropsWithRef, forwardRef } from "react";
|
|
996
1412
|
import { Slottable } from "@radix-ui/react-slot";
|
|
997
1413
|
|
|
998
1414
|
import {
|
|
@@ -1003,7 +1419,7 @@ import {
|
|
|
1003
1419
|
import { Button } from "@/components/ui/button";
|
|
1004
1420
|
import { cn } from "@/lib/utils";
|
|
1005
1421
|
|
|
1006
|
-
export type TooltipIconButtonProps =
|
|
1422
|
+
export type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
|
|
1007
1423
|
tooltip: string;
|
|
1008
1424
|
side?: "top" | "bottom" | "left" | "right";
|
|
1009
1425
|
};
|
|
@@ -1019,11 +1435,11 @@ export const TooltipIconButton = forwardRef<
|
|
|
1019
1435
|
variant="ghost"
|
|
1020
1436
|
size="icon"
|
|
1021
1437
|
{...rest}
|
|
1022
|
-
className={cn("size-6 p-1", className)}
|
|
1438
|
+
className={cn("aui-button-icon size-6 p-1", className)}
|
|
1023
1439
|
ref={ref}
|
|
1024
1440
|
>
|
|
1025
1441
|
<Slottable>{children}</Slottable>
|
|
1026
|
-
<span className="sr-only">{tooltip}</span>
|
|
1442
|
+
<span className="aui-sr-only sr-only">{tooltip}</span>
|
|
1027
1443
|
</Button>
|
|
1028
1444
|
</TooltipTrigger>
|
|
1029
1445
|
<TooltipContent side={side}>{tooltip}</TooltipContent>
|
|
@@ -1035,6 +1451,62 @@ TooltipIconButton.displayName = "TooltipIconButton";
|
|
|
1035
1451
|
|
|
1036
1452
|
```
|
|
1037
1453
|
|
|
1454
|
+
## components/ui/avatar.tsx
|
|
1455
|
+
|
|
1456
|
+
```tsx
|
|
1457
|
+
"use client";
|
|
1458
|
+
|
|
1459
|
+
import * as React from "react";
|
|
1460
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
1461
|
+
|
|
1462
|
+
import { cn } from "@/lib/utils";
|
|
1463
|
+
|
|
1464
|
+
const Avatar = React.forwardRef<
|
|
1465
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
1466
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
1467
|
+
>(({ className, ...props }, ref) => (
|
|
1468
|
+
<AvatarPrimitive.Root
|
|
1469
|
+
ref={ref}
|
|
1470
|
+
className={cn(
|
|
1471
|
+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
|
1472
|
+
className,
|
|
1473
|
+
)}
|
|
1474
|
+
{...props}
|
|
1475
|
+
/>
|
|
1476
|
+
));
|
|
1477
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
1478
|
+
|
|
1479
|
+
const AvatarImage = React.forwardRef<
|
|
1480
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
1481
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
1482
|
+
>(({ className, ...props }, ref) => (
|
|
1483
|
+
<AvatarPrimitive.Image
|
|
1484
|
+
ref={ref}
|
|
1485
|
+
className={cn("aspect-square h-full w-full", className)}
|
|
1486
|
+
{...props}
|
|
1487
|
+
/>
|
|
1488
|
+
));
|
|
1489
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
1490
|
+
|
|
1491
|
+
const AvatarFallback = React.forwardRef<
|
|
1492
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
1493
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
1494
|
+
>(({ className, ...props }, ref) => (
|
|
1495
|
+
<AvatarPrimitive.Fallback
|
|
1496
|
+
ref={ref}
|
|
1497
|
+
className={cn(
|
|
1498
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
1499
|
+
className,
|
|
1500
|
+
)}
|
|
1501
|
+
{...props}
|
|
1502
|
+
/>
|
|
1503
|
+
));
|
|
1504
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
1505
|
+
|
|
1506
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
1507
|
+
|
|
1508
|
+
```
|
|
1509
|
+
|
|
1038
1510
|
## components/ui/button.tsx
|
|
1039
1511
|
|
|
1040
1512
|
```tsx
|
|
@@ -1047,16 +1519,16 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|
|
1047
1519
|
import { cn } from "@/lib/utils";
|
|
1048
1520
|
|
|
1049
1521
|
const buttonVariants = cva(
|
|
1050
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm
|
|
1522
|
+
"inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
1051
1523
|
{
|
|
1052
1524
|
variants: {
|
|
1053
1525
|
variant: {
|
|
1054
1526
|
default:
|
|
1055
1527
|
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
1056
1528
|
destructive:
|
|
1057
|
-
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40
|
|
1529
|
+
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
1058
1530
|
outline:
|
|
1059
|
-
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:
|
|
1531
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
1060
1532
|
secondary:
|
|
1061
1533
|
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
1062
1534
|
ghost:
|
|
@@ -1065,7 +1537,7 @@ const buttonVariants = cva(
|
|
|
1065
1537
|
},
|
|
1066
1538
|
size: {
|
|
1067
1539
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
1068
|
-
sm: "h-8
|
|
1540
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
1069
1541
|
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
1070
1542
|
icon: "size-9",
|
|
1071
1543
|
},
|
|
@@ -1102,6 +1574,147 @@ export { Button, buttonVariants };
|
|
|
1102
1574
|
|
|
1103
1575
|
```
|
|
1104
1576
|
|
|
1577
|
+
## components/ui/dialog.tsx
|
|
1578
|
+
|
|
1579
|
+
```tsx
|
|
1580
|
+
"use client";
|
|
1581
|
+
|
|
1582
|
+
import * as React from "react";
|
|
1583
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
1584
|
+
import { XIcon } from "lucide-react";
|
|
1585
|
+
|
|
1586
|
+
import { cn } from "@/lib/utils";
|
|
1587
|
+
|
|
1588
|
+
function Dialog({
|
|
1589
|
+
...props
|
|
1590
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
1591
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
function DialogTrigger({
|
|
1595
|
+
...props
|
|
1596
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
1597
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
function DialogPortal({
|
|
1601
|
+
...props
|
|
1602
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
1603
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
function DialogClose({
|
|
1607
|
+
...props
|
|
1608
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
1609
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
function DialogOverlay({
|
|
1613
|
+
className,
|
|
1614
|
+
...props
|
|
1615
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
1616
|
+
return (
|
|
1617
|
+
<DialogPrimitive.Overlay
|
|
1618
|
+
data-slot="dialog-overlay"
|
|
1619
|
+
className={cn(
|
|
1620
|
+
"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",
|
|
1621
|
+
className,
|
|
1622
|
+
)}
|
|
1623
|
+
{...props}
|
|
1624
|
+
/>
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
function DialogContent({
|
|
1629
|
+
className,
|
|
1630
|
+
children,
|
|
1631
|
+
...props
|
|
1632
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content>) {
|
|
1633
|
+
return (
|
|
1634
|
+
<DialogPortal data-slot="dialog-portal">
|
|
1635
|
+
<DialogOverlay />
|
|
1636
|
+
<DialogPrimitive.Content
|
|
1637
|
+
data-slot="dialog-content"
|
|
1638
|
+
className={cn(
|
|
1639
|
+
"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",
|
|
1640
|
+
className,
|
|
1641
|
+
)}
|
|
1642
|
+
{...props}
|
|
1643
|
+
>
|
|
1644
|
+
{children}
|
|
1645
|
+
<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">
|
|
1646
|
+
<XIcon />
|
|
1647
|
+
<span className="sr-only">Close</span>
|
|
1648
|
+
</DialogPrimitive.Close>
|
|
1649
|
+
</DialogPrimitive.Content>
|
|
1650
|
+
</DialogPortal>
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
1655
|
+
return (
|
|
1656
|
+
<div
|
|
1657
|
+
data-slot="dialog-header"
|
|
1658
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
1659
|
+
{...props}
|
|
1660
|
+
/>
|
|
1661
|
+
);
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
1665
|
+
return (
|
|
1666
|
+
<div
|
|
1667
|
+
data-slot="dialog-footer"
|
|
1668
|
+
className={cn(
|
|
1669
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
1670
|
+
className,
|
|
1671
|
+
)}
|
|
1672
|
+
{...props}
|
|
1673
|
+
/>
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
function DialogTitle({
|
|
1678
|
+
className,
|
|
1679
|
+
...props
|
|
1680
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
1681
|
+
return (
|
|
1682
|
+
<DialogPrimitive.Title
|
|
1683
|
+
data-slot="dialog-title"
|
|
1684
|
+
className={cn("font-semibold text-lg leading-none", className)}
|
|
1685
|
+
{...props}
|
|
1686
|
+
/>
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
function DialogDescription({
|
|
1691
|
+
className,
|
|
1692
|
+
...props
|
|
1693
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
1694
|
+
return (
|
|
1695
|
+
<DialogPrimitive.Description
|
|
1696
|
+
data-slot="dialog-description"
|
|
1697
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
1698
|
+
{...props}
|
|
1699
|
+
/>
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
export {
|
|
1704
|
+
Dialog,
|
|
1705
|
+
DialogClose,
|
|
1706
|
+
DialogContent,
|
|
1707
|
+
DialogDescription,
|
|
1708
|
+
DialogFooter,
|
|
1709
|
+
DialogHeader,
|
|
1710
|
+
DialogOverlay,
|
|
1711
|
+
DialogPortal,
|
|
1712
|
+
DialogTitle,
|
|
1713
|
+
DialogTrigger,
|
|
1714
|
+
};
|
|
1715
|
+
|
|
1716
|
+
```
|
|
1717
|
+
|
|
1105
1718
|
## components/ui/tooltip.tsx
|
|
1106
1719
|
|
|
1107
1720
|
```tsx
|
|
@@ -1153,13 +1766,13 @@ function TooltipContent({
|
|
|
1153
1766
|
data-slot="tooltip-content"
|
|
1154
1767
|
sideOffset={sideOffset}
|
|
1155
1768
|
className={cn(
|
|
1156
|
-
"
|
|
1769
|
+
"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",
|
|
1157
1770
|
className,
|
|
1158
1771
|
)}
|
|
1159
1772
|
{...props}
|
|
1160
1773
|
>
|
|
1161
1774
|
{children}
|
|
1162
|
-
<TooltipPrimitive.Arrow className="
|
|
1775
|
+
<TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" />
|
|
1163
1776
|
</TooltipPrimitive.Content>
|
|
1164
1777
|
</TooltipPrimitive.Portal>
|
|
1165
1778
|
);
|
|
@@ -1181,18 +1794,6 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
1181
1794
|
|
|
1182
1795
|
```
|
|
1183
1796
|
|
|
1184
|
-
## next-env.d.ts
|
|
1185
|
-
|
|
1186
|
-
```typescript
|
|
1187
|
-
/// <reference types="next" />
|
|
1188
|
-
/// <reference types="next/image-types/global" />
|
|
1189
|
-
import "./.next/types/routes.d.ts";
|
|
1190
|
-
|
|
1191
|
-
// NOTE: This file should not be edited
|
|
1192
|
-
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
1193
|
-
|
|
1194
|
-
```
|
|
1195
|
-
|
|
1196
1797
|
## next.config.ts
|
|
1197
1798
|
|
|
1198
1799
|
```typescript
|
|
@@ -1216,11 +1817,10 @@ export default nextConfig;
|
|
|
1216
1817
|
"scripts": {
|
|
1217
1818
|
"dev": "next dev --turbo",
|
|
1218
1819
|
"build": "next build",
|
|
1219
|
-
"start": "next start"
|
|
1220
|
-
"lint": "eslint ."
|
|
1820
|
+
"start": "next start"
|
|
1221
1821
|
},
|
|
1222
1822
|
"dependencies": {
|
|
1223
|
-
"@ai-sdk/openai": "^2.0.
|
|
1823
|
+
"@ai-sdk/openai": "^2.0.77",
|
|
1224
1824
|
"@assistant-ui/react": "workspace:*",
|
|
1225
1825
|
"@assistant-ui/react-ai-sdk": "workspace:*",
|
|
1226
1826
|
"@assistant-ui/react-hook-form": "workspace:*",
|
|
@@ -1229,27 +1829,27 @@ export default nextConfig;
|
|
|
1229
1829
|
"@ffmpeg/util": "^0.12.2",
|
|
1230
1830
|
"@hookform/resolvers": "^5.2.2",
|
|
1231
1831
|
"@radix-ui/react-avatar": "^1.1.11",
|
|
1832
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
1232
1833
|
"@radix-ui/react-icons": "^1.3.2",
|
|
1233
1834
|
"@radix-ui/react-label": "^2.1.8",
|
|
1234
1835
|
"@radix-ui/react-slot": "^1.2.4",
|
|
1235
1836
|
"@radix-ui/react-tabs": "^1.1.13",
|
|
1236
1837
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
1237
1838
|
"@react-hook/media-query": "^1.1.1",
|
|
1238
|
-
"ai": "^5.0.
|
|
1839
|
+
"ai": "^5.0.107",
|
|
1239
1840
|
"class-variance-authority": "^0.7.1",
|
|
1240
1841
|
"clsx": "^2.1.1",
|
|
1241
|
-
"
|
|
1242
|
-
"
|
|
1243
|
-
"
|
|
1244
|
-
"react": "19.2.
|
|
1245
|
-
"react-
|
|
1246
|
-
"react-hook-form": "^7.66.1",
|
|
1842
|
+
"lucide-react": "^0.556.0",
|
|
1843
|
+
"next": "16.0.7",
|
|
1844
|
+
"react": "19.2.1",
|
|
1845
|
+
"react-dom": "19.2.1",
|
|
1846
|
+
"react-hook-form": "^7.68.0",
|
|
1247
1847
|
"react-resizable-panels": "^3.0.6",
|
|
1248
1848
|
"remark-gfm": "^4.0.1",
|
|
1249
1849
|
"tailwind-merge": "^3.4.0",
|
|
1250
1850
|
"tw-animate-css": "^1.4.0",
|
|
1251
|
-
"zod": "^4.1.
|
|
1252
|
-
"zustand": "^5.0.
|
|
1851
|
+
"zod": "^4.1.13",
|
|
1852
|
+
"zustand": "^5.0.9"
|
|
1253
1853
|
},
|
|
1254
1854
|
"devDependencies": {
|
|
1255
1855
|
"@assistant-ui/x-buildutils": "workspace:*",
|