@truefoundry/agent-ui-sdk 0.0.1 → 0.0.3

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 (79) hide show
  1. package/README.md +192 -80
  2. package/dist/index.d.ts +229 -281
  3. package/dist/index.js +1824 -1791
  4. package/dist/index.js.map +1 -1
  5. package/dist/styles.css +2 -0
  6. package/package.json +36 -19
  7. package/src/atoms/AskUserPrompt.tsx +0 -102
  8. package/src/atoms/AttachmentCard.tsx +0 -92
  9. package/src/atoms/AttachmentPickerButton.tsx +0 -19
  10. package/src/atoms/AttachmentPreviewDialog.tsx +0 -34
  11. package/src/atoms/BranchIndicator.tsx +0 -41
  12. package/src/atoms/CodeBlockHeader.tsx +0 -44
  13. package/src/atoms/ComposerShell.tsx +0 -112
  14. package/src/atoms/Markdown.test.tsx +0 -28
  15. package/src/atoms/Markdown.tsx +0 -288
  16. package/src/atoms/McpAuthPrompt.tsx +0 -60
  17. package/src/atoms/MessageActionBar.tsx +0 -60
  18. package/src/atoms/MessageBubble.tsx +0 -80
  19. package/src/atoms/MessageErrorBanner.tsx +0 -26
  20. package/src/atoms/MessageIndicator.tsx +0 -23
  21. package/src/atoms/OpenUIBlock.test.tsx +0 -37
  22. package/src/atoms/OpenUIBlock.tsx +0 -50
  23. package/src/atoms/ReasoningCard.tsx +0 -52
  24. package/src/atoms/SandboxArtifactList.tsx +0 -63
  25. package/src/atoms/ScrollToBottomButton.tsx +0 -34
  26. package/src/atoms/Skeletons.tsx +0 -32
  27. package/src/atoms/ThreadListMisc.tsx +0 -76
  28. package/src/atoms/ThreadListRow.tsx +0 -81
  29. package/src/atoms/ThreadShell.tsx +0 -93
  30. package/src/atoms/Toast.tsx +0 -60
  31. package/src/atoms/ToolApprovalBar.tsx +0 -92
  32. package/src/atoms/ToolCallCard.tsx +0 -186
  33. package/src/atoms/ToolGroupCard.tsx +0 -52
  34. package/src/atoms/UserMessageActionBar.tsx +0 -62
  35. package/src/atoms/WelcomeScreen.tsx +0 -22
  36. package/src/atoms/lib/cn.ts +0 -6
  37. package/src/atoms/primitives/Avatar.tsx +0 -57
  38. package/src/atoms/primitives/Button.tsx +0 -73
  39. package/src/atoms/primitives/Collapsible.tsx +0 -32
  40. package/src/atoms/primitives/Dialog.tsx +0 -152
  41. package/src/atoms/primitives/IconButton.tsx +0 -43
  42. package/src/atoms/primitives/Skeleton.tsx +0 -17
  43. package/src/atoms/primitives/Tooltip.tsx +0 -58
  44. package/src/containers/AskUserContainer.tsx +0 -49
  45. package/src/containers/AssistantMessageContainer.test.tsx +0 -56
  46. package/src/containers/AssistantMessageContainer.tsx +0 -128
  47. package/src/containers/AssistantTextContainer.test.tsx +0 -111
  48. package/src/containers/AssistantTextContainer.tsx +0 -54
  49. package/src/containers/AttachmentsContainer.tsx +0 -83
  50. package/src/containers/ComposerContainer.tsx +0 -66
  51. package/src/containers/ErrorToasterContainer.tsx +0 -76
  52. package/src/containers/McpAuthContainer.test.tsx +0 -100
  53. package/src/containers/McpAuthContainer.tsx +0 -22
  54. package/src/containers/MessageImageContainer.tsx +0 -37
  55. package/src/containers/ReasoningContainer.tsx +0 -32
  56. package/src/containers/RuntimeHarness.tsx +0 -39
  57. package/src/containers/Thread.tsx +0 -9
  58. package/src/containers/ThreadContainer.test.tsx +0 -52
  59. package/src/containers/ThreadContainer.tsx +0 -87
  60. package/src/containers/ThreadListContainer.tsx +0 -63
  61. package/src/containers/ToolCallContainer.test.tsx +0 -135
  62. package/src/containers/ToolCallContainer.tsx +0 -167
  63. package/src/containers/ToolGroupContainer.test.tsx +0 -56
  64. package/src/containers/ToolGroupContainer.tsx +0 -24
  65. package/src/containers/UserEditComposerContainer.test.tsx +0 -52
  66. package/src/containers/UserEditComposerContainer.tsx +0 -86
  67. package/src/containers/UserMessageContainer.test.tsx +0 -99
  68. package/src/containers/UserMessageContainer.tsx +0 -26
  69. package/src/containers/nestedApprovalBridge.ts +0 -20
  70. package/src/containers/useAttachmentPreviewSrc.ts +0 -42
  71. package/src/hooks/useComposerBusyState.test.ts +0 -78
  72. package/src/hooks/useComposerBusyState.ts +0 -69
  73. package/src/index.ts +0 -193
  74. package/src/testSetup.ts +0 -42
  75. package/src/theme/SlotsProvider.test.tsx +0 -64
  76. package/src/theme/SlotsProvider.tsx +0 -41
  77. package/src/theme/defaultSlots.ts +0 -131
  78. package/src/theme/tokens.ts +0 -98
  79. package/src/theme/useClassDarkMode.ts +0 -24
