@assistant-ui/mcp-docs-server 0.1.15 → 0.1.17

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.
Files changed (55) hide show
  1. package/.docs/organized/code-examples/store-example.md +249 -147
  2. package/.docs/organized/code-examples/with-ag-ui.md +250 -186
  3. package/.docs/organized/code-examples/with-ai-sdk-v5.md +250 -199
  4. package/.docs/organized/code-examples/with-assistant-transport.md +195 -243
  5. package/.docs/organized/code-examples/with-cloud.md +277 -226
  6. package/.docs/organized/code-examples/with-custom-thread-list.md +1855 -0
  7. package/.docs/organized/code-examples/with-external-store.md +246 -180
  8. package/.docs/organized/code-examples/with-ffmpeg.md +255 -189
  9. package/.docs/organized/code-examples/with-langgraph.md +293 -242
  10. package/.docs/organized/code-examples/with-parent-id-grouping.md +243 -263
  11. package/.docs/organized/code-examples/with-react-hook-form.md +262 -196
  12. package/.docs/organized/code-examples/with-tanstack.md +1578 -0
  13. package/.docs/raw/blog/2024-07-29-hello/index.mdx +2 -2
  14. package/.docs/raw/docs/api-reference/overview.mdx +6 -6
  15. package/.docs/raw/docs/api-reference/primitives/ActionBar.mdx +85 -4
  16. package/.docs/raw/docs/api-reference/primitives/AssistantIf.mdx +200 -0
  17. package/.docs/raw/docs/api-reference/primitives/Composer.mdx +0 -20
  18. package/.docs/raw/docs/api-reference/primitives/Message.mdx +0 -45
  19. package/.docs/raw/docs/api-reference/primitives/Thread.mdx +0 -50
  20. package/.docs/raw/docs/cloud/persistence/ai-sdk.mdx +2 -3
  21. package/.docs/raw/docs/cloud/persistence/langgraph.mdx +2 -3
  22. package/.docs/raw/docs/devtools.mdx +2 -3
  23. package/.docs/raw/docs/getting-started.mdx +36 -1102
  24. package/.docs/raw/docs/guides/Attachments.mdx +3 -25
  25. package/.docs/raw/docs/guides/Branching.mdx +1 -1
  26. package/.docs/raw/docs/guides/Speech.mdx +1 -1
  27. package/.docs/raw/docs/guides/ToolUI.mdx +1 -1
  28. package/.docs/raw/docs/legacy/styled/AssistantModal.mdx +2 -3
  29. package/.docs/raw/docs/legacy/styled/Decomposition.mdx +6 -5
  30. package/.docs/raw/docs/legacy/styled/Markdown.mdx +2 -3
  31. package/.docs/raw/docs/legacy/styled/Thread.mdx +2 -3
  32. package/.docs/raw/docs/react-compatibility.mdx +2 -5
  33. package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +3 -4
  34. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +3 -6
  35. package/.docs/raw/docs/runtimes/custom/external-store.mdx +2 -3
  36. package/.docs/raw/docs/runtimes/custom/local.mdx +11 -41
  37. package/.docs/raw/docs/runtimes/data-stream.mdx +15 -11
  38. package/.docs/raw/docs/runtimes/langgraph/index.mdx +3 -3
  39. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +1 -1
  40. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +2 -3
  41. package/.docs/raw/docs/runtimes/langserve.mdx +2 -3
  42. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +2 -3
  43. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +2 -3
  44. package/.docs/raw/docs/ui/AssistantModal.mdx +3 -25
  45. package/.docs/raw/docs/ui/AssistantSidebar.mdx +2 -24
  46. package/.docs/raw/docs/ui/Attachment.mdx +3 -25
  47. package/.docs/raw/docs/ui/Markdown.mdx +2 -24
  48. package/.docs/raw/docs/ui/Mermaid.mdx +2 -24
  49. package/.docs/raw/docs/ui/Reasoning.mdx +2 -24
  50. package/.docs/raw/docs/ui/Scrollbar.mdx +4 -6
  51. package/.docs/raw/docs/ui/SyntaxHighlighting.mdx +3 -47
  52. package/.docs/raw/docs/ui/Thread.mdx +38 -53
  53. package/.docs/raw/docs/ui/ThreadList.mdx +4 -47
  54. package/.docs/raw/docs/ui/ToolFallback.mdx +2 -24
  55. package/package.json +6 -7
