assistant-ui 0.0.120 → 0.0.122
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 +60 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +1 -2
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/cloud.d.ts +25 -0
- package/dist/commands/cloud.d.ts.map +1 -0
- package/dist/commands/cloud.js +194 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +10 -2
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/info.js +2 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -2
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +95 -23
- package/dist/commands/mcp.js.map +1 -1
- package/dist/lib/agent-skill.d.ts +2 -2
- package/dist/lib/agent-skill.d.ts.map +1 -1
- package/dist/lib/agent-skill.js +10 -28
- package/dist/lib/agent-skill.js.map +1 -1
- package/dist/lib/cloud-abort.d.ts +2 -0
- package/dist/lib/cloud-abort.d.ts.map +1 -0
- package/dist/lib/cloud-abort.js +13 -0
- package/dist/lib/cloud-abort.js.map +1 -0
- package/dist/lib/cloud-auth.d.ts +28 -0
- package/dist/lib/cloud-auth.d.ts.map +1 -0
- package/dist/lib/cloud-auth.js +169 -0
- package/dist/lib/cloud-auth.js.map +1 -0
- package/dist/lib/cloud-config.d.ts +21 -0
- package/dist/lib/cloud-config.d.ts.map +1 -0
- package/dist/lib/cloud-config.js +76 -0
- package/dist/lib/cloud-config.js.map +1 -0
- package/dist/lib/cloud-provision.d.ts +20 -0
- package/dist/lib/cloud-provision.d.ts.map +1 -0
- package/dist/lib/cloud-provision.js +55 -0
- package/dist/lib/cloud-provision.js.map +1 -0
- package/dist/lib/cloud-setup-login.d.ts +9 -0
- package/dist/lib/cloud-setup-login.d.ts.map +1 -0
- package/dist/lib/cloud-setup-login.js +137 -0
- package/dist/lib/cloud-setup-login.js.map +1 -0
- package/dist/lib/cloud-url.d.ts +2 -0
- package/dist/lib/cloud-url.d.ts.map +1 -0
- package/dist/lib/cloud-url.js +14 -0
- package/dist/lib/cloud-url.js.map +1 -0
- package/dist/lib/create-project.d.ts +0 -9
- package/dist/lib/create-project.d.ts.map +1 -1
- package/dist/lib/create-project.js +15 -46
- package/dist/lib/create-project.js.map +1 -1
- package/dist/lib/transform.d.ts +0 -4
- package/dist/lib/transform.d.ts.map +1 -1
- package/dist/lib/transform.js +8 -17
- package/dist/lib/transform.js.map +1 -1
- package/dist/lib/utils/download.d.ts +5 -0
- package/dist/lib/utils/download.d.ts.map +1 -0
- package/dist/lib/utils/download.js +41 -0
- package/dist/lib/utils/download.js.map +1 -0
- package/dist/lib/utils/file-scanner.d.ts +0 -1
- package/dist/lib/utils/file-scanner.d.ts.map +1 -1
- package/dist/lib/utils/file-scanner.js +1 -16
- package/dist/lib/utils/file-scanner.js.map +1 -1
- package/dist/lib/utils/package-manager.d.ts +7 -0
- package/dist/lib/utils/package-manager.d.ts.map +1 -1
- package/dist/lib/utils/package-manager.js +15 -1
- package/dist/lib/utils/package-manager.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +2 -1
- package/dist/program.js.map +1 -1
- package/package.json +12 -8
- package/src/commands/add.ts +2 -1
- package/src/commands/cloud.test.ts +238 -0
- package/src/commands/cloud.ts +455 -0
- package/src/commands/create.ts +13 -3
- package/src/commands/init.ts +5 -2
- package/src/commands/mcp.ts +223 -56
- package/src/lib/agent-skill.ts +18 -44
- package/src/lib/cloud-abort.ts +12 -0
- package/src/lib/cloud-auth.test.ts +500 -0
- package/src/lib/cloud-auth.ts +273 -0
- package/src/lib/cloud-config.test.ts +82 -0
- package/src/lib/cloud-config.ts +138 -0
- package/src/lib/cloud-provision.test.ts +132 -0
- package/src/lib/cloud-provision.ts +93 -0
- package/src/lib/cloud-setup-login.test.ts +361 -0
- package/src/lib/cloud-setup-login.ts +240 -0
- package/src/lib/cloud-url.ts +19 -0
- package/src/lib/create-project.test.ts +0 -17
- package/src/lib/create-project.ts +33 -98
- package/src/lib/transform-files.test.ts +1 -3
- package/src/lib/transform.ts +6 -20
- package/src/lib/utils/download.ts +57 -0
- package/src/lib/utils/file-scanner.ts +0 -26
- package/src/lib/utils/package-manager.ts +26 -0
- package/src/lib/utils/registry.test.ts +0 -6
- package/src/program.ts +2 -0
- package/templates/cloud-harness/.assistant-ui/template.json +3 -0
- package/templates/cloud-harness/.env.example +1 -0
- package/templates/cloud-harness/.gitignore +42 -0
- package/templates/cloud-harness/README.md +28 -0
- package/templates/cloud-harness/app/api/chat/route.ts +14 -0
- package/templates/cloud-harness/app/api/credential/route.ts +14 -0
- package/templates/cloud-harness/app/assistant.tsx +83 -0
- package/templates/cloud-harness/app/favicon.ico +0 -0
- package/templates/cloud-harness/app/globals.css +139 -0
- package/templates/cloud-harness/app/layout.tsx +37 -0
- package/templates/cloud-harness/app/page.tsx +5 -0
- package/templates/cloud-harness/components/assistant-ui/elements/attachment.aui.tsx +279 -0
- package/templates/cloud-harness/components/assistant-ui/elements/collapsible-root.tsx +19 -0
- package/templates/cloud-harness/components/assistant-ui/elements/markdown-text.tsx +238 -0
- package/templates/cloud-harness/components/assistant-ui/elements/thread.aui.tsx +521 -0
- package/templates/cloud-harness/components/assistant-ui/elements/tool-fallback.aui.tsx +1321 -0
- package/templates/cloud-harness/components/assistant-ui/elements/tooltip-icon-button.tsx +49 -0
- package/templates/cloud-harness/components/ui/avatar.tsx +109 -0
- package/templates/cloud-harness/components/ui/button.tsx +58 -0
- package/templates/cloud-harness/components/ui/collapsible.tsx +21 -0
- package/templates/cloud-harness/components/ui/dialog.tsx +159 -0
- package/templates/cloud-harness/components/ui/textarea.tsx +18 -0
- package/templates/cloud-harness/components/ui/tooltip.tsx +69 -0
- package/templates/cloud-harness/components.json +24 -0
- package/templates/cloud-harness/hooks/use-attachment-src.ts +46 -0
- package/templates/cloud-harness/hooks/use-copy-to-clipboard.ts +54 -0
- package/templates/cloud-harness/lib/utils.ts +1 -0
- package/templates/cloud-harness/next.config.ts +6 -0
- package/templates/cloud-harness/package.json +51 -0
- package/templates/cloud-harness/postcss.config.mjs +5 -0
- package/templates/cloud-harness/tsconfig.json +33 -0
- package/templates/cloud-harness/vendor/README.md +13 -0
- package/templates/cloud-harness/vendor/assistant-ui-react-harness-sdk-0.0.2.tgz +0 -0
- package/templates/cloud-harness/vendor/harness-sdk-0.3.1.tgz +0 -0
- package/templates/cloud-harness/vendor/provenance.json +38 -0
- package/templates/cloud-harness/vendor/statewire-0.19.3.tgz +0 -0
- /package/{LICENSE → templates/cloud-harness/vendor/LICENSE} +0 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComposerAddAttachment,
|
|
3
|
+
ComposerAttachments,
|
|
4
|
+
UserMessageAttachments,
|
|
5
|
+
} from "@/components/assistant-ui/elements/attachment.aui";
|
|
6
|
+
import { MarkdownText } from "@/components/assistant-ui/elements/markdown-text";
|
|
7
|
+
import { ToolFallback } from "@/components/assistant-ui/elements/tool-fallback.aui";
|
|
8
|
+
import { TooltipIconButton } from "@/components/assistant-ui/elements/tooltip-icon-button";
|
|
9
|
+
import { Button } from "@/components/ui/button";
|
|
10
|
+
import { cn } from "@/lib/utils";
|
|
11
|
+
import {
|
|
12
|
+
ActionBarMorePrimitive,
|
|
13
|
+
ActionBarPrimitive,
|
|
14
|
+
AuiIf,
|
|
15
|
+
type AssistantState,
|
|
16
|
+
BranchPickerPrimitive,
|
|
17
|
+
ComposerPrimitive,
|
|
18
|
+
ErrorPrimitive,
|
|
19
|
+
MessagePrimitive,
|
|
20
|
+
SuggestionPrimitive,
|
|
21
|
+
ThreadPrimitive,
|
|
22
|
+
useAuiState,
|
|
23
|
+
} from "@assistant-ui/react";
|
|
24
|
+
import {
|
|
25
|
+
ArrowDownIcon,
|
|
26
|
+
ArrowUpIcon,
|
|
27
|
+
CheckIcon,
|
|
28
|
+
ChevronLeftIcon,
|
|
29
|
+
ChevronRightIcon,
|
|
30
|
+
CopyIcon,
|
|
31
|
+
DownloadIcon,
|
|
32
|
+
MicIcon,
|
|
33
|
+
MoreHorizontalIcon,
|
|
34
|
+
PencilIcon,
|
|
35
|
+
RefreshCwIcon,
|
|
36
|
+
SquareIcon,
|
|
37
|
+
} from "lucide-react";
|
|
38
|
+
import type { FC } from "react";
|
|
39
|
+
|
|
40
|
+
// Startup exposes a loading placeholder thread; treat it as a new chat so
|
|
41
|
+
// the composer mounts centered. Loads after startup keep the docked layout.
|
|
42
|
+
const isNewChatView = (s: AssistantState) =>
|
|
43
|
+
s.thread.messages.length === 0 &&
|
|
44
|
+
(!s.thread.isLoading || s.threads.isLoading);
|
|
45
|
+
|
|
46
|
+
// A switched thread that is still fetching its history: skeleton, not welcome.
|
|
47
|
+
const isHistoryLoadingView = (s: AssistantState) =>
|
|
48
|
+
s.thread.messages.length === 0 &&
|
|
49
|
+
s.thread.isLoading &&
|
|
50
|
+
!s.thread.isDisabled &&
|
|
51
|
+
!s.threads.isLoading;
|
|
52
|
+
|
|
53
|
+
const ThreadHistorySkeleton: FC = () => (
|
|
54
|
+
<div
|
|
55
|
+
data-slot="aui_thread-history-skeleton"
|
|
56
|
+
role="status"
|
|
57
|
+
className="animate-in fade-in fill-mode-both flex flex-col [animation-delay:150ms] [animation-duration:200ms]"
|
|
58
|
+
>
|
|
59
|
+
<span className="sr-only">Loading conversation</span>
|
|
60
|
+
<div className="flex animate-pulse flex-col gap-y-6 motion-reduce:animate-none">
|
|
61
|
+
<div className="bg-muted ml-auto h-9 w-2/5 rounded-xl" />
|
|
62
|
+
<div className="flex flex-col gap-y-2">
|
|
63
|
+
<div className="bg-muted h-4 w-11/12 rounded-md" />
|
|
64
|
+
<div className="bg-muted h-4 w-4/5 rounded-md" />
|
|
65
|
+
<div className="bg-muted h-4 w-3/5 rounded-md" />
|
|
66
|
+
</div>
|
|
67
|
+
<div className="bg-muted ml-auto h-9 w-1/3 rounded-xl" />
|
|
68
|
+
<div className="flex flex-col gap-y-2">
|
|
69
|
+
<div className="bg-muted h-4 w-10/12 rounded-md" />
|
|
70
|
+
<div className="bg-muted h-4 w-2/3 rounded-md" />
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
export const Thread: FC = () => {
|
|
77
|
+
const isEmpty = useAuiState(isNewChatView);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<ThreadPrimitive.Root
|
|
81
|
+
className="aui-root aui-thread-root bg-background @container flex h-full flex-col"
|
|
82
|
+
style={{
|
|
83
|
+
["--thread-max-width" as string]: "44rem",
|
|
84
|
+
["--composer-bg" as string]:
|
|
85
|
+
"color-mix(in oklab, var(--color-muted) 30%, transparent)",
|
|
86
|
+
["--composer-radius" as string]: "1rem",
|
|
87
|
+
["--composer-padding" as string]: "8px",
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
<ThreadPrimitive.Viewport
|
|
91
|
+
turnAnchor="top"
|
|
92
|
+
data-slot="aui_thread-viewport"
|
|
93
|
+
className="relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth"
|
|
94
|
+
>
|
|
95
|
+
<div
|
|
96
|
+
className={cn(
|
|
97
|
+
"mx-auto flex w-full max-w-(--thread-max-width) flex-1 flex-col px-4 pt-4",
|
|
98
|
+
isEmpty && "justify-center",
|
|
99
|
+
)}
|
|
100
|
+
>
|
|
101
|
+
<AuiIf condition={isNewChatView}>
|
|
102
|
+
<ThreadWelcome />
|
|
103
|
+
</AuiIf>
|
|
104
|
+
<AuiIf condition={isHistoryLoadingView}>
|
|
105
|
+
<ThreadHistorySkeleton />
|
|
106
|
+
</AuiIf>
|
|
107
|
+
|
|
108
|
+
<div
|
|
109
|
+
data-slot="aui_message-group"
|
|
110
|
+
className="mb-14 flex flex-col gap-y-6 empty:hidden"
|
|
111
|
+
>
|
|
112
|
+
<ThreadPrimitive.Messages>
|
|
113
|
+
{() => <ThreadMessage />}
|
|
114
|
+
</ThreadPrimitive.Messages>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<ThreadPrimitive.ViewportFooter
|
|
118
|
+
className={cn(
|
|
119
|
+
"aui-thread-viewport-footer bg-background flex flex-col gap-4 overflow-visible pb-4 md:pb-6",
|
|
120
|
+
!isEmpty &&
|
|
121
|
+
"sticky bottom-0 mt-auto rounded-t-(--composer-radius)",
|
|
122
|
+
)}
|
|
123
|
+
>
|
|
124
|
+
<ThreadScrollToBottom />
|
|
125
|
+
<Composer />
|
|
126
|
+
<AuiIf condition={(s) => isNewChatView(s) && s.composer.isEmpty}>
|
|
127
|
+
<ThreadSuggestions />
|
|
128
|
+
</AuiIf>
|
|
129
|
+
</ThreadPrimitive.ViewportFooter>
|
|
130
|
+
</div>
|
|
131
|
+
</ThreadPrimitive.Viewport>
|
|
132
|
+
</ThreadPrimitive.Root>
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const ThreadMessage: FC = () => {
|
|
137
|
+
const role = useAuiState((s) => s.message.role);
|
|
138
|
+
const isEditing = useAuiState((s) => s.message.composer.isEditing);
|
|
139
|
+
|
|
140
|
+
if (isEditing) return <EditComposer />;
|
|
141
|
+
if (role === "user") return <UserMessage />;
|
|
142
|
+
return <AssistantMessage />;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const ThreadScrollToBottom: FC = () => {
|
|
146
|
+
return (
|
|
147
|
+
<ThreadPrimitive.ScrollToBottom asChild>
|
|
148
|
+
<TooltipIconButton
|
|
149
|
+
tooltip="Scroll to bottom"
|
|
150
|
+
variant="outline"
|
|
151
|
+
className="aui-thread-scroll-to-bottom dark:border-border dark:bg-background dark:hover:bg-accent absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible"
|
|
152
|
+
>
|
|
153
|
+
<ArrowDownIcon />
|
|
154
|
+
</TooltipIconButton>
|
|
155
|
+
</ThreadPrimitive.ScrollToBottom>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const ThreadWelcome: FC = () => {
|
|
160
|
+
return (
|
|
161
|
+
<div className="aui-thread-welcome-root mb-6 flex flex-col px-2">
|
|
162
|
+
<p className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-2xl font-medium tracking-tight duration-200">
|
|
163
|
+
How can I help you today?
|
|
164
|
+
</p>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const ThreadSuggestions: FC = () => {
|
|
170
|
+
return (
|
|
171
|
+
<div className="aui-thread-welcome-suggestions flex w-full flex-col">
|
|
172
|
+
<ThreadPrimitive.Suggestions>
|
|
173
|
+
{() => <ThreadSuggestionItem />}
|
|
174
|
+
</ThreadPrimitive.Suggestions>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const ThreadSuggestionItem: FC = () => {
|
|
180
|
+
return (
|
|
181
|
+
<div className="aui-thread-welcome-suggestion-display fade-in slide-in-from-bottom-2 animate-in fill-mode-both duration-200">
|
|
182
|
+
<SuggestionPrimitive.Trigger send asChild>
|
|
183
|
+
<button
|
|
184
|
+
type="button"
|
|
185
|
+
className="aui-thread-welcome-suggestion group hover:bg-foreground/[0.03] focus-visible:ring-ring/50 flex w-full items-baseline gap-2.5 rounded-md px-2 py-2 text-start text-sm transition-colors outline-none focus-visible:ring-1 motion-reduce:transition-none"
|
|
186
|
+
>
|
|
187
|
+
<span
|
|
188
|
+
aria-hidden
|
|
189
|
+
className="text-muted-foreground/60 group-hover:text-foreground font-mono text-xs transition-colors motion-reduce:transition-none"
|
|
190
|
+
>
|
|
191
|
+
{">"}
|
|
192
|
+
</span>
|
|
193
|
+
<span className="min-w-0 flex-1 truncate">
|
|
194
|
+
<SuggestionPrimitive.Title className="aui-thread-welcome-suggestion-text-1 text-foreground" />{" "}
|
|
195
|
+
<SuggestionPrimitive.Description className="aui-thread-welcome-suggestion-text-2 text-muted-foreground empty:hidden" />
|
|
196
|
+
</span>
|
|
197
|
+
</button>
|
|
198
|
+
</SuggestionPrimitive.Trigger>
|
|
199
|
+
</div>
|
|
200
|
+
);
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const Composer: FC = () => {
|
|
204
|
+
return (
|
|
205
|
+
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
|
|
206
|
+
<ComposerPrimitive.AttachmentDropzone asChild>
|
|
207
|
+
<div
|
|
208
|
+
data-slot="aui_composer-shell"
|
|
209
|
+
className="border-foreground/10 focus-within:border-foreground/25 data-[dragging=true]:border-ring flex w-full cursor-text flex-col gap-2 rounded-(--composer-radius) border bg-(--composer-bg) p-(--composer-padding) transition-[border-color] data-[dragging=true]:border-dashed data-[dragging=true]:bg-[color-mix(in_oklab,var(--color-accent)_50%,var(--color-background))]"
|
|
210
|
+
>
|
|
211
|
+
<ComposerAttachments />
|
|
212
|
+
<ComposerPrimitive.Input
|
|
213
|
+
placeholder="Send a message..."
|
|
214
|
+
className="aui-composer-input placeholder:text-muted-foreground/60 max-h-48 min-h-10 w-full resize-none bg-transparent px-2.5 py-1 text-base leading-6 outline-none"
|
|
215
|
+
rows={1}
|
|
216
|
+
autoFocus
|
|
217
|
+
aria-label="Message input"
|
|
218
|
+
/>
|
|
219
|
+
<ComposerAction />
|
|
220
|
+
</div>
|
|
221
|
+
</ComposerPrimitive.AttachmentDropzone>
|
|
222
|
+
</ComposerPrimitive.Root>
|
|
223
|
+
);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const ComposerAction: FC = () => {
|
|
227
|
+
// The stop control only cancels the send while no run it could stop is going.
|
|
228
|
+
const isSending = useAuiState(
|
|
229
|
+
(s) =>
|
|
230
|
+
s.composer.submission !== undefined &&
|
|
231
|
+
!(s.thread.isRunning && s.thread.capabilities.cancel),
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<div className="aui-composer-action-wrapper relative flex items-center justify-between">
|
|
236
|
+
<ComposerAddAttachment />
|
|
237
|
+
<div className="flex items-center gap-1.5">
|
|
238
|
+
<AuiIf condition={(s) => s.thread.capabilities.dictation}>
|
|
239
|
+
<AuiIf condition={(s) => s.composer.dictation == null}>
|
|
240
|
+
<ComposerPrimitive.Dictate asChild>
|
|
241
|
+
<TooltipIconButton
|
|
242
|
+
tooltip="Voice input"
|
|
243
|
+
side="bottom"
|
|
244
|
+
type="button"
|
|
245
|
+
variant="ghost"
|
|
246
|
+
size="icon"
|
|
247
|
+
className="aui-composer-dictate text-muted-foreground hover:text-foreground size-7 rounded-full"
|
|
248
|
+
aria-label="Start voice input"
|
|
249
|
+
>
|
|
250
|
+
<MicIcon className="aui-composer-dictate-icon size-4" />
|
|
251
|
+
</TooltipIconButton>
|
|
252
|
+
</ComposerPrimitive.Dictate>
|
|
253
|
+
</AuiIf>
|
|
254
|
+
<AuiIf condition={(s) => s.composer.dictation != null}>
|
|
255
|
+
<ComposerPrimitive.StopDictation asChild>
|
|
256
|
+
<TooltipIconButton
|
|
257
|
+
tooltip="Stop dictation"
|
|
258
|
+
side="bottom"
|
|
259
|
+
type="button"
|
|
260
|
+
variant="ghost"
|
|
261
|
+
size="icon"
|
|
262
|
+
className="aui-composer-stop-dictation text-destructive size-7 rounded-full"
|
|
263
|
+
aria-label="Stop voice input"
|
|
264
|
+
>
|
|
265
|
+
<SquareIcon className="aui-composer-stop-dictation-icon size-3.5 animate-pulse fill-current" />
|
|
266
|
+
</TooltipIconButton>
|
|
267
|
+
</ComposerPrimitive.StopDictation>
|
|
268
|
+
</AuiIf>
|
|
269
|
+
</AuiIf>
|
|
270
|
+
<AuiIf
|
|
271
|
+
condition={(s) =>
|
|
272
|
+
!s.composer.canCancel ||
|
|
273
|
+
(s.thread.voice !== undefined &&
|
|
274
|
+
s.composer.submission === undefined)
|
|
275
|
+
}
|
|
276
|
+
>
|
|
277
|
+
<ComposerPrimitive.Send asChild>
|
|
278
|
+
<TooltipIconButton
|
|
279
|
+
tooltip="Send message"
|
|
280
|
+
side="bottom"
|
|
281
|
+
type="button"
|
|
282
|
+
variant="default"
|
|
283
|
+
size="icon"
|
|
284
|
+
className="aui-composer-send size-7 rounded-full"
|
|
285
|
+
aria-label="Send message"
|
|
286
|
+
>
|
|
287
|
+
<ArrowUpIcon className="aui-composer-send-icon size-4" />
|
|
288
|
+
</TooltipIconButton>
|
|
289
|
+
</ComposerPrimitive.Send>
|
|
290
|
+
</AuiIf>
|
|
291
|
+
<AuiIf
|
|
292
|
+
condition={(s) =>
|
|
293
|
+
s.composer.canCancel &&
|
|
294
|
+
(s.thread.voice === undefined ||
|
|
295
|
+
s.composer.submission !== undefined)
|
|
296
|
+
}
|
|
297
|
+
>
|
|
298
|
+
<ComposerPrimitive.Cancel asChild>
|
|
299
|
+
<Button
|
|
300
|
+
type="button"
|
|
301
|
+
variant="default"
|
|
302
|
+
size="icon"
|
|
303
|
+
className="aui-composer-cancel size-7 rounded-full"
|
|
304
|
+
aria-label={isSending ? "Cancel sending" : "Stop generating"}
|
|
305
|
+
>
|
|
306
|
+
<SquareIcon className="aui-composer-cancel-icon size-3.5 fill-current" />
|
|
307
|
+
</Button>
|
|
308
|
+
</ComposerPrimitive.Cancel>
|
|
309
|
+
</AuiIf>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
);
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const MessageError: FC = () => {
|
|
316
|
+
return (
|
|
317
|
+
<MessagePrimitive.Error>
|
|
318
|
+
<ErrorPrimitive.Root className="aui-message-error-root border-destructive bg-destructive/10 text-destructive dark:bg-destructive/5 mt-2 rounded-md border p-3 text-sm dark:text-red-200">
|
|
319
|
+
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
|
|
320
|
+
</ErrorPrimitive.Root>
|
|
321
|
+
</MessagePrimitive.Error>
|
|
322
|
+
);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const AssistantMessage: FC = () => {
|
|
326
|
+
const ACTION_BAR_PT = "pt-1.5";
|
|
327
|
+
const ACTION_BAR_HEIGHT = `min-h-7.5 ${ACTION_BAR_PT}`;
|
|
328
|
+
|
|
329
|
+
return (
|
|
330
|
+
<MessagePrimitive.Root
|
|
331
|
+
data-slot="aui_assistant-message-root"
|
|
332
|
+
data-role="assistant"
|
|
333
|
+
className="fade-in slide-in-from-bottom-1 animate-in relative -mb-7.5 pb-7.5 duration-150 [contain-intrinsic-size:auto_200px] [content-visibility:auto]"
|
|
334
|
+
>
|
|
335
|
+
<div
|
|
336
|
+
data-slot="aui_assistant-message-content"
|
|
337
|
+
className="text-foreground px-2 leading-relaxed wrap-break-word"
|
|
338
|
+
>
|
|
339
|
+
<MessagePrimitive.Parts>
|
|
340
|
+
{({ part }) => {
|
|
341
|
+
if (part.type === "text") return <MarkdownText />;
|
|
342
|
+
if (part.type === "tool-call")
|
|
343
|
+
return part.toolUI ?? <ToolFallback {...part} />;
|
|
344
|
+
return null;
|
|
345
|
+
}}
|
|
346
|
+
</MessagePrimitive.Parts>
|
|
347
|
+
<AuiIf
|
|
348
|
+
condition={(s) =>
|
|
349
|
+
s.message.status?.type === "running" && s.message.parts.length === 0
|
|
350
|
+
}
|
|
351
|
+
>
|
|
352
|
+
<span
|
|
353
|
+
data-slot="aui_assistant-message-indicator"
|
|
354
|
+
className="animate-pulse font-sans"
|
|
355
|
+
aria-label="Assistant is working"
|
|
356
|
+
>
|
|
357
|
+
{"●"}
|
|
358
|
+
</span>
|
|
359
|
+
</AuiIf>
|
|
360
|
+
<MessageError />
|
|
361
|
+
</div>
|
|
362
|
+
|
|
363
|
+
<div
|
|
364
|
+
data-slot="aui_assistant-message-footer"
|
|
365
|
+
className={cn("ms-2 flex items-center", ACTION_BAR_HEIGHT)}
|
|
366
|
+
>
|
|
367
|
+
<BranchPicker />
|
|
368
|
+
<AssistantActionBar />
|
|
369
|
+
</div>
|
|
370
|
+
</MessagePrimitive.Root>
|
|
371
|
+
);
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
const AssistantActionBar: FC = () => {
|
|
375
|
+
return (
|
|
376
|
+
<ActionBarPrimitive.Root
|
|
377
|
+
hideWhenRunning
|
|
378
|
+
autohide="not-last"
|
|
379
|
+
className="aui-assistant-action-bar-root text-muted-foreground animate-in fade-in col-start-3 row-start-2 -ms-1 flex gap-1 duration-200"
|
|
380
|
+
>
|
|
381
|
+
<ActionBarPrimitive.Copy asChild>
|
|
382
|
+
<TooltipIconButton tooltip="Copy">
|
|
383
|
+
<AuiIf condition={(s) => s.message.isCopied}>
|
|
384
|
+
<CheckIcon className="animate-in zoom-in-50 fade-in duration-200 ease-out" />
|
|
385
|
+
</AuiIf>
|
|
386
|
+
<AuiIf condition={(s) => !s.message.isCopied}>
|
|
387
|
+
<CopyIcon className="animate-in zoom-in-75 fade-in duration-150" />
|
|
388
|
+
</AuiIf>
|
|
389
|
+
</TooltipIconButton>
|
|
390
|
+
</ActionBarPrimitive.Copy>
|
|
391
|
+
<ActionBarPrimitive.Reload asChild>
|
|
392
|
+
<TooltipIconButton tooltip="Refresh">
|
|
393
|
+
<RefreshCwIcon />
|
|
394
|
+
</TooltipIconButton>
|
|
395
|
+
</ActionBarPrimitive.Reload>
|
|
396
|
+
<ActionBarMorePrimitive.Root>
|
|
397
|
+
<ActionBarMorePrimitive.Trigger asChild>
|
|
398
|
+
<TooltipIconButton
|
|
399
|
+
tooltip="More"
|
|
400
|
+
className="data-[state=open]:bg-accent"
|
|
401
|
+
>
|
|
402
|
+
<MoreHorizontalIcon />
|
|
403
|
+
</TooltipIconButton>
|
|
404
|
+
</ActionBarMorePrimitive.Trigger>
|
|
405
|
+
<ActionBarMorePrimitive.Content
|
|
406
|
+
side="bottom"
|
|
407
|
+
align="start"
|
|
408
|
+
sideOffset={6}
|
|
409
|
+
className="aui-action-bar-more-content bg-popover/95 text-popover-foreground data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=closed]:animate-out 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 min-w-[8rem] overflow-hidden rounded-xl border p-1.5 shadow-lg backdrop-blur-sm"
|
|
410
|
+
>
|
|
411
|
+
<ActionBarPrimitive.ExportMarkdown asChild>
|
|
412
|
+
<ActionBarMorePrimitive.Item className="aui-action-bar-more-item hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-sm outline-none select-none">
|
|
413
|
+
<DownloadIcon className="size-4" />
|
|
414
|
+
Export as Markdown
|
|
415
|
+
</ActionBarMorePrimitive.Item>
|
|
416
|
+
</ActionBarPrimitive.ExportMarkdown>
|
|
417
|
+
</ActionBarMorePrimitive.Content>
|
|
418
|
+
</ActionBarMorePrimitive.Root>
|
|
419
|
+
</ActionBarPrimitive.Root>
|
|
420
|
+
);
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const UserMessage: FC = () => {
|
|
424
|
+
return (
|
|
425
|
+
<MessagePrimitive.Root
|
|
426
|
+
data-slot="aui_user-message-root"
|
|
427
|
+
className="fade-in slide-in-from-bottom-1 animate-in grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] content-start gap-y-2 px-2 duration-150 [contain-intrinsic-size:auto_200px] [content-visibility:auto] [&:where(>*)]:col-start-2"
|
|
428
|
+
data-role="user"
|
|
429
|
+
>
|
|
430
|
+
<UserMessageAttachments />
|
|
431
|
+
|
|
432
|
+
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
|
|
433
|
+
<div className="aui-user-message-content peer bg-muted text-foreground rounded-(--composer-radius) px-4 py-2 wrap-break-word empty:hidden">
|
|
434
|
+
<MessagePrimitive.Parts />
|
|
435
|
+
</div>
|
|
436
|
+
<div className="aui-user-action-bar-wrapper absolute start-0 top-1/2 -translate-x-full -translate-y-1/2 pe-2 peer-empty:hidden rtl:translate-x-full">
|
|
437
|
+
<UserActionBar />
|
|
438
|
+
</div>
|
|
439
|
+
</div>
|
|
440
|
+
|
|
441
|
+
<BranchPicker
|
|
442
|
+
data-slot="aui_user-branch-picker"
|
|
443
|
+
className="col-span-full col-start-1 -me-1 justify-end"
|
|
444
|
+
/>
|
|
445
|
+
</MessagePrimitive.Root>
|
|
446
|
+
);
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const UserActionBar: FC = () => {
|
|
450
|
+
return (
|
|
451
|
+
<ActionBarPrimitive.Root
|
|
452
|
+
hideWhenRunning
|
|
453
|
+
autohide="not-last"
|
|
454
|
+
className="aui-user-action-bar-root flex flex-col items-end"
|
|
455
|
+
>
|
|
456
|
+
<ActionBarPrimitive.Edit asChild>
|
|
457
|
+
<TooltipIconButton tooltip="Edit" className="aui-user-action-edit">
|
|
458
|
+
<PencilIcon />
|
|
459
|
+
</TooltipIconButton>
|
|
460
|
+
</ActionBarPrimitive.Edit>
|
|
461
|
+
</ActionBarPrimitive.Root>
|
|
462
|
+
);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const EditComposer: FC = () => {
|
|
466
|
+
return (
|
|
467
|
+
<MessagePrimitive.Root
|
|
468
|
+
data-slot="aui_edit-composer-wrapper"
|
|
469
|
+
className="flex flex-col px-2 [contain-intrinsic-size:auto_200px] [content-visibility:auto]"
|
|
470
|
+
>
|
|
471
|
+
<ComposerPrimitive.Root className="aui-edit-composer-root border-foreground/10 focus-within:border-foreground/25 ms-auto flex w-full max-w-[85%] cursor-text flex-col rounded-(--composer-radius) border bg-(--composer-bg) shadow-[0_4px_16px_-8px_rgba(0,0,0,0.08),0_1px_2px_rgba(0,0,0,0.04)] transition-[border-color] dark:shadow-none">
|
|
472
|
+
<ComposerPrimitive.Input
|
|
473
|
+
className="aui-edit-composer-input text-foreground min-h-14 w-full resize-none bg-transparent px-4 pt-3 pb-1 text-base outline-none"
|
|
474
|
+
autoFocus
|
|
475
|
+
/>
|
|
476
|
+
<div className="aui-edit-composer-footer mx-2.5 mb-2.5 flex items-center gap-1.5 self-end">
|
|
477
|
+
<ComposerPrimitive.Cancel asChild>
|
|
478
|
+
<Button variant="ghost" size="sm" className="h-8 px-3">
|
|
479
|
+
Cancel
|
|
480
|
+
</Button>
|
|
481
|
+
</ComposerPrimitive.Cancel>
|
|
482
|
+
<ComposerPrimitive.Send asChild>
|
|
483
|
+
<Button size="sm" className="h-8 px-3">
|
|
484
|
+
Update
|
|
485
|
+
</Button>
|
|
486
|
+
</ComposerPrimitive.Send>
|
|
487
|
+
</div>
|
|
488
|
+
</ComposerPrimitive.Root>
|
|
489
|
+
</MessagePrimitive.Root>
|
|
490
|
+
);
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
494
|
+
className,
|
|
495
|
+
...rest
|
|
496
|
+
}) => {
|
|
497
|
+
return (
|
|
498
|
+
<BranchPickerPrimitive.Root
|
|
499
|
+
hideWhenSingleBranch
|
|
500
|
+
className={cn(
|
|
501
|
+
"aui-branch-picker-root text-muted-foreground -ms-2 me-2 inline-flex items-center text-xs",
|
|
502
|
+
className,
|
|
503
|
+
)}
|
|
504
|
+
{...rest}
|
|
505
|
+
>
|
|
506
|
+
<BranchPickerPrimitive.Previous asChild>
|
|
507
|
+
<TooltipIconButton tooltip="Previous">
|
|
508
|
+
<ChevronLeftIcon />
|
|
509
|
+
</TooltipIconButton>
|
|
510
|
+
</BranchPickerPrimitive.Previous>
|
|
511
|
+
<span className="aui-branch-picker-state font-medium">
|
|
512
|
+
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
|
513
|
+
</span>
|
|
514
|
+
<BranchPickerPrimitive.Next asChild>
|
|
515
|
+
<TooltipIconButton tooltip="Next">
|
|
516
|
+
<ChevronRightIcon />
|
|
517
|
+
</TooltipIconButton>
|
|
518
|
+
</BranchPickerPrimitive.Next>
|
|
519
|
+
</BranchPickerPrimitive.Root>
|
|
520
|
+
);
|
|
521
|
+
};
|