@agents24/chat-react 0.1.9 → 0.2.0
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 +21 -5
- package/dist/{chunk-E3TJ3I6G.js → chunk-FFO6KEB4.js} +2 -1
- package/dist/chunk-FFO6KEB4.js.map +1 -0
- package/dist/controller-actions.d.ts +45 -0
- package/dist/controller-helpers.d.ts +27 -0
- package/dist/controller.d.ts +2 -7
- package/dist/index.cjs +600 -225
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +543 -175
- package/dist/index.js.map +1 -1
- package/dist/message-lifecycle.d.ts +15 -0
- package/dist/model.d.ts +2 -1
- package/dist/renderers.d.ts +1 -1
- package/dist/sse.d.ts +3 -1
- package/dist/templates/agent-chat-shell.d.ts +13 -1
- package/dist/templates/index.cjs +91 -24
- package/dist/templates/index.cjs.map +1 -1
- package/dist/templates/index.js +89 -24
- package/dist/templates/index.js.map +1 -1
- package/dist/transport.d.ts +14 -0
- package/dist/types.d.ts +63 -6
- package/dist/ui/adapters.d.ts +1 -2
- package/dist/ui/agent-chat-actions.d.ts +16 -0
- package/dist/ui/agent-chat-composer.d.ts +28 -0
- package/dist/ui/agent-chat-message.d.ts +40 -0
- package/dist/ui/agent-response-timeline.d.ts +24 -0
- package/dist/ui/index.cjs +944 -206
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.js +932 -202
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/mcp-connect-required-card.d.ts +13 -0
- package/package.json +2 -1
- package/dist/chunk-E3TJ3I6G.js.map +0 -1
package/dist/ui/index.js
CHANGED
|
@@ -5,15 +5,260 @@ import {
|
|
|
5
5
|
cn
|
|
6
6
|
} from "../chunk-UU7OXHL3.js";
|
|
7
7
|
|
|
8
|
-
// src/ui/
|
|
8
|
+
// src/ui/agent-chat-composer.tsx
|
|
9
9
|
import * as React from "react";
|
|
10
|
+
import { ArrowUp, Paperclip, Plus, Square, X } from "lucide-react";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var createId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `file-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
13
|
+
function createComposerFile(file) {
|
|
14
|
+
return {
|
|
15
|
+
id: createId(),
|
|
16
|
+
type: "file",
|
|
17
|
+
url: URL.createObjectURL(file),
|
|
18
|
+
filename: file.name || "attachment",
|
|
19
|
+
mediaType: file.type || "application/octet-stream"
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function revokeComposerFiles(files) {
|
|
23
|
+
files.forEach((file) => {
|
|
24
|
+
try {
|
|
25
|
+
URL.revokeObjectURL(file.url);
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function formatFileCount(files) {
|
|
31
|
+
if (files.length === 1) return files[0].filename;
|
|
32
|
+
return `${files.length} files`;
|
|
33
|
+
}
|
|
34
|
+
var pillButtonClass = "inline-flex size-8 shrink-0 items-center justify-center gap-2 rounded-full border-0 bg-neutral-100 text-sm text-neutral-600 shadow-none transition-colors hover:bg-neutral-200 hover:text-neutral-800 focus-visible:border-neutral-300 focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50 dark:bg-neutral-800 dark:text-neutral-300 dark:hover:bg-neutral-700";
|
|
35
|
+
var submitButtonClass = "inline-flex size-9 shrink-0 items-center justify-center gap-2 rounded-full border-0 bg-neutral-900 text-sm text-white shadow-none transition-all duration-200 hover:bg-neutral-800 hover:text-white focus-visible:border-neutral-300 focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50 dark:bg-neutral-100 dark:text-neutral-900 dark:hover:bg-white";
|
|
36
|
+
function AgentChatComposer({
|
|
37
|
+
accept,
|
|
38
|
+
allowAttachments = true,
|
|
39
|
+
attachmentLayout = "flow",
|
|
40
|
+
className,
|
|
41
|
+
disabled = false,
|
|
42
|
+
inputToolbarContent,
|
|
43
|
+
isRunning = false,
|
|
44
|
+
onAttachmentCountChange,
|
|
45
|
+
onStop,
|
|
46
|
+
onSubmit,
|
|
47
|
+
placeholder = "Send follow-up",
|
|
48
|
+
textareaRef
|
|
49
|
+
}) {
|
|
50
|
+
const fileInputRef = React.useRef(null);
|
|
51
|
+
const filesRef = React.useRef([]);
|
|
52
|
+
const localTextareaRef = React.useRef(null);
|
|
53
|
+
const [text, setText] = React.useState("");
|
|
54
|
+
const [files, setFiles] = React.useState([]);
|
|
55
|
+
const [isSubmitting, setIsSubmitting] = React.useState(false);
|
|
56
|
+
const isExpanded = text.includes("\n") || text.length > 62;
|
|
57
|
+
const setTextareaRef = React.useCallback(
|
|
58
|
+
(node) => {
|
|
59
|
+
localTextareaRef.current = node;
|
|
60
|
+
if (typeof textareaRef === "function") {
|
|
61
|
+
textareaRef(node);
|
|
62
|
+
} else if (textareaRef) {
|
|
63
|
+
textareaRef.current = node;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
[textareaRef]
|
|
67
|
+
);
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
filesRef.current = files;
|
|
70
|
+
onAttachmentCountChange?.(files.length);
|
|
71
|
+
}, [files, onAttachmentCountChange]);
|
|
72
|
+
React.useEffect(() => () => revokeComposerFiles(filesRef.current), []);
|
|
73
|
+
React.useLayoutEffect(() => {
|
|
74
|
+
const textarea = localTextareaRef.current;
|
|
75
|
+
if (!textarea) return;
|
|
76
|
+
if (isExpanded) {
|
|
77
|
+
textarea.style.height = "auto";
|
|
78
|
+
const scrollHeight = textarea.scrollHeight;
|
|
79
|
+
textarea.style.height = `${Math.min(scrollHeight, 224)}px`;
|
|
80
|
+
textarea.style.overflowY = scrollHeight >= 224 ? "auto" : "hidden";
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
textarea.style.height = "";
|
|
84
|
+
textarea.style.overflowY = "hidden";
|
|
85
|
+
}, [isExpanded, text]);
|
|
86
|
+
const canSubmit = !disabled && !isSubmitting && !isRunning && (text.trim().length > 0 || files.length > 0);
|
|
87
|
+
const handleFilesChange = (event) => {
|
|
88
|
+
const selected = Array.from(event.target.files || []).map(createComposerFile);
|
|
89
|
+
if (selected.length > 0) {
|
|
90
|
+
setFiles((current) => [...current, ...selected]);
|
|
91
|
+
}
|
|
92
|
+
event.currentTarget.value = "";
|
|
93
|
+
};
|
|
94
|
+
const removeFile = (fileId) => {
|
|
95
|
+
setFiles((current) => {
|
|
96
|
+
const target = current.find((file) => file.id === fileId);
|
|
97
|
+
if (target) revokeComposerFiles([target]);
|
|
98
|
+
return current.filter((file) => file.id !== fileId);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const submit = async () => {
|
|
102
|
+
if (!canSubmit) return;
|
|
103
|
+
const submittedText = text.trim();
|
|
104
|
+
const submittedFiles = files;
|
|
105
|
+
setIsSubmitting(true);
|
|
106
|
+
try {
|
|
107
|
+
await onSubmit({ text: submittedText, files: submittedFiles });
|
|
108
|
+
setText("");
|
|
109
|
+
setFiles([]);
|
|
110
|
+
revokeComposerFiles(submittedFiles);
|
|
111
|
+
} finally {
|
|
112
|
+
setIsSubmitting(false);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const handleKeyDown = (event) => {
|
|
116
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
void submit();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative mx-auto w-full max-w-3xl overflow-visible", className), children: [
|
|
122
|
+
files.length > 0 ? /* @__PURE__ */ jsx(
|
|
123
|
+
"div",
|
|
124
|
+
{
|
|
125
|
+
"data-testid": "agent-chat-composer-attachments",
|
|
126
|
+
className: cn(
|
|
127
|
+
"flex min-w-0 gap-2 py-1",
|
|
128
|
+
attachmentLayout === "overlay" ? "absolute bottom-full left-0 right-0 mb-1.5 flex-nowrap overflow-x-auto overflow-y-hidden overscroll-x-contain px-2" : "mb-2 flex-wrap px-1"
|
|
129
|
+
),
|
|
130
|
+
children: files.map((file) => /* @__PURE__ */ jsxs(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
className: "group relative flex h-8 max-w-[min(20rem,calc(100vw-2rem))] cursor-default select-none items-center gap-1.5 rounded-md border border-neutral-200 bg-white px-1.5 text-sm font-medium text-foreground transition-colors hover:bg-neutral-50",
|
|
134
|
+
children: [
|
|
135
|
+
/* @__PURE__ */ jsx("span", { className: "flex size-5 shrink-0 items-center justify-center rounded bg-background text-muted-foreground", children: /* @__PURE__ */ jsx(Paperclip, { className: "size-3" }) }),
|
|
136
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: file.filename }),
|
|
137
|
+
/* @__PURE__ */ jsx(
|
|
138
|
+
"button",
|
|
139
|
+
{
|
|
140
|
+
"aria-label": `Remove ${file.filename}`,
|
|
141
|
+
className: "inline-flex size-5 shrink-0 items-center justify-center rounded text-muted-foreground opacity-70 transition-colors hover:bg-muted hover:text-foreground hover:opacity-100 focus-visible:outline-none",
|
|
142
|
+
onClick: () => removeFile(file.id),
|
|
143
|
+
type: "button",
|
|
144
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3" })
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
file.id
|
|
150
|
+
))
|
|
151
|
+
}
|
|
152
|
+
) : null,
|
|
153
|
+
/* @__PURE__ */ jsx(
|
|
154
|
+
"div",
|
|
155
|
+
{
|
|
156
|
+
className: cn(
|
|
157
|
+
"relative w-full border border-neutral-200 bg-white shadow-sm transition-colors duration-200 focus-within:border-neutral-300 dark:border-neutral-700 dark:bg-card dark:focus-within:border-neutral-600",
|
|
158
|
+
isExpanded ? "rounded-[18px] p-2 pb-1.5" : "rounded-full px-2 py-[3px]"
|
|
159
|
+
),
|
|
160
|
+
children: /* @__PURE__ */ jsxs(
|
|
161
|
+
"div",
|
|
162
|
+
{
|
|
163
|
+
className: "w-full",
|
|
164
|
+
style: {
|
|
165
|
+
alignItems: "center",
|
|
166
|
+
display: "grid",
|
|
167
|
+
gridTemplateAreas: isExpanded ? `"textarea textarea textarea" "plus toolbar submit"` : `"plus textarea composer mic submit"`,
|
|
168
|
+
gridTemplateColumns: isExpanded ? "auto 1fr auto" : "auto 1fr auto auto auto",
|
|
169
|
+
gap: isExpanded ? "3px 10px" : "8px"
|
|
170
|
+
},
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ jsxs("div", { style: { gridArea: "plus" }, className: "flex shrink-0 items-center justify-center", children: [
|
|
173
|
+
/* @__PURE__ */ jsx(
|
|
174
|
+
"input",
|
|
175
|
+
{
|
|
176
|
+
ref: fileInputRef,
|
|
177
|
+
accept,
|
|
178
|
+
"aria-label": "Attach files",
|
|
179
|
+
className: "hidden",
|
|
180
|
+
multiple: true,
|
|
181
|
+
onChange: handleFilesChange,
|
|
182
|
+
type: "file"
|
|
183
|
+
}
|
|
184
|
+
),
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
"button",
|
|
187
|
+
{
|
|
188
|
+
"aria-label": "Attach files",
|
|
189
|
+
className: pillButtonClass,
|
|
190
|
+
disabled: disabled || isSubmitting || isRunning || !allowAttachments,
|
|
191
|
+
onClick: () => fileInputRef.current?.click(),
|
|
192
|
+
title: "Attach files",
|
|
193
|
+
type: "button",
|
|
194
|
+
children: /* @__PURE__ */ jsx(Plus, { className: "size-4" })
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
] }),
|
|
198
|
+
/* @__PURE__ */ jsx("div", { style: { gridArea: "textarea" }, className: "min-w-0 w-full", children: /* @__PURE__ */ jsx(
|
|
199
|
+
"textarea",
|
|
200
|
+
{
|
|
201
|
+
ref: setTextareaRef,
|
|
202
|
+
"aria-label": "Message",
|
|
203
|
+
className: cn(
|
|
204
|
+
"w-full resize-none border-0 bg-transparent px-1 text-[15px] leading-relaxed text-foreground shadow-none outline-none placeholder:text-neutral-400 focus-visible:ring-0 scrollbar-thin",
|
|
205
|
+
isExpanded ? "min-h-9 max-h-[224px] py-1" : "min-h-9 h-9 max-h-9 py-2"
|
|
206
|
+
),
|
|
207
|
+
disabled: disabled || isSubmitting || isRunning,
|
|
208
|
+
onChange: (event) => setText(event.target.value),
|
|
209
|
+
onKeyDown: handleKeyDown,
|
|
210
|
+
placeholder,
|
|
211
|
+
rows: isExpanded ? 2 : 1,
|
|
212
|
+
value: text
|
|
213
|
+
}
|
|
214
|
+
) }),
|
|
215
|
+
isExpanded ? /* @__PURE__ */ jsx("div", { style: { gridArea: "toolbar" }, className: "flex min-w-0 items-center gap-1.5", children: inputToolbarContent }) : null,
|
|
216
|
+
!isExpanded ? /* @__PURE__ */ jsx("div", { style: { gridArea: "composer" }, className: "flex min-w-0 items-center gap-1.5" }) : null,
|
|
217
|
+
!isExpanded ? /* @__PURE__ */ jsx("div", { style: { gridArea: "mic" }, className: "flex shrink-0 items-center justify-end" }) : null,
|
|
218
|
+
/* @__PURE__ */ jsx("div", { style: { gridArea: "submit" }, className: "flex shrink-0 items-center justify-end", children: isRunning ? /* @__PURE__ */ jsx(
|
|
219
|
+
"button",
|
|
220
|
+
{
|
|
221
|
+
"aria-label": "Stop generating",
|
|
222
|
+
className: submitButtonClass,
|
|
223
|
+
disabled: disabled || !onStop,
|
|
224
|
+
onClick: onStop,
|
|
225
|
+
title: "Stop",
|
|
226
|
+
type: "button",
|
|
227
|
+
children: /* @__PURE__ */ jsx(Square, { className: "size-3.5 fill-current" })
|
|
228
|
+
}
|
|
229
|
+
) : /* @__PURE__ */ jsx(
|
|
230
|
+
"button",
|
|
231
|
+
{
|
|
232
|
+
"aria-label": files.length > 0 ? `Send ${formatFileCount(files)}` : "Send message",
|
|
233
|
+
className: cn(submitButtonClass, text.trim().length > 0 && "hover:scale-105"),
|
|
234
|
+
disabled: !canSubmit,
|
|
235
|
+
onClick: () => void submit(),
|
|
236
|
+
title: "Send",
|
|
237
|
+
type: "button",
|
|
238
|
+
children: /* @__PURE__ */ jsx(ArrowUp, { className: "size-4", strokeWidth: 2.5 })
|
|
239
|
+
}
|
|
240
|
+
) })
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
),
|
|
246
|
+
!isExpanded && inputToolbarContent ? /* @__PURE__ */ jsx("div", { className: "mt-2 flex items-center gap-2 px-1", children: inputToolbarContent }) : null
|
|
247
|
+
] });
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/ui/agent-chat-actions.tsx
|
|
251
|
+
import { Check, Copy, RefreshCcw, ThumbsDown, ThumbsUp } from "lucide-react";
|
|
252
|
+
|
|
253
|
+
// src/ui/adapters.ts
|
|
254
|
+
import * as React2 from "react";
|
|
10
255
|
|
|
11
256
|
// src/ui/attachment.tsx
|
|
12
257
|
import { cva } from "class-variance-authority";
|
|
13
258
|
import { Slot } from "@radix-ui/react-slot";
|
|
14
|
-
import { jsx } from "react/jsx-runtime";
|
|
259
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
15
260
|
var attachmentVariants = cva(
|
|
16
|
-
"group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:
|
|
261
|
+
"group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:border-neutral-300 focus-within:ring-0 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed",
|
|
17
262
|
{
|
|
18
263
|
variants: {
|
|
19
264
|
size: {
|
|
@@ -35,7 +280,7 @@ function Attachment({
|
|
|
35
280
|
orientation = "horizontal",
|
|
36
281
|
...props
|
|
37
282
|
}) {
|
|
38
|
-
return /* @__PURE__ */
|
|
283
|
+
return /* @__PURE__ */ jsx2(
|
|
39
284
|
"div",
|
|
40
285
|
{
|
|
41
286
|
"data-slot": "attachment",
|
|
@@ -66,7 +311,7 @@ function AttachmentMedia({
|
|
|
66
311
|
variant = "icon",
|
|
67
312
|
...props
|
|
68
313
|
}) {
|
|
69
|
-
return /* @__PURE__ */
|
|
314
|
+
return /* @__PURE__ */ jsx2(
|
|
70
315
|
"div",
|
|
71
316
|
{
|
|
72
317
|
"data-slot": "attachment-media",
|
|
@@ -80,7 +325,7 @@ function AttachmentContent({
|
|
|
80
325
|
className,
|
|
81
326
|
...props
|
|
82
327
|
}) {
|
|
83
|
-
return /* @__PURE__ */
|
|
328
|
+
return /* @__PURE__ */ jsx2(
|
|
84
329
|
"div",
|
|
85
330
|
{
|
|
86
331
|
"data-slot": "attachment-content",
|
|
@@ -96,7 +341,7 @@ function AttachmentTitle({
|
|
|
96
341
|
className,
|
|
97
342
|
...props
|
|
98
343
|
}) {
|
|
99
|
-
return /* @__PURE__ */
|
|
344
|
+
return /* @__PURE__ */ jsx2(
|
|
100
345
|
"span",
|
|
101
346
|
{
|
|
102
347
|
"data-slot": "attachment-title",
|
|
@@ -112,7 +357,7 @@ function AttachmentDescription({
|
|
|
112
357
|
className,
|
|
113
358
|
...props
|
|
114
359
|
}) {
|
|
115
|
-
return /* @__PURE__ */
|
|
360
|
+
return /* @__PURE__ */ jsx2(
|
|
116
361
|
"span",
|
|
117
362
|
{
|
|
118
363
|
"data-slot": "attachment-description",
|
|
@@ -129,7 +374,7 @@ function AttachmentActions({
|
|
|
129
374
|
className,
|
|
130
375
|
...props
|
|
131
376
|
}) {
|
|
132
|
-
return /* @__PURE__ */
|
|
377
|
+
return /* @__PURE__ */ jsx2(
|
|
133
378
|
"div",
|
|
134
379
|
{
|
|
135
380
|
"data-slot": "attachment-actions",
|
|
@@ -146,13 +391,13 @@ function AttachmentAction({
|
|
|
146
391
|
type = "button",
|
|
147
392
|
...props
|
|
148
393
|
}) {
|
|
149
|
-
return /* @__PURE__ */
|
|
394
|
+
return /* @__PURE__ */ jsx2(
|
|
150
395
|
"button",
|
|
151
396
|
{
|
|
152
397
|
"data-slot": "attachment-action",
|
|
153
398
|
type,
|
|
154
399
|
className: cn(
|
|
155
|
-
"inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:
|
|
400
|
+
"inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:border-neutral-300 focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50",
|
|
156
401
|
className
|
|
157
402
|
),
|
|
158
403
|
...props
|
|
@@ -166,7 +411,7 @@ function AttachmentTrigger({
|
|
|
166
411
|
...props
|
|
167
412
|
}) {
|
|
168
413
|
const Comp = asChild ? Slot : "button";
|
|
169
|
-
return /* @__PURE__ */
|
|
414
|
+
return /* @__PURE__ */ jsx2(
|
|
170
415
|
Comp,
|
|
171
416
|
{
|
|
172
417
|
"data-slot": "attachment-trigger",
|
|
@@ -177,7 +422,7 @@ function AttachmentTrigger({
|
|
|
177
422
|
);
|
|
178
423
|
}
|
|
179
424
|
function AttachmentGroup({ className, ...props }) {
|
|
180
|
-
return /* @__PURE__ */
|
|
425
|
+
return /* @__PURE__ */ jsx2(
|
|
181
426
|
"div",
|
|
182
427
|
{
|
|
183
428
|
"data-slot": "attachment-group",
|
|
@@ -190,111 +435,6 @@ function AttachmentGroup({ className, ...props }) {
|
|
|
190
435
|
);
|
|
191
436
|
}
|
|
192
437
|
|
|
193
|
-
// src/ui/bubble.tsx
|
|
194
|
-
import { cva as cva2 } from "class-variance-authority";
|
|
195
|
-
import { Slot as Slot2 } from "@radix-ui/react-slot";
|
|
196
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
197
|
-
function BubbleGroup({ className, ...props }) {
|
|
198
|
-
return /* @__PURE__ */ jsx2(
|
|
199
|
-
"div",
|
|
200
|
-
{
|
|
201
|
-
"data-slot": "bubble-group",
|
|
202
|
-
className: cn("flex min-w-0 flex-col gap-2", className),
|
|
203
|
-
...props
|
|
204
|
-
}
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
var bubbleVariants = cva2(
|
|
208
|
-
"group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
|
|
209
|
-
{
|
|
210
|
-
variants: {
|
|
211
|
-
variant: {
|
|
212
|
-
default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
|
|
213
|
-
secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
|
|
214
|
-
muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
|
|
215
|
-
tinted: "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
|
|
216
|
-
outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
|
|
217
|
-
ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
|
|
218
|
-
destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
defaultVariants: {
|
|
222
|
-
variant: "default"
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
);
|
|
226
|
-
function Bubble({
|
|
227
|
-
variant = "default",
|
|
228
|
-
align = "start",
|
|
229
|
-
className,
|
|
230
|
-
...props
|
|
231
|
-
}) {
|
|
232
|
-
return /* @__PURE__ */ jsx2(
|
|
233
|
-
"div",
|
|
234
|
-
{
|
|
235
|
-
"data-slot": "bubble",
|
|
236
|
-
"data-variant": variant,
|
|
237
|
-
"data-align": align,
|
|
238
|
-
className: cn(bubbleVariants({ variant }), className),
|
|
239
|
-
...props
|
|
240
|
-
}
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
function BubbleContent({
|
|
244
|
-
asChild = false,
|
|
245
|
-
className,
|
|
246
|
-
...props
|
|
247
|
-
}) {
|
|
248
|
-
const Comp = asChild ? Slot2 : "div";
|
|
249
|
-
return /* @__PURE__ */ jsx2(
|
|
250
|
-
Comp,
|
|
251
|
-
{
|
|
252
|
-
"data-slot": "bubble-content",
|
|
253
|
-
className: cn(
|
|
254
|
-
"w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50",
|
|
255
|
-
className
|
|
256
|
-
),
|
|
257
|
-
...props
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
var bubbleReactionsVariants = cva2(
|
|
262
|
-
"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
|
|
263
|
-
{
|
|
264
|
-
variants: {
|
|
265
|
-
side: {
|
|
266
|
-
top: "top-0 -translate-y-3/4",
|
|
267
|
-
bottom: "bottom-0 translate-y-3/4"
|
|
268
|
-
},
|
|
269
|
-
align: {
|
|
270
|
-
start: "left-3",
|
|
271
|
-
end: "right-3"
|
|
272
|
-
}
|
|
273
|
-
},
|
|
274
|
-
defaultVariants: {
|
|
275
|
-
side: "bottom",
|
|
276
|
-
align: "end"
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
);
|
|
280
|
-
function BubbleReactions({
|
|
281
|
-
side = "bottom",
|
|
282
|
-
align = "end",
|
|
283
|
-
className,
|
|
284
|
-
...props
|
|
285
|
-
}) {
|
|
286
|
-
return /* @__PURE__ */ jsx2(
|
|
287
|
-
"div",
|
|
288
|
-
{
|
|
289
|
-
"data-slot": "bubble-reactions",
|
|
290
|
-
"data-align": align,
|
|
291
|
-
"data-side": side,
|
|
292
|
-
className: cn(bubbleReactionsVariants({ side, align }), className),
|
|
293
|
-
...props
|
|
294
|
-
}
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
438
|
// src/ui/message.tsx
|
|
299
439
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
300
440
|
function MessageGroup({ className, ...props }) {
|
|
@@ -387,25 +527,25 @@ function ChatMessage(input) {
|
|
|
387
527
|
const messageProps = Object.assign({}, props);
|
|
388
528
|
messageProps.align = resolvedAlign;
|
|
389
529
|
messageProps.className = cn(
|
|
390
|
-
"group flex w-full flex-col gap-2
|
|
391
|
-
isUser ? cn("is-user
|
|
530
|
+
"group flex w-full max-w-[80%] flex-col gap-2",
|
|
531
|
+
isUser ? cn("is-user justify-end", isRtl ? "mr-auto" : "ml-auto") : "is-assistant",
|
|
392
532
|
className
|
|
393
533
|
);
|
|
394
|
-
return
|
|
534
|
+
return React2.createElement(Message, messageProps);
|
|
395
535
|
}
|
|
396
536
|
function ChatMessageContent({
|
|
397
537
|
className,
|
|
398
538
|
...props
|
|
399
539
|
}) {
|
|
400
|
-
return
|
|
540
|
+
return React2.createElement("div", {
|
|
401
541
|
className: cn(
|
|
402
|
-
"flex w-
|
|
403
|
-
"group-[.is-user]:
|
|
404
|
-
"group-[.is-assistant]:w-full group-[.is-assistant]:max-w-full group-[.is-assistant]:
|
|
405
|
-
props.dir === "rtl" ? "group-[.is-assistant]:pr-0" : "group-[.is-assistant]:pl-0",
|
|
542
|
+
"is-user:dark flex w-fit max-w-full min-w-0 flex-col gap-2 overflow-hidden text-sm",
|
|
543
|
+
"group-[.is-user]:rounded-lg group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3 group-[.is-user]:text-foreground",
|
|
544
|
+
"group-[.is-assistant]:w-full group-[.is-assistant]:max-w-full group-[.is-assistant]:text-foreground",
|
|
406
545
|
props.dir === "rtl" ? "group-[.is-user]:mr-auto" : "group-[.is-user]:ml-auto",
|
|
407
546
|
className
|
|
408
547
|
),
|
|
548
|
+
"data-slot": "message-content",
|
|
409
549
|
...props
|
|
410
550
|
});
|
|
411
551
|
}
|
|
@@ -413,7 +553,7 @@ function ChatMessageActions({
|
|
|
413
553
|
className,
|
|
414
554
|
...props
|
|
415
555
|
}) {
|
|
416
|
-
return
|
|
556
|
+
return React2.createElement("div", {
|
|
417
557
|
className: cn("flex items-center gap-1", className),
|
|
418
558
|
"data-slot": "message-actions",
|
|
419
559
|
...props
|
|
@@ -428,12 +568,12 @@ function ChatMessageAction({
|
|
|
428
568
|
...props
|
|
429
569
|
}) {
|
|
430
570
|
const tooltipLabel = typeof tooltip === "string" ? tooltip : void 0;
|
|
431
|
-
return
|
|
571
|
+
return React2.createElement(
|
|
432
572
|
"button",
|
|
433
573
|
{
|
|
434
574
|
"aria-label": label || tooltipLabel,
|
|
435
575
|
className: cn(
|
|
436
|
-
"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:
|
|
576
|
+
"inline-flex size-8 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:border-neutral-300 focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50",
|
|
437
577
|
className
|
|
438
578
|
),
|
|
439
579
|
title: tooltipLabel,
|
|
@@ -441,7 +581,7 @@ function ChatMessageAction({
|
|
|
441
581
|
...props
|
|
442
582
|
},
|
|
443
583
|
children,
|
|
444
|
-
|
|
584
|
+
React2.createElement(
|
|
445
585
|
"span",
|
|
446
586
|
{ className: "sr-only" },
|
|
447
587
|
label || tooltipLabel
|
|
@@ -457,32 +597,32 @@ function ChatAttachment({
|
|
|
457
597
|
const mediaType = data.mediaType || data.contentType || String(data.type || "application/octet-stream");
|
|
458
598
|
const filename = data.filename || data.name || "Attachment";
|
|
459
599
|
const isImage = mediaType.startsWith("image/") && Boolean(data.url);
|
|
460
|
-
return
|
|
600
|
+
return React2.createElement(
|
|
461
601
|
Attachment,
|
|
462
602
|
{
|
|
463
603
|
orientation: orientation || (isImage ? "vertical" : "horizontal"),
|
|
464
604
|
...props
|
|
465
605
|
},
|
|
466
|
-
|
|
606
|
+
React2.createElement(
|
|
467
607
|
AttachmentMedia,
|
|
468
608
|
{ variant: isImage ? "image" : "icon" },
|
|
469
|
-
isImage ?
|
|
609
|
+
isImage ? React2.createElement("img", {
|
|
470
610
|
alt: filename,
|
|
471
611
|
className: "size-full object-cover",
|
|
472
612
|
src: data.url
|
|
473
|
-
}) :
|
|
613
|
+
}) : React2.createElement(
|
|
474
614
|
"span",
|
|
475
615
|
{ "aria-hidden": "true", className: "text-sm" },
|
|
476
616
|
filename.slice(0, 1).toUpperCase()
|
|
477
617
|
)
|
|
478
618
|
),
|
|
479
|
-
|
|
619
|
+
React2.createElement(
|
|
480
620
|
AttachmentContent,
|
|
481
621
|
null,
|
|
482
|
-
|
|
483
|
-
|
|
622
|
+
React2.createElement(AttachmentTitle, null, filename),
|
|
623
|
+
React2.createElement(AttachmentDescription, null, mediaType)
|
|
484
624
|
),
|
|
485
|
-
onRemove ?
|
|
625
|
+
onRemove ? React2.createElement(
|
|
486
626
|
"button",
|
|
487
627
|
{
|
|
488
628
|
"aria-label": "Remove attachment",
|
|
@@ -493,7 +633,7 @@ function ChatAttachment({
|
|
|
493
633
|
},
|
|
494
634
|
type: "button"
|
|
495
635
|
},
|
|
496
|
-
|
|
636
|
+
React2.createElement("span", { "aria-hidden": "true" }, "x")
|
|
497
637
|
) : null
|
|
498
638
|
);
|
|
499
639
|
}
|
|
@@ -503,7 +643,7 @@ function ChatAttachments({
|
|
|
503
643
|
...props
|
|
504
644
|
}) {
|
|
505
645
|
if (!children) return null;
|
|
506
|
-
return
|
|
646
|
+
return React2.createElement(
|
|
507
647
|
AttachmentGroup,
|
|
508
648
|
{
|
|
509
649
|
className: cn(
|
|
@@ -517,71 +657,124 @@ function ChatAttachments({
|
|
|
517
657
|
);
|
|
518
658
|
}
|
|
519
659
|
|
|
520
|
-
// src/ui/
|
|
521
|
-
import {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
660
|
+
// src/ui/agent-chat-actions.tsx
|
|
661
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
662
|
+
function AgentChatDefaultActions({
|
|
663
|
+
handlers,
|
|
664
|
+
message
|
|
665
|
+
}) {
|
|
666
|
+
if (!handlers || message.role !== "assistant" || message.isFinal === false) return null;
|
|
667
|
+
return /* @__PURE__ */ jsxs2(ChatMessageActions, { children: [
|
|
668
|
+
handlers.onRetry ? /* @__PURE__ */ jsx4(
|
|
669
|
+
ChatMessageAction,
|
|
670
|
+
{
|
|
671
|
+
label: "Retry",
|
|
672
|
+
onClick: () => void handlers.onRetry?.(message),
|
|
673
|
+
tooltip: "Regenerate response",
|
|
674
|
+
children: /* @__PURE__ */ jsx4(RefreshCcw, { className: "size-4" })
|
|
532
675
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
676
|
+
) : null,
|
|
677
|
+
handlers.onLike ? /* @__PURE__ */ jsx4(
|
|
678
|
+
ChatMessageAction,
|
|
679
|
+
{
|
|
680
|
+
label: "Like",
|
|
681
|
+
onClick: () => void handlers.onLike?.(message),
|
|
682
|
+
tooltip: "Like this response",
|
|
683
|
+
children: /* @__PURE__ */ jsx4(ThumbsUp, { className: "size-4", fill: handlers.liked ? "currentColor" : "none" })
|
|
684
|
+
}
|
|
685
|
+
) : null,
|
|
686
|
+
handlers.onDislike ? /* @__PURE__ */ jsx4(
|
|
687
|
+
ChatMessageAction,
|
|
688
|
+
{
|
|
689
|
+
label: "Dislike",
|
|
690
|
+
onClick: () => void handlers.onDislike?.(message),
|
|
691
|
+
tooltip: "Dislike this response",
|
|
692
|
+
children: /* @__PURE__ */ jsx4(ThumbsDown, { className: "size-4", fill: handlers.disliked ? "currentColor" : "none" })
|
|
693
|
+
}
|
|
694
|
+
) : null,
|
|
695
|
+
handlers.onCopy ? /* @__PURE__ */ jsx4(
|
|
696
|
+
ChatMessageAction,
|
|
697
|
+
{
|
|
698
|
+
label: "Copy",
|
|
699
|
+
onClick: () => handlers.onCopy?.(message.content || "", message.id),
|
|
700
|
+
tooltip: handlers.copied ? "Copied!" : "Copy to clipboard",
|
|
701
|
+
children: handlers.copied ? /* @__PURE__ */ jsx4(Check, { className: "size-4 text-green-600" }) : /* @__PURE__ */ jsx4(Copy, { className: "size-4" })
|
|
702
|
+
}
|
|
703
|
+
) : null
|
|
704
|
+
] });
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// src/ui/agent-chat-message.tsx
|
|
708
|
+
import * as React5 from "react";
|
|
709
|
+
import { ChevronDown as ChevronDown2, ChevronUp } from "lucide-react";
|
|
710
|
+
|
|
711
|
+
// src/ui/agent-response-timeline.tsx
|
|
712
|
+
import * as React4 from "react";
|
|
713
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
714
|
+
|
|
715
|
+
// src/ui/mcp-connect-required-card.tsx
|
|
716
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
717
|
+
var STATUS_LABELS = {
|
|
718
|
+
pending: "Connect",
|
|
719
|
+
connecting: "Connecting",
|
|
720
|
+
connected: "Connected",
|
|
721
|
+
resuming: "Resuming",
|
|
722
|
+
error: "Try again"
|
|
723
|
+
};
|
|
724
|
+
function McpConnectRequiredCard({
|
|
725
|
+
serverName,
|
|
726
|
+
providerKey,
|
|
727
|
+
message,
|
|
728
|
+
status = "pending",
|
|
729
|
+
disabled = false,
|
|
730
|
+
loading = false,
|
|
731
|
+
error,
|
|
732
|
+
onConnect,
|
|
537
733
|
className,
|
|
538
|
-
variant = "default",
|
|
539
|
-
asChild = false,
|
|
540
734
|
...props
|
|
541
735
|
}) {
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
className: cn(markerVariants({ variant, className })),
|
|
549
|
-
...props
|
|
550
|
-
}
|
|
551
|
-
);
|
|
552
|
-
}
|
|
553
|
-
function MarkerIcon({ className, ...props }) {
|
|
554
|
-
return /* @__PURE__ */ jsx4(
|
|
555
|
-
"span",
|
|
556
|
-
{
|
|
557
|
-
"data-slot": "marker-icon",
|
|
558
|
-
"aria-hidden": "true",
|
|
559
|
-
className: cn(
|
|
560
|
-
"size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
561
|
-
className
|
|
562
|
-
),
|
|
563
|
-
...props
|
|
564
|
-
}
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
function MarkerContent({ className, ...props }) {
|
|
568
|
-
return /* @__PURE__ */ jsx4(
|
|
569
|
-
"span",
|
|
736
|
+
const label = String(serverName || providerKey || "MCP server").trim();
|
|
737
|
+
const isBusy = loading || status === "connecting" || status === "resuming";
|
|
738
|
+
const isConnected = status === "connected";
|
|
739
|
+
const buttonDisabled = disabled || isBusy || isConnected || !onConnect;
|
|
740
|
+
return /* @__PURE__ */ jsx5(
|
|
741
|
+
"div",
|
|
570
742
|
{
|
|
571
|
-
"data-
|
|
743
|
+
"data-agents24-mcp-connect-card": true,
|
|
744
|
+
"data-status": status,
|
|
572
745
|
className: cn(
|
|
573
|
-
"
|
|
746
|
+
"w-full rounded-lg border border-border/50 bg-muted/25 p-3 text-sm text-foreground",
|
|
574
747
|
className
|
|
575
748
|
),
|
|
576
|
-
...props
|
|
749
|
+
...props,
|
|
750
|
+
children: /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 items-start justify-between gap-3", children: [
|
|
751
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
752
|
+
/* @__PURE__ */ jsx5("div", { className: "truncate text-sm font-medium", children: label }),
|
|
753
|
+
/* @__PURE__ */ jsx5("div", { className: "mt-1 text-sm text-muted-foreground", children: message || "Connect your account to continue." }),
|
|
754
|
+
status === "error" && error ? /* @__PURE__ */ jsx5("div", { className: "mt-2 text-sm text-destructive", children: error }) : null
|
|
755
|
+
] }),
|
|
756
|
+
/* @__PURE__ */ jsx5(
|
|
757
|
+
"button",
|
|
758
|
+
{
|
|
759
|
+
type: "button",
|
|
760
|
+
className: cn(
|
|
761
|
+
"shrink-0 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-60",
|
|
762
|
+
status === "pending" || status === "error" ? "border-neutral-900 bg-neutral-900 text-white hover:bg-neutral-800" : "border-border bg-background text-foreground hover:bg-muted"
|
|
763
|
+
),
|
|
764
|
+
disabled: buttonDisabled,
|
|
765
|
+
onClick: onConnect,
|
|
766
|
+
children: STATUS_LABELS[status]
|
|
767
|
+
}
|
|
768
|
+
)
|
|
769
|
+
] })
|
|
577
770
|
}
|
|
578
771
|
);
|
|
579
772
|
}
|
|
580
773
|
|
|
581
774
|
// src/ui/message-response.tsx
|
|
582
|
-
import * as
|
|
775
|
+
import * as React3 from "react";
|
|
583
776
|
import { defaultRehypePlugins, Streamdown } from "streamdown";
|
|
584
|
-
import { Fragment, jsx as
|
|
777
|
+
import { Fragment, jsx as jsx6 } from "react/jsx-runtime";
|
|
585
778
|
var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
|
|
586
779
|
"blockquote",
|
|
587
780
|
"div",
|
|
@@ -601,7 +794,7 @@ function isMultilineCodeNode(node) {
|
|
|
601
794
|
return node?.tagName === "code" && node.position?.start?.line !== void 0 && node.position?.end?.line !== void 0 && node.position.start.line !== node.position.end.line;
|
|
602
795
|
}
|
|
603
796
|
function hasBlockMarkdownChild(child) {
|
|
604
|
-
if (!
|
|
797
|
+
if (!React3.isValidElement(child)) {
|
|
605
798
|
return false;
|
|
606
799
|
}
|
|
607
800
|
if (typeof child.type === "string" && BLOCK_MARKDOWN_TAGS.has(child.type)) {
|
|
@@ -611,7 +804,7 @@ function hasBlockMarkdownChild(child) {
|
|
|
611
804
|
if (BLOCK_MARKDOWN_TAGS.has(props.node?.tagName || "") || isMultilineCodeNode(props.node)) {
|
|
612
805
|
return true;
|
|
613
806
|
}
|
|
614
|
-
return
|
|
807
|
+
return React3.Children.toArray(props.children).some(hasBlockMarkdownChild);
|
|
615
808
|
}
|
|
616
809
|
function MessageMarkdownParagraph({
|
|
617
810
|
children,
|
|
@@ -619,17 +812,17 @@ function MessageMarkdownParagraph({
|
|
|
619
812
|
}) {
|
|
620
813
|
const domProps = { ...props };
|
|
621
814
|
delete domProps.node;
|
|
622
|
-
const childArray =
|
|
815
|
+
const childArray = React3.Children.toArray(children).filter(
|
|
623
816
|
(child) => child !== null && child !== ""
|
|
624
817
|
);
|
|
625
|
-
const isImageOnly = childArray.length === 1 &&
|
|
818
|
+
const isImageOnly = childArray.length === 1 && React3.isValidElement(childArray[0]) && childArray[0].props.node?.tagName === "img";
|
|
626
819
|
if (isImageOnly) {
|
|
627
|
-
return /* @__PURE__ */
|
|
820
|
+
return /* @__PURE__ */ jsx6(Fragment, { children });
|
|
628
821
|
}
|
|
629
822
|
if (childArray.some(hasBlockMarkdownChild)) {
|
|
630
|
-
return /* @__PURE__ */
|
|
823
|
+
return /* @__PURE__ */ jsx6("div", { ...domProps, children });
|
|
631
824
|
}
|
|
632
|
-
return /* @__PURE__ */
|
|
825
|
+
return /* @__PURE__ */ jsx6("p", { ...domProps, children });
|
|
633
826
|
}
|
|
634
827
|
var MESSAGE_RESPONSE_COMPONENTS = {
|
|
635
828
|
p: MessageMarkdownParagraph
|
|
@@ -653,7 +846,7 @@ var MESSAGE_RESPONSE_REHYPE_PLUGINS = [
|
|
|
653
846
|
]
|
|
654
847
|
] : []
|
|
655
848
|
];
|
|
656
|
-
var MessageResponse =
|
|
849
|
+
var MessageResponse = React3.memo(
|
|
657
850
|
({
|
|
658
851
|
children,
|
|
659
852
|
className,
|
|
@@ -671,11 +864,11 @@ var MessageResponse = React2.memo(
|
|
|
671
864
|
maxCatchupChars: 32,
|
|
672
865
|
text
|
|
673
866
|
});
|
|
674
|
-
const streamdownComponents =
|
|
867
|
+
const streamdownComponents = React3.useMemo(
|
|
675
868
|
() => ({ ...MESSAGE_RESPONSE_COMPONENTS, ...components }),
|
|
676
869
|
[components]
|
|
677
870
|
);
|
|
678
|
-
return /* @__PURE__ */
|
|
871
|
+
return /* @__PURE__ */ jsx6(
|
|
679
872
|
Streamdown,
|
|
680
873
|
{
|
|
681
874
|
className: cn("size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", className),
|
|
@@ -689,7 +882,542 @@ var MessageResponse = React2.memo(
|
|
|
689
882
|
(prevProps, nextProps) => prevProps.children === nextProps.children && prevProps.className === nextProps.className && prevProps.streaming === nextProps.streaming && prevProps.streamingId === nextProps.streamingId && prevProps.components === nextProps.components
|
|
690
883
|
);
|
|
691
884
|
MessageResponse.displayName = "MessageResponse";
|
|
885
|
+
|
|
886
|
+
// src/ui/agent-response-timeline.tsx
|
|
887
|
+
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
888
|
+
var CONNECT_DECISION = "connect";
|
|
889
|
+
var HITL_DECISIONS = ["approve", "edit", "reject", "respond", "connect"];
|
|
890
|
+
function asRecord(value) {
|
|
891
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
892
|
+
}
|
|
893
|
+
function optionalString(value) {
|
|
894
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
895
|
+
}
|
|
896
|
+
function presentationValue(part, key) {
|
|
897
|
+
const presentation = part.presentation || {};
|
|
898
|
+
const snakeKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
899
|
+
return optionalString(presentation[key]) || optionalString(presentation[snakeKey]);
|
|
900
|
+
}
|
|
901
|
+
function groupKey(part) {
|
|
902
|
+
return presentationValue(part, "groupKey");
|
|
903
|
+
}
|
|
904
|
+
function groupLabel(part) {
|
|
905
|
+
return presentationValue(part, "groupLabel") || toolLabel(part);
|
|
906
|
+
}
|
|
907
|
+
function toolLabel(part) {
|
|
908
|
+
return presentationValue(part, "activity") || presentationValue(part, "title") || part.toolName || "Tool activity";
|
|
909
|
+
}
|
|
910
|
+
function toolDetail(part) {
|
|
911
|
+
return presentationValue(part, "detail") || part.errorText || null;
|
|
912
|
+
}
|
|
913
|
+
function isActiveTool(part, activeToolId) {
|
|
914
|
+
return part.id === activeToolId || part.toolCallId === activeToolId || part.state === "input-available" || part.state === "input-streaming";
|
|
915
|
+
}
|
|
916
|
+
function Shimmer({ children, className }) {
|
|
917
|
+
return /* @__PURE__ */ jsx7("span", { className: cn("inline-block animate-pulse", className), children });
|
|
918
|
+
}
|
|
919
|
+
function CompactTask({
|
|
920
|
+
children,
|
|
921
|
+
defaultOpen = false,
|
|
922
|
+
detail,
|
|
923
|
+
error,
|
|
924
|
+
label,
|
|
925
|
+
loading
|
|
926
|
+
}) {
|
|
927
|
+
const [open, setOpen] = React4.useState(defaultOpen);
|
|
928
|
+
const expandable = Boolean(children || detail);
|
|
929
|
+
const content = loading ? /* @__PURE__ */ jsx7(Shimmer, { children: label }) : /* @__PURE__ */ jsx7("span", { children: label });
|
|
930
|
+
if (!expandable) {
|
|
931
|
+
return /* @__PURE__ */ jsx7("div", { className: cn("flex min-w-0 items-center gap-1.5 text-sm", error ? "text-destructive" : "text-muted-foreground"), children: content });
|
|
932
|
+
}
|
|
933
|
+
return /* @__PURE__ */ jsxs4("div", { className: "w-full", children: [
|
|
934
|
+
/* @__PURE__ */ jsxs4(
|
|
935
|
+
"button",
|
|
936
|
+
{
|
|
937
|
+
"aria-expanded": open,
|
|
938
|
+
className: cn(
|
|
939
|
+
"group flex min-w-0 items-center gap-1.5 rounded-md px-0 py-0.5 text-left text-sm transition-colors hover:text-foreground",
|
|
940
|
+
error ? "text-destructive" : "text-muted-foreground"
|
|
941
|
+
),
|
|
942
|
+
onClick: () => setOpen((value) => !value),
|
|
943
|
+
type: "button",
|
|
944
|
+
children: [
|
|
945
|
+
content,
|
|
946
|
+
open ? /* @__PURE__ */ jsx7(ChevronDown, { className: "size-3" }) : /* @__PURE__ */ jsx7(ChevronRight, { className: "size-3 opacity-70" })
|
|
947
|
+
]
|
|
948
|
+
}
|
|
949
|
+
),
|
|
950
|
+
open ? /* @__PURE__ */ jsxs4("div", { className: "mt-1 pl-4 text-sm text-muted-foreground", children: [
|
|
951
|
+
detail ? /* @__PURE__ */ jsx7("div", { children: detail }) : null,
|
|
952
|
+
children
|
|
953
|
+
] }) : null
|
|
954
|
+
] });
|
|
955
|
+
}
|
|
956
|
+
function ToolPartRow({
|
|
957
|
+
activeToolId,
|
|
958
|
+
part
|
|
959
|
+
}) {
|
|
960
|
+
return /* @__PURE__ */ jsx7("div", { "data-agents24-tool-part": part.type, "data-state": part.state, children: /* @__PURE__ */ jsx7(
|
|
961
|
+
CompactTask,
|
|
962
|
+
{
|
|
963
|
+
defaultOpen: part.state === "output-error",
|
|
964
|
+
detail: toolDetail(part),
|
|
965
|
+
error: part.state === "output-error",
|
|
966
|
+
label: toolLabel(part),
|
|
967
|
+
loading: isActiveTool(part, activeToolId)
|
|
968
|
+
}
|
|
969
|
+
) });
|
|
970
|
+
}
|
|
971
|
+
function ToolGroup({
|
|
972
|
+
activeToolId,
|
|
973
|
+
parts
|
|
974
|
+
}) {
|
|
975
|
+
const loading = parts.some((part) => isActiveTool(part, activeToolId));
|
|
976
|
+
return /* @__PURE__ */ jsx7(CompactTask, { label: groupLabel(parts[0]), loading, children: /* @__PURE__ */ jsx7("div", { className: "space-y-1", children: parts.map((part) => /* @__PURE__ */ jsxs4(
|
|
977
|
+
"div",
|
|
978
|
+
{
|
|
979
|
+
className: cn("text-sm", part.state === "output-error" ? "text-destructive" : "text-muted-foreground"),
|
|
980
|
+
children: [
|
|
981
|
+
isActiveTool(part, activeToolId) ? /* @__PURE__ */ jsx7(Shimmer, { children: toolLabel(part) }) : toolLabel(part),
|
|
982
|
+
toolDetail(part) ? /* @__PURE__ */ jsx7("span", { className: "ml-1 text-xs text-muted-foreground/75", children: toolDetail(part) }) : null
|
|
983
|
+
]
|
|
984
|
+
},
|
|
985
|
+
part.id
|
|
986
|
+
)) }) });
|
|
987
|
+
}
|
|
988
|
+
function collectHitlDecisions(part) {
|
|
989
|
+
const configs = Array.isArray(part.hitl.review_configs) ? part.hitl.review_configs : [];
|
|
990
|
+
const decisions = configs.flatMap((config) => {
|
|
991
|
+
const record = asRecord(config);
|
|
992
|
+
const allowed = Array.isArray(record?.allowed_decisions) ? record?.allowed_decisions : [];
|
|
993
|
+
return allowed.filter((item) => HITL_DECISIONS.includes(String(item)));
|
|
994
|
+
});
|
|
995
|
+
return Array.from(new Set(decisions));
|
|
996
|
+
}
|
|
997
|
+
function isMcpConnectHitl(part) {
|
|
998
|
+
const kind = `${part.hitlKind || optionalString(part.hitl.kind) || ""}`.toLowerCase();
|
|
999
|
+
const decisions = collectHitlDecisions(part);
|
|
1000
|
+
return decisions.includes(CONNECT_DECISION) || kind.includes("mcp") || kind.includes("connection");
|
|
1001
|
+
}
|
|
1002
|
+
function mcpConnectLabel(part) {
|
|
1003
|
+
const payload = asRecord(part.hitl.client_safe_payload);
|
|
1004
|
+
const origin = asRecord(part.hitl.origin);
|
|
1005
|
+
return optionalString(part.hitl.server_name) || optionalString(part.hitl.provider_name) || optionalString(payload?.server_name) || optionalString(payload?.provider_name) || optionalString(origin?.server_name) || optionalString(origin?.provider_name) || "MCP server";
|
|
1006
|
+
}
|
|
1007
|
+
function normalizedMcpStatus(status) {
|
|
1008
|
+
if (status === "connecting" || status === "connected" || status === "resuming" || status === "error") return status;
|
|
1009
|
+
return "pending";
|
|
1010
|
+
}
|
|
1011
|
+
function HitlPartRow({
|
|
1012
|
+
getHitlActionState,
|
|
1013
|
+
isLoading,
|
|
1014
|
+
onHitlAction,
|
|
1015
|
+
part
|
|
1016
|
+
}) {
|
|
1017
|
+
const state = getHitlActionState?.(part);
|
|
1018
|
+
const message = optionalString(part.hitl.message) || optionalString(part.hitl.text) || "Input is required to continue.";
|
|
1019
|
+
if (isMcpConnectHitl(part)) {
|
|
1020
|
+
return /* @__PURE__ */ jsx7(
|
|
1021
|
+
McpConnectRequiredCard,
|
|
1022
|
+
{
|
|
1023
|
+
error: state?.error,
|
|
1024
|
+
message,
|
|
1025
|
+
onConnect: onHitlAction ? () => onHitlAction(part, CONNECT_DECISION) : void 0,
|
|
1026
|
+
serverName: mcpConnectLabel(part),
|
|
1027
|
+
status: normalizedMcpStatus(state?.status)
|
|
1028
|
+
}
|
|
1029
|
+
);
|
|
1030
|
+
}
|
|
1031
|
+
const decisions = collectHitlDecisions(part);
|
|
1032
|
+
return /* @__PURE__ */ jsxs4("div", { className: "space-y-3", children: [
|
|
1033
|
+
/* @__PURE__ */ jsx7(MessageResponse, { children: message }),
|
|
1034
|
+
state?.error ? /* @__PURE__ */ jsx7("div", { className: "text-sm text-destructive", children: state.error }) : null,
|
|
1035
|
+
/* @__PURE__ */ jsx7("div", { className: "flex flex-wrap items-center gap-2", children: decisions.map((decision) => /* @__PURE__ */ jsx7(
|
|
1036
|
+
"button",
|
|
1037
|
+
{
|
|
1038
|
+
className: cn(
|
|
1039
|
+
"min-w-24 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-60",
|
|
1040
|
+
decision === "approve" || decision === "connect" ? "border-neutral-900 bg-neutral-900 text-white hover:bg-neutral-800" : "border-border bg-background text-foreground hover:bg-muted"
|
|
1041
|
+
),
|
|
1042
|
+
disabled: !onHitlAction || isLoading || state?.status === "connecting" || state?.status === "resuming",
|
|
1043
|
+
onClick: () => onHitlAction?.(part, decision),
|
|
1044
|
+
type: "button",
|
|
1045
|
+
children: decision === "connect" ? "Connect" : decision
|
|
1046
|
+
},
|
|
1047
|
+
decision
|
|
1048
|
+
)) })
|
|
1049
|
+
] });
|
|
1050
|
+
}
|
|
1051
|
+
function DefaultPartRow({
|
|
1052
|
+
activeToolId,
|
|
1053
|
+
getHitlActionState,
|
|
1054
|
+
isLoading,
|
|
1055
|
+
message,
|
|
1056
|
+
onHitlAction,
|
|
1057
|
+
part
|
|
1058
|
+
}) {
|
|
1059
|
+
if (part.kind === "text") return /* @__PURE__ */ jsx7(MessageResponse, { children: part.text });
|
|
1060
|
+
if (part.kind === "tool") return /* @__PURE__ */ jsx7(ToolPartRow, { activeToolId, part });
|
|
1061
|
+
if (part.kind === "reasoning") {
|
|
1062
|
+
const label = part.text || part.label || "Thinking";
|
|
1063
|
+
return part.status === "running" || part.status === "streaming" ? /* @__PURE__ */ jsx7(Shimmer, { className: "text-sm text-muted-foreground", children: label }) : /* @__PURE__ */ jsx7("div", { className: "text-sm text-muted-foreground", children: label });
|
|
1064
|
+
}
|
|
1065
|
+
if (part.kind === "ui-blocks") {
|
|
1066
|
+
if (part.state === "output-error") {
|
|
1067
|
+
return /* @__PURE__ */ jsx7("div", { className: "text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
|
|
1068
|
+
}
|
|
1069
|
+
return /* @__PURE__ */ jsx7(CompactTask, { label: part.state === "input-streaming" ? "Rendering UI block" : "Rendered UI block", loading: part.state === "input-streaming" });
|
|
1070
|
+
}
|
|
1071
|
+
if (part.kind === "hitl") {
|
|
1072
|
+
return /* @__PURE__ */ jsx7(
|
|
1073
|
+
HitlPartRow,
|
|
1074
|
+
{
|
|
1075
|
+
getHitlActionState,
|
|
1076
|
+
isLoading,
|
|
1077
|
+
onHitlAction,
|
|
1078
|
+
part
|
|
1079
|
+
}
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
if (part.kind === "error") return /* @__PURE__ */ jsx7("div", { className: "text-sm text-destructive", children: part.errorText });
|
|
1083
|
+
if (part.kind === "data") return /* @__PURE__ */ jsx7("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
function AgentResponseTimeline({
|
|
1087
|
+
getHitlActionState,
|
|
1088
|
+
isLoading = false,
|
|
1089
|
+
message,
|
|
1090
|
+
onHitlAction,
|
|
1091
|
+
renderPart
|
|
1092
|
+
}) {
|
|
1093
|
+
const parts = message.parts || [];
|
|
1094
|
+
const activeToolId = [...parts].reverse().find((part) => part.kind === "tool" && (part.state === "input-available" || part.state === "input-streaming"))?.id;
|
|
1095
|
+
const rendered = [];
|
|
1096
|
+
let index = 0;
|
|
1097
|
+
while (index < parts.length) {
|
|
1098
|
+
const part = parts[index];
|
|
1099
|
+
if (part.kind === "tool" && groupKey(part)) {
|
|
1100
|
+
const key = groupKey(part);
|
|
1101
|
+
const group = [];
|
|
1102
|
+
while (index < parts.length) {
|
|
1103
|
+
const candidate = parts[index];
|
|
1104
|
+
if (candidate.kind !== "tool" || groupKey(candidate) !== key) break;
|
|
1105
|
+
group.push(candidate);
|
|
1106
|
+
index += 1;
|
|
1107
|
+
}
|
|
1108
|
+
rendered.push(group.length === 1 ? /* @__PURE__ */ jsx7(ToolPartRow, { activeToolId, part: group[0] }, group[0].id) : /* @__PURE__ */ jsx7(ToolGroup, { activeToolId, parts: group }, `tool-group-${key}-${group[0].id}`));
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
rendered.push(
|
|
1112
|
+
/* @__PURE__ */ jsx7(React4.Fragment, { children: renderPart ? renderPart(part, message) : /* @__PURE__ */ jsx7(
|
|
1113
|
+
DefaultPartRow,
|
|
1114
|
+
{
|
|
1115
|
+
activeToolId,
|
|
1116
|
+
getHitlActionState,
|
|
1117
|
+
isLoading,
|
|
1118
|
+
message,
|
|
1119
|
+
onHitlAction,
|
|
1120
|
+
part
|
|
1121
|
+
}
|
|
1122
|
+
) }, part.id)
|
|
1123
|
+
);
|
|
1124
|
+
index += 1;
|
|
1125
|
+
}
|
|
1126
|
+
if (rendered.length === 0 && message.content) {
|
|
1127
|
+
rendered.push(/* @__PURE__ */ jsx7(MessageResponse, { children: message.content }, `${message.id}-fallback`));
|
|
1128
|
+
}
|
|
1129
|
+
if (rendered.length === 0 && isLoading) {
|
|
1130
|
+
rendered.push(/* @__PURE__ */ jsx7("div", { className: "text-sm text-muted-foreground", children: "Thinking" }, `${message.id}-thinking`));
|
|
1131
|
+
}
|
|
1132
|
+
return /* @__PURE__ */ jsx7("div", { className: "space-y-3", children: rendered });
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
// src/ui/agent-chat-message.tsx
|
|
1136
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1137
|
+
var DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD = 360;
|
|
1138
|
+
var DEFAULT_USER_MESSAGE_COLLAPSED_LINES = 4;
|
|
1139
|
+
function shouldCollapseUserMessage(content, threshold = DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD) {
|
|
1140
|
+
return typeof threshold === "number" && threshold > 0 && content.length > threshold;
|
|
1141
|
+
}
|
|
1142
|
+
function AgentChatUserMessageContent({
|
|
1143
|
+
collapsedLines = DEFAULT_USER_MESSAGE_COLLAPSED_LINES,
|
|
1144
|
+
collapseThreshold = DEFAULT_USER_MESSAGE_COLLAPSE_THRESHOLD,
|
|
1145
|
+
content,
|
|
1146
|
+
showLessLabel = "Show less",
|
|
1147
|
+
showMoreLabel = "Show more"
|
|
1148
|
+
}) {
|
|
1149
|
+
const [isExpanded, setIsExpanded] = React5.useState(false);
|
|
1150
|
+
const contentId = React5.useId();
|
|
1151
|
+
const shouldCollapse = shouldCollapseUserMessage(content, collapseThreshold);
|
|
1152
|
+
const Icon = isExpanded ? ChevronUp : ChevronDown2;
|
|
1153
|
+
const clampedStyle = shouldCollapse && !isExpanded ? {
|
|
1154
|
+
WebkitBoxOrient: "vertical",
|
|
1155
|
+
WebkitLineClamp: Math.max(1, collapsedLines),
|
|
1156
|
+
display: "-webkit-box",
|
|
1157
|
+
overflow: "hidden"
|
|
1158
|
+
} : void 0;
|
|
1159
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-col gap-3", children: [
|
|
1160
|
+
/* @__PURE__ */ jsx8("div", { id: contentId, className: "min-w-0", style: clampedStyle, children: content }),
|
|
1161
|
+
shouldCollapse ? /* @__PURE__ */ jsxs5(
|
|
1162
|
+
"button",
|
|
1163
|
+
{
|
|
1164
|
+
"aria-controls": contentId,
|
|
1165
|
+
"aria-expanded": isExpanded,
|
|
1166
|
+
className: cn(
|
|
1167
|
+
"inline-flex w-fit items-center gap-1 rounded-md text-left text-sm font-medium text-muted-foreground transition-colors",
|
|
1168
|
+
"hover:text-foreground focus-visible:border-neutral-300 focus-visible:outline-none focus-visible:ring-0"
|
|
1169
|
+
),
|
|
1170
|
+
onClick: () => setIsExpanded((current) => !current),
|
|
1171
|
+
type: "button",
|
|
1172
|
+
children: [
|
|
1173
|
+
isExpanded ? showLessLabel : showMoreLabel,
|
|
1174
|
+
/* @__PURE__ */ jsx8(Icon, { "aria-hidden": "true", className: "size-4", strokeWidth: 2 })
|
|
1175
|
+
]
|
|
1176
|
+
}
|
|
1177
|
+
) : null
|
|
1178
|
+
] });
|
|
1179
|
+
}
|
|
1180
|
+
function AgentChatMessage({
|
|
1181
|
+
actionHandlers,
|
|
1182
|
+
actions,
|
|
1183
|
+
actionsClassName,
|
|
1184
|
+
className,
|
|
1185
|
+
contentClassName,
|
|
1186
|
+
dir,
|
|
1187
|
+
getHitlActionState,
|
|
1188
|
+
message,
|
|
1189
|
+
onHitlAction,
|
|
1190
|
+
renderAssistantContent,
|
|
1191
|
+
renderPart,
|
|
1192
|
+
renderUserContent,
|
|
1193
|
+
showAssistantAttachments = false,
|
|
1194
|
+
streamingMessageId,
|
|
1195
|
+
userMessageCollapsedLines,
|
|
1196
|
+
userMessageContent,
|
|
1197
|
+
userMessageCollapseThreshold,
|
|
1198
|
+
userMessageShowLessLabel,
|
|
1199
|
+
userMessageShowMoreLabel
|
|
1200
|
+
}) {
|
|
1201
|
+
const isAssistant = message.role === "assistant";
|
|
1202
|
+
const isStreaming = isAssistant && message.id === streamingMessageId;
|
|
1203
|
+
const resolvedUserContent = userMessageContent ?? message.content;
|
|
1204
|
+
const shouldRenderContent = isAssistant || Boolean(renderUserContent || resolvedUserContent);
|
|
1205
|
+
const showAttachments = Boolean(message.attachments?.length) && (message.role === "user" || showAssistantAttachments);
|
|
1206
|
+
const renderedActions = actions ?? (actionHandlers ? /* @__PURE__ */ jsx8(AgentChatDefaultActions, { handlers: actionHandlers, message }) : null);
|
|
1207
|
+
return /* @__PURE__ */ jsxs5(ChatMessage, { className, dir, from: message.role, children: [
|
|
1208
|
+
showAttachments ? /* @__PURE__ */ jsx8(ChatAttachments, { className: "mb-2", dir, children: message.attachments?.map((attachment, index) => /* @__PURE__ */ jsx8(
|
|
1209
|
+
ChatAttachment,
|
|
1210
|
+
{
|
|
1211
|
+
data: attachment,
|
|
1212
|
+
dir: "ltr"
|
|
1213
|
+
},
|
|
1214
|
+
String(attachment.url || attachment.filename || index)
|
|
1215
|
+
)) }) : null,
|
|
1216
|
+
shouldRenderContent ? /* @__PURE__ */ jsxs5(
|
|
1217
|
+
ChatMessageContent,
|
|
1218
|
+
{
|
|
1219
|
+
className: cn(isAssistant ? "bg-transparent p-0" : void 0, contentClassName),
|
|
1220
|
+
dir,
|
|
1221
|
+
children: [
|
|
1222
|
+
isAssistant ? renderAssistantContent ? renderAssistantContent({ isStreaming, message }) : /* @__PURE__ */ jsx8(
|
|
1223
|
+
AgentResponseTimeline,
|
|
1224
|
+
{
|
|
1225
|
+
getHitlActionState,
|
|
1226
|
+
isLoading: isStreaming,
|
|
1227
|
+
message,
|
|
1228
|
+
onHitlAction,
|
|
1229
|
+
renderPart
|
|
1230
|
+
}
|
|
1231
|
+
) : null,
|
|
1232
|
+
!isAssistant ? renderUserContent ? renderUserContent({ message }) : resolvedUserContent ? /* @__PURE__ */ jsx8(
|
|
1233
|
+
AgentChatUserMessageContent,
|
|
1234
|
+
{
|
|
1235
|
+
collapsedLines: userMessageCollapsedLines,
|
|
1236
|
+
collapseThreshold: userMessageCollapseThreshold,
|
|
1237
|
+
content: resolvedUserContent,
|
|
1238
|
+
showLessLabel: userMessageShowLessLabel,
|
|
1239
|
+
showMoreLabel: userMessageShowMoreLabel
|
|
1240
|
+
}
|
|
1241
|
+
) : null : null
|
|
1242
|
+
]
|
|
1243
|
+
}
|
|
1244
|
+
) : null,
|
|
1245
|
+
renderedActions ? /* @__PURE__ */ jsx8("div", { className: cn(dir === "rtl" ? "mt-1 h-9 w-full translate-x-2" : "mt-1 h-9 w-full -translate-x-2", actionsClassName), children: renderedActions }) : null
|
|
1246
|
+
] });
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
// src/ui/bubble.tsx
|
|
1250
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
1251
|
+
import { Slot as Slot2 } from "@radix-ui/react-slot";
|
|
1252
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1253
|
+
function BubbleGroup({ className, ...props }) {
|
|
1254
|
+
return /* @__PURE__ */ jsx9(
|
|
1255
|
+
"div",
|
|
1256
|
+
{
|
|
1257
|
+
"data-slot": "bubble-group",
|
|
1258
|
+
className: cn("flex min-w-0 flex-col gap-2", className),
|
|
1259
|
+
...props
|
|
1260
|
+
}
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
var bubbleVariants = cva2(
|
|
1264
|
+
"group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
|
|
1265
|
+
{
|
|
1266
|
+
variants: {
|
|
1267
|
+
variant: {
|
|
1268
|
+
default: "*:data-[slot=bubble-content]:bg-neutral-900 *:data-[slot=bubble-content]:text-white [&>[data-slot=bubble-content]:is(button,a):hover]:bg-neutral-800",
|
|
1269
|
+
secondary: "*:data-[slot=bubble-content]:bg-muted *:data-[slot=bubble-content]:text-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted",
|
|
1270
|
+
muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
|
|
1271
|
+
tinted: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-muted *:data-[slot=bubble-content]:text-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted",
|
|
1272
|
+
outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
|
|
1273
|
+
ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
|
|
1274
|
+
destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
|
|
1275
|
+
}
|
|
1276
|
+
},
|
|
1277
|
+
defaultVariants: {
|
|
1278
|
+
variant: "default"
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
);
|
|
1282
|
+
function Bubble({
|
|
1283
|
+
variant = "default",
|
|
1284
|
+
align = "start",
|
|
1285
|
+
className,
|
|
1286
|
+
...props
|
|
1287
|
+
}) {
|
|
1288
|
+
return /* @__PURE__ */ jsx9(
|
|
1289
|
+
"div",
|
|
1290
|
+
{
|
|
1291
|
+
"data-slot": "bubble",
|
|
1292
|
+
"data-variant": variant,
|
|
1293
|
+
"data-align": align,
|
|
1294
|
+
className: cn(bubbleVariants({ variant }), className),
|
|
1295
|
+
...props
|
|
1296
|
+
}
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
function BubbleContent({
|
|
1300
|
+
asChild = false,
|
|
1301
|
+
className,
|
|
1302
|
+
...props
|
|
1303
|
+
}) {
|
|
1304
|
+
const Comp = asChild ? Slot2 : "div";
|
|
1305
|
+
return /* @__PURE__ */ jsx9(
|
|
1306
|
+
Comp,
|
|
1307
|
+
{
|
|
1308
|
+
"data-slot": "bubble-content",
|
|
1309
|
+
className: cn(
|
|
1310
|
+
"w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-neutral-300 [button,a]:focus-visible:ring-0",
|
|
1311
|
+
className
|
|
1312
|
+
),
|
|
1313
|
+
...props
|
|
1314
|
+
}
|
|
1315
|
+
);
|
|
1316
|
+
}
|
|
1317
|
+
var bubbleReactionsVariants = cva2(
|
|
1318
|
+
"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
|
|
1319
|
+
{
|
|
1320
|
+
variants: {
|
|
1321
|
+
side: {
|
|
1322
|
+
top: "top-0 -translate-y-3/4",
|
|
1323
|
+
bottom: "bottom-0 translate-y-3/4"
|
|
1324
|
+
},
|
|
1325
|
+
align: {
|
|
1326
|
+
start: "left-3",
|
|
1327
|
+
end: "right-3"
|
|
1328
|
+
}
|
|
1329
|
+
},
|
|
1330
|
+
defaultVariants: {
|
|
1331
|
+
side: "bottom",
|
|
1332
|
+
align: "end"
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
);
|
|
1336
|
+
function BubbleReactions({
|
|
1337
|
+
side = "bottom",
|
|
1338
|
+
align = "end",
|
|
1339
|
+
className,
|
|
1340
|
+
...props
|
|
1341
|
+
}) {
|
|
1342
|
+
return /* @__PURE__ */ jsx9(
|
|
1343
|
+
"div",
|
|
1344
|
+
{
|
|
1345
|
+
"data-slot": "bubble-reactions",
|
|
1346
|
+
"data-align": align,
|
|
1347
|
+
"data-side": side,
|
|
1348
|
+
className: cn(bubbleReactionsVariants({ side, align }), className),
|
|
1349
|
+
...props
|
|
1350
|
+
}
|
|
1351
|
+
);
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// src/ui/marker.tsx
|
|
1355
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
1356
|
+
import { Slot as Slot3 } from "@radix-ui/react-slot";
|
|
1357
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1358
|
+
var markerVariants = cva3(
|
|
1359
|
+
"group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground",
|
|
1360
|
+
{
|
|
1361
|
+
variants: {
|
|
1362
|
+
variant: {
|
|
1363
|
+
default: "",
|
|
1364
|
+
separator: "before:mr-1 before:h-px before:min-w-0 before:flex-1 before:bg-border after:ml-1 after:h-px after:min-w-0 after:flex-1 after:bg-border",
|
|
1365
|
+
border: "border-b border-border pb-2"
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
function Marker({
|
|
1371
|
+
className,
|
|
1372
|
+
variant = "default",
|
|
1373
|
+
asChild = false,
|
|
1374
|
+
...props
|
|
1375
|
+
}) {
|
|
1376
|
+
const Comp = asChild ? Slot3 : "div";
|
|
1377
|
+
return /* @__PURE__ */ jsx10(
|
|
1378
|
+
Comp,
|
|
1379
|
+
{
|
|
1380
|
+
"data-slot": "marker",
|
|
1381
|
+
"data-variant": variant,
|
|
1382
|
+
className: cn(markerVariants({ variant, className })),
|
|
1383
|
+
...props
|
|
1384
|
+
}
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
function MarkerIcon({ className, ...props }) {
|
|
1388
|
+
return /* @__PURE__ */ jsx10(
|
|
1389
|
+
"span",
|
|
1390
|
+
{
|
|
1391
|
+
"data-slot": "marker-icon",
|
|
1392
|
+
"aria-hidden": "true",
|
|
1393
|
+
className: cn(
|
|
1394
|
+
"size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
1395
|
+
className
|
|
1396
|
+
),
|
|
1397
|
+
...props
|
|
1398
|
+
}
|
|
1399
|
+
);
|
|
1400
|
+
}
|
|
1401
|
+
function MarkerContent({ className, ...props }) {
|
|
1402
|
+
return /* @__PURE__ */ jsx10(
|
|
1403
|
+
"span",
|
|
1404
|
+
{
|
|
1405
|
+
"data-slot": "marker-content",
|
|
1406
|
+
className: cn(
|
|
1407
|
+
"min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
1408
|
+
className
|
|
1409
|
+
),
|
|
1410
|
+
...props
|
|
1411
|
+
}
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
692
1414
|
export {
|
|
1415
|
+
AgentChatComposer,
|
|
1416
|
+
AgentChatDefaultActions,
|
|
1417
|
+
AgentChatMessage,
|
|
1418
|
+
DefaultPartRow as AgentChatPartRow,
|
|
1419
|
+
AgentChatUserMessageContent,
|
|
1420
|
+
AgentResponseTimeline,
|
|
693
1421
|
Attachment,
|
|
694
1422
|
AttachmentAction,
|
|
695
1423
|
AttachmentActions,
|
|
@@ -712,6 +1440,7 @@ export {
|
|
|
712
1440
|
Marker,
|
|
713
1441
|
MarkerContent,
|
|
714
1442
|
MarkerIcon,
|
|
1443
|
+
McpConnectRequiredCard,
|
|
715
1444
|
ChatMessage as Message,
|
|
716
1445
|
ChatMessageAction as MessageAction,
|
|
717
1446
|
ChatMessageActions as MessageActions,
|
|
@@ -729,6 +1458,7 @@ export {
|
|
|
729
1458
|
attachmentVariants,
|
|
730
1459
|
bubbleVariants,
|
|
731
1460
|
cn,
|
|
732
|
-
markerVariants
|
|
1461
|
+
markerVariants,
|
|
1462
|
+
shouldCollapseUserMessage
|
|
733
1463
|
};
|
|
734
1464
|
//# sourceMappingURL=index.js.map
|