@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
|
@@ -151,8 +151,8 @@ export default function RootLayout({
|
|
|
151
151
|
<html lang="en">
|
|
152
152
|
<body className="font-sans antialiased">
|
|
153
153
|
<div className="flex h-screen flex-col">
|
|
154
|
-
<header className="bg-background
|
|
155
|
-
<h1 className="text-lg
|
|
154
|
+
<header className="border-b bg-background px-4 py-2">
|
|
155
|
+
<h1 className="font-semibold text-lg">
|
|
156
156
|
Assistant Transport Example
|
|
157
157
|
</h1>
|
|
158
158
|
</header>
|
|
@@ -181,7 +181,7 @@ import {
|
|
|
181
181
|
convertLangChainMessages,
|
|
182
182
|
LangChainMessage,
|
|
183
183
|
} from "@assistant-ui/react-langgraph";
|
|
184
|
-
import
|
|
184
|
+
import { ReactNode } from "react";
|
|
185
185
|
import { z } from "zod";
|
|
186
186
|
|
|
187
187
|
// Frontend tool with execute function
|
|
@@ -265,7 +265,6 @@ const converter = (
|
|
|
265
265
|
);
|
|
266
266
|
|
|
267
267
|
const messages = [...state.messages, ...optimisticStateMessages.flat()];
|
|
268
|
-
console.log({ state, messages });
|
|
269
268
|
return {
|
|
270
269
|
messages: LangChainMessageConverter.toThreadMessages(messages),
|
|
271
270
|
isRunning: connectionMetadata.isSending || false,
|
|
@@ -359,6 +358,247 @@ export default function Home() {
|
|
|
359
358
|
|
|
360
359
|
```
|
|
361
360
|
|
|
361
|
+
## components/assistant-ui/attachment.tsx
|
|
362
|
+
|
|
363
|
+
```tsx
|
|
364
|
+
"use client";
|
|
365
|
+
|
|
366
|
+
import { PropsWithChildren, useEffect, useState, type FC } from "react";
|
|
367
|
+
import Image from "next/image";
|
|
368
|
+
import { XIcon, PlusIcon, FileText } from "lucide-react";
|
|
369
|
+
import {
|
|
370
|
+
AttachmentPrimitive,
|
|
371
|
+
ComposerPrimitive,
|
|
372
|
+
MessagePrimitive,
|
|
373
|
+
useAssistantState,
|
|
374
|
+
useAssistantApi,
|
|
375
|
+
} from "@assistant-ui/react";
|
|
376
|
+
import { useShallow } from "zustand/shallow";
|
|
377
|
+
import {
|
|
378
|
+
Tooltip,
|
|
379
|
+
TooltipContent,
|
|
380
|
+
TooltipTrigger,
|
|
381
|
+
} from "@/components/ui/tooltip";
|
|
382
|
+
import {
|
|
383
|
+
Dialog,
|
|
384
|
+
DialogTitle,
|
|
385
|
+
DialogContent,
|
|
386
|
+
DialogTrigger,
|
|
387
|
+
} from "@/components/ui/dialog";
|
|
388
|
+
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
|
389
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
390
|
+
import { cn } from "@/lib/utils";
|
|
391
|
+
|
|
392
|
+
const useFileSrc = (file: File | undefined) => {
|
|
393
|
+
const [src, setSrc] = useState<string | undefined>(undefined);
|
|
394
|
+
|
|
395
|
+
useEffect(() => {
|
|
396
|
+
if (!file) {
|
|
397
|
+
setSrc(undefined);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const objectUrl = URL.createObjectURL(file);
|
|
402
|
+
setSrc(objectUrl);
|
|
403
|
+
|
|
404
|
+
return () => {
|
|
405
|
+
URL.revokeObjectURL(objectUrl);
|
|
406
|
+
};
|
|
407
|
+
}, [file]);
|
|
408
|
+
|
|
409
|
+
return src;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
const useAttachmentSrc = () => {
|
|
413
|
+
const { file, src } = useAssistantState(
|
|
414
|
+
useShallow(({ attachment }): { file?: File; src?: string } => {
|
|
415
|
+
if (attachment.type !== "image") return {};
|
|
416
|
+
if (attachment.file) return { file: attachment.file };
|
|
417
|
+
const src = attachment.content?.filter((c) => c.type === "image")[0]
|
|
418
|
+
?.image;
|
|
419
|
+
if (!src) return {};
|
|
420
|
+
return { src };
|
|
421
|
+
}),
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
return useFileSrc(file) ?? src;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
type AttachmentPreviewProps = {
|
|
428
|
+
src: string;
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const AttachmentPreview: FC<AttachmentPreviewProps> = ({ src }) => {
|
|
432
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
433
|
+
return (
|
|
434
|
+
<Image
|
|
435
|
+
src={src}
|
|
436
|
+
alt="Image Preview"
|
|
437
|
+
width={1}
|
|
438
|
+
height={1}
|
|
439
|
+
className={
|
|
440
|
+
isLoaded
|
|
441
|
+
? "aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain"
|
|
442
|
+
: "aui-attachment-preview-image-loading hidden"
|
|
443
|
+
}
|
|
444
|
+
onLoadingComplete={() => setIsLoaded(true)}
|
|
445
|
+
priority={false}
|
|
446
|
+
/>
|
|
447
|
+
);
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
|
|
451
|
+
const src = useAttachmentSrc();
|
|
452
|
+
|
|
453
|
+
if (!src) return children;
|
|
454
|
+
|
|
455
|
+
return (
|
|
456
|
+
<Dialog>
|
|
457
|
+
<DialogTrigger
|
|
458
|
+
className="aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50"
|
|
459
|
+
asChild
|
|
460
|
+
>
|
|
461
|
+
{children}
|
|
462
|
+
</DialogTrigger>
|
|
463
|
+
<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">
|
|
464
|
+
<DialogTitle className="aui-sr-only sr-only">
|
|
465
|
+
Image Attachment Preview
|
|
466
|
+
</DialogTitle>
|
|
467
|
+
<div className="aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background">
|
|
468
|
+
<AttachmentPreview src={src} />
|
|
469
|
+
</div>
|
|
470
|
+
</DialogContent>
|
|
471
|
+
</Dialog>
|
|
472
|
+
);
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const AttachmentThumb: FC = () => {
|
|
476
|
+
const isImage = useAssistantState(
|
|
477
|
+
({ attachment }) => attachment.type === "image",
|
|
478
|
+
);
|
|
479
|
+
const src = useAttachmentSrc();
|
|
480
|
+
|
|
481
|
+
return (
|
|
482
|
+
<Avatar className="aui-attachment-tile-avatar h-full w-full rounded-none">
|
|
483
|
+
<AvatarImage
|
|
484
|
+
src={src}
|
|
485
|
+
alt="Attachment preview"
|
|
486
|
+
className="aui-attachment-tile-image object-cover"
|
|
487
|
+
/>
|
|
488
|
+
<AvatarFallback delayMs={isImage ? 200 : 0}>
|
|
489
|
+
<FileText className="aui-attachment-tile-fallback-icon size-8 text-muted-foreground" />
|
|
490
|
+
</AvatarFallback>
|
|
491
|
+
</Avatar>
|
|
492
|
+
);
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const AttachmentUI: FC = () => {
|
|
496
|
+
const api = useAssistantApi();
|
|
497
|
+
const isComposer = api.attachment.source === "composer";
|
|
498
|
+
|
|
499
|
+
const isImage = useAssistantState(
|
|
500
|
+
({ attachment }) => attachment.type === "image",
|
|
501
|
+
);
|
|
502
|
+
const typeLabel = useAssistantState(({ attachment }) => {
|
|
503
|
+
const type = attachment.type;
|
|
504
|
+
switch (type) {
|
|
505
|
+
case "image":
|
|
506
|
+
return "Image";
|
|
507
|
+
case "document":
|
|
508
|
+
return "Document";
|
|
509
|
+
case "file":
|
|
510
|
+
return "File";
|
|
511
|
+
default:
|
|
512
|
+
const _exhaustiveCheck: never = type;
|
|
513
|
+
throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
return (
|
|
518
|
+
<Tooltip>
|
|
519
|
+
<AttachmentPrimitive.Root
|
|
520
|
+
className={cn(
|
|
521
|
+
"aui-attachment-root relative",
|
|
522
|
+
isImage &&
|
|
523
|
+
"aui-attachment-root-composer only:[&>#attachment-tile]:size-24",
|
|
524
|
+
)}
|
|
525
|
+
>
|
|
526
|
+
<AttachmentPreviewDialog>
|
|
527
|
+
<TooltipTrigger asChild>
|
|
528
|
+
<div
|
|
529
|
+
className={cn(
|
|
530
|
+
"aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
|
|
531
|
+
isComposer &&
|
|
532
|
+
"aui-attachment-tile-composer border-foreground/20",
|
|
533
|
+
)}
|
|
534
|
+
role="button"
|
|
535
|
+
id="attachment-tile"
|
|
536
|
+
aria-label={`${typeLabel} attachment`}
|
|
537
|
+
>
|
|
538
|
+
<AttachmentThumb />
|
|
539
|
+
</div>
|
|
540
|
+
</TooltipTrigger>
|
|
541
|
+
</AttachmentPreviewDialog>
|
|
542
|
+
{isComposer && <AttachmentRemove />}
|
|
543
|
+
</AttachmentPrimitive.Root>
|
|
544
|
+
<TooltipContent side="top">
|
|
545
|
+
<AttachmentPrimitive.Name />
|
|
546
|
+
</TooltipContent>
|
|
547
|
+
</Tooltip>
|
|
548
|
+
);
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
const AttachmentRemove: FC = () => {
|
|
552
|
+
return (
|
|
553
|
+
<AttachmentPrimitive.Remove asChild>
|
|
554
|
+
<TooltipIconButton
|
|
555
|
+
tooltip="Remove file"
|
|
556
|
+
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"
|
|
557
|
+
side="top"
|
|
558
|
+
>
|
|
559
|
+
<XIcon className="aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" />
|
|
560
|
+
</TooltipIconButton>
|
|
561
|
+
</AttachmentPrimitive.Remove>
|
|
562
|
+
);
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
export const UserMessageAttachments: FC = () => {
|
|
566
|
+
return (
|
|
567
|
+
<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">
|
|
568
|
+
<MessagePrimitive.Attachments components={{ Attachment: AttachmentUI }} />
|
|
569
|
+
</div>
|
|
570
|
+
);
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
export const ComposerAttachments: FC = () => {
|
|
574
|
+
return (
|
|
575
|
+
<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">
|
|
576
|
+
<ComposerPrimitive.Attachments
|
|
577
|
+
components={{ Attachment: AttachmentUI }}
|
|
578
|
+
/>
|
|
579
|
+
</div>
|
|
580
|
+
);
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
export const ComposerAddAttachment: FC = () => {
|
|
584
|
+
return (
|
|
585
|
+
<ComposerPrimitive.AddAttachment asChild>
|
|
586
|
+
<TooltipIconButton
|
|
587
|
+
tooltip="Add Attachment"
|
|
588
|
+
side="bottom"
|
|
589
|
+
variant="ghost"
|
|
590
|
+
size="icon"
|
|
591
|
+
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"
|
|
592
|
+
aria-label="Add Attachment"
|
|
593
|
+
>
|
|
594
|
+
<PlusIcon className="aui-attachment-add-icon size-5 stroke-[1.5px]" />
|
|
595
|
+
</TooltipIconButton>
|
|
596
|
+
</ComposerPrimitive.AddAttachment>
|
|
597
|
+
);
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
```
|
|
601
|
+
|
|
362
602
|
## components/assistant-ui/markdown-text.tsx
|
|
363
603
|
|
|
364
604
|
```tsx
|
|
@@ -399,8 +639,10 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
|
|
|
399
639
|
};
|
|
400
640
|
|
|
401
641
|
return (
|
|
402
|
-
<div className="mt-4 flex items-center justify-between gap-4 rounded-t-lg bg-
|
|
403
|
-
<span className="lowercase [&>span]:text-xs">
|
|
642
|
+
<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">
|
|
643
|
+
<span className="aui-code-header-language lowercase [&>span]:text-xs">
|
|
644
|
+
{language}
|
|
645
|
+
</span>
|
|
404
646
|
<TooltipIconButton tooltip="Copy" onClick={onCopy}>
|
|
405
647
|
{!isCopied && <CopyIcon />}
|
|
406
648
|
{isCopied && <CheckIcon />}
|
|
@@ -432,7 +674,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
432
674
|
h1: ({ className, ...props }) => (
|
|
433
675
|
<h1
|
|
434
676
|
className={cn(
|
|
435
|
-
"mb-8 scroll-m-20 text-4xl
|
|
677
|
+
"aui-md-h1 mb-8 scroll-m-20 font-extrabold text-4xl tracking-tight last:mb-0",
|
|
436
678
|
className,
|
|
437
679
|
)}
|
|
438
680
|
{...props}
|
|
@@ -441,7 +683,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
441
683
|
h2: ({ className, ...props }) => (
|
|
442
684
|
<h2
|
|
443
685
|
className={cn(
|
|
444
|
-
"mt-8 mb-4 scroll-m-20 text-3xl
|
|
686
|
+
"aui-md-h2 mt-8 mb-4 scroll-m-20 font-semibold text-3xl tracking-tight first:mt-0 last:mb-0",
|
|
445
687
|
className,
|
|
446
688
|
)}
|
|
447
689
|
{...props}
|
|
@@ -450,7 +692,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
450
692
|
h3: ({ className, ...props }) => (
|
|
451
693
|
<h3
|
|
452
694
|
className={cn(
|
|
453
|
-
"mt-6 mb-4 scroll-m-20 text-2xl
|
|
695
|
+
"aui-md-h3 mt-6 mb-4 scroll-m-20 font-semibold text-2xl tracking-tight first:mt-0 last:mb-0",
|
|
454
696
|
className,
|
|
455
697
|
)}
|
|
456
698
|
{...props}
|
|
@@ -459,7 +701,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
459
701
|
h4: ({ className, ...props }) => (
|
|
460
702
|
<h4
|
|
461
703
|
className={cn(
|
|
462
|
-
"mt-6 mb-4 scroll-m-20 text-xl
|
|
704
|
+
"aui-md-h4 mt-6 mb-4 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0",
|
|
463
705
|
className,
|
|
464
706
|
)}
|
|
465
707
|
{...props}
|
|
@@ -468,7 +710,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
468
710
|
h5: ({ className, ...props }) => (
|
|
469
711
|
<h5
|
|
470
712
|
className={cn(
|
|
471
|
-
"my-4 text-lg
|
|
713
|
+
"aui-md-h5 my-4 font-semibold text-lg first:mt-0 last:mb-0",
|
|
472
714
|
className,
|
|
473
715
|
)}
|
|
474
716
|
{...props}
|
|
@@ -476,20 +718,26 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
476
718
|
),
|
|
477
719
|
h6: ({ className, ...props }) => (
|
|
478
720
|
<h6
|
|
479
|
-
className={cn(
|
|
721
|
+
className={cn(
|
|
722
|
+
"aui-md-h6 my-4 font-semibold first:mt-0 last:mb-0",
|
|
723
|
+
className,
|
|
724
|
+
)}
|
|
480
725
|
{...props}
|
|
481
726
|
/>
|
|
482
727
|
),
|
|
483
728
|
p: ({ className, ...props }) => (
|
|
484
729
|
<p
|
|
485
|
-
className={cn(
|
|
730
|
+
className={cn(
|
|
731
|
+
"aui-md-p mt-5 mb-5 leading-7 first:mt-0 last:mb-0",
|
|
732
|
+
className,
|
|
733
|
+
)}
|
|
486
734
|
{...props}
|
|
487
735
|
/>
|
|
488
736
|
),
|
|
489
737
|
a: ({ className, ...props }) => (
|
|
490
738
|
<a
|
|
491
739
|
className={cn(
|
|
492
|
-
"
|
|
740
|
+
"aui-md-a font-medium text-primary underline underline-offset-4",
|
|
493
741
|
className,
|
|
494
742
|
)}
|
|
495
743
|
{...props}
|
|
@@ -497,29 +745,29 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
497
745
|
),
|
|
498
746
|
blockquote: ({ className, ...props }) => (
|
|
499
747
|
<blockquote
|
|
500
|
-
className={cn("border-l-2 pl-6 italic", className)}
|
|
748
|
+
className={cn("aui-md-blockquote border-l-2 pl-6 italic", className)}
|
|
501
749
|
{...props}
|
|
502
750
|
/>
|
|
503
751
|
),
|
|
504
752
|
ul: ({ className, ...props }) => (
|
|
505
753
|
<ul
|
|
506
|
-
className={cn("my-5 ml-6 list-disc [&>li]:mt-2", className)}
|
|
754
|
+
className={cn("aui-md-ul my-5 ml-6 list-disc [&>li]:mt-2", className)}
|
|
507
755
|
{...props}
|
|
508
756
|
/>
|
|
509
757
|
),
|
|
510
758
|
ol: ({ className, ...props }) => (
|
|
511
759
|
<ol
|
|
512
|
-
className={cn("my-5 ml-6 list-decimal [&>li]:mt-2", className)}
|
|
760
|
+
className={cn("aui-md-ol my-5 ml-6 list-decimal [&>li]:mt-2", className)}
|
|
513
761
|
{...props}
|
|
514
762
|
/>
|
|
515
763
|
),
|
|
516
764
|
hr: ({ className, ...props }) => (
|
|
517
|
-
<hr className={cn("my-5 border-b", className)} {...props} />
|
|
765
|
+
<hr className={cn("aui-md-hr my-5 border-b", className)} {...props} />
|
|
518
766
|
),
|
|
519
767
|
table: ({ className, ...props }) => (
|
|
520
768
|
<table
|
|
521
769
|
className={cn(
|
|
522
|
-
"my-5 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
770
|
+
"aui-md-table my-5 w-full border-separate border-spacing-0 overflow-y-auto",
|
|
523
771
|
className,
|
|
524
772
|
)}
|
|
525
773
|
{...props}
|
|
@@ -528,7 +776,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
528
776
|
th: ({ className, ...props }) => (
|
|
529
777
|
<th
|
|
530
778
|
className={cn(
|
|
531
|
-
"bg-muted px-4 py-2 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [
|
|
779
|
+
"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",
|
|
532
780
|
className,
|
|
533
781
|
)}
|
|
534
782
|
{...props}
|
|
@@ -537,7 +785,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
537
785
|
td: ({ className, ...props }) => (
|
|
538
786
|
<td
|
|
539
787
|
className={cn(
|
|
540
|
-
"border-b border-l px-4 py-2 text-left last:border-r [
|
|
788
|
+
"aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right",
|
|
541
789
|
className,
|
|
542
790
|
)}
|
|
543
791
|
{...props}
|
|
@@ -546,7 +794,7 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
546
794
|
tr: ({ className, ...props }) => (
|
|
547
795
|
<tr
|
|
548
796
|
className={cn(
|
|
549
|
-
"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",
|
|
797
|
+
"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",
|
|
550
798
|
className,
|
|
551
799
|
)}
|
|
552
800
|
{...props}
|
|
@@ -554,14 +802,14 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
554
802
|
),
|
|
555
803
|
sup: ({ className, ...props }) => (
|
|
556
804
|
<sup
|
|
557
|
-
className={cn("[&>a]:text-xs [&>a]:no-underline", className)}
|
|
805
|
+
className={cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className)}
|
|
558
806
|
{...props}
|
|
559
807
|
/>
|
|
560
808
|
),
|
|
561
809
|
pre: ({ className, ...props }) => (
|
|
562
810
|
<pre
|
|
563
811
|
className={cn(
|
|
564
|
-
"overflow-x-auto
|
|
812
|
+
"aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-black p-4 text-white",
|
|
565
813
|
className,
|
|
566
814
|
)}
|
|
567
815
|
{...props}
|
|
@@ -572,7 +820,8 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
572
820
|
return (
|
|
573
821
|
<code
|
|
574
822
|
className={cn(
|
|
575
|
-
!isCodeBlock &&
|
|
823
|
+
!isCodeBlock &&
|
|
824
|
+
"aui-md-inline-code rounded border bg-muted font-semibold",
|
|
576
825
|
className,
|
|
577
826
|
)}
|
|
578
827
|
{...props}
|
|
@@ -588,45 +837,53 @@ const defaultComponents = memoizeMarkdownComponents({
|
|
|
588
837
|
|
|
589
838
|
```tsx
|
|
590
839
|
import {
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
840
|
+
ComposerAddAttachment,
|
|
841
|
+
ComposerAttachments,
|
|
842
|
+
UserMessageAttachments,
|
|
843
|
+
} from "@/components/assistant-ui/attachment";
|
|
844
|
+
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
845
|
+
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
|
846
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
847
|
+
import { Button } from "@/components/ui/button";
|
|
848
|
+
import { cn } from "@/lib/utils";
|
|
849
|
+
import {
|
|
594
850
|
ActionBarPrimitive,
|
|
851
|
+
AssistantIf,
|
|
595
852
|
BranchPickerPrimitive,
|
|
853
|
+
ComposerPrimitive,
|
|
596
854
|
ErrorPrimitive,
|
|
855
|
+
MessagePrimitive,
|
|
856
|
+
ThreadPrimitive,
|
|
597
857
|
} from "@assistant-ui/react";
|
|
598
|
-
import type { FC } from "react";
|
|
599
858
|
import {
|
|
600
859
|
ArrowDownIcon,
|
|
601
860
|
ArrowUpIcon,
|
|
602
|
-
PlusIcon,
|
|
603
|
-
CopyIcon,
|
|
604
861
|
CheckIcon,
|
|
605
|
-
PencilIcon,
|
|
606
|
-
RefreshCwIcon,
|
|
607
862
|
ChevronLeftIcon,
|
|
608
863
|
ChevronRightIcon,
|
|
609
|
-
|
|
864
|
+
CopyIcon,
|
|
865
|
+
DownloadIcon,
|
|
866
|
+
PencilIcon,
|
|
867
|
+
RefreshCwIcon,
|
|
868
|
+
SquareIcon,
|
|
610
869
|
} from "lucide-react";
|
|
611
|
-
|
|
612
|
-
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
613
|
-
import { motion } from "framer-motion";
|
|
614
|
-
import { Button } from "@/components/ui/button";
|
|
615
|
-
import { cn } from "@/lib/utils";
|
|
616
|
-
import { MarkdownText } from "./markdown-text";
|
|
617
|
-
import { ToolFallback } from "./tool-fallback";
|
|
870
|
+
import type { FC } from "react";
|
|
618
871
|
|
|
619
872
|
export const Thread: FC = () => {
|
|
620
873
|
return (
|
|
621
874
|
<ThreadPrimitive.Root
|
|
622
|
-
className="
|
|
875
|
+
className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
|
|
623
876
|
style={{
|
|
624
|
-
["--thread-max-width" as string]: "
|
|
625
|
-
["--thread-padding-x" as string]: "1rem",
|
|
877
|
+
["--thread-max-width" as string]: "44rem",
|
|
626
878
|
}}
|
|
627
879
|
>
|
|
628
|
-
<ThreadPrimitive.Viewport
|
|
629
|
-
|
|
880
|
+
<ThreadPrimitive.Viewport
|
|
881
|
+
turnAnchor="top"
|
|
882
|
+
className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
|
|
883
|
+
>
|
|
884
|
+
<AssistantIf condition={({ thread }) => thread.isEmpty}>
|
|
885
|
+
<ThreadWelcome />
|
|
886
|
+
</AssistantIf>
|
|
630
887
|
|
|
631
888
|
<ThreadPrimitive.Messages
|
|
632
889
|
components={{
|
|
@@ -636,12 +893,11 @@ export const Thread: FC = () => {
|
|
|
636
893
|
}}
|
|
637
894
|
/>
|
|
638
895
|
|
|
639
|
-
<ThreadPrimitive.
|
|
640
|
-
<
|
|
641
|
-
|
|
896
|
+
<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">
|
|
897
|
+
<ThreadScrollToBottom />
|
|
898
|
+
<Composer />
|
|
899
|
+
</ThreadPrimitive.ViewportFooter>
|
|
642
900
|
</ThreadPrimitive.Viewport>
|
|
643
|
-
|
|
644
|
-
<Composer />
|
|
645
901
|
</ThreadPrimitive.Root>
|
|
646
902
|
);
|
|
647
903
|
};
|
|
@@ -652,7 +908,7 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
652
908
|
<TooltipIconButton
|
|
653
909
|
tooltip="Scroll to bottom"
|
|
654
910
|
variant="outline"
|
|
655
|
-
className="
|
|
911
|
+
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"
|
|
656
912
|
>
|
|
657
913
|
<ArrowDownIcon />
|
|
658
914
|
</TooltipIconButton>
|
|
@@ -662,84 +918,59 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
662
918
|
|
|
663
919
|
const ThreadWelcome: FC = () => {
|
|
664
920
|
return (
|
|
665
|
-
<
|
|
666
|
-
<div className="
|
|
667
|
-
<div className="flex
|
|
668
|
-
<
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
className="text-2xl font-semibold"
|
|
675
|
-
>
|
|
676
|
-
Hello there!
|
|
677
|
-
</motion.div>
|
|
678
|
-
<motion.div
|
|
679
|
-
initial={{ opacity: 0, y: 10 }}
|
|
680
|
-
animate={{ opacity: 1, y: 0 }}
|
|
681
|
-
exit={{ opacity: 0, y: 10 }}
|
|
682
|
-
transition={{ delay: 0.6 }}
|
|
683
|
-
className="text-muted-foreground/65 text-2xl"
|
|
684
|
-
>
|
|
685
|
-
How can I help you today?
|
|
686
|
-
</motion.div>
|
|
687
|
-
</div>
|
|
921
|
+
<div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
|
|
922
|
+
<div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
|
|
923
|
+
<div className="aui-thread-welcome-message flex size-full flex-col justify-center px-4">
|
|
924
|
+
<h1 className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-2xl duration-200">
|
|
925
|
+
Hello there!
|
|
926
|
+
</h1>
|
|
927
|
+
<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">
|
|
928
|
+
How can I help you today?
|
|
929
|
+
</p>
|
|
688
930
|
</div>
|
|
689
931
|
</div>
|
|
690
|
-
|
|
932
|
+
<ThreadSuggestions />
|
|
933
|
+
</div>
|
|
691
934
|
);
|
|
692
935
|
};
|
|
693
936
|
|
|
694
|
-
const
|
|
937
|
+
const SUGGESTIONS = [
|
|
938
|
+
{
|
|
939
|
+
title: "What's the weather",
|
|
940
|
+
label: "in San Francisco?",
|
|
941
|
+
prompt: "What's the weather in San Francisco?",
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
title: "Explain React hooks",
|
|
945
|
+
label: "like useState and useEffect",
|
|
946
|
+
prompt: "Explain React hooks like useState and useEffect",
|
|
947
|
+
},
|
|
948
|
+
] as const;
|
|
949
|
+
|
|
950
|
+
const ThreadSuggestions: FC = () => {
|
|
695
951
|
return (
|
|
696
|
-
<div className="grid w-full
|
|
697
|
-
{
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
},
|
|
703
|
-
{
|
|
704
|
-
title: "Write code to",
|
|
705
|
-
label: `demonstrate topological sorting`,
|
|
706
|
-
action: `Write code to demonstrate topological sorting`,
|
|
707
|
-
},
|
|
708
|
-
{
|
|
709
|
-
title: "Help me write an essay",
|
|
710
|
-
label: `about AI chat applications`,
|
|
711
|
-
action: `Help me write an essay about AI chat applications`,
|
|
712
|
-
},
|
|
713
|
-
{
|
|
714
|
-
title: "What is the weather",
|
|
715
|
-
label: "in San Francisco?",
|
|
716
|
-
action: "What is the weather in San Francisco?",
|
|
717
|
-
},
|
|
718
|
-
].map((suggestedAction, index) => (
|
|
719
|
-
<motion.div
|
|
720
|
-
initial={{ opacity: 0, y: 20 }}
|
|
721
|
-
animate={{ opacity: 1, y: 0 }}
|
|
722
|
-
exit={{ opacity: 0, y: 20 }}
|
|
723
|
-
transition={{ delay: 0.05 * index }}
|
|
724
|
-
key={`suggested-action-${suggestedAction.title}-${index}`}
|
|
725
|
-
className="[&:nth-child(n+3)]:hidden sm:[&:nth-child(n+3)]:block"
|
|
952
|
+
<div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
|
|
953
|
+
{SUGGESTIONS.map((suggestion, index) => (
|
|
954
|
+
<div
|
|
955
|
+
key={suggestion.prompt}
|
|
956
|
+
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"
|
|
957
|
+
style={{ animationDelay: `${100 + index * 50}ms` }}
|
|
726
958
|
>
|
|
727
|
-
<ThreadPrimitive.Suggestion
|
|
728
|
-
prompt={suggestedAction.action}
|
|
729
|
-
method="replace"
|
|
730
|
-
autoSend
|
|
731
|
-
asChild
|
|
732
|
-
>
|
|
959
|
+
<ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
|
|
733
960
|
<Button
|
|
734
961
|
variant="ghost"
|
|
735
|
-
className="
|
|
736
|
-
aria-label={
|
|
962
|
+
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"
|
|
963
|
+
aria-label={suggestion.prompt}
|
|
737
964
|
>
|
|
738
|
-
<span className="font-medium">
|
|
739
|
-
|
|
965
|
+
<span className="aui-thread-welcome-suggestion-text-1 font-medium">
|
|
966
|
+
{suggestion.title}
|
|
967
|
+
</span>
|
|
968
|
+
<span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
|
|
969
|
+
{suggestion.label}
|
|
970
|
+
</span>
|
|
740
971
|
</Button>
|
|
741
972
|
</ThreadPrimitive.Suggestion>
|
|
742
|
-
</
|
|
973
|
+
</div>
|
|
743
974
|
))}
|
|
744
975
|
</div>
|
|
745
976
|
);
|
|
@@ -747,64 +978,56 @@ const ThreadWelcomeSuggestions: FC = () => {
|
|
|
747
978
|
|
|
748
979
|
const Composer: FC = () => {
|
|
749
980
|
return (
|
|
750
|
-
<
|
|
751
|
-
<
|
|
752
|
-
|
|
753
|
-
<ThreadWelcomeSuggestions />
|
|
754
|
-
</ThreadPrimitive.Empty>
|
|
755
|
-
<ComposerPrimitive.Root className="relative flex w-full flex-col rounded-2xl focus-within:ring-2 focus-within:ring-black focus-within:ring-offset-2 dark:focus-within:ring-white">
|
|
981
|
+
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
|
|
982
|
+
<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">
|
|
983
|
+
<ComposerAttachments />
|
|
756
984
|
<ComposerPrimitive.Input
|
|
757
985
|
placeholder="Send a message..."
|
|
758
|
-
className="
|
|
986
|
+
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"
|
|
759
987
|
rows={1}
|
|
760
988
|
autoFocus
|
|
761
989
|
aria-label="Message input"
|
|
762
990
|
/>
|
|
763
991
|
<ComposerAction />
|
|
764
|
-
</ComposerPrimitive.
|
|
765
|
-
</
|
|
992
|
+
</ComposerPrimitive.AttachmentDropzone>
|
|
993
|
+
</ComposerPrimitive.Root>
|
|
766
994
|
);
|
|
767
995
|
};
|
|
768
996
|
|
|
769
997
|
const ComposerAction: FC = () => {
|
|
770
998
|
return (
|
|
771
|
-
<div className="
|
|
772
|
-
<
|
|
773
|
-
tooltip="Attach file"
|
|
774
|
-
variant="ghost"
|
|
775
|
-
className="hover:bg-foreground/15 dark:hover:bg-background/50 scale-115 p-3.5"
|
|
776
|
-
onClick={() => {
|
|
777
|
-
console.log("Attachment clicked - not implemented");
|
|
778
|
-
}}
|
|
779
|
-
>
|
|
780
|
-
<PlusIcon />
|
|
781
|
-
</TooltipIconButton>
|
|
999
|
+
<div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
|
|
1000
|
+
<ComposerAddAttachment />
|
|
782
1001
|
|
|
783
|
-
<
|
|
1002
|
+
<AssistantIf condition={({ thread }) => !thread.isRunning}>
|
|
784
1003
|
<ComposerPrimitive.Send asChild>
|
|
785
|
-
<
|
|
1004
|
+
<TooltipIconButton
|
|
1005
|
+
tooltip="Send message"
|
|
1006
|
+
side="bottom"
|
|
786
1007
|
type="submit"
|
|
787
1008
|
variant="default"
|
|
788
|
-
|
|
1009
|
+
size="icon"
|
|
1010
|
+
className="aui-composer-send size-8 rounded-full"
|
|
789
1011
|
aria-label="Send message"
|
|
790
1012
|
>
|
|
791
|
-
<ArrowUpIcon className="size-
|
|
792
|
-
</
|
|
1013
|
+
<ArrowUpIcon className="aui-composer-send-icon size-4" />
|
|
1014
|
+
</TooltipIconButton>
|
|
793
1015
|
</ComposerPrimitive.Send>
|
|
794
|
-
</
|
|
1016
|
+
</AssistantIf>
|
|
795
1017
|
|
|
796
|
-
<
|
|
1018
|
+
<AssistantIf condition={({ thread }) => thread.isRunning}>
|
|
797
1019
|
<ComposerPrimitive.Cancel asChild>
|
|
798
1020
|
<Button
|
|
799
1021
|
type="button"
|
|
800
1022
|
variant="default"
|
|
801
|
-
|
|
1023
|
+
size="icon"
|
|
1024
|
+
className="aui-composer-cancel size-8 rounded-full"
|
|
802
1025
|
aria-label="Stop generating"
|
|
803
1026
|
>
|
|
804
|
-
<
|
|
1027
|
+
<SquareIcon className="aui-composer-cancel-icon size-3 fill-current" />
|
|
805
1028
|
</Button>
|
|
806
1029
|
</ComposerPrimitive.Cancel>
|
|
807
|
-
</
|
|
1030
|
+
</AssistantIf>
|
|
808
1031
|
</div>
|
|
809
1032
|
);
|
|
810
1033
|
};
|
|
@@ -812,8 +1035,8 @@ const ComposerAction: FC = () => {
|
|
|
812
1035
|
const MessageError: FC = () => {
|
|
813
1036
|
return (
|
|
814
1037
|
<MessagePrimitive.Error>
|
|
815
|
-
<ErrorPrimitive.Root className="
|
|
816
|
-
<ErrorPrimitive.Message className="line-clamp-2" />
|
|
1038
|
+
<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">
|
|
1039
|
+
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
|
|
817
1040
|
</ErrorPrimitive.Root>
|
|
818
1041
|
</MessagePrimitive.Error>
|
|
819
1042
|
);
|
|
@@ -821,31 +1044,24 @@ const MessageError: FC = () => {
|
|
|
821
1044
|
|
|
822
1045
|
const AssistantMessage: FC = () => {
|
|
823
1046
|
return (
|
|
824
|
-
<MessagePrimitive.Root
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
<
|
|
836
|
-
|
|
837
|
-
components={{
|
|
838
|
-
Text: MarkdownText,
|
|
839
|
-
tools: { Fallback: ToolFallback },
|
|
840
|
-
}}
|
|
841
|
-
/>
|
|
842
|
-
<MessageError />
|
|
843
|
-
</div>
|
|
1047
|
+
<MessagePrimitive.Root
|
|
1048
|
+
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"
|
|
1049
|
+
data-role="assistant"
|
|
1050
|
+
>
|
|
1051
|
+
<div className="aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed">
|
|
1052
|
+
<MessagePrimitive.Parts
|
|
1053
|
+
components={{
|
|
1054
|
+
Text: MarkdownText,
|
|
1055
|
+
tools: { Fallback: ToolFallback },
|
|
1056
|
+
}}
|
|
1057
|
+
/>
|
|
1058
|
+
<MessageError />
|
|
1059
|
+
</div>
|
|
844
1060
|
|
|
1061
|
+
<div className="aui-assistant-message-footer mt-1 ml-2 flex">
|
|
1062
|
+
<BranchPicker />
|
|
845
1063
|
<AssistantActionBar />
|
|
846
|
-
|
|
847
|
-
<BranchPicker className="col-start-2 row-start-2 mr-2 -ml-2" />
|
|
848
|
-
</motion.div>
|
|
1064
|
+
</div>
|
|
849
1065
|
</MessagePrimitive.Root>
|
|
850
1066
|
);
|
|
851
1067
|
};
|
|
@@ -856,18 +1072,23 @@ const AssistantActionBar: FC = () => {
|
|
|
856
1072
|
hideWhenRunning
|
|
857
1073
|
autohide="not-last"
|
|
858
1074
|
autohideFloat="single-branch"
|
|
859
|
-
className="
|
|
1075
|
+
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"
|
|
860
1076
|
>
|
|
861
1077
|
<ActionBarPrimitive.Copy asChild>
|
|
862
1078
|
<TooltipIconButton tooltip="Copy">
|
|
863
|
-
<
|
|
1079
|
+
<AssistantIf condition={({ message }) => message.isCopied}>
|
|
864
1080
|
<CheckIcon />
|
|
865
|
-
</
|
|
866
|
-
<
|
|
1081
|
+
</AssistantIf>
|
|
1082
|
+
<AssistantIf condition={({ message }) => !message.isCopied}>
|
|
867
1083
|
<CopyIcon />
|
|
868
|
-
</
|
|
1084
|
+
</AssistantIf>
|
|
869
1085
|
</TooltipIconButton>
|
|
870
1086
|
</ActionBarPrimitive.Copy>
|
|
1087
|
+
<ActionBarPrimitive.ExportMarkdown asChild>
|
|
1088
|
+
<TooltipIconButton tooltip="Export as Markdown">
|
|
1089
|
+
<DownloadIcon />
|
|
1090
|
+
</TooltipIconButton>
|
|
1091
|
+
</ActionBarPrimitive.ExportMarkdown>
|
|
871
1092
|
<ActionBarPrimitive.Reload asChild>
|
|
872
1093
|
<TooltipIconButton tooltip="Refresh">
|
|
873
1094
|
<RefreshCwIcon />
|
|
@@ -879,21 +1100,22 @@ const AssistantActionBar: FC = () => {
|
|
|
879
1100
|
|
|
880
1101
|
const UserMessage: FC = () => {
|
|
881
1102
|
return (
|
|
882
|
-
<MessagePrimitive.Root
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
data-role="user"
|
|
888
|
-
>
|
|
889
|
-
<UserActionBar />
|
|
1103
|
+
<MessagePrimitive.Root
|
|
1104
|
+
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"
|
|
1105
|
+
data-role="user"
|
|
1106
|
+
>
|
|
1107
|
+
<UserMessageAttachments />
|
|
890
1108
|
|
|
891
|
-
|
|
892
|
-
|
|
1109
|
+
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
|
|
1110
|
+
<div className="aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground">
|
|
1111
|
+
<MessagePrimitive.Parts />
|
|
893
1112
|
</div>
|
|
1113
|
+
<div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
|
|
1114
|
+
<UserActionBar />
|
|
1115
|
+
</div>
|
|
1116
|
+
</div>
|
|
894
1117
|
|
|
895
|
-
|
|
896
|
-
</motion.div>
|
|
1118
|
+
<BranchPicker className="aui-user-branch-picker -mr-1 col-span-full col-start-1 row-start-3 justify-end" />
|
|
897
1119
|
</MessagePrimitive.Root>
|
|
898
1120
|
);
|
|
899
1121
|
};
|
|
@@ -903,10 +1125,10 @@ const UserActionBar: FC = () => {
|
|
|
903
1125
|
<ActionBarPrimitive.Root
|
|
904
1126
|
hideWhenRunning
|
|
905
1127
|
autohide="not-last"
|
|
906
|
-
className="
|
|
1128
|
+
className="aui-user-action-bar-root flex flex-col items-end"
|
|
907
1129
|
>
|
|
908
1130
|
<ActionBarPrimitive.Edit asChild>
|
|
909
|
-
<TooltipIconButton tooltip="Edit">
|
|
1131
|
+
<TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
|
|
910
1132
|
<PencilIcon />
|
|
911
1133
|
</TooltipIconButton>
|
|
912
1134
|
</ActionBarPrimitive.Edit>
|
|
@@ -916,27 +1138,24 @@ const UserActionBar: FC = () => {
|
|
|
916
1138
|
|
|
917
1139
|
const EditComposer: FC = () => {
|
|
918
1140
|
return (
|
|
919
|
-
<
|
|
920
|
-
<ComposerPrimitive.Root className="
|
|
1141
|
+
<MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3">
|
|
1142
|
+
<ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted">
|
|
921
1143
|
<ComposerPrimitive.Input
|
|
922
|
-
className="
|
|
1144
|
+
className="aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none"
|
|
923
1145
|
autoFocus
|
|
924
1146
|
/>
|
|
925
|
-
|
|
926
|
-
<div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
|
|
1147
|
+
<div className="aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end">
|
|
927
1148
|
<ComposerPrimitive.Cancel asChild>
|
|
928
|
-
<Button variant="ghost" size="sm"
|
|
1149
|
+
<Button variant="ghost" size="sm">
|
|
929
1150
|
Cancel
|
|
930
1151
|
</Button>
|
|
931
1152
|
</ComposerPrimitive.Cancel>
|
|
932
1153
|
<ComposerPrimitive.Send asChild>
|
|
933
|
-
<Button size="sm"
|
|
934
|
-
Update
|
|
935
|
-
</Button>
|
|
1154
|
+
<Button size="sm">Update</Button>
|
|
936
1155
|
</ComposerPrimitive.Send>
|
|
937
1156
|
</div>
|
|
938
1157
|
</ComposerPrimitive.Root>
|
|
939
|
-
</
|
|
1158
|
+
</MessagePrimitive.Root>
|
|
940
1159
|
);
|
|
941
1160
|
};
|
|
942
1161
|
|
|
@@ -948,7 +1167,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
948
1167
|
<BranchPickerPrimitive.Root
|
|
949
1168
|
hideWhenSingleBranch
|
|
950
1169
|
className={cn(
|
|
951
|
-
"
|
|
1170
|
+
"aui-branch-picker-root -ml-2 mr-2 inline-flex items-center text-muted-foreground text-xs",
|
|
952
1171
|
className,
|
|
953
1172
|
)}
|
|
954
1173
|
{...rest}
|
|
@@ -958,7 +1177,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
958
1177
|
<ChevronLeftIcon />
|
|
959
1178
|
</TooltipIconButton>
|
|
960
1179
|
</BranchPickerPrimitive.Previous>
|
|
961
|
-
<span className="font-medium">
|
|
1180
|
+
<span className="aui-branch-picker-state font-medium">
|
|
962
1181
|
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
|
963
1182
|
</span>
|
|
964
1183
|
<BranchPickerPrimitive.Next asChild>
|
|
@@ -970,57 +1189,93 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
|
970
1189
|
);
|
|
971
1190
|
};
|
|
972
1191
|
|
|
973
|
-
const StarIcon = ({ size = 14 }: { size?: number }) => (
|
|
974
|
-
<svg
|
|
975
|
-
width={size}
|
|
976
|
-
height={size}
|
|
977
|
-
viewBox="0 0 16 16"
|
|
978
|
-
fill="none"
|
|
979
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
980
|
-
>
|
|
981
|
-
<path
|
|
982
|
-
d="M8 0L9.79611 6.20389L16 8L9.79611 9.79611L8 16L6.20389 9.79611L0 8L6.20389 6.20389L8 0Z"
|
|
983
|
-
fill="currentColor"
|
|
984
|
-
/>
|
|
985
|
-
</svg>
|
|
986
|
-
);
|
|
987
|
-
|
|
988
1192
|
```
|
|
989
1193
|
|
|
990
1194
|
## components/assistant-ui/tool-fallback.tsx
|
|
991
1195
|
|
|
992
1196
|
```tsx
|
|
993
|
-
import { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
994
|
-
import {
|
|
1197
|
+
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
1198
|
+
import {
|
|
1199
|
+
CheckIcon,
|
|
1200
|
+
ChevronDownIcon,
|
|
1201
|
+
ChevronUpIcon,
|
|
1202
|
+
XCircleIcon,
|
|
1203
|
+
} from "lucide-react";
|
|
995
1204
|
import { useState } from "react";
|
|
996
|
-
import { Button } from "
|
|
1205
|
+
import { Button } from "@/components/ui/button";
|
|
1206
|
+
import { cn } from "@/lib/utils";
|
|
997
1207
|
|
|
998
1208
|
export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
999
1209
|
toolName,
|
|
1000
1210
|
argsText,
|
|
1001
1211
|
result,
|
|
1212
|
+
status,
|
|
1002
1213
|
}) => {
|
|
1003
1214
|
const [isCollapsed, setIsCollapsed] = useState(true);
|
|
1215
|
+
|
|
1216
|
+
const isCancelled =
|
|
1217
|
+
status?.type === "incomplete" && status.reason === "cancelled";
|
|
1218
|
+
const cancelledReason =
|
|
1219
|
+
isCancelled && status.error
|
|
1220
|
+
? typeof status.error === "string"
|
|
1221
|
+
? status.error
|
|
1222
|
+
: JSON.stringify(status.error)
|
|
1223
|
+
: null;
|
|
1224
|
+
|
|
1004
1225
|
return (
|
|
1005
|
-
<div
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1226
|
+
<div
|
|
1227
|
+
className={cn(
|
|
1228
|
+
"aui-tool-fallback-root mb-4 flex w-full flex-col gap-3 rounded-lg border py-3",
|
|
1229
|
+
isCancelled && "border-muted-foreground/30 bg-muted/30",
|
|
1230
|
+
)}
|
|
1231
|
+
>
|
|
1232
|
+
<div className="aui-tool-fallback-header flex items-center gap-2 px-4">
|
|
1233
|
+
{isCancelled ? (
|
|
1234
|
+
<XCircleIcon className="aui-tool-fallback-icon size-4 text-muted-foreground" />
|
|
1235
|
+
) : (
|
|
1236
|
+
<CheckIcon className="aui-tool-fallback-icon size-4" />
|
|
1237
|
+
)}
|
|
1238
|
+
<p
|
|
1239
|
+
className={cn(
|
|
1240
|
+
"aui-tool-fallback-title grow",
|
|
1241
|
+
isCancelled && "text-muted-foreground line-through",
|
|
1242
|
+
)}
|
|
1243
|
+
>
|
|
1244
|
+
{isCancelled ? "Cancelled tool: " : "Used tool: "}
|
|
1245
|
+
<b>{toolName}</b>
|
|
1010
1246
|
</p>
|
|
1011
1247
|
<Button onClick={() => setIsCollapsed(!isCollapsed)}>
|
|
1012
1248
|
{isCollapsed ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
1013
1249
|
</Button>
|
|
1014
1250
|
</div>
|
|
1015
1251
|
{!isCollapsed && (
|
|
1016
|
-
<div className="flex flex-col gap-2 border-t pt-2">
|
|
1017
|
-
|
|
1018
|
-
<
|
|
1252
|
+
<div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
|
|
1253
|
+
{cancelledReason && (
|
|
1254
|
+
<div className="aui-tool-fallback-cancelled-root px-4">
|
|
1255
|
+
<p className="aui-tool-fallback-cancelled-header font-semibold text-muted-foreground">
|
|
1256
|
+
Cancelled reason:
|
|
1257
|
+
</p>
|
|
1258
|
+
<p className="aui-tool-fallback-cancelled-reason text-muted-foreground">
|
|
1259
|
+
{cancelledReason}
|
|
1260
|
+
</p>
|
|
1261
|
+
</div>
|
|
1262
|
+
)}
|
|
1263
|
+
<div
|
|
1264
|
+
className={cn(
|
|
1265
|
+
"aui-tool-fallback-args-root px-4",
|
|
1266
|
+
isCancelled && "opacity-60",
|
|
1267
|
+
)}
|
|
1268
|
+
>
|
|
1269
|
+
<pre className="aui-tool-fallback-args-value whitespace-pre-wrap">
|
|
1270
|
+
{argsText}
|
|
1271
|
+
</pre>
|
|
1019
1272
|
</div>
|
|
1020
|
-
{result !== undefined && (
|
|
1021
|
-
<div className="border-t border-dashed px-4 pt-2">
|
|
1022
|
-
<p className="font-semibold">
|
|
1023
|
-
|
|
1273
|
+
{!isCancelled && result !== undefined && (
|
|
1274
|
+
<div className="aui-tool-fallback-result-root border-t border-dashed px-4 pt-2">
|
|
1275
|
+
<p className="aui-tool-fallback-result-header font-semibold">
|
|
1276
|
+
Result:
|
|
1277
|
+
</p>
|
|
1278
|
+
<pre className="aui-tool-fallback-result-content whitespace-pre-wrap">
|
|
1024
1279
|
{typeof result === "string"
|
|
1025
1280
|
? result
|
|
1026
1281
|
: JSON.stringify(result, null, 2)}
|
|
@@ -1040,7 +1295,7 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
|
|
|
1040
1295
|
```tsx
|
|
1041
1296
|
"use client";
|
|
1042
1297
|
|
|
1043
|
-
import {
|
|
1298
|
+
import { ComponentPropsWithRef, forwardRef } from "react";
|
|
1044
1299
|
import { Slottable } from "@radix-ui/react-slot";
|
|
1045
1300
|
|
|
1046
1301
|
import {
|
|
@@ -1051,7 +1306,7 @@ import {
|
|
|
1051
1306
|
import { Button } from "@/components/ui/button";
|
|
1052
1307
|
import { cn } from "@/lib/utils";
|
|
1053
1308
|
|
|
1054
|
-
export type TooltipIconButtonProps =
|
|
1309
|
+
export type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
|
|
1055
1310
|
tooltip: string;
|
|
1056
1311
|
side?: "top" | "bottom" | "left" | "right";
|
|
1057
1312
|
};
|
|
@@ -1067,11 +1322,11 @@ export const TooltipIconButton = forwardRef<
|
|
|
1067
1322
|
variant="ghost"
|
|
1068
1323
|
size="icon"
|
|
1069
1324
|
{...rest}
|
|
1070
|
-
className={cn("size-6 p-1", className)}
|
|
1325
|
+
className={cn("aui-button-icon size-6 p-1", className)}
|
|
1071
1326
|
ref={ref}
|
|
1072
1327
|
>
|
|
1073
1328
|
<Slottable>{children}</Slottable>
|
|
1074
|
-
<span className="sr-only">{tooltip}</span>
|
|
1329
|
+
<span className="aui-sr-only sr-only">{tooltip}</span>
|
|
1075
1330
|
</Button>
|
|
1076
1331
|
</TooltipTrigger>
|
|
1077
1332
|
<TooltipContent side={side}>{tooltip}</TooltipContent>
|
|
@@ -1083,6 +1338,62 @@ TooltipIconButton.displayName = "TooltipIconButton";
|
|
|
1083
1338
|
|
|
1084
1339
|
```
|
|
1085
1340
|
|
|
1341
|
+
## components/ui/avatar.tsx
|
|
1342
|
+
|
|
1343
|
+
```tsx
|
|
1344
|
+
"use client";
|
|
1345
|
+
|
|
1346
|
+
import * as React from "react";
|
|
1347
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
1348
|
+
|
|
1349
|
+
import { cn } from "@/lib/utils";
|
|
1350
|
+
|
|
1351
|
+
const Avatar = React.forwardRef<
|
|
1352
|
+
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
1353
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
1354
|
+
>(({ className, ...props }, ref) => (
|
|
1355
|
+
<AvatarPrimitive.Root
|
|
1356
|
+
ref={ref}
|
|
1357
|
+
className={cn(
|
|
1358
|
+
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
|
|
1359
|
+
className,
|
|
1360
|
+
)}
|
|
1361
|
+
{...props}
|
|
1362
|
+
/>
|
|
1363
|
+
));
|
|
1364
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
1365
|
+
|
|
1366
|
+
const AvatarImage = React.forwardRef<
|
|
1367
|
+
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
1368
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
1369
|
+
>(({ className, ...props }, ref) => (
|
|
1370
|
+
<AvatarPrimitive.Image
|
|
1371
|
+
ref={ref}
|
|
1372
|
+
className={cn("aspect-square h-full w-full", className)}
|
|
1373
|
+
{...props}
|
|
1374
|
+
/>
|
|
1375
|
+
));
|
|
1376
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
1377
|
+
|
|
1378
|
+
const AvatarFallback = React.forwardRef<
|
|
1379
|
+
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
1380
|
+
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
1381
|
+
>(({ className, ...props }, ref) => (
|
|
1382
|
+
<AvatarPrimitive.Fallback
|
|
1383
|
+
ref={ref}
|
|
1384
|
+
className={cn(
|
|
1385
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
1386
|
+
className,
|
|
1387
|
+
)}
|
|
1388
|
+
{...props}
|
|
1389
|
+
/>
|
|
1390
|
+
));
|
|
1391
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
1392
|
+
|
|
1393
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
1394
|
+
|
|
1395
|
+
```
|
|
1396
|
+
|
|
1086
1397
|
## components/ui/button.tsx
|
|
1087
1398
|
|
|
1088
1399
|
```tsx
|
|
@@ -1093,16 +1404,16 @@ import { cva, type VariantProps } from "class-variance-authority";
|
|
|
1093
1404
|
import { cn } from "@/lib/utils";
|
|
1094
1405
|
|
|
1095
1406
|
const buttonVariants = cva(
|
|
1096
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm
|
|
1407
|
+
"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",
|
|
1097
1408
|
{
|
|
1098
1409
|
variants: {
|
|
1099
1410
|
variant: {
|
|
1100
1411
|
default:
|
|
1101
1412
|
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
1102
1413
|
destructive:
|
|
1103
|
-
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40
|
|
1414
|
+
"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",
|
|
1104
1415
|
outline:
|
|
1105
|
-
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:
|
|
1416
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
1106
1417
|
secondary:
|
|
1107
1418
|
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
1108
1419
|
ghost:
|
|
@@ -1111,7 +1422,7 @@ const buttonVariants = cva(
|
|
|
1111
1422
|
},
|
|
1112
1423
|
size: {
|
|
1113
1424
|
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
1114
|
-
sm: "h-8
|
|
1425
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
1115
1426
|
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
1116
1427
|
icon: "size-9",
|
|
1117
1428
|
},
|
|
@@ -1148,6 +1459,147 @@ export { Button, buttonVariants };
|
|
|
1148
1459
|
|
|
1149
1460
|
```
|
|
1150
1461
|
|
|
1462
|
+
## components/ui/dialog.tsx
|
|
1463
|
+
|
|
1464
|
+
```tsx
|
|
1465
|
+
"use client";
|
|
1466
|
+
|
|
1467
|
+
import * as React from "react";
|
|
1468
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
1469
|
+
import { XIcon } from "lucide-react";
|
|
1470
|
+
|
|
1471
|
+
import { cn } from "@/lib/utils";
|
|
1472
|
+
|
|
1473
|
+
function Dialog({
|
|
1474
|
+
...props
|
|
1475
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
1476
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function DialogTrigger({
|
|
1480
|
+
...props
|
|
1481
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
1482
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
function DialogPortal({
|
|
1486
|
+
...props
|
|
1487
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
1488
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
function DialogClose({
|
|
1492
|
+
...props
|
|
1493
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
1494
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
function DialogOverlay({
|
|
1498
|
+
className,
|
|
1499
|
+
...props
|
|
1500
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
1501
|
+
return (
|
|
1502
|
+
<DialogPrimitive.Overlay
|
|
1503
|
+
data-slot="dialog-overlay"
|
|
1504
|
+
className={cn(
|
|
1505
|
+
"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",
|
|
1506
|
+
className,
|
|
1507
|
+
)}
|
|
1508
|
+
{...props}
|
|
1509
|
+
/>
|
|
1510
|
+
);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
function DialogContent({
|
|
1514
|
+
className,
|
|
1515
|
+
children,
|
|
1516
|
+
...props
|
|
1517
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content>) {
|
|
1518
|
+
return (
|
|
1519
|
+
<DialogPortal data-slot="dialog-portal">
|
|
1520
|
+
<DialogOverlay />
|
|
1521
|
+
<DialogPrimitive.Content
|
|
1522
|
+
data-slot="dialog-content"
|
|
1523
|
+
className={cn(
|
|
1524
|
+
"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",
|
|
1525
|
+
className,
|
|
1526
|
+
)}
|
|
1527
|
+
{...props}
|
|
1528
|
+
>
|
|
1529
|
+
{children}
|
|
1530
|
+
<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">
|
|
1531
|
+
<XIcon />
|
|
1532
|
+
<span className="sr-only">Close</span>
|
|
1533
|
+
</DialogPrimitive.Close>
|
|
1534
|
+
</DialogPrimitive.Content>
|
|
1535
|
+
</DialogPortal>
|
|
1536
|
+
);
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
1540
|
+
return (
|
|
1541
|
+
<div
|
|
1542
|
+
data-slot="dialog-header"
|
|
1543
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
1544
|
+
{...props}
|
|
1545
|
+
/>
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
1550
|
+
return (
|
|
1551
|
+
<div
|
|
1552
|
+
data-slot="dialog-footer"
|
|
1553
|
+
className={cn(
|
|
1554
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
1555
|
+
className,
|
|
1556
|
+
)}
|
|
1557
|
+
{...props}
|
|
1558
|
+
/>
|
|
1559
|
+
);
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
function DialogTitle({
|
|
1563
|
+
className,
|
|
1564
|
+
...props
|
|
1565
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
1566
|
+
return (
|
|
1567
|
+
<DialogPrimitive.Title
|
|
1568
|
+
data-slot="dialog-title"
|
|
1569
|
+
className={cn("font-semibold text-lg leading-none", className)}
|
|
1570
|
+
{...props}
|
|
1571
|
+
/>
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
function DialogDescription({
|
|
1576
|
+
className,
|
|
1577
|
+
...props
|
|
1578
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
1579
|
+
return (
|
|
1580
|
+
<DialogPrimitive.Description
|
|
1581
|
+
data-slot="dialog-description"
|
|
1582
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
1583
|
+
{...props}
|
|
1584
|
+
/>
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
export {
|
|
1589
|
+
Dialog,
|
|
1590
|
+
DialogClose,
|
|
1591
|
+
DialogContent,
|
|
1592
|
+
DialogDescription,
|
|
1593
|
+
DialogFooter,
|
|
1594
|
+
DialogHeader,
|
|
1595
|
+
DialogOverlay,
|
|
1596
|
+
DialogPortal,
|
|
1597
|
+
DialogTitle,
|
|
1598
|
+
DialogTrigger,
|
|
1599
|
+
};
|
|
1600
|
+
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1151
1603
|
## components/ui/tooltip.tsx
|
|
1152
1604
|
|
|
1153
1605
|
```tsx
|
|
@@ -1199,13 +1651,13 @@ function TooltipContent({
|
|
|
1199
1651
|
data-slot="tooltip-content"
|
|
1200
1652
|
sideOffset={sideOffset}
|
|
1201
1653
|
className={cn(
|
|
1202
|
-
"
|
|
1654
|
+
"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",
|
|
1203
1655
|
className,
|
|
1204
1656
|
)}
|
|
1205
1657
|
{...props}
|
|
1206
1658
|
>
|
|
1207
1659
|
{children}
|
|
1208
|
-
<TooltipPrimitive.Arrow className="
|
|
1660
|
+
<TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" />
|
|
1209
1661
|
</TooltipPrimitive.Content>
|
|
1210
1662
|
</TooltipPrimitive.Portal>
|
|
1211
1663
|
);
|
|
@@ -1261,28 +1713,30 @@ export default nextConfig;
|
|
|
1261
1713
|
"@assistant-ui/react": "workspace:^",
|
|
1262
1714
|
"@assistant-ui/react-langgraph": "workspace:^",
|
|
1263
1715
|
"@assistant-ui/react-markdown": "workspace:^",
|
|
1716
|
+
"@radix-ui/react-avatar": "^1.1.11",
|
|
1717
|
+
"@radix-ui/react-dialog": "^1.1.15",
|
|
1264
1718
|
"@radix-ui/react-slot": "^1.2.4",
|
|
1265
1719
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
1266
1720
|
"@tailwindcss/postcss": "^4.1.17",
|
|
1267
|
-
"assistant-stream": "^0.2.
|
|
1721
|
+
"assistant-stream": "^0.2.44",
|
|
1268
1722
|
"class-variance-authority": "^0.7.1",
|
|
1269
1723
|
"clsx": "^2.1.1",
|
|
1270
|
-
"
|
|
1271
|
-
"
|
|
1272
|
-
"next": "16.0.3",
|
|
1724
|
+
"lucide-react": "^0.556.0",
|
|
1725
|
+
"next": "16.0.7",
|
|
1273
1726
|
"postcss": "^8.5.6",
|
|
1274
|
-
"react": "19.2.
|
|
1275
|
-
"react-dom": "19.2.
|
|
1727
|
+
"react": "19.2.1",
|
|
1728
|
+
"react-dom": "19.2.1",
|
|
1276
1729
|
"remark-gfm": "^4.0.1",
|
|
1277
1730
|
"tailwind-merge": "^3.4.0",
|
|
1278
1731
|
"tailwindcss": "^4.1.17",
|
|
1279
1732
|
"tailwindcss-animate": "^1.0.7",
|
|
1280
|
-
"zod": "^4.1.
|
|
1733
|
+
"zod": "^4.1.13",
|
|
1734
|
+
"zustand": "^5.0.9"
|
|
1281
1735
|
},
|
|
1282
1736
|
"devDependencies": {
|
|
1283
1737
|
"@assistant-ui/x-buildutils": "workspace:*",
|
|
1284
1738
|
"@types/node": "^24.10.1",
|
|
1285
|
-
"@types/react": "^19.2.
|
|
1739
|
+
"@types/react": "^19.2.7",
|
|
1286
1740
|
"@types/react-dom": "^19.2.3",
|
|
1287
1741
|
"tw-animate-css": "^1.4.0",
|
|
1288
1742
|
"typescript": "^5.9.3"
|
|
@@ -1290,8 +1744,7 @@ export default nextConfig;
|
|
|
1290
1744
|
"scripts": {
|
|
1291
1745
|
"dev": "next dev",
|
|
1292
1746
|
"build": "next build",
|
|
1293
|
-
"start": "next start"
|
|
1294
|
-
"lint": "eslint ."
|
|
1747
|
+
"start": "next start"
|
|
1295
1748
|
}
|
|
1296
1749
|
}
|
|
1297
1750
|
|