@truefoundry/agent-ui-sdk 0.0.1 → 0.0.2
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/README.md +192 -80
- package/dist/index.d.ts +228 -281
- package/dist/index.js +1823 -1791
- package/dist/index.js.map +1 -1
- package/dist/styles.css +2 -0
- package/package.json +36 -19
- package/src/atoms/AskUserPrompt.tsx +0 -102
- package/src/atoms/AttachmentCard.tsx +0 -92
- package/src/atoms/AttachmentPickerButton.tsx +0 -19
- package/src/atoms/AttachmentPreviewDialog.tsx +0 -34
- package/src/atoms/BranchIndicator.tsx +0 -41
- package/src/atoms/CodeBlockHeader.tsx +0 -44
- package/src/atoms/ComposerShell.tsx +0 -112
- package/src/atoms/Markdown.test.tsx +0 -28
- package/src/atoms/Markdown.tsx +0 -288
- package/src/atoms/McpAuthPrompt.tsx +0 -60
- package/src/atoms/MessageActionBar.tsx +0 -60
- package/src/atoms/MessageBubble.tsx +0 -80
- package/src/atoms/MessageErrorBanner.tsx +0 -26
- package/src/atoms/MessageIndicator.tsx +0 -23
- package/src/atoms/OpenUIBlock.test.tsx +0 -37
- package/src/atoms/OpenUIBlock.tsx +0 -50
- package/src/atoms/ReasoningCard.tsx +0 -52
- package/src/atoms/SandboxArtifactList.tsx +0 -63
- package/src/atoms/ScrollToBottomButton.tsx +0 -34
- package/src/atoms/Skeletons.tsx +0 -32
- package/src/atoms/ThreadListMisc.tsx +0 -76
- package/src/atoms/ThreadListRow.tsx +0 -81
- package/src/atoms/ThreadShell.tsx +0 -93
- package/src/atoms/Toast.tsx +0 -60
- package/src/atoms/ToolApprovalBar.tsx +0 -92
- package/src/atoms/ToolCallCard.tsx +0 -186
- package/src/atoms/ToolGroupCard.tsx +0 -52
- package/src/atoms/UserMessageActionBar.tsx +0 -62
- package/src/atoms/WelcomeScreen.tsx +0 -22
- package/src/atoms/lib/cn.ts +0 -6
- package/src/atoms/primitives/Avatar.tsx +0 -57
- package/src/atoms/primitives/Button.tsx +0 -73
- package/src/atoms/primitives/Collapsible.tsx +0 -32
- package/src/atoms/primitives/Dialog.tsx +0 -152
- package/src/atoms/primitives/IconButton.tsx +0 -43
- package/src/atoms/primitives/Skeleton.tsx +0 -17
- package/src/atoms/primitives/Tooltip.tsx +0 -58
- package/src/containers/AskUserContainer.tsx +0 -49
- package/src/containers/AssistantMessageContainer.test.tsx +0 -56
- package/src/containers/AssistantMessageContainer.tsx +0 -128
- package/src/containers/AssistantTextContainer.test.tsx +0 -111
- package/src/containers/AssistantTextContainer.tsx +0 -54
- package/src/containers/AttachmentsContainer.tsx +0 -83
- package/src/containers/ComposerContainer.tsx +0 -66
- package/src/containers/ErrorToasterContainer.tsx +0 -76
- package/src/containers/McpAuthContainer.test.tsx +0 -100
- package/src/containers/McpAuthContainer.tsx +0 -22
- package/src/containers/MessageImageContainer.tsx +0 -37
- package/src/containers/ReasoningContainer.tsx +0 -32
- package/src/containers/RuntimeHarness.tsx +0 -39
- package/src/containers/Thread.tsx +0 -9
- package/src/containers/ThreadContainer.test.tsx +0 -52
- package/src/containers/ThreadContainer.tsx +0 -87
- package/src/containers/ThreadListContainer.tsx +0 -63
- package/src/containers/ToolCallContainer.test.tsx +0 -135
- package/src/containers/ToolCallContainer.tsx +0 -167
- package/src/containers/ToolGroupContainer.test.tsx +0 -56
- package/src/containers/ToolGroupContainer.tsx +0 -24
- package/src/containers/UserEditComposerContainer.test.tsx +0 -52
- package/src/containers/UserEditComposerContainer.tsx +0 -86
- package/src/containers/UserMessageContainer.test.tsx +0 -99
- package/src/containers/UserMessageContainer.tsx +0 -26
- package/src/containers/nestedApprovalBridge.ts +0 -20
- package/src/containers/useAttachmentPreviewSrc.ts +0 -42
- package/src/hooks/useComposerBusyState.test.ts +0 -78
- package/src/hooks/useComposerBusyState.ts +0 -69
- package/src/index.ts +0 -193
- package/src/testSetup.ts +0 -42
- package/src/theme/SlotsProvider.test.tsx +0 -64
- package/src/theme/SlotsProvider.tsx +0 -41
- package/src/theme/defaultSlots.ts +0 -131
- package/src/theme/tokens.ts +0 -98
- package/src/theme/useClassDarkMode.ts +0 -24
package/package.json
CHANGED
|
@@ -1,45 +1,54 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truefoundry/agent-ui-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Design-system-agnostic Atom/Container UI SDK for TrueFoundry agent chat, built on assistant-ui.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
|
-
"type": "module",
|
|
7
6
|
"publishConfig": {
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
"access": "public",
|
|
8
|
+
"provenance": false
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
12
13
|
"types": "./dist/index.d.ts",
|
|
13
14
|
"default": "./dist/index.js"
|
|
14
15
|
},
|
|
16
|
+
"./styles.css": "./dist/styles.css",
|
|
15
17
|
"./openui.css": "./src/openui.css"
|
|
16
18
|
},
|
|
17
19
|
"main": "./dist/index.js",
|
|
18
20
|
"types": "./dist/index.d.ts",
|
|
19
21
|
"files": [
|
|
20
22
|
"dist",
|
|
21
|
-
"src",
|
|
23
|
+
"src/openui.css",
|
|
22
24
|
"README.md"
|
|
23
25
|
],
|
|
24
26
|
"sideEffects": [
|
|
25
27
|
"src/openui.css",
|
|
26
|
-
"dist/
|
|
28
|
+
"dist/styles.css",
|
|
29
|
+
"dist/openui.css",
|
|
30
|
+
"src/icons/fontawesome.ts",
|
|
31
|
+
"src/icons/registerAgentIcons.ts"
|
|
27
32
|
],
|
|
28
33
|
"scripts": {
|
|
29
|
-
"prepare": "
|
|
30
|
-
"build": "tsup",
|
|
34
|
+
"prepare": "yarn build",
|
|
35
|
+
"build": "tsup && tailwindcss --input src/build-styles.css --output dist/styles.css --minify",
|
|
36
|
+
"dev:watch": "tsup --watch",
|
|
31
37
|
"pack:tgz": "yarn install && yarn build && yarn pack",
|
|
38
|
+
"pack:dev": "bash scripts/pack-dev.sh",
|
|
32
39
|
"test": "vitest run",
|
|
33
40
|
"typecheck": "tsc --noEmit"
|
|
34
41
|
},
|
|
35
42
|
"peerDependencies": {
|
|
36
43
|
"@assistant-ui/core": "^0.2.19",
|
|
37
44
|
"@assistant-ui/react": "^0.14.0",
|
|
38
|
-
"@truefoundry/assistant-ui-runtime": "^0.1.
|
|
45
|
+
"@truefoundry/assistant-ui-runtime": "^0.1.1",
|
|
39
46
|
"@types/react": "*",
|
|
47
|
+
"monaco-editor": "^0.52.0",
|
|
40
48
|
"react": "^18 || ^19",
|
|
41
49
|
"react-dom": "^18 || ^19",
|
|
42
|
-
"
|
|
50
|
+
"tfy-web-components": "^0.0.22",
|
|
51
|
+
"truefoundry-gateway-sdk": "^0.3.1"
|
|
43
52
|
},
|
|
44
53
|
"peerDependenciesMeta": {
|
|
45
54
|
"@types/react": {
|
|
@@ -47,12 +56,20 @@
|
|
|
47
56
|
}
|
|
48
57
|
},
|
|
49
58
|
"dependencies": {
|
|
59
|
+
"@emotion/react": "^11.14.0",
|
|
60
|
+
"@emotion/styled": "^11.14.0",
|
|
61
|
+
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
|
62
|
+
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
|
63
|
+
"@fortawesome/react-fontawesome": "^0.2.2",
|
|
64
|
+
"@mui/material": "^6.2.0",
|
|
65
|
+
"@openuidev/react-headless": "^0.9.1",
|
|
50
66
|
"@openuidev/react-lang": "^0.2.8",
|
|
51
67
|
"@openuidev/react-ui": "^0.12.1",
|
|
52
68
|
"class-variance-authority": "^0.7.1",
|
|
69
|
+
"classnames": "^2.5.1",
|
|
53
70
|
"clsx": "^2.1.1",
|
|
71
|
+
"lodash-es": "^4.17.21",
|
|
54
72
|
"lucide-react": "^1.21.0",
|
|
55
|
-
"radix-ui": "^1.6.0",
|
|
56
73
|
"react-markdown": "^9.0.1",
|
|
57
74
|
"remark-gfm": "^4.0.1",
|
|
58
75
|
"tailwind-merge": "^3.6.0"
|
|
@@ -60,24 +77,24 @@
|
|
|
60
77
|
"devDependencies": {
|
|
61
78
|
"@assistant-ui/core": "^0.2.19",
|
|
62
79
|
"@assistant-ui/react": "^0.14.24",
|
|
80
|
+
"@tailwindcss/cli": "^4.3.2",
|
|
63
81
|
"@testing-library/dom": "^10.0.0",
|
|
64
82
|
"@testing-library/jest-dom": "^6.6.3",
|
|
65
83
|
"@testing-library/react": "^16.3.2",
|
|
66
|
-
"@truefoundry/assistant-ui-runtime": "0.1.
|
|
84
|
+
"@truefoundry/assistant-ui-runtime": "^0.1.1",
|
|
67
85
|
"@types/node": "^20",
|
|
68
86
|
"@types/react": "^19.2.17",
|
|
87
|
+
"esbuild-plugin-svgr": "3.1.1",
|
|
69
88
|
"jsdom": "^24.1.3",
|
|
89
|
+
"monaco-editor": "^0.52.0",
|
|
70
90
|
"react": "^19.2.4",
|
|
71
91
|
"react-dom": "^19.2.4",
|
|
72
|
-
"
|
|
92
|
+
"tailwindcss": "^4.3.2",
|
|
93
|
+
"tfy-web-components": "^0.0.22",
|
|
94
|
+
"truefoundry-gateway-sdk": "^0.3.1",
|
|
73
95
|
"tsup": "^8.5.0",
|
|
74
96
|
"typescript": "^5.9.3",
|
|
75
97
|
"vitest": "^4.1.9"
|
|
76
98
|
},
|
|
77
|
-
"packageManager": "yarn@
|
|
78
|
-
"dependenciesMeta": {
|
|
79
|
-
"esbuild": {
|
|
80
|
-
"built": true
|
|
81
|
-
}
|
|
82
|
-
}
|
|
99
|
+
"packageManager": "yarn@1.22.22"
|
|
83
100
|
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { cn } from "./lib/cn.js";
|
|
2
|
-
import { Button } from "./primitives/Button.js";
|
|
3
|
-
|
|
4
|
-
export type AskUserOption = { id: string; label: string };
|
|
5
|
-
|
|
6
|
-
const OTHER_OPTION_ID = "__other";
|
|
7
|
-
|
|
8
|
-
export type AskUserPromptProps = {
|
|
9
|
-
question: string;
|
|
10
|
-
options: AskUserOption[];
|
|
11
|
-
allowOther: boolean;
|
|
12
|
-
selectedOptionId?: string;
|
|
13
|
-
otherValue: string;
|
|
14
|
-
disabled: boolean;
|
|
15
|
-
onSelectOption: (optionId: string) => void;
|
|
16
|
-
onOtherValueChange: (value: string) => void;
|
|
17
|
-
onSubmit: () => void;
|
|
18
|
-
className?: string;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export function AskUserPrompt({
|
|
22
|
-
question,
|
|
23
|
-
options,
|
|
24
|
-
allowOther,
|
|
25
|
-
selectedOptionId,
|
|
26
|
-
otherValue,
|
|
27
|
-
disabled,
|
|
28
|
-
onSelectOption,
|
|
29
|
-
onOtherValueChange,
|
|
30
|
-
onSubmit,
|
|
31
|
-
className,
|
|
32
|
-
}: AskUserPromptProps) {
|
|
33
|
-
const canSubmit = selectedOptionId != null && selectedOptionId !== OTHER_OPTION_ID
|
|
34
|
-
? true
|
|
35
|
-
: selectedOptionId === OTHER_OPTION_ID && otherValue.trim().length > 0;
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div
|
|
39
|
-
data-slot="aui_ask-user-prompt"
|
|
40
|
-
className={cn(
|
|
41
|
-
"border-border/60 flex w-full flex-col gap-3 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)]",
|
|
42
|
-
className,
|
|
43
|
-
)}
|
|
44
|
-
>
|
|
45
|
-
<p className="text-foreground px-2.5 text-sm font-medium">{question}</p>
|
|
46
|
-
<div className="flex flex-col gap-1.5 px-2.5">
|
|
47
|
-
{options.map((option) => (
|
|
48
|
-
<label key={option.id} className="flex items-center gap-2 text-sm">
|
|
49
|
-
<input
|
|
50
|
-
type="radio"
|
|
51
|
-
name="ask-user-option"
|
|
52
|
-
checked={selectedOptionId === option.id}
|
|
53
|
-
disabled={disabled}
|
|
54
|
-
onChange={() => onSelectOption(option.id)}
|
|
55
|
-
/>
|
|
56
|
-
{option.label}
|
|
57
|
-
</label>
|
|
58
|
-
))}
|
|
59
|
-
{allowOther && (
|
|
60
|
-
<label className="flex items-center gap-2 text-sm">
|
|
61
|
-
<input
|
|
62
|
-
type="radio"
|
|
63
|
-
name="ask-user-option"
|
|
64
|
-
checked={selectedOptionId === OTHER_OPTION_ID}
|
|
65
|
-
disabled={disabled}
|
|
66
|
-
onChange={() => onSelectOption(OTHER_OPTION_ID)}
|
|
67
|
-
/>
|
|
68
|
-
<input
|
|
69
|
-
type="text"
|
|
70
|
-
value={otherValue}
|
|
71
|
-
placeholder="Type your answer..."
|
|
72
|
-
disabled={disabled}
|
|
73
|
-
onFocus={() => onSelectOption(OTHER_OPTION_ID)}
|
|
74
|
-
onChange={(event) => {
|
|
75
|
-
onSelectOption(OTHER_OPTION_ID);
|
|
76
|
-
onOtherValueChange(event.target.value);
|
|
77
|
-
}}
|
|
78
|
-
aria-label="Other answer"
|
|
79
|
-
className="border-border/60 flex-1 rounded-md border bg-transparent px-2 py-1 text-sm outline-none"
|
|
80
|
-
/>
|
|
81
|
-
</label>
|
|
82
|
-
)}
|
|
83
|
-
</div>
|
|
84
|
-
<div className="flex justify-end px-2.5">
|
|
85
|
-
<Button
|
|
86
|
-
type="button"
|
|
87
|
-
className="rounded-full px-4"
|
|
88
|
-
disabled={disabled || !canSubmit}
|
|
89
|
-
onClick={onSubmit}
|
|
90
|
-
>
|
|
91
|
-
Submit
|
|
92
|
-
</Button>
|
|
93
|
-
</div>
|
|
94
|
-
</div>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
declare module "../theme/SlotsProvider.js" {
|
|
99
|
-
interface AtomSlots {
|
|
100
|
-
AskUserPrompt: typeof AskUserPrompt;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { FileTextIcon, XIcon } from "lucide-react";
|
|
2
|
-
|
|
3
|
-
import { cn } from "./lib/cn.js";
|
|
4
|
-
import { Avatar, AvatarFallback, AvatarImage } from "./primitives/Avatar.js";
|
|
5
|
-
import { IconButton } from "./primitives/IconButton.js";
|
|
6
|
-
|
|
7
|
-
export type AttachmentCardSize = "chip" | "preview";
|
|
8
|
-
|
|
9
|
-
/** Fixed preview bounds for attachments rendered in user message bubbles. */
|
|
10
|
-
export const USER_MESSAGE_ATTACHMENT_PREVIEW_REM = 12;
|
|
11
|
-
|
|
12
|
-
export type AttachmentCardProps = {
|
|
13
|
-
name: string;
|
|
14
|
-
contentType?: string;
|
|
15
|
-
previewSrc?: string;
|
|
16
|
-
isImage?: boolean;
|
|
17
|
-
size?: AttachmentCardSize;
|
|
18
|
-
/** When set, constrains image preview and file chip width to this rem size. */
|
|
19
|
-
previewRem?: number;
|
|
20
|
-
onRemove?: () => void;
|
|
21
|
-
className?: string;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export function AttachmentCard({
|
|
25
|
-
name,
|
|
26
|
-
previewSrc,
|
|
27
|
-
isImage = false,
|
|
28
|
-
size = "chip",
|
|
29
|
-
previewRem,
|
|
30
|
-
onRemove,
|
|
31
|
-
className,
|
|
32
|
-
}: AttachmentCardProps) {
|
|
33
|
-
if (size === "preview" && isImage && previewSrc) {
|
|
34
|
-
const previewSize =
|
|
35
|
-
previewRem != null ? { width: `${previewRem}rem`, height: `${previewRem}rem` } : undefined;
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div
|
|
39
|
-
data-slot="aui_attachment-preview"
|
|
40
|
-
style={previewSize}
|
|
41
|
-
className={cn(
|
|
42
|
-
"aui-attachment-preview relative shrink-0 cursor-pointer overflow-hidden rounded-lg border",
|
|
43
|
-
previewRem == null && "size-24",
|
|
44
|
-
className,
|
|
45
|
-
)}
|
|
46
|
-
>
|
|
47
|
-
<img src={previewSrc} alt={name} className="h-full w-full object-cover" />
|
|
48
|
-
</div>
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<div
|
|
54
|
-
data-slot="aui_attachment-chip"
|
|
55
|
-
style={previewRem != null ? { maxWidth: `${previewRem}rem` } : undefined}
|
|
56
|
-
className={cn(
|
|
57
|
-
"aui-attachment-chip bg-muted flex max-w-full shrink-0 items-center gap-2 rounded-lg border px-2 py-1.5",
|
|
58
|
-
className,
|
|
59
|
-
)}
|
|
60
|
-
>
|
|
61
|
-
<div className="bg-background flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md border">
|
|
62
|
-
{isImage && previewSrc ? (
|
|
63
|
-
<Avatar className="size-7 rounded-none">
|
|
64
|
-
<AvatarImage src={previewSrc} alt={name} className="object-cover" />
|
|
65
|
-
<AvatarFallback>
|
|
66
|
-
<FileTextIcon className="text-muted-foreground size-4" />
|
|
67
|
-
</AvatarFallback>
|
|
68
|
-
</Avatar>
|
|
69
|
-
) : (
|
|
70
|
-
<FileTextIcon className="text-muted-foreground size-4" />
|
|
71
|
-
)}
|
|
72
|
-
</div>
|
|
73
|
-
<span className="text-foreground min-w-0 truncate text-sm">{name}</span>
|
|
74
|
-
{onRemove && (
|
|
75
|
-
<IconButton
|
|
76
|
-
tooltip="Remove file"
|
|
77
|
-
side="top"
|
|
78
|
-
className="size-6 shrink-0 rounded-full [&_svg]:size-3"
|
|
79
|
-
onClick={onRemove}
|
|
80
|
-
>
|
|
81
|
-
<XIcon />
|
|
82
|
-
</IconButton>
|
|
83
|
-
)}
|
|
84
|
-
</div>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
declare module "../theme/SlotsProvider.js" {
|
|
89
|
-
interface AtomSlots {
|
|
90
|
-
AttachmentCard: typeof AttachmentCard;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { PlusIcon } from "lucide-react";
|
|
2
|
-
|
|
3
|
-
import { IconButton, type IconButtonProps } from "./primitives/IconButton.js";
|
|
4
|
-
|
|
5
|
-
export type AttachmentPickerButtonProps = Omit<IconButtonProps, "tooltip" | "children">;
|
|
6
|
-
|
|
7
|
-
export function AttachmentPickerButton(props: AttachmentPickerButtonProps) {
|
|
8
|
-
return (
|
|
9
|
-
<IconButton tooltip="Add Attachment" variant="ghost" className="size-7 rounded-full p-1" {...props}>
|
|
10
|
-
<PlusIcon className="size-4.5" />
|
|
11
|
-
</IconButton>
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
declare module "../theme/SlotsProvider.js" {
|
|
16
|
-
interface AtomSlots {
|
|
17
|
-
AttachmentPickerButton: typeof AttachmentPickerButton;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
import { Dialog, DialogContent, DialogTitle, DialogTrigger } from "./primitives/Dialog.js";
|
|
4
|
-
|
|
5
|
-
export type AttachmentPreviewDialogProps = {
|
|
6
|
-
previewSrc?: string;
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export function AttachmentPreviewDialog({ previewSrc, children }: AttachmentPreviewDialogProps) {
|
|
11
|
-
if (!previewSrc) return <>{children}</>;
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<Dialog>
|
|
15
|
-
<DialogTrigger asChild>{children}</DialogTrigger>
|
|
16
|
-
<DialogContent className="p-2 sm:max-w-3xl">
|
|
17
|
-
<DialogTitle className="sr-only">Image Attachment Preview</DialogTitle>
|
|
18
|
-
<div className="bg-background relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden">
|
|
19
|
-
<img
|
|
20
|
-
src={previewSrc}
|
|
21
|
-
alt="Attachment preview"
|
|
22
|
-
className="block h-auto max-h-[80vh] w-auto max-w-full object-contain"
|
|
23
|
-
/>
|
|
24
|
-
</div>
|
|
25
|
-
</DialogContent>
|
|
26
|
-
</Dialog>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
declare module "../theme/SlotsProvider.js" {
|
|
31
|
-
interface AtomSlots {
|
|
32
|
-
AttachmentPreviewDialog: typeof AttachmentPreviewDialog;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
2
|
-
|
|
3
|
-
import { cn } from "./lib/cn.js";
|
|
4
|
-
import { IconButton } from "./primitives/IconButton.js";
|
|
5
|
-
|
|
6
|
-
export type BranchIndicatorProps = {
|
|
7
|
-
index: number;
|
|
8
|
-
count: number;
|
|
9
|
-
onPrevious: () => void;
|
|
10
|
-
onNext: () => void;
|
|
11
|
-
className?: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export function BranchIndicator({ index, count, onPrevious, onNext, className }: BranchIndicatorProps) {
|
|
15
|
-
if (count <= 1) return null;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div
|
|
19
|
-
className={cn(
|
|
20
|
-
"aui-branch-picker-root text-muted-foreground -ms-2 me-2 inline-flex items-center text-xs",
|
|
21
|
-
className,
|
|
22
|
-
)}
|
|
23
|
-
>
|
|
24
|
-
<IconButton tooltip="Previous" onClick={onPrevious}>
|
|
25
|
-
<ChevronLeftIcon />
|
|
26
|
-
</IconButton>
|
|
27
|
-
<span className="aui-branch-picker-state font-medium">
|
|
28
|
-
{index} / {count}
|
|
29
|
-
</span>
|
|
30
|
-
<IconButton tooltip="Next" onClick={onNext}>
|
|
31
|
-
<ChevronRightIcon />
|
|
32
|
-
</IconButton>
|
|
33
|
-
</div>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
declare module "../theme/SlotsProvider.js" {
|
|
38
|
-
interface AtomSlots {
|
|
39
|
-
BranchIndicator: typeof BranchIndicator;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
2
|
-
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
3
|
-
|
|
4
|
-
import { IconButton } from "./primitives/IconButton.js";
|
|
5
|
-
|
|
6
|
-
export type CodeBlockHeaderProps = {
|
|
7
|
-
language: string;
|
|
8
|
-
code: string;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export function CodeBlockHeader({ language, code }: CodeBlockHeaderProps) {
|
|
12
|
-
const [isCopied, setIsCopied] = useState(false);
|
|
13
|
-
|
|
14
|
-
const onCopy = () => {
|
|
15
|
-
if (!code || isCopied || typeof navigator === "undefined" || !navigator.clipboard) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
navigator.clipboard.writeText(code).then(
|
|
19
|
-
() => {
|
|
20
|
-
setIsCopied(true);
|
|
21
|
-
setTimeout(() => setIsCopied(false), 3000);
|
|
22
|
-
},
|
|
23
|
-
() => {},
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<div className="aui-code-header-root border-border/50 bg-muted/50 mt-3 flex items-center justify-between rounded-t-xl border border-b-0 px-3.5 py-1.5 text-xs">
|
|
29
|
-
<span className="aui-code-header-language text-muted-foreground font-medium lowercase">
|
|
30
|
-
{language}
|
|
31
|
-
</span>
|
|
32
|
-
<IconButton tooltip="Copy" onClick={onCopy}>
|
|
33
|
-
{!isCopied && <CopyIcon className="animate-in zoom-in-75 fade-in duration-150" />}
|
|
34
|
-
{isCopied && <CheckIcon className="animate-in zoom-in-50 fade-in duration-200 ease-out" />}
|
|
35
|
-
</IconButton>
|
|
36
|
-
</div>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
declare module "../theme/SlotsProvider.js" {
|
|
41
|
-
interface AtomSlots {
|
|
42
|
-
CodeBlockHeader: typeof CodeBlockHeader;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import { ArrowUpIcon, LoaderIcon, PlusIcon } from "lucide-react";
|
|
3
|
-
|
|
4
|
-
import { cn } from "./lib/cn.js";
|
|
5
|
-
import { Button } from "./primitives/Button.js";
|
|
6
|
-
import { IconButton } from "./primitives/IconButton.js";
|
|
7
|
-
|
|
8
|
-
export type ComposerShellProps = {
|
|
9
|
-
value: string;
|
|
10
|
-
placeholder: string;
|
|
11
|
-
disabled: boolean;
|
|
12
|
-
isRunning?: boolean;
|
|
13
|
-
attachments?: ReactNode;
|
|
14
|
-
modelLabel?: string;
|
|
15
|
-
modelIcon?: ReactNode;
|
|
16
|
-
connectorStatusLabel?: string;
|
|
17
|
-
onValueChange: (value: string) => void;
|
|
18
|
-
onSubmit: () => void;
|
|
19
|
-
onCancel?: () => void;
|
|
20
|
-
onAttach?: () => void;
|
|
21
|
-
className?: string;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export function ComposerShell({
|
|
25
|
-
value,
|
|
26
|
-
placeholder,
|
|
27
|
-
disabled,
|
|
28
|
-
isRunning = false,
|
|
29
|
-
attachments,
|
|
30
|
-
modelLabel,
|
|
31
|
-
modelIcon,
|
|
32
|
-
connectorStatusLabel,
|
|
33
|
-
onValueChange,
|
|
34
|
-
onSubmit,
|
|
35
|
-
onCancel,
|
|
36
|
-
onAttach,
|
|
37
|
-
className,
|
|
38
|
-
}: ComposerShellProps) {
|
|
39
|
-
return (
|
|
40
|
-
<div
|
|
41
|
-
data-slot="aui_composer-shell"
|
|
42
|
-
className={cn(
|
|
43
|
-
"border-border/60 focus-within:border-ring focus-within:ring-ring/20 flex w-full flex-col gap-2 rounded-[var(--composer-radius,1.5rem)] border bg-[var(--composer-bg,var(--muted))] p-[var(--composer-padding,8px)] shadow-sm transition-colors focus-within:ring-3",
|
|
44
|
-
className,
|
|
45
|
-
)}
|
|
46
|
-
>
|
|
47
|
-
{attachments}
|
|
48
|
-
<textarea
|
|
49
|
-
value={value}
|
|
50
|
-
placeholder={placeholder}
|
|
51
|
-
disabled={disabled}
|
|
52
|
-
rows={1}
|
|
53
|
-
aria-label="Message input"
|
|
54
|
-
onChange={(event) => onValueChange(event.target.value)}
|
|
55
|
-
onKeyDown={(event) => {
|
|
56
|
-
if (event.key === "Enter" && !event.shiftKey) {
|
|
57
|
-
event.preventDefault();
|
|
58
|
-
onSubmit();
|
|
59
|
-
}
|
|
60
|
-
}}
|
|
61
|
-
className="placeholder:text-muted-foreground/80 max-h-32 min-h-10 w-full resize-none rounded-lg bg-transparent px-2.5 py-1 text-base outline-none"
|
|
62
|
-
/>
|
|
63
|
-
<div className="flex items-center justify-between px-1">
|
|
64
|
-
<div className="flex items-center gap-2">
|
|
65
|
-
{onAttach && (
|
|
66
|
-
<IconButton tooltip="Attach" onClick={onAttach}>
|
|
67
|
-
<PlusIcon />
|
|
68
|
-
</IconButton>
|
|
69
|
-
)}
|
|
70
|
-
{connectorStatusLabel && (
|
|
71
|
-
<span className="text-muted-foreground text-xs">{connectorStatusLabel}</span>
|
|
72
|
-
)}
|
|
73
|
-
</div>
|
|
74
|
-
<div className="flex items-center gap-2">
|
|
75
|
-
{modelLabel && (
|
|
76
|
-
<span className="bg-muted text-muted-foreground flex items-center gap-1 rounded-full px-2 py-0.5 text-xs">
|
|
77
|
-
{modelIcon}
|
|
78
|
-
{modelLabel}
|
|
79
|
-
</span>
|
|
80
|
-
)}
|
|
81
|
-
{isRunning ? (
|
|
82
|
-
<Button
|
|
83
|
-
variant="default"
|
|
84
|
-
size="sm"
|
|
85
|
-
className="gap-1.5 rounded-full"
|
|
86
|
-
disabled={!onCancel}
|
|
87
|
-
onClick={onCancel}
|
|
88
|
-
>
|
|
89
|
-
<LoaderIcon className="size-3.5 animate-spin [animation-duration:0.6s]" />
|
|
90
|
-
Cancel
|
|
91
|
-
</Button>
|
|
92
|
-
) : (
|
|
93
|
-
<IconButton
|
|
94
|
-
tooltip="Send message"
|
|
95
|
-
variant="default"
|
|
96
|
-
disabled={disabled || value.trim().length === 0}
|
|
97
|
-
onClick={onSubmit}
|
|
98
|
-
>
|
|
99
|
-
<ArrowUpIcon />
|
|
100
|
-
</IconButton>
|
|
101
|
-
)}
|
|
102
|
-
</div>
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
declare module "../theme/SlotsProvider.js" {
|
|
109
|
-
interface AtomSlots {
|
|
110
|
-
ComposerShell: typeof ComposerShell;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
-
import { describe, expect, it, vi } from "vitest";
|
|
4
|
-
|
|
5
|
-
import { Markdown } from "./Markdown.js";
|
|
6
|
-
|
|
7
|
-
describe("Markdown sandbox_artifact rendering", () => {
|
|
8
|
-
it("calls onDownloadArtifact with the link's exact path when clicked", () => {
|
|
9
|
-
const onDownloadArtifact = vi.fn();
|
|
10
|
-
render(
|
|
11
|
-
<Markdown
|
|
12
|
-
content="sandbox_artifact [Download the pink dog SVG](/tmp/pink_dog.svg)"
|
|
13
|
-
onDownloadArtifact={onDownloadArtifact}
|
|
14
|
-
/>,
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
fireEvent.click(screen.getByRole("button", { name: /Download the pink dog SVG/ }));
|
|
18
|
-
|
|
19
|
-
expect(onDownloadArtifact).toHaveBeenCalledExactlyOnceWith("/tmp/pink_dog.svg");
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("does not throw when no onDownloadArtifact handler is provided", () => {
|
|
23
|
-
render(<Markdown content="sandbox_artifact [Download](/tmp/a.svg)" />);
|
|
24
|
-
expect(() =>
|
|
25
|
-
fireEvent.click(screen.getByRole("button", { name: /Download/ })),
|
|
26
|
-
).not.toThrow();
|
|
27
|
-
});
|
|
28
|
-
});
|