@@ -1,63 +0,0 @@
1
- import { useState } from "react";
2
- import { DownloadIcon, FileIcon, LoaderIcon } from "lucide-react";
3
-
4
- import { cn } from "./lib/cn.js";
5
-
6
- export type SandboxArtifactLink = { label: string; path: string };
7
-
8
- export type SandboxArtifactListProps = {
9
- artifacts: SandboxArtifactLink[];
10
- onDownload?: (path: string) => void | Promise<unknown>;
11
- className?: string;
12
- };
13
-
14
- export function SandboxArtifactList({ artifacts, onDownload, className }: SandboxArtifactListProps) {
15
- const [downloadingPath, setDownloadingPath] = useState<string | null>(null);
16
-
17
- const handleClick = async (path: string) => {
18
- if (downloadingPath != null) return;
19
- setDownloadingPath(path);
20
- try {
21
- await onDownload?.(path);
22
- } finally {
23
- setDownloadingPath(null);
24
- }
25
- };
26
-
27
- return (
28
- <div
29
- data-slot="aui_sandbox-artifact-list"
30
- className={cn("aui-sandbox-artifact-list my-3 flex w-fit max-w-full flex-wrap items-stretch text-sm", className)}
31
- >
32
- {artifacts.map((artifact, index) => {
33
- const isDownloading = downloadingPath === artifact.path;
34
- return (
35
- <button
36
- key={artifact.path}
37
- type="button"
38
- className={cn(
39
- "aui-sandbox-artifact-button text-muted-foreground hover:text-foreground flex min-w-0 items-center gap-1.5 py-1 pr-2 pl-2 transition-colors disabled:pointer-events-none disabled:opacity-70",
40
- index > 0 && "border-border/60 ml-1 border-l pl-3",
41
- )}
42
- disabled={isDownloading}
43
- onClick={() => handleClick(artifact.path)}
44
- >
45
- <FileIcon className="size-4 shrink-0" aria-hidden />
46
- <span className="max-w-40 truncate">{artifact.label}</span>
47
- {isDownloading ? (
48
- <LoaderIcon className="size-3.5 shrink-0 animate-spin [animation-duration:0.6s]" aria-hidden />
49
- ) : (
50
- <DownloadIcon className="size-3.5 shrink-0" aria-hidden />
51
- )}
52
- </button>
53
- );
54
- })}
55
- </div>
56
- );
57
- }
58
-
59
- declare module "../theme/SlotsProvider.js" {
60
- interface AtomSlots {
61
- SandboxArtifactList: typeof SandboxArtifactList;
62
- }
63
- }
@@ -1,34 +0,0 @@
1
- import { forwardRef } from "react";
2
- import { ArrowDownIcon } from "lucide-react";
3
-
4
- import { cn } from "./lib/cn.js";
5
- import { IconButton, type IconButtonProps } from "./primitives/IconButton.js";
6
-
7
- export type ScrollToBottomButtonProps = Omit<IconButtonProps, "tooltip" | "children">;
8
-
9
- export const ScrollToBottomButton = forwardRef<HTMLButtonElement, ScrollToBottomButtonProps>(
10
- ({ className, ...rest }, ref) => {
11
- return (
12
- <IconButton
13
- ref={ref}
14
- tooltip="Scroll to bottom"
15
- variant="outline"
16
- className={cn(
17
- "aui-thread-scroll-to-bottom dark:border-border dark:bg-background dark:hover:bg-accent absolute -top-14 z-10 self-center rounded-full p-4 disabled:invisible",
18
- className,
19
- )}
20
- {...rest}
21
- >
22
- <ArrowDownIcon />
23
- </IconButton>
24
- );
25
- },
26
- );
27
-
28
- ScrollToBottomButton.displayName = "ScrollToBottomButton";
29
-
30
- declare module "../theme/SlotsProvider.js" {
31
- interface AtomSlots {
32
- ScrollToBottomButton: typeof ScrollToBottomButton;
33
- }
34
- }
@@ -1,32 +0,0 @@
1
- import { cn } from "./lib/cn.js";
2
- import { Skeleton } from "./primitives/Skeleton.js";
3
-
4
- export type MessageListSkeletonProps = {
5
- className?: string;
6
- };
7
-
8
- export function MessageListSkeleton({ className }: MessageListSkeletonProps) {
9
- return (
10
- <div
11
- role="status"
12
- aria-label="Loading conversation"
13
- data-slot="aui_thread-history-skeleton"
14
- className={cn("mb-14 flex flex-col gap-y-6", className)}
15
- >
16
- <div className="flex justify-end">
17
- <Skeleton className="h-10 w-[min(85%,20rem)] rounded-xl" />
18
- </div>
19
- <div className="flex flex-col gap-2 px-2">
20
- <Skeleton className="h-4 w-full max-w-md" />
21
- <Skeleton className="h-4 w-full max-w-sm" />
22
- <Skeleton className="h-4 w-2/3 max-w-xs" />
23
- </div>
24
- </div>
25
- );
26
- }
27
-
28
- declare module "../theme/SlotsProvider.js" {
29
- interface AtomSlots {
30
- MessageListSkeleton: typeof MessageListSkeleton;
31
- }
32
- }
@@ -1,76 +0,0 @@
1
- import type { ReactNode } from "react";
2
- import { PlusIcon } from "lucide-react";
3
-
4
- import { cn } from "./lib/cn.js";
5
- import { Button, type ButtonProps } from "./primitives/Button.js";
6
- import { Skeleton } from "./primitives/Skeleton.js";
7
-
8
- export type ThreadListNewButtonProps = Omit<ButtonProps, "children">;
9
-
10
- export function ThreadListNewButton({ className, ...rest }: ThreadListNewButtonProps) {
11
- return (
12
- <Button
13
- variant="ghost"
14
- data-slot="aui_thread-list-new"
15
- className={cn("hover:bg-muted h-8 justify-start gap-2 rounded-md px-2.5 text-sm font-normal", className)}
16
- {...rest}
17
- >
18
- <PlusIcon className="size-4 shrink-0" />
19
- <span className="whitespace-nowrap">New Thread</span>
20
- </Button>
21
- );
22
- }
23
-
24
- export type ThreadListRowSkeletonProps = {
25
- count?: number;
26
- className?: string;
27
- };
28
-
29
- export function ThreadListRowSkeleton({ count = 5, className }: ThreadListRowSkeletonProps) {
30
- return (
31
- <div className={cn("flex flex-col gap-1", className)} role="status" aria-label="Loading threads">
32
- {Array.from({ length: count }, (_, i) => (
33
- <div key={i} className="flex h-8 items-center px-2.5">
34
- <Skeleton className="h-3.5 w-full" />
35
- </div>
36
- ))}
37
- </div>
38
- );
39
- }
40
-
41
- export type ThreadListEmptyStateProps = {
42
- message?: string;
43
- className?: string;
44
- };
45
-
46
- export function ThreadListEmptyState({ message = "No threads yet", className }: ThreadListEmptyStateProps) {
47
- return (
48
- <div className={cn("text-muted-foreground flex flex-1 items-center justify-center px-4 text-center text-sm", className)}>
49
- {message}
50
- </div>
51
- );
52
- }
53
-
54
- export type ThreadListShellProps = {
55
- header: ReactNode;
56
- children: ReactNode;
57
- className?: string;
58
- };
59
-
60
- export function ThreadListShell({ header, children, className }: ThreadListShellProps) {
61
- return (
62
- <div className={cn("flex min-h-0 flex-1 flex-col gap-1 overflow-hidden p-3", className)}>
63
- {header}
64
- <div className="flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto pb-1">{children}</div>
65
- </div>
66
- );
67
- }
68
-
69
- declare module "../theme/SlotsProvider.js" {
70
- interface AtomSlots {
71
- ThreadListNewButton: typeof ThreadListNewButton;
72
- ThreadListRowSkeleton: typeof ThreadListRowSkeleton;
73
- ThreadListEmptyState: typeof ThreadListEmptyState;
74
- ThreadListShell: typeof ThreadListShell;
75
- }
76
- }
@@ -1,81 +0,0 @@
1
- import { ArchiveIcon, MoreHorizontalIcon, TrashIcon } from "lucide-react";
2
- import { DropdownMenu } from "radix-ui";
3
-
4
- import { cn } from "./lib/cn.js";
5
- import { IconButton } from "./primitives/IconButton.js";
6
-
7
- export type ThreadListRowProps = {
8
- title: string;
9
- active: boolean;
10
- onSelect: () => void;
11
- onArchive?: () => void;
12
- onDelete?: () => void;
13
- className?: string;
14
- };
15
-
16
- export function ThreadListRow({ title, active, onSelect, onArchive, onDelete, className }: ThreadListRowProps) {
17
- return (
18
- <div
19
- data-slot="aui_thread-list-item"
20
- data-active={active || undefined}
21
- className={cn(
22
- "group hover:bg-muted data-[active]:bg-muted relative flex min-h-9 items-center rounded-lg transition-colors",
23
- className,
24
- )}
25
- >
26
- <button
27
- type="button"
28
- onClick={onSelect}
29
- data-slot="aui_thread-list-item-trigger"
30
- className="flex min-h-9 min-w-0 flex-1 items-center rounded-lg px-2.5 py-2 text-start text-sm outline-none group-hover:pe-9"
31
- >
32
- <span className="min-w-0 flex-1 truncate">{title}</span>
33
- </button>
34
- {(onArchive || onDelete) && (
35
- <DropdownMenu.Root>
36
- <DropdownMenu.Trigger asChild>
37
- <IconButton
38
- tooltip="More options"
39
- className="absolute end-1.5 top-1/2 size-6 -translate-y-1/2 p-0 opacity-0 group-hover:opacity-100 data-[state=open]:opacity-100"
40
- >
41
- <MoreHorizontalIcon className="size-3.5" />
42
- </IconButton>
43
- </DropdownMenu.Trigger>
44
- <DropdownMenu.Portal>
45
- <DropdownMenu.Content
46
- side="right"
47
- align="start"
48
- sideOffset={6}
49
- className="bg-popover/95 text-popover-foreground z-50 min-w-32 overflow-hidden rounded-xl border p-1.5 shadow-lg backdrop-blur-sm"
50
- >
51
- {onArchive && (
52
- <DropdownMenu.Item
53
- onSelect={onArchive}
54
- className="hover:bg-accent hover:text-accent-foreground flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none"
55
- >
56
- <ArchiveIcon className="size-4" />
57
- Archive
58
- </DropdownMenu.Item>
59
- )}
60
- {onDelete && (
61
- <DropdownMenu.Item
62
- onSelect={onDelete}
63
- className="text-destructive hover:bg-destructive/10 flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none"
64
- >
65
- <TrashIcon className="size-4" />
66
- Delete
67
- </DropdownMenu.Item>
68
- )}
69
- </DropdownMenu.Content>
70
- </DropdownMenu.Portal>
71
- </DropdownMenu.Root>
72
- )}
73
- </div>
74
- );
75
- }
76
-
77
- declare module "../theme/SlotsProvider.js" {
78
- interface AtomSlots {
79
- ThreadListRow: typeof ThreadListRow;
80
- }
81
- }
@@ -1,93 +0,0 @@
1
- import { forwardRef, type ComponentPropsWithRef, type CSSProperties } from "react";
2
-
3
- import { cn } from "./lib/cn.js";
4
-
5
- const THREAD_CSS_VARS: CSSProperties = {
6
- ["--thread-max-width" as string]: "44rem",
7
- ["--composer-bg" as string]: "color-mix(in oklab, var(--color-muted) 30%, var(--color-background))",
8
- ["--composer-radius" as string]: "1.5rem",
9
- ["--composer-padding" as string]: "8px",
10
- };
11
-
12
- export type ThreadRootShellProps = ComponentPropsWithRef<"div">;
13
-
14
- export const ThreadRootShell = forwardRef<HTMLDivElement, ThreadRootShellProps>(
15
- ({ className, style, ...rest }, ref) => (
16
- <div
17
- ref={ref}
18
- className={cn(
19
- "aui-root aui-thread-root bg-background @container flex h-full min-h-0 flex-col overflow-hidden",
20
- className,
21
- )}
22
- style={{ ...THREAD_CSS_VARS, ...style }}
23
- {...rest}
24
- />
25
- ),
26
- );
27
- ThreadRootShell.displayName = "ThreadRootShell";
28
-
29
- export type ThreadViewportShellProps = ComponentPropsWithRef<"div"> & {
30
- isEmpty?: boolean;
31
- };
32
-
33
- export const ThreadViewportShell = forwardRef<HTMLDivElement, ThreadViewportShellProps>(
34
- ({ className, isEmpty, children, ...rest }, ref) => (
35
- <div
36
- ref={ref}
37
- data-slot="aui_thread-viewport"
38
- className={cn("relative flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto scroll-smooth", className)}
39
- {...rest}
40
- >
41
- <div
42
- className={cn(
43
- "mx-auto flex w-full max-w-(--thread-max-width) flex-col px-4 pt-4 pb-4",
44
- isEmpty && "min-h-full justify-center",
45
- )}
46
- >
47
- {children}
48
- </div>
49
- </div>
50
- ),
51
- );
52
- ThreadViewportShell.displayName = "ThreadViewportShell";
53
-
54
- export type ThreadComposerAreaShellProps = ComponentPropsWithRef<"div"> & {
55
- isEmpty?: boolean;
56
- };
57
-
58
- export const ThreadComposerAreaShell = forwardRef<HTMLDivElement, ThreadComposerAreaShellProps>(
59
- ({ className, isEmpty, ...rest }, ref) => (
60
- <div
61
- ref={ref}
62
- data-slot="aui_thread-composer"
63
- className={cn(
64
- "aui-thread-composer bg-background relative mx-auto flex w-full max-w-(--thread-max-width) shrink-0 flex-col gap-4 px-4 pb-4 md:pb-6",
65
- !isEmpty && "rounded-t-(--composer-radius)",
66
- className,
67
- )}
68
- {...rest}
69
- />
70
- ),
71
- );
72
- ThreadComposerAreaShell.displayName = "ThreadComposerAreaShell";
73
-
74
- export type MessageGroupProps = ComponentPropsWithRef<"div">;
75
-
76
- export const MessageGroup = forwardRef<HTMLDivElement, MessageGroupProps>(({ className, ...rest }, ref) => (
77
- <div
78
- ref={ref}
79
- data-slot="aui_message-group"
80
- className={cn("flex flex-col gap-y-6 empty:hidden", className)}
81
- {...rest}
82
- />
83
- ));
84
- MessageGroup.displayName = "MessageGroup";
85
-
86
- declare module "../theme/SlotsProvider.js" {
87
- interface AtomSlots {
88
- ThreadRootShell: typeof ThreadRootShell;
89
- ThreadViewportShell: typeof ThreadViewportShell;
90
- ThreadComposerAreaShell: typeof ThreadComposerAreaShell;
91
- MessageGroup: typeof MessageGroup;
92
- }
93
- }
@@ -1,60 +0,0 @@
1
- import type { ReactNode } from "react";
2
- import { XIcon } from "lucide-react";
3
- import { Toast as ToastPrimitive } from "radix-ui";
4
-
5
- import { cn } from "./lib/cn.js";
6
-
7
- export type ToastProps = {
8
- title: string;
9
- description: string;
10
- open: boolean;
11
- onOpenChange: (open: boolean) => void;
12
- className?: string;
13
- };
14
-
15
- export function Toast({ title, description, open, onOpenChange, className }: ToastProps) {
16
- return (
17
- <ToastPrimitive.Root
18
- open={open}
19
- onOpenChange={onOpenChange}
20
- className={cn(
21
- "border-destructive bg-background text-destructive dark:bg-card pointer-events-auto relative flex max-h-[min(70vh,32rem)] w-full items-start gap-3 rounded-xl border p-4 shadow-lg dark:text-red-200",
22
- "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-4",
23
- "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-bottom-4",
24
- className,
25
- )}
26
- >
27
- <div className="grid min-h-0 min-w-0 flex-1 gap-1 overflow-y-auto pe-6">
28
- <ToastPrimitive.Title className="text-sm leading-none font-semibold">{title}</ToastPrimitive.Title>
29
- <ToastPrimitive.Description className="font-mono text-sm break-words whitespace-pre-wrap">
30
- {description}
31
- </ToastPrimitive.Description>
32
- </div>
33
- <ToastPrimitive.Close className="text-destructive hover:bg-muted focus-visible:ring-ring absolute top-3 right-3 rounded-md p-1 transition-colors focus:outline-none focus-visible:ring-2">
34
- <XIcon className="size-4" />
35
- <span className="sr-only">Close</span>
36
- </ToastPrimitive.Close>
37
- </ToastPrimitive.Root>
38
- );
39
- }
40
-
41
- export type ToastStackProps = {
42
- children: ReactNode;
43
- duration?: number;
44
- };
45
-
46
- export function ToastStack({ children, duration = Number.POSITIVE_INFINITY }: ToastStackProps) {
47
- return (
48
- <ToastPrimitive.Provider duration={duration}>
49
- {children}
50
- <ToastPrimitive.Viewport className="fixed inset-x-0 bottom-0 z-50 flex max-h-screen flex-col-reverse gap-2 p-4 sm:bottom-4 sm:left-1/2 sm:w-full sm:max-w-2xl sm:-translate-x-1/2" />
51
- </ToastPrimitive.Provider>
52
- );
53
- }
54
-
55
- declare module "../theme/SlotsProvider.js" {
56
- interface AtomSlots {
57
- Toast: typeof Toast;
58
- ToastStack: typeof ToastStack;
59
- }
60
- }
@@ -1,92 +0,0 @@
1
- import { useState } from "react";
2
-
3
- import { cn } from "./lib/cn.js";
4
- import { Button } from "./primitives/Button.js";
5
-
6
- export type ToolApprovalOption = {
7
- id: string;
8
- label: string;
9
- isAllow: boolean;
10
- grants?: readonly string[];
11
- confirm?: {
12
- title?: string;
13
- description?: string;
14
- };
15
- };
16
-
17
- export type ToolApprovalBarProps = {
18
- options: ToolApprovalOption[];
19
- onSelectOption: (optionId: string) => void;
20
- className?: string;
21
- };
22
-
23
- export function ToolApprovalBar({ options, onSelectOption, className }: ToolApprovalBarProps) {
24
- const [confirmingId, setConfirmingId] = useState<string | null>(null);
25
- const confirming = confirmingId != null ? options.find((o) => o.id === confirmingId) : undefined;
26
-
27
- if (confirming) {
28
- return (
29
- <div className={cn("aui-tool-approval-confirm flex flex-col gap-2 pt-1", className)}>
30
- <p className="font-semibold">{confirming.confirm?.title ?? `${confirming.label}?`}</p>
31
- {confirming.confirm?.description && (
32
- <p className="text-muted-foreground">{confirming.confirm.description}</p>
33
- )}
34
- {confirming.grants && confirming.grants.length > 0 && (
35
- <ul className="flex flex-col gap-1">
36
- {confirming.grants.map((grant) => (
37
- <li key={grant}>
38
- <code className="bg-muted rounded px-1.5 py-0.5 text-xs">{grant}</code>
39
- </li>
40
- ))}
41
- </ul>
42
- )}
43
- <div className="flex items-center gap-2">
44
- <Button
45
- size="sm"
46
- className="active:scale-[0.98]"
47
- onClick={() => {
48
- onSelectOption(confirming.id);
49
- setConfirmingId(null);
50
- }}
51
- >
52
- Confirm
53
- </Button>
54
- <Button
55
- size="sm"
56
- variant="outline"
57
- className="active:scale-[0.98]"
58
- onClick={() => setConfirmingId(null)}
59
- >
60
- Back
61
- </Button>
62
- </div>
63
- </div>
64
- );
65
- }
66
-
67
- const firstAllowId = options.find((o) => o.isAllow)?.id;
68
-
69
- return (
70
- <div className={cn("aui-tool-approval-bar flex flex-wrap items-center gap-2 pt-1", className)}>
71
- {options.map((option) => (
72
- <Button
73
- key={option.id}
74
- size="sm"
75
- variant={option.id === firstAllowId ? "default" : "outline"}
76
- className="active:scale-[0.98]"
77
- onClick={() =>
78
- option.confirm ? setConfirmingId(option.id) : onSelectOption(option.id)
79
- }
80
- >
81
- {option.label}
82
- </Button>
83
- ))}
84
- </div>
85
- );
86
- }
87
-
88
- declare module "../theme/SlotsProvider.js" {
89
- interface AtomSlots {
90
- ToolApprovalBar: typeof ToolApprovalBar;
91
- }
92
- }