@@ -358,16 +358,16 @@ const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
358
358
  return (
359
359
  <Dialog>
360
360
  <DialogTrigger
361
- className="aui-attachment-preview-trigger hover:bg-accent/50 cursor-pointer transition-colors"
361
+ className="aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50"
362
362
  asChild
363
363
  >
364
364
  {children}
365
365
  </DialogTrigger>
366
- <DialogContent className="aui-attachment-preview-dialog-content [&_svg]:text-background [&>button]:bg-foreground/60 [&>button]:hover:[&_svg]:text-destructive p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:p-1 [&>button]:opacity-100 [&>button]:!ring-0">
366
+ <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">
367
367
  <DialogTitle className="aui-sr-only sr-only">
368
368
  Image Attachment Preview
369
369
  </DialogTitle>
370
- <div className="aui-attachment-preview bg-background relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden">
370
+ <div className="aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background">
371
371
  <AttachmentPreview src={src} />
372
372
  </div>
373
373
  </DialogContent>
@@ -389,7 +389,7 @@ const AttachmentThumb: FC = () => {
389
389
  className="aui-attachment-tile-image object-cover"
390
390
  />
391
391
  <AvatarFallback delayMs={isImage ? 200 : 0}>
392
- <FileText className="aui-attachment-tile-fallback-icon text-muted-foreground size-8" />
392
+ <FileText className="aui-attachment-tile-fallback-icon size-8 text-muted-foreground" />
393
393
  </AvatarFallback>
394
394
  </Avatar>
395
395
  );
@@ -430,7 +430,7 @@ const AttachmentUI: FC = () => {
430
430
  <TooltipTrigger asChild>
431
431
  <div
432
432
  className={cn(
433
- "aui-attachment-tile bg-muted size-14 cursor-pointer overflow-hidden rounded-[14px] border transition-opacity hover:opacity-75",
433
+ "aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75",
434
434
  isComposer &&
435
435
  "aui-attachment-tile-composer border-foreground/20",
436
436
  )}
@@ -456,7 +456,7 @@ const AttachmentRemove: FC = () => {
456
456
  <AttachmentPrimitive.Remove asChild>
457
457
  <TooltipIconButton
458
458
  tooltip="Remove file"
459
- className="aui-attachment-tile-remove text-muted-foreground hover:[&_svg]:text-destructive absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white opacity-100 shadow-sm hover:!bg-white [&_svg]:text-black"
459
+ 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"
460
460
  side="top"
461
461
  >
462
462
  <XIcon className="aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" />
@@ -491,7 +491,7 @@ export const ComposerAddAttachment: FC = () => {
491
491
  side="bottom"
492
492
  variant="ghost"
493
493
  size="icon"
494
- className="aui-composer-add-attachment hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30 size-[34px] rounded-full p-1 text-xs font-semibold"
494
+ 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"
495
495
  aria-label="Add Attachment"
496
496
  >
497
497
  <PlusIcon className="aui-attachment-add-icon size-5 stroke-[1.5px]" />
@@ -542,7 +542,7 @@ const CodeHeader: FC<CodeHeaderProps> = ({ language, code }) => {
542
542
  };
543
543
 
544
544
  return (
545
- <div className="aui-code-header-root bg-muted-foreground/15 text-foreground dark:bg-muted-foreground/20 mt-4 flex items-center justify-between gap-4 rounded-t-lg px-4 py-2 text-sm font-semibold">
545
+ <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">
546
546
  <span className="aui-code-header-language lowercase [&>span]:text-xs">
547
547
  {language}
548
548
  </span>
@@ -577,7 +577,7 @@ const defaultComponents = memoizeMarkdownComponents({
577
577
  h1: ({ className, ...props }) => (
578
578
  <h1
579
579
  className={cn(
580
- "aui-md-h1 mb-8 scroll-m-20 text-4xl font-extrabold tracking-tight last:mb-0",
580
+ "aui-md-h1 mb-8 scroll-m-20 font-extrabold text-4xl tracking-tight last:mb-0",
581
581
  className,
582
582
  )}
583
583
  {...props}
@@ -586,7 +586,7 @@ const defaultComponents = memoizeMarkdownComponents({
586
586
  h2: ({ className, ...props }) => (
587
587
  <h2
588
588
  className={cn(
589
- "aui-md-h2 mt-8 mb-4 scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0 last:mb-0",
589
+ "aui-md-h2 mt-8 mb-4 scroll-m-20 font-semibold text-3xl tracking-tight first:mt-0 last:mb-0",
590
590
  className,
591
591
  )}
592
592
  {...props}
@@ -595,7 +595,7 @@ const defaultComponents = memoizeMarkdownComponents({
595
595
  h3: ({ className, ...props }) => (
596
596
  <h3
597
597
  className={cn(
598
- "aui-md-h3 mt-6 mb-4 scroll-m-20 text-2xl font-semibold tracking-tight first:mt-0 last:mb-0",
598
+ "aui-md-h3 mt-6 mb-4 scroll-m-20 font-semibold text-2xl tracking-tight first:mt-0 last:mb-0",
599
599
  className,
600
600
  )}
601
601
  {...props}
@@ -604,7 +604,7 @@ const defaultComponents = memoizeMarkdownComponents({
604
604
  h4: ({ className, ...props }) => (
605
605
  <h4
606
606
  className={cn(
607
- "aui-md-h4 mt-6 mb-4 scroll-m-20 text-xl font-semibold tracking-tight first:mt-0 last:mb-0",
607
+ "aui-md-h4 mt-6 mb-4 scroll-m-20 font-semibold text-xl tracking-tight first:mt-0 last:mb-0",
608
608
  className,
609
609
  )}
610
610
  {...props}
@@ -613,7 +613,7 @@ const defaultComponents = memoizeMarkdownComponents({
613
613
  h5: ({ className, ...props }) => (
614
614
  <h5
615
615
  className={cn(
616
- "aui-md-h5 my-4 text-lg font-semibold first:mt-0 last:mb-0",
616
+ "aui-md-h5 my-4 font-semibold text-lg first:mt-0 last:mb-0",
617
617
  className,
618
618
  )}
619
619
  {...props}
@@ -640,7 +640,7 @@ const defaultComponents = memoizeMarkdownComponents({
640
640
  a: ({ className, ...props }) => (
641
641
  <a
642
642
  className={cn(
643
- "aui-md-a text-primary font-medium underline underline-offset-4",
643
+ "aui-md-a font-medium text-primary underline underline-offset-4",
644
644
  className,
645
645
  )}
646
646
  {...props}
@@ -679,7 +679,7 @@ const defaultComponents = memoizeMarkdownComponents({
679
679
  th: ({ className, ...props }) => (
680
680
  <th
681
681
  className={cn(
682
- "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",
682
+ "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",
683
683
  className,
684
684
  )}
685
685
  {...props}
@@ -688,7 +688,7 @@ const defaultComponents = memoizeMarkdownComponents({
688
688
  td: ({ className, ...props }) => (
689
689
  <td
690
690
  className={cn(
691
- "aui-md-td border-b border-l px-4 py-2 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right",
691
+ "aui-md-td border-b border-l px-4 py-2 text-left last:border-r [[align=center]]:text-center [[align=right]]:text-right",
692
692
  className,
693
693
  )}
694
694
  {...props}
@@ -712,7 +712,7 @@ const defaultComponents = memoizeMarkdownComponents({
712
712
  pre: ({ className, ...props }) => (
713
713
  <pre
714
714
  className={cn(
715
- "aui-md-pre overflow-x-auto !rounded-t-none rounded-b-lg bg-black p-4 text-white",
715
+ "aui-md-pre overflow-x-auto rounded-t-none! rounded-b-lg bg-black p-4 text-white",
716
716
  className,
717
717
  )}
718
718
  {...props}
@@ -724,7 +724,7 @@ const defaultComponents = memoizeMarkdownComponents({
724
724
  <code
725
725
  className={cn(
726
726
  !isCodeBlock &&
727
- "aui-md-inline-code bg-muted rounded border font-semibold",
727
+ "aui-md-inline-code rounded border bg-muted font-semibold",
728
728
  className,
729
729
  )}
730
730
  {...props}
@@ -739,57 +739,67 @@ const defaultComponents = memoizeMarkdownComponents({
739
739
  ## components/assistant-ui/thread.tsx
740
740
 
741
741
  ```tsx
742
+ import {
743
+ ComposerAddAttachment,
744
+ ComposerAttachments,
745
+ UserMessageAttachments,
746
+ } from "@/components/assistant-ui/attachment";
747
+ import { MarkdownText } from "@/components/assistant-ui/markdown-text";
748
+ import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
749
+ import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
750
+ import { Button } from "@/components/ui/button";
751
+ import { cn } from "@/lib/utils";
742
752
  import {
743
753
  ActionBarPrimitive,
754
+ AssistantIf,
744
755
  BranchPickerPrimitive,
745
756
  ComposerPrimitive,
757
+ ErrorPrimitive,
746
758
  MessagePrimitive,
747
759
  ThreadPrimitive,
748
760
  } from "@assistant-ui/react";
749
- import type { FC } from "react";
750
761
  import {
751
762
  ArrowDownIcon,
763
+ ArrowUpIcon,
752
764
  CheckIcon,
753
765
  ChevronLeftIcon,
754
766
  ChevronRightIcon,
755
767
  CopyIcon,
768
+ DownloadIcon,
756
769
  PencilIcon,
757
770
  RefreshCwIcon,
758
- SendHorizontalIcon,
771
+ SquareIcon,
759
772
  } from "lucide-react";
760
- import { cn } from "@/lib/utils";
761
-
762
- import { Button } from "@/components/ui/button";
763
- import { MarkdownText } from "@/components/assistant-ui/markdown-text";
764
- import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
773
+ import type { FC } from "react";
765
774
 
766
775
  export const Thread: FC = () => {
767
776
  return (
768
777
  <ThreadPrimitive.Root
769
- className="bg-background box-border flex h-full flex-col overflow-hidden"
778
+ className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
770
779
  style={{
771
- ["--thread-max-width" as string]: "42rem",
780
+ ["--thread-max-width" as string]: "44rem",
772
781
  }}
773
782
  >
774
- <ThreadPrimitive.Viewport className="flex h-full flex-col items-center overflow-y-scroll scroll-smooth bg-inherit px-4 pt-8">
775
- <ThreadWelcome />
783
+ <ThreadPrimitive.Viewport
784
+ turnAnchor="top"
785
+ className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
786
+ >
787
+ <AssistantIf condition={({ thread }) => thread.isEmpty}>
788
+ <ThreadWelcome />
789
+ </AssistantIf>
776
790
 
777
791
  <ThreadPrimitive.Messages
778
792
  components={{
779
- UserMessage: UserMessage,
780
- EditComposer: EditComposer,
781
- AssistantMessage: AssistantMessage,
793
+ UserMessage,
794
+ EditComposer,
795
+ AssistantMessage,
782
796
  }}
783
797
  />
784
798
 
785
- <ThreadPrimitive.If empty={false}>
786
- <div className="min-h-8 flex-grow" />
787
- </ThreadPrimitive.If>
788
-
789
- <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">
799
+ <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">
790
800
  <ThreadScrollToBottom />
791
801
  <Composer />
792
- </div>
802
+ </ThreadPrimitive.ViewportFooter>
793
803
  </ThreadPrimitive.Viewport>
794
804
  </ThreadPrimitive.Root>
795
805
  );
@@ -801,7 +811,7 @@ const ThreadScrollToBottom: FC = () => {
801
811
  <TooltipIconButton
802
812
  tooltip="Scroll to bottom"
803
813
  variant="outline"
804
- className="absolute -top-8 rounded-full disabled:invisible"
814
+ 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"
805
815
  >
806
816
  <ArrowDownIcon />
807
817
  </TooltipIconButton>
@@ -811,175 +821,247 @@ const ThreadScrollToBottom: FC = () => {
811
821
 
812
822
  const ThreadWelcome: FC = () => {
813
823
  return (
814
- <ThreadPrimitive.Empty>
815
- <div className="flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col">
816
- <div className="flex w-full flex-grow flex-col items-center justify-center">
817
- <p className="mt-4 font-medium">How can I help you today?</p>
824
+ <div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
825
+ <div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
826
+ <div className="aui-thread-welcome-message flex size-full flex-col justify-center px-4">
827
+ <h1 className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in font-semibold text-2xl duration-200">
828
+ Hello there!
829
+ </h1>
830
+ <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">
831
+ How can I help you today?
832
+ </p>
818
833
  </div>
819
- <ThreadWelcomeSuggestions />
820
834
  </div>
821
- </ThreadPrimitive.Empty>
835
+ <ThreadSuggestions />
836
+ </div>
822
837
  );
823
838
  };
824
839
 
825
- const ThreadWelcomeSuggestions: FC = () => {
840
+ const SUGGESTIONS = [
841
+ {
842
+ title: "What's the weather",
843
+ label: "in San Francisco?",
844
+ prompt: "What's the weather in San Francisco?",
845
+ },
846
+ {
847
+ title: "Explain React hooks",
848
+ label: "like useState and useEffect",
849
+ prompt: "Explain React hooks like useState and useEffect",
850
+ },
851
+ ] as const;
852
+
853
+ const ThreadSuggestions: FC = () => {
826
854
  return (
827
- <div className="mt-3 flex w-full items-stretch justify-center gap-4">
828
- <ThreadPrimitive.Suggestion
829
- className="hover:bg-muted/80 flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-lg border p-3 transition-colors ease-in"
830
- prompt="What is the weather in Tokyo?"
831
- method="replace"
832
- autoSend
833
- >
834
- <span className="line-clamp-2 text-sm font-semibold text-ellipsis">
835
- What is the weather in Tokyo?
836
- </span>
837
- </ThreadPrimitive.Suggestion>
838
- <ThreadPrimitive.Suggestion
839
- className="hover:bg-muted/80 flex max-w-sm grow basis-0 flex-col items-center justify-center rounded-lg border p-3 transition-colors ease-in"
840
- prompt="What is assistant-ui?"
841
- method="replace"
842
- autoSend
843
- >
844
- <span className="line-clamp-2 text-sm font-semibold text-ellipsis">
845
- What is assistant-ui?
846
- </span>
847
- </ThreadPrimitive.Suggestion>
855
+ <div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
856
+ {SUGGESTIONS.map((suggestion, index) => (
857
+ <div
858
+ key={suggestion.prompt}
859
+ 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"
860
+ style={{ animationDelay: `${100 + index * 50}ms` }}
861
+ >
862
+ <ThreadPrimitive.Suggestion prompt={suggestion.prompt} send asChild>
863
+ <Button
864
+ variant="ghost"
865
+ 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"
866
+ aria-label={suggestion.prompt}
867
+ >
868
+ <span className="aui-thread-welcome-suggestion-text-1 font-medium">
869
+ {suggestion.title}
870
+ </span>
871
+ <span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
872
+ {suggestion.label}
873
+ </span>
874
+ </Button>
875
+ </ThreadPrimitive.Suggestion>
876
+ </div>
877
+ ))}
848
878
  </div>
849
879
  );
850
880
  };
851
881
 
852
882
  const Composer: FC = () => {
853
883
  return (
854
- <ComposerPrimitive.Root className="focus-within:border-ring/20 flex w-full flex-wrap items-end rounded-lg border bg-inherit px-2.5 shadow-sm transition-colors ease-in">
855
- <ComposerPrimitive.Input
856
- rows={1}
857
- autoFocus
858
- placeholder="Write a message..."
859
- className="placeholder:text-muted-foreground max-h-40 flex-grow resize-none border-none bg-transparent px-2 py-4 text-sm outline-none focus:ring-0 disabled:cursor-not-allowed"
860
- />
861
- <ComposerAction />
884
+ <ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
885
+ <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">
886
+ <ComposerAttachments />
887
+ <ComposerPrimitive.Input
888
+ placeholder="Send a message..."
889
+ 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"
890
+ rows={1}
891
+ autoFocus
892
+ aria-label="Message input"
893
+ />
894
+ <ComposerAction />
895
+ </ComposerPrimitive.AttachmentDropzone>
862
896
  </ComposerPrimitive.Root>
863
897
  );
864
898
  };
865
899
 
866
900
  const ComposerAction: FC = () => {
867
901
  return (
868
- <>
869
- <ThreadPrimitive.If running={false}>
902
+ <div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
903
+ <ComposerAddAttachment />
904
+
905
+ <AssistantIf condition={({ thread }) => !thread.isRunning}>
870
906
  <ComposerPrimitive.Send asChild>
871
907
  <TooltipIconButton
872
- tooltip="Send"
908
+ tooltip="Send message"
909
+ side="bottom"
910
+ type="submit"
873
911
  variant="default"
874
- className="my-2.5 size-8 p-2 transition-opacity ease-in"
912
+ size="icon"
913
+ className="aui-composer-send size-8 rounded-full"
914
+ aria-label="Send message"
875
915
  >
876
- <SendHorizontalIcon />
916
+ <ArrowUpIcon className="aui-composer-send-icon size-4" />
877
917
  </TooltipIconButton>
878
918
  </ComposerPrimitive.Send>
879
- </ThreadPrimitive.If>
880
- <ThreadPrimitive.If running>
919
+ </AssistantIf>
920
+
921
+ <AssistantIf condition={({ thread }) => thread.isRunning}>
881
922
  <ComposerPrimitive.Cancel asChild>
882
- <TooltipIconButton
883
- tooltip="Cancel"
923
+ <Button
924
+ type="button"
884
925
  variant="default"
885
- className="my-2.5 size-8 p-2 transition-opacity ease-in"
926
+ size="icon"
927
+ className="aui-composer-cancel size-8 rounded-full"
928
+ aria-label="Stop generating"
886
929
  >
887
- <CircleStopIcon />
888
- </TooltipIconButton>
930
+ <SquareIcon className="aui-composer-cancel-icon size-3 fill-current" />
931
+ </Button>
889
932
  </ComposerPrimitive.Cancel>
890
- </ThreadPrimitive.If>
891
- </>
933
+ </AssistantIf>
934
+ </div>
892
935
  );
893
936
  };
894
937
 
895
- const UserMessage: FC = () => {
938
+ const MessageError: FC = () => {
896
939
  return (
897
- <MessagePrimitive.Root className="grid w-full max-w-[var(--thread-max-width)] auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 py-4 [&:where(>*)]:col-start-2">
898
- <UserActionBar />
940
+ <MessagePrimitive.Error>
941
+ <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">
942
+ <ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
943
+ </ErrorPrimitive.Root>
944
+ </MessagePrimitive.Error>
945
+ );
946
+ };
899
947
 
900
- <div className="bg-muted text-foreground col-start-2 row-start-2 max-w-[calc(var(--thread-max-width)*0.8)] rounded-3xl px-5 py-2.5 break-words">
901
- <MessagePrimitive.Parts />
948
+ const AssistantMessage: FC = () => {
949
+ return (
950
+ <MessagePrimitive.Root
951
+ 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"
952
+ data-role="assistant"
953
+ >
954
+ <div className="aui-assistant-message-content wrap-break-word px-2 text-foreground leading-relaxed">
955
+ <MessagePrimitive.Parts
956
+ components={{
957
+ Text: MarkdownText,
958
+ tools: { Fallback: ToolFallback },
959
+ }}
960
+ />
961
+ <MessageError />
902
962
  </div>
903
963
 
904
- <BranchPicker className="col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
964
+ <div className="aui-assistant-message-footer mt-1 ml-2 flex">
965
+ <BranchPicker />
966
+ <AssistantActionBar />
967
+ </div>
905
968
  </MessagePrimitive.Root>
906
969
  );
907
970
  };
908
971
 
909
- const UserActionBar: FC = () => {
972
+ const AssistantActionBar: FC = () => {
910
973
  return (
911
974
  <ActionBarPrimitive.Root
912
975
  hideWhenRunning
913
976
  autohide="not-last"
914
- className="col-start-1 row-start-2 mt-2.5 mr-3 flex flex-col items-end"
977
+ autohideFloat="single-branch"
978
+ 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"
915
979
  >
916
- <ActionBarPrimitive.Edit asChild>
917
- <TooltipIconButton tooltip="Edit">
918
- <PencilIcon />
980
+ <ActionBarPrimitive.Copy asChild>
981
+ <TooltipIconButton tooltip="Copy">
982
+ <AssistantIf condition={({ message }) => message.isCopied}>
983
+ <CheckIcon />
984
+ </AssistantIf>
985
+ <AssistantIf condition={({ message }) => !message.isCopied}>
986
+ <CopyIcon />
987
+ </AssistantIf>
919
988
  </TooltipIconButton>
920
- </ActionBarPrimitive.Edit>
989
+ </ActionBarPrimitive.Copy>
990
+ <ActionBarPrimitive.ExportMarkdown asChild>
991
+ <TooltipIconButton tooltip="Export as Markdown">
992
+ <DownloadIcon />
993
+ </TooltipIconButton>
994
+ </ActionBarPrimitive.ExportMarkdown>
995
+ <ActionBarPrimitive.Reload asChild>
996
+ <TooltipIconButton tooltip="Refresh">
997
+ <RefreshCwIcon />
998
+ </TooltipIconButton>
999
+ </ActionBarPrimitive.Reload>
921
1000
  </ActionBarPrimitive.Root>
922
1001
  );
923
1002
  };
924
1003
 
925
- const EditComposer: FC = () => {
1004
+ const UserMessage: FC = () => {
926
1005
  return (
927
- <ComposerPrimitive.Root className="bg-muted my-4 flex w-full max-w-[var(--thread-max-width)] flex-col gap-2 rounded-xl">
928
- <ComposerPrimitive.Input className="text-foreground flex h-8 w-full resize-none bg-transparent p-4 pb-0 outline-none" />
929
-
930
- <div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
931
- <ComposerPrimitive.Cancel asChild>
932
- <Button variant="ghost">Cancel</Button>
933
- </ComposerPrimitive.Cancel>
934
- <ComposerPrimitive.Send asChild>
935
- <Button>Send</Button>
936
- </ComposerPrimitive.Send>
937
- </div>
938
- </ComposerPrimitive.Root>
939
- );
940
- };
1006
+ <MessagePrimitive.Root
1007
+ 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"
1008
+ data-role="user"
1009
+ >
1010
+ <UserMessageAttachments />
941
1011
 
942
- const AssistantMessage: FC = () => {
943
- return (
944
- <MessagePrimitive.Root className="relative grid w-full max-w-[var(--thread-max-width)] grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] py-4">
945
- <div className="text-foreground col-span-2 col-start-2 row-start-1 my-1.5 max-w-[calc(var(--thread-max-width)*0.8)] leading-7 break-words">
946
- <MessagePrimitive.Parts components={{ Text: MarkdownText }} />
1012
+ <div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
1013
+ <div className="aui-user-message-content wrap-break-word rounded-2xl bg-muted px-4 py-2.5 text-foreground">
1014
+ <MessagePrimitive.Parts />
1015
+ </div>
1016
+ <div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
1017
+ <UserActionBar />
1018
+ </div>
947
1019
  </div>
948
1020
 
949
- <AssistantActionBar />
950
-
951
- <BranchPicker className="col-start-2 row-start-2 mr-2 -ml-2" />
1021
+ <BranchPicker className="aui-user-branch-picker -mr-1 col-span-full col-start-1 row-start-3 justify-end" />
952
1022
  </MessagePrimitive.Root>
953
1023
  );
954
1024
  };
955
1025
 
956
- const AssistantActionBar: FC = () => {
1026
+ const UserActionBar: FC = () => {
957
1027
  return (
958
1028
  <ActionBarPrimitive.Root
959
1029
  hideWhenRunning
960
1030
  autohide="not-last"
961
- autohideFloat="single-branch"
962
- 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"
1031
+ className="aui-user-action-bar-root flex flex-col items-end"
963
1032
  >
964
- <ActionBarPrimitive.Copy asChild>
965
- <TooltipIconButton tooltip="Copy">
966
- <MessagePrimitive.If copied>
967
- <CheckIcon />
968
- </MessagePrimitive.If>
969
- <MessagePrimitive.If copied={false}>
970
- <CopyIcon />
971
- </MessagePrimitive.If>
972
- </TooltipIconButton>
973
- </ActionBarPrimitive.Copy>
974
- <ActionBarPrimitive.Reload asChild>
975
- <TooltipIconButton tooltip="Refresh">
976
- <RefreshCwIcon />
1033
+ <ActionBarPrimitive.Edit asChild>
1034
+ <TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
1035
+ <PencilIcon />
977
1036
  </TooltipIconButton>
978
- </ActionBarPrimitive.Reload>
1037
+ </ActionBarPrimitive.Edit>
979
1038
  </ActionBarPrimitive.Root>
980
1039
  );
981
1040
  };
982
1041
 
1042
+ const EditComposer: FC = () => {
1043
+ return (
1044
+ <MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col px-2 py-3">
1045
+ <ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-[85%] flex-col rounded-2xl bg-muted">
1046
+ <ComposerPrimitive.Input
1047
+ className="aui-edit-composer-input min-h-14 w-full resize-none bg-transparent p-4 text-foreground text-sm outline-none"
1048
+ autoFocus
1049
+ />
1050
+ <div className="aui-edit-composer-footer mx-3 mb-3 flex items-center gap-2 self-end">
1051
+ <ComposerPrimitive.Cancel asChild>
1052
+ <Button variant="ghost" size="sm">
1053
+ Cancel
1054
+ </Button>
1055
+ </ComposerPrimitive.Cancel>
1056
+ <ComposerPrimitive.Send asChild>
1057
+ <Button size="sm">Update</Button>
1058
+ </ComposerPrimitive.Send>
1059
+ </div>
1060
+ </ComposerPrimitive.Root>
1061
+ </MessagePrimitive.Root>
1062
+ );
1063
+ };
1064
+
983
1065
  const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
984
1066
  className,
985
1067
  ...rest
@@ -988,7 +1070,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
988
1070
  <BranchPickerPrimitive.Root
989
1071
  hideWhenSingleBranch
990
1072
  className={cn(
991
- "text-muted-foreground inline-flex items-center text-xs",
1073
+ "aui-branch-picker-root -ml-2 mr-2 inline-flex items-center text-muted-foreground text-xs",
992
1074
  className,
993
1075
  )}
994
1076
  {...rest}
@@ -998,7 +1080,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
998
1080
  <ChevronLeftIcon />
999
1081
  </TooltipIconButton>
1000
1082
  </BranchPickerPrimitive.Previous>
1001
- <span className="font-medium">
1083
+ <span className="aui-branch-picker-state font-medium">
1002
1084
  <BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
1003
1085
  </span>
1004
1086
  <BranchPickerPrimitive.Next asChild>
@@ -1010,20 +1092,6 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
1010
1092
  );
1011
1093
  };
1012
1094
 
1013
- const CircleStopIcon = () => {
1014
- return (
1015
- <svg
1016
- xmlns="http://www.w3.org/2000/svg"
1017
- viewBox="0 0 16 16"
1018
- fill="currentColor"
1019
- width="16"
1020
- height="16"
1021
- >
1022
- <rect width="10" height="10" x="3" y="3" rx="2" />
1023
- </svg>
1024
- );
1025
- };
1026
-
1027
1095
  ```
1028
1096
 
1029
1097
  ## components/assistant-ui/tool-fallback.tsx
@@ -1066,7 +1134,7 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
1066
1134
  >
1067
1135
  <div className="aui-tool-fallback-header flex items-center gap-2 px-4">
1068
1136
  {isCancelled ? (
1069
- <XCircleIcon className="aui-tool-fallback-icon text-muted-foreground size-4" />
1137
+ <XCircleIcon className="aui-tool-fallback-icon size-4 text-muted-foreground" />
1070
1138
  ) : (
1071
1139
  <CheckIcon className="aui-tool-fallback-icon size-4" />
1072
1140
  )}
@@ -1087,7 +1155,7 @@ export const ToolFallback: ToolCallMessagePartComponent = ({
1087
1155
  <div className="aui-tool-fallback-content flex flex-col gap-2 border-t pt-2">
1088
1156
  {cancelledReason && (
1089
1157
  <div className="aui-tool-fallback-cancelled-root px-4">
1090
- <p className="aui-tool-fallback-cancelled-header text-muted-foreground font-semibold">
1158
+ <p className="aui-tool-fallback-cancelled-header font-semibold text-muted-foreground">
1091
1159
  Cancelled reason:
1092
1160
  </p>
1093
1161
  <p className="aui-tool-fallback-cancelled-reason text-muted-foreground">
@@ -1217,7 +1285,7 @@ const AvatarFallback = React.forwardRef<
1217
1285
  <AvatarPrimitive.Fallback
1218
1286
  ref={ref}
1219
1287
  className={cn(
1220
- "bg-muted flex h-full w-full items-center justify-center rounded-full",
1288
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
1221
1289
  className,
1222
1290
  )}
1223
1291
  {...props}
@@ -1241,7 +1309,7 @@ import { cva, type VariantProps } from "class-variance-authority";
1241
1309
  import { cn } from "@/lib/utils";
1242
1310
 
1243
1311
  const buttonVariants = cva(
1244
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1312
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1245
1313
  {
1246
1314
  variants: {
1247
1315
  variant: {
@@ -1337,7 +1405,7 @@ function DialogOverlay({
1337
1405
  <DialogPrimitive.Overlay
1338
1406
  data-slot="dialog-overlay"
1339
1407
  className={cn(
1340
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
1408
+ "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",
1341
1409
  className,
1342
1410
  )}
1343
1411
  {...props}
@@ -1356,13 +1424,13 @@ function DialogContent({
1356
1424
  <DialogPrimitive.Content
1357
1425
  data-slot="dialog-content"
1358
1426
  className={cn(
1359
- "bg-background data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in 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 p-6 shadow-lg duration-200 sm:max-w-lg",
1427
+ "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",
1360
1428
  className,
1361
1429
  )}
1362
1430
  {...props}
1363
1431
  >
1364
1432
  {children}
1365
- <DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4">
1433
+ <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">
1366
1434
  <XIcon />
1367
1435
  <span className="sr-only">Close</span>
1368
1436
  </DialogPrimitive.Close>
@@ -1401,7 +1469,7 @@ function DialogTitle({
1401
1469
  return (
1402
1470
  <DialogPrimitive.Title
1403
1471
  data-slot="dialog-title"
1404
- className={cn("text-lg leading-none font-semibold", className)}
1472
+ className={cn("font-semibold text-lg leading-none", className)}
1405
1473
  {...props}
1406
1474
  />
1407
1475
  );
@@ -1486,13 +1554,13 @@ function TooltipContent({
1486
1554
  data-slot="tooltip-content"
1487
1555
  sideOffset={sideOffset}
1488
1556
  className={cn(
1489
- "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out 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] rounded-md px-3 py-1.5 text-xs text-balance",
1557
+ "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",
1490
1558
  className,
1491
1559
  )}
1492
1560
  {...props}
1493
1561
  >
1494
1562
  {children}
1495
- <TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
1563
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" />
1496
1564
  </TooltipPrimitive.Content>
1497
1565
  </TooltipPrimitive.Portal>
1498
1566
  );
@@ -1537,36 +1605,34 @@ export default nextConfig;
1537
1605
  "scripts": {
1538
1606
  "dev": "next dev --turbo",
1539
1607
  "build": "next build",
1540
- "start": "next start",
1541
- "lint": "eslint ."
1608
+ "start": "next start"
1542
1609
  },
1543
1610
  "dependencies": {
1544
- "@ai-sdk/openai": "^2.0.73",
1611
+ "@ai-sdk/openai": "^2.0.84",
1545
1612
  "@assistant-ui/react": "workspace:*",
1546
1613
  "@assistant-ui/react-markdown": "workspace:*",
1547
- "@radix-ui/react-avatar": "^1.1.4",
1548
- "@radix-ui/react-dialog": "^1.1.7",
1614
+ "@radix-ui/react-avatar": "^1.1.11",
1615
+ "@radix-ui/react-dialog": "^1.1.15",
1549
1616
  "@radix-ui/react-slot": "^1.2.4",
1550
1617
  "@radix-ui/react-tooltip": "^1.2.8",
1551
1618
  "class-variance-authority": "^0.7.1",
1552
1619
  "clsx": "^2.1.1",
1553
- "lucide-react": "^0.555.0",
1554
- "motion": "^11.18.2",
1555
- "next": "16.0.4",
1556
- "react": "19.2.0",
1557
- "react-dom": "19.2.0",
1620
+ "lucide-react": "^0.560.0",
1621
+ "next": "16.0.10",
1622
+ "react": "19.2.3",
1623
+ "react-dom": "19.2.3",
1558
1624
  "remark-gfm": "^4.0.1",
1559
1625
  "tailwind-merge": "^3.4.0",
1560
1626
  "tw-animate-css": "^1.4.0",
1561
- "zustand": "^5.0.8"
1627
+ "zustand": "^5.0.9"
1562
1628
  },
1563
1629
  "devDependencies": {
1564
1630
  "@assistant-ui/x-buildutils": "workspace:*",
1565
- "@types/node": "^24",
1631
+ "@types/node": "^25",
1566
1632
  "@types/react": "^19",
1567
1633
  "@types/react-dom": "^19",
1568
1634
  "postcss": "^8",
1569
- "tailwindcss": "^4.1.17",
1635
+ "tailwindcss": "^4.1.18",
1570
1636
  "typescript": "^5"
1571
1637
  }
1572
1638
  }