@applica-software-guru/persona-sdk 0.1.79 → 0.1.82
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/components.json +5 -2
- package/dist/bundle.cjs.js +23 -19
- package/dist/bundle.cjs.js.map +1 -1
- package/dist/bundle.es.js +7132 -3178
- package/dist/bundle.es.js.map +1 -1
- package/dist/bundle.iife.js +23 -19
- package/dist/bundle.iife.js.map +1 -1
- package/dist/bundle.umd.js +23 -19
- package/dist/bundle.umd.js.map +1 -1
- package/dist/messages.d.ts.map +1 -1
- package/package.json +8 -9
- package/playground/src/components/assistant-ui/attachment.tsx +72 -89
- package/playground/src/components/assistant-ui/markdown-text.tsx +139 -34
- package/playground/src/components/assistant-ui/thread.tsx +238 -235
- package/playground/src/components/assistant-ui/tool-fallback.tsx +79 -19
- package/playground/src/components/assistant-ui/tooltip-icon-button.tsx +35 -31
- package/playground/src/components/ui/avatar.tsx +46 -30
- package/playground/src/components/ui/button.tsx +45 -28
- package/playground/src/components/ui/dialog.tsx +13 -5
- package/playground/src/components/ui/tooltip.tsx +54 -25
- package/src/messages.ts +13 -5
|
@@ -1,121 +1,66 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
import {
|
|
3
|
-
ActionBarPrimitive,
|
|
4
|
-
BranchPickerPrimitive,
|
|
5
|
-
ComposerPrimitive,
|
|
6
|
-
FileContentPart,
|
|
7
|
-
ImageContentPart,
|
|
8
|
-
MessagePrimitive,
|
|
9
|
-
ReasoningContentPartProps,
|
|
10
|
-
ThreadPrimitive,
|
|
11
|
-
} from '@assistant-ui/react';
|
|
12
|
-
import { JSX, useCallback, useMemo, useState, type FC } from 'react';
|
|
13
1
|
import {
|
|
14
2
|
ArrowDownIcon,
|
|
3
|
+
ArrowUpIcon,
|
|
15
4
|
CheckIcon,
|
|
16
5
|
ChevronLeftIcon,
|
|
17
6
|
ChevronRightIcon,
|
|
18
7
|
CopyIcon,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
ArchiveIcon,
|
|
24
|
-
ChevronUpIcon,
|
|
25
|
-
LightbulbIcon,
|
|
26
|
-
ChevronDownIcon,
|
|
27
|
-
} from 'lucide-react';
|
|
28
|
-
import { cn } from '@/lib/utils';
|
|
29
|
-
|
|
30
|
-
import { Button } from '@/components/ui/button';
|
|
31
|
-
import { MarkdownText } from '@/components/assistant-ui/markdown-text';
|
|
32
|
-
import { TooltipIconButton } from '@/components/assistant-ui/tooltip-icon-button';
|
|
33
|
-
import { ToolFallback } from '@/components/assistant-ui/tool-fallback';
|
|
34
|
-
|
|
35
|
-
import { usePersonaRuntimeEndpoint, usePersonaRuntimeWebRTCProtocol } from '@applica-software-guru/persona-sdk';
|
|
36
|
-
import { ComposerAddAttachment, ComposerAttachments, UserMessageAttachments } from './attachment';
|
|
37
|
-
import Markdown from 'react-markdown';
|
|
38
|
-
import remarkGfm from 'remark-gfm';
|
|
8
|
+
PencilIcon,
|
|
9
|
+
RefreshCwIcon,
|
|
10
|
+
Square,
|
|
11
|
+
} from "lucide-react";
|
|
39
12
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
13
|
+
import {
|
|
14
|
+
ActionBarPrimitive,
|
|
15
|
+
BranchPickerPrimitive,
|
|
16
|
+
ComposerPrimitive,
|
|
17
|
+
ErrorPrimitive,
|
|
18
|
+
MessagePrimitive,
|
|
19
|
+
ThreadPrimitive,
|
|
20
|
+
} from "@assistant-ui/react";
|
|
43
21
|
|
|
44
|
-
|
|
45
|
-
const matches = [...text.matchAll(regex)];
|
|
46
|
-
let title = matches.length > 0 ? matches[matches.length - 1][1] : 'Thinking';
|
|
47
|
-
if (isThinking) {
|
|
48
|
-
title = `${title}...`;
|
|
49
|
-
} else {
|
|
50
|
-
title = `Done thinking!`;
|
|
51
|
-
}
|
|
52
|
-
const rest = text;
|
|
22
|
+
import type { FC } from "react";
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
24
|
+
import { Button } from "@/components/ui/button";
|
|
25
|
+
import { MarkdownText } from "@/components/assistant-ui/markdown-text";
|
|
26
|
+
import { ToolFallback } from "@/components/assistant-ui/tool-fallback";
|
|
27
|
+
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
|
28
|
+
import {
|
|
29
|
+
ComposerAddAttachment,
|
|
30
|
+
ComposerAttachments,
|
|
31
|
+
UserMessageAttachments,
|
|
32
|
+
} from "@/components/assistant-ui/attachment";
|
|
60
33
|
|
|
61
|
-
|
|
62
|
-
<span className="align-bottom">
|
|
63
|
-
<span className={`text-gray-700 ${isThinking ? 'animate-pulse' : ''}`}>
|
|
64
|
-
<b>{title}</b>
|
|
65
|
-
</span>
|
|
66
|
-
{open && (
|
|
67
|
-
<div className="mt-4 border-l-2 rounded border-gray-200 pl-4 text-sm text-gray-900 flex flex-col gap-2">
|
|
68
|
-
<div className="bg-gray-100 rounded px-3 py-2">
|
|
69
|
-
<div className="whitespace-pre-wrap text-gray-900">
|
|
70
|
-
<Markdown remarkPlugins={[remarkGfm]}>{rest}</Markdown>
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
)}
|
|
75
|
-
</span>
|
|
76
|
-
</span>
|
|
34
|
+
import { cn } from "@/lib/utils";
|
|
77
35
|
|
|
78
|
-
<div className="flex-0 ml-2 flex justify-end w-auto">
|
|
79
|
-
<button
|
|
80
|
-
className="p-1 rounded hover:bg-gray-100 transition-colors"
|
|
81
|
-
aria-label={open ? 'Show reasoning' : 'Hide reasoning'}
|
|
82
|
-
onClick={() => setOpen((v) => !v)}
|
|
83
|
-
type="button"
|
|
84
|
-
>
|
|
85
|
-
{open ? <ChevronUpIcon className="size-4" /> : <ChevronDownIcon className="size-4" />}
|
|
86
|
-
</button>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
};
|
|
92
36
|
export const Thread: FC = () => {
|
|
93
37
|
return (
|
|
94
38
|
<ThreadPrimitive.Root
|
|
95
|
-
className="
|
|
39
|
+
className="aui-root aui-thread-root @container flex h-full flex-col bg-background"
|
|
96
40
|
style={{
|
|
97
|
-
[
|
|
41
|
+
["--thread-max-width" as string]: "44rem",
|
|
98
42
|
}}
|
|
99
43
|
>
|
|
100
|
-
<ThreadPrimitive.Viewport
|
|
101
|
-
|
|
44
|
+
<ThreadPrimitive.Viewport
|
|
45
|
+
turnAnchor="top"
|
|
46
|
+
className="aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll scroll-smooth px-4 pt-4"
|
|
47
|
+
>
|
|
48
|
+
<ThreadPrimitive.If empty>
|
|
49
|
+
<ThreadWelcome />
|
|
50
|
+
</ThreadPrimitive.If>
|
|
102
51
|
|
|
103
52
|
<ThreadPrimitive.Messages
|
|
104
53
|
components={{
|
|
105
|
-
UserMessage
|
|
106
|
-
EditComposer
|
|
107
|
-
AssistantMessage
|
|
54
|
+
UserMessage,
|
|
55
|
+
EditComposer,
|
|
56
|
+
AssistantMessage,
|
|
108
57
|
}}
|
|
109
58
|
/>
|
|
110
59
|
|
|
111
|
-
<ThreadPrimitive.
|
|
112
|
-
<div className="min-h-8 flex-grow" />
|
|
113
|
-
</ThreadPrimitive.If>
|
|
114
|
-
|
|
115
|
-
<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">
|
|
60
|
+
<ThreadPrimitive.ViewportFooter className="aui-thread-viewport-footer sticky bottom-0 mx-auto mt-4 flex w-full max-w-(--thread-max-width) flex-col gap-4 overflow-visible rounded-t-3xl bg-background pb-4 md:pb-6">
|
|
116
61
|
<ThreadScrollToBottom />
|
|
117
62
|
<Composer />
|
|
118
|
-
</
|
|
63
|
+
</ThreadPrimitive.ViewportFooter>
|
|
119
64
|
</ThreadPrimitive.Viewport>
|
|
120
65
|
</ThreadPrimitive.Root>
|
|
121
66
|
);
|
|
@@ -124,7 +69,11 @@ export const Thread: FC = () => {
|
|
|
124
69
|
const ThreadScrollToBottom: FC = () => {
|
|
125
70
|
return (
|
|
126
71
|
<ThreadPrimitive.ScrollToBottom asChild>
|
|
127
|
-
<TooltipIconButton
|
|
72
|
+
<TooltipIconButton
|
|
73
|
+
tooltip="Scroll to bottom"
|
|
74
|
+
variant="outline"
|
|
75
|
+
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"
|
|
76
|
+
>
|
|
128
77
|
<ArrowDownIcon />
|
|
129
78
|
</TooltipIconButton>
|
|
130
79
|
</ThreadPrimitive.ScrollToBottom>
|
|
@@ -133,175 +82,162 @@ const ThreadScrollToBottom: FC = () => {
|
|
|
133
82
|
|
|
134
83
|
const ThreadWelcome: FC = () => {
|
|
135
84
|
return (
|
|
136
|
-
<
|
|
137
|
-
<div className="
|
|
138
|
-
<div className="flex
|
|
139
|
-
<
|
|
85
|
+
<div className="aui-thread-welcome-root mx-auto my-auto flex w-full max-w-(--thread-max-width) grow flex-col">
|
|
86
|
+
<div className="aui-thread-welcome-center flex w-full grow flex-col items-center justify-center">
|
|
87
|
+
<div className="aui-thread-welcome-message flex size-full flex-col justify-center px-8">
|
|
88
|
+
<div className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-2 animate-in font-semibold text-2xl duration-300 ease-out">
|
|
89
|
+
Hello there!
|
|
90
|
+
</div>
|
|
91
|
+
<div className="aui-thread-welcome-message-inner fade-in slide-in-from-bottom-2 animate-in text-2xl text-muted-foreground/65 delay-100 duration-300 ease-out">
|
|
92
|
+
How can I help you today?
|
|
93
|
+
</div>
|
|
140
94
|
</div>
|
|
141
|
-
{/* <ThreadWelcomeSuggestions /> */}
|
|
142
95
|
</div>
|
|
143
|
-
|
|
96
|
+
<ThreadSuggestions />
|
|
97
|
+
</div>
|
|
144
98
|
);
|
|
145
99
|
};
|
|
146
100
|
|
|
147
|
-
const
|
|
101
|
+
const ThreadSuggestions: FC = () => {
|
|
148
102
|
return (
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
103
|
+
<div className="aui-thread-welcome-suggestions grid w-full @md:grid-cols-2 gap-2 pb-4">
|
|
104
|
+
{[
|
|
105
|
+
{
|
|
106
|
+
title: "What's the weather",
|
|
107
|
+
label: "in San Francisco?",
|
|
108
|
+
action: "What's the weather in San Francisco?",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
title: "Explain React hooks",
|
|
112
|
+
label: "like useState and useEffect",
|
|
113
|
+
action: "Explain React hooks like useState and useEffect",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
title: "Write a SQL query",
|
|
117
|
+
label: "to find top customers",
|
|
118
|
+
action: "Write a SQL query to find top customers",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
title: "Create a meal plan",
|
|
122
|
+
label: "for healthy weight loss",
|
|
123
|
+
action: "Create a meal plan for healthy weight loss",
|
|
124
|
+
},
|
|
125
|
+
].map((suggestedAction, index) => (
|
|
126
|
+
<div
|
|
127
|
+
key={`suggested-action-${suggestedAction.title}-${index}`}
|
|
128
|
+
className="aui-thread-welcome-suggestion-display fade-in slide-in-from-bottom-4 @md:nth-[n+3]:block nth-[n+3]:hidden animate-in fill-mode-both duration-300 ease-out"
|
|
129
|
+
style={{ animationDelay: `${index * 50}ms` }}
|
|
130
|
+
>
|
|
131
|
+
<ThreadPrimitive.Suggestion
|
|
132
|
+
prompt={suggestedAction.action}
|
|
133
|
+
send
|
|
134
|
+
asChild
|
|
135
|
+
>
|
|
136
|
+
<Button
|
|
137
|
+
variant="ghost"
|
|
138
|
+
className="aui-thread-welcome-suggestion h-auto w-full flex-1 @md:flex-col flex-wrap items-start justify-start gap-1 rounded-3xl border px-5 py-4 text-left text-sm dark:hover:bg-accent/60"
|
|
139
|
+
aria-label={suggestedAction.action}
|
|
140
|
+
>
|
|
141
|
+
<span className="aui-thread-welcome-suggestion-text-1 font-medium">
|
|
142
|
+
{suggestedAction.title}
|
|
143
|
+
</span>
|
|
144
|
+
<span className="aui-thread-welcome-suggestion-text-2 text-muted-foreground">
|
|
145
|
+
{suggestedAction.label}
|
|
146
|
+
</span>
|
|
147
|
+
</Button>
|
|
148
|
+
</ThreadPrimitive.Suggestion>
|
|
149
|
+
</div>
|
|
150
|
+
))}
|
|
151
|
+
</div>
|
|
160
152
|
);
|
|
161
153
|
};
|
|
162
154
|
|
|
163
|
-
const
|
|
164
|
-
const webrtcProtocol = usePersonaRuntimeWebRTCProtocol()!;
|
|
165
|
-
|
|
166
|
-
const isConnected = useMemo(() => webrtcProtocol?.status === 'connected', [webrtcProtocol?.status]);
|
|
167
|
-
const handleConnection = useCallback(() => {
|
|
168
|
-
if (webrtcProtocol.status === 'connected') {
|
|
169
|
-
webrtcProtocol.disconnect();
|
|
170
|
-
} else {
|
|
171
|
-
webrtcProtocol.connect();
|
|
172
|
-
}
|
|
173
|
-
}, [webrtcProtocol]);
|
|
174
|
-
|
|
175
|
-
if (!webrtcProtocol) {
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
155
|
+
const Composer: FC = () => {
|
|
178
156
|
return (
|
|
179
|
-
<
|
|
180
|
-
className=
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
157
|
+
<ComposerPrimitive.Root className="aui-composer-root relative flex w-full flex-col">
|
|
158
|
+
<ComposerPrimitive.AttachmentDropzone className="aui-composer-attachment-dropzone flex w-full flex-col rounded-3xl border border-input bg-background px-1 pt-2 shadow-xs outline-none transition-[color,box-shadow] has-[textarea:focus-visible]:border-ring has-[textarea:focus-visible]:ring-[3px] has-[textarea:focus-visible]:ring-ring/50 data-[dragging=true]:border-ring data-[dragging=true]:border-dashed data-[dragging=true]:bg-accent/50 dark:bg-background">
|
|
159
|
+
<ComposerAttachments />
|
|
160
|
+
<ComposerPrimitive.Input
|
|
161
|
+
placeholder="Send a message..."
|
|
162
|
+
className="aui-composer-input mb-1 max-h-32 min-h-16 w-full resize-none bg-transparent px-3.5 pt-1.5 pb-3 text-base outline-none placeholder:text-muted-foreground focus-visible:ring-0"
|
|
163
|
+
rows={1}
|
|
164
|
+
autoFocus
|
|
165
|
+
aria-label="Message input"
|
|
166
|
+
/>
|
|
167
|
+
<ComposerAction />
|
|
168
|
+
</ComposerPrimitive.AttachmentDropzone>
|
|
169
|
+
</ComposerPrimitive.Root>
|
|
190
170
|
);
|
|
191
171
|
};
|
|
192
172
|
|
|
193
173
|
const ComposerAction: FC = () => {
|
|
194
174
|
return (
|
|
195
|
-
|
|
175
|
+
<div className="aui-composer-action-wrapper relative mx-1 mt-2 mb-2 flex items-center justify-between">
|
|
176
|
+
<ComposerAddAttachment />
|
|
177
|
+
|
|
196
178
|
<ThreadPrimitive.If running={false}>
|
|
197
179
|
<ComposerPrimitive.Send asChild>
|
|
198
|
-
<TooltipIconButton
|
|
199
|
-
|
|
180
|
+
<TooltipIconButton
|
|
181
|
+
tooltip="Send message"
|
|
182
|
+
side="bottom"
|
|
183
|
+
type="submit"
|
|
184
|
+
variant="default"
|
|
185
|
+
size="icon"
|
|
186
|
+
className="aui-composer-send size-[34px] rounded-full p-1"
|
|
187
|
+
aria-label="Send message"
|
|
188
|
+
>
|
|
189
|
+
<ArrowUpIcon className="aui-composer-send-icon size-5" />
|
|
200
190
|
</TooltipIconButton>
|
|
201
191
|
</ComposerPrimitive.Send>
|
|
202
192
|
</ThreadPrimitive.If>
|
|
193
|
+
|
|
203
194
|
<ThreadPrimitive.If running>
|
|
204
195
|
<ComposerPrimitive.Cancel asChild>
|
|
205
|
-
<
|
|
206
|
-
|
|
207
|
-
|
|
196
|
+
<Button
|
|
197
|
+
type="button"
|
|
198
|
+
variant="default"
|
|
199
|
+
size="icon"
|
|
200
|
+
className="aui-composer-cancel size-[34px] rounded-full border border-muted-foreground/60 hover:bg-primary/75 dark:border-muted-foreground/90"
|
|
201
|
+
aria-label="Stop generating"
|
|
202
|
+
>
|
|
203
|
+
<Square className="aui-composer-cancel-icon size-3.5 fill-white dark:fill-black" />
|
|
204
|
+
</Button>
|
|
208
205
|
</ComposerPrimitive.Cancel>
|
|
209
206
|
</ThreadPrimitive.If>
|
|
210
|
-
<SpeakButton />
|
|
211
|
-
</>
|
|
212
|
-
);
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const UserMessage: FC = () => {
|
|
216
|
-
return (
|
|
217
|
-
<MessagePrimitive.Root className="grid auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 [&:where(>*)]:col-start-2 w-full max-w-[var(--thread-max-width)] py-4">
|
|
218
|
-
<div className="bg-muted text-foreground max-w-[calc(var(--thread-max-width)*0.8)] break-words rounded-3xl px-5 py-2.5 col-start-2 row-start-2">
|
|
219
|
-
<UserMessageAttachments />
|
|
220
|
-
<MessagePrimitive.Content />
|
|
221
|
-
</div>
|
|
222
|
-
|
|
223
|
-
<BranchPicker className="col-span-full col-start-1 row-start-3 -mr-1 justify-end" />
|
|
224
|
-
</MessagePrimitive.Root>
|
|
225
|
-
);
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
const EditComposer: FC = () => {
|
|
229
|
-
return (
|
|
230
|
-
<ComposerPrimitive.Root className="bg-muted my-4 flex w-full max-w-[var(--thread-max-width)] flex-col gap-2 rounded-xl">
|
|
231
|
-
<ComposerPrimitive.Input className="text-foreground flex h-8 w-full resize-none bg-transparent p-4 pb-0 outline-none" />
|
|
232
|
-
|
|
233
|
-
<div className="mx-3 mb-3 flex items-center justify-center gap-2 self-end">
|
|
234
|
-
<ComposerPrimitive.Cancel asChild>
|
|
235
|
-
<Button variant="ghost">Cancel</Button>
|
|
236
|
-
</ComposerPrimitive.Cancel>
|
|
237
|
-
<ComposerPrimitive.Send asChild>
|
|
238
|
-
<Button>Send</Button>
|
|
239
|
-
</ComposerPrimitive.Send>
|
|
240
|
-
</div>
|
|
241
|
-
</ComposerPrimitive.Root>
|
|
242
|
-
);
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
const Image: FC<ImageContentPart> = ({ image }: ImageContentPart) => {
|
|
246
|
-
const baseEndpoint = usePersonaRuntimeEndpoint();
|
|
247
|
-
return (
|
|
248
|
-
<div className="flex items-center gap-2 border rounded-lg border-muted bg-muted p-4 my-2">
|
|
249
|
-
<img src={`${baseEndpoint}/files/${image}`} alt="Image" className="max-h-96 max-w-full rounded-lg object-cover" />
|
|
250
207
|
</div>
|
|
251
208
|
);
|
|
252
209
|
};
|
|
253
210
|
|
|
254
|
-
const
|
|
255
|
-
const isImage = useMemo(() => mimeType.startsWith('image/'), [mimeType]);
|
|
256
|
-
if (isImage) {
|
|
257
|
-
return <Image image={data} type="image" />;
|
|
258
|
-
}
|
|
259
|
-
const fileName = useMemo(() => {
|
|
260
|
-
const parts = data.split('/');
|
|
261
|
-
return parts[parts.length - 1];
|
|
262
|
-
}, [data]);
|
|
263
|
-
const baseEndpoint = usePersonaRuntimeEndpoint();
|
|
264
|
-
const getIconByMimeType = (mimeType: string) => {
|
|
265
|
-
const iconMap: Record<string, JSX.Element> = {
|
|
266
|
-
'application/pdf': <FileIcon />,
|
|
267
|
-
'image/png': <ImageIcon />,
|
|
268
|
-
'image/jpeg': <ImageIcon />,
|
|
269
|
-
'application/zip': <ArchiveIcon />,
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
return iconMap[mimeType] || <FileIcon />;
|
|
273
|
-
};
|
|
274
|
-
const icon = getIconByMimeType(mimeType);
|
|
275
|
-
|
|
211
|
+
const MessageError: FC = () => {
|
|
276
212
|
return (
|
|
277
|
-
<
|
|
278
|
-
<
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
</div>
|
|
213
|
+
<MessagePrimitive.Error>
|
|
214
|
+
<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">
|
|
215
|
+
<ErrorPrimitive.Message className="aui-message-error-message line-clamp-2" />
|
|
216
|
+
</ErrorPrimitive.Root>
|
|
217
|
+
</MessagePrimitive.Error>
|
|
283
218
|
);
|
|
284
219
|
};
|
|
285
220
|
|
|
286
221
|
const AssistantMessage: FC = () => {
|
|
287
222
|
return (
|
|
288
|
-
<MessagePrimitive.Root
|
|
289
|
-
|
|
290
|
-
|
|
223
|
+
<MessagePrimitive.Root
|
|
224
|
+
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-4 duration-150 ease-out"
|
|
225
|
+
data-role="assistant"
|
|
226
|
+
>
|
|
227
|
+
<div className="aui-assistant-message-content wrap-break-word mx-2 text-foreground leading-7">
|
|
228
|
+
<MessagePrimitive.Parts
|
|
291
229
|
components={{
|
|
292
230
|
Text: MarkdownText,
|
|
293
|
-
|
|
294
|
-
Reasoning,
|
|
295
|
-
tools: {
|
|
296
|
-
Fallback: ToolFallback,
|
|
297
|
-
},
|
|
231
|
+
tools: { Fallback: ToolFallback },
|
|
298
232
|
}}
|
|
299
233
|
/>
|
|
234
|
+
<MessageError />
|
|
300
235
|
</div>
|
|
301
236
|
|
|
302
|
-
<
|
|
303
|
-
|
|
304
|
-
|
|
237
|
+
<div className="aui-assistant-message-footer mt-2 ml-2 flex">
|
|
238
|
+
<BranchPicker />
|
|
239
|
+
<AssistantActionBar />
|
|
240
|
+
</div>
|
|
305
241
|
</MessagePrimitive.Root>
|
|
306
242
|
);
|
|
307
243
|
};
|
|
@@ -312,7 +248,7 @@ const AssistantActionBar: FC = () => {
|
|
|
312
248
|
hideWhenRunning
|
|
313
249
|
autohide="not-last"
|
|
314
250
|
autohideFloat="single-branch"
|
|
315
|
-
className="
|
|
251
|
+
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"
|
|
316
252
|
>
|
|
317
253
|
<ActionBarPrimitive.Copy asChild>
|
|
318
254
|
<TooltipIconButton tooltip="Copy">
|
|
@@ -324,15 +260,90 @@ const AssistantActionBar: FC = () => {
|
|
|
324
260
|
</MessagePrimitive.If>
|
|
325
261
|
</TooltipIconButton>
|
|
326
262
|
</ActionBarPrimitive.Copy>
|
|
263
|
+
<ActionBarPrimitive.Reload asChild>
|
|
264
|
+
<TooltipIconButton tooltip="Refresh">
|
|
265
|
+
<RefreshCwIcon />
|
|
266
|
+
</TooltipIconButton>
|
|
267
|
+
</ActionBarPrimitive.Reload>
|
|
327
268
|
</ActionBarPrimitive.Root>
|
|
328
269
|
);
|
|
329
270
|
};
|
|
330
271
|
|
|
331
|
-
const
|
|
272
|
+
const UserMessage: FC = () => {
|
|
273
|
+
return (
|
|
274
|
+
<MessagePrimitive.Root
|
|
275
|
+
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-4 duration-150 ease-out [&:where(>*)]:col-start-2"
|
|
276
|
+
data-role="user"
|
|
277
|
+
>
|
|
278
|
+
<UserMessageAttachments />
|
|
279
|
+
|
|
280
|
+
<div className="aui-user-message-content-wrapper relative col-start-2 min-w-0">
|
|
281
|
+
<div className="aui-user-message-content wrap-break-word rounded-3xl bg-muted px-5 py-2.5 text-foreground">
|
|
282
|
+
<MessagePrimitive.Parts />
|
|
283
|
+
</div>
|
|
284
|
+
<div className="aui-user-action-bar-wrapper -translate-x-full -translate-y-1/2 absolute top-1/2 left-0 pr-2">
|
|
285
|
+
<UserActionBar />
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
|
|
289
|
+
<BranchPicker className="aui-user-branch-picker -mr-1 col-span-full col-start-1 row-start-3 justify-end" />
|
|
290
|
+
</MessagePrimitive.Root>
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const UserActionBar: FC = () => {
|
|
295
|
+
return (
|
|
296
|
+
<ActionBarPrimitive.Root
|
|
297
|
+
hideWhenRunning
|
|
298
|
+
autohide="not-last"
|
|
299
|
+
className="aui-user-action-bar-root flex flex-col items-end"
|
|
300
|
+
>
|
|
301
|
+
<ActionBarPrimitive.Edit asChild>
|
|
302
|
+
<TooltipIconButton tooltip="Edit" className="aui-user-action-edit p-4">
|
|
303
|
+
<PencilIcon />
|
|
304
|
+
</TooltipIconButton>
|
|
305
|
+
</ActionBarPrimitive.Edit>
|
|
306
|
+
</ActionBarPrimitive.Root>
|
|
307
|
+
);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const EditComposer: FC = () => {
|
|
311
|
+
return (
|
|
312
|
+
<MessagePrimitive.Root className="aui-edit-composer-wrapper mx-auto flex w-full max-w-(--thread-max-width) flex-col gap-4 px-2">
|
|
313
|
+
<ComposerPrimitive.Root className="aui-edit-composer-root ml-auto flex w-full max-w-7/8 flex-col rounded-xl bg-muted">
|
|
314
|
+
<ComposerPrimitive.Input
|
|
315
|
+
className="aui-edit-composer-input flex min-h-[60px] w-full resize-none bg-transparent p-4 text-foreground outline-none"
|
|
316
|
+
autoFocus
|
|
317
|
+
/>
|
|
318
|
+
|
|
319
|
+
<div className="aui-edit-composer-footer mx-3 mb-3 flex items-center justify-center gap-2 self-end">
|
|
320
|
+
<ComposerPrimitive.Cancel asChild>
|
|
321
|
+
<Button variant="ghost" size="sm" aria-label="Cancel edit">
|
|
322
|
+
Cancel
|
|
323
|
+
</Button>
|
|
324
|
+
</ComposerPrimitive.Cancel>
|
|
325
|
+
<ComposerPrimitive.Send asChild>
|
|
326
|
+
<Button size="sm" aria-label="Update message">
|
|
327
|
+
Update
|
|
328
|
+
</Button>
|
|
329
|
+
</ComposerPrimitive.Send>
|
|
330
|
+
</div>
|
|
331
|
+
</ComposerPrimitive.Root>
|
|
332
|
+
</MessagePrimitive.Root>
|
|
333
|
+
);
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({
|
|
337
|
+
className,
|
|
338
|
+
...rest
|
|
339
|
+
}) => {
|
|
332
340
|
return (
|
|
333
341
|
<BranchPickerPrimitive.Root
|
|
334
342
|
hideWhenSingleBranch
|
|
335
|
-
className={cn(
|
|
343
|
+
className={cn(
|
|
344
|
+
"aui-branch-picker-root -ml-2 mr-2 inline-flex items-center text-muted-foreground text-xs",
|
|
345
|
+
className,
|
|
346
|
+
)}
|
|
336
347
|
{...rest}
|
|
337
348
|
>
|
|
338
349
|
<BranchPickerPrimitive.Previous asChild>
|
|
@@ -340,7 +351,7 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({ className, ...rest
|
|
|
340
351
|
<ChevronLeftIcon />
|
|
341
352
|
</TooltipIconButton>
|
|
342
353
|
</BranchPickerPrimitive.Previous>
|
|
343
|
-
<span className="font-medium">
|
|
354
|
+
<span className="aui-branch-picker-state font-medium">
|
|
344
355
|
<BranchPickerPrimitive.Number /> / <BranchPickerPrimitive.Count />
|
|
345
356
|
</span>
|
|
346
357
|
<BranchPickerPrimitive.Next asChild>
|
|
@@ -351,11 +362,3 @@ const BranchPicker: FC<BranchPickerPrimitive.Root.Props> = ({ className, ...rest
|
|
|
351
362
|
</BranchPickerPrimitive.Root>
|
|
352
363
|
);
|
|
353
364
|
};
|
|
354
|
-
|
|
355
|
-
const CircleStopIcon = () => {
|
|
356
|
-
return (
|
|
357
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" width="16" height="16">
|
|
358
|
-
<rect width="10" height="10" x="3" y="3" rx="2" />
|
|
359
|
-
</svg>
|
|
360
|
-
);
|
|
361
|
-
};
|