@agents24/chat-react 0.3.2 → 0.5.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/LICENSE +19 -0
- package/README.md +24 -64
- package/compatibility.json +54 -0
- package/dist/active-content.d.ts +10 -0
- package/dist/{chunk-EWZO4QJI.js → chunk-CHAU7FNW.js} +3 -3
- package/dist/chunk-CHAU7FNW.js.map +1 -0
- package/dist/{chunk-FFO6KEB4.js → chunk-LI67M74F.js} +98 -12
- package/dist/chunk-LI67M74F.js.map +1 -0
- package/dist/chunk-R7WFL3YR.js +1327 -0
- package/dist/chunk-R7WFL3YR.js.map +1 -0
- package/dist/index.cjs +66 -1852
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -6
- package/dist/index.js +6 -1841
- package/dist/index.js.map +1 -1
- package/dist/latest-thread-scroller.d.ts +7 -7
- package/dist/mcp-oauth.d.ts +3 -1
- package/dist/renderers.d.ts +3 -3
- package/dist/styles.css +493 -0
- package/dist/templates/agent-chat-app.d.ts +18 -0
- package/dist/templates/agent-chat-layout.d.ts +77 -0
- package/dist/templates/agent-chat-shell.d.ts +1 -1
- package/dist/templates/appearance-control.d.ts +5 -0
- package/dist/templates/index.cjs +2028 -18
- package/dist/templates/index.cjs.map +1 -1
- package/dist/templates/index.d.ts +3 -0
- package/dist/templates/index.js +652 -11
- package/dist/templates/index.js.map +1 -1
- package/dist/types.d.ts +12 -380
- package/dist/ui/agent-chat-actions.d.ts +1 -2
- package/dist/ui/agent-chat-composer.d.ts +2 -1
- package/dist/ui/agent-chat-message.d.ts +3 -3
- package/dist/ui/agent-response-timeline.d.ts +2 -2
- package/dist/ui/attachment.d.ts +9 -9
- package/dist/ui/bubble.d.ts +4 -4
- package/dist/ui/index.cjs +138 -44
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.js +62 -1220
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/marker.d.ts +3 -3
- package/dist/ui/mcp-connect-required-card.d.ts +1 -1
- package/dist/ui/message-response.d.ts +1 -1
- package/dist/ui/message.d.ts +6 -6
- package/package.json +27 -8
- package/dist/chunk-EWZO4QJI.js.map +0 -1
- package/dist/chunk-FFO6KEB4.js.map +0 -1
- package/dist/chunk-UU7OXHL3.js +0 -11
- package/dist/chunk-UU7OXHL3.js.map +0 -1
- package/dist/context-window.d.ts +0 -38
- package/dist/controller-actions.d.ts +0 -45
- package/dist/controller-helpers.d.ts +0 -27
- package/dist/controller-hitl.d.ts +0 -22
- package/dist/controller-options.d.ts +0 -15
- package/dist/controller-thread-events.d.ts +0 -7
- package/dist/controller.d.ts +0 -5
- package/dist/message-lifecycle.d.ts +0 -15
- package/dist/model.d.ts +0 -30
- package/dist/sse.d.ts +0 -5
- package/dist/transport.d.ts +0 -43
package/dist/ui/attachment.d.ts
CHANGED
|
@@ -6,18 +6,18 @@ declare const attachmentVariants: (props?: ({
|
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
declare function Attachment({ className, state, size, orientation, ...props }: React.ComponentProps<"div"> & VariantProps<typeof attachmentVariants> & {
|
|
8
8
|
state?: "idle" | "uploading" | "processing" | "error" | "done";
|
|
9
|
-
}):
|
|
9
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
10
10
|
declare const attachmentMediaVariants: (props?: ({
|
|
11
11
|
variant?: "image" | "icon" | null | undefined;
|
|
12
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
|
-
declare function AttachmentMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>):
|
|
14
|
-
declare function AttachmentContent({ className, ...props }: React.ComponentProps<"div">):
|
|
15
|
-
declare function AttachmentTitle({ className, ...props }: React.ComponentProps<"span">):
|
|
16
|
-
declare function AttachmentDescription({ className, ...props }: React.ComponentProps<"span">):
|
|
17
|
-
declare function AttachmentActions({ className, ...props }: React.ComponentProps<"div">):
|
|
18
|
-
declare function AttachmentAction({ className, type, ...props }: React.ComponentProps<"button">):
|
|
13
|
+
declare function AttachmentMedia({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof attachmentMediaVariants>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
declare function AttachmentContent({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function AttachmentTitle({ className, ...props }: React.ComponentProps<"span">): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
declare function AttachmentDescription({ className, ...props }: React.ComponentProps<"span">): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
declare function AttachmentActions({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
declare function AttachmentAction({ className, type, ...props }: React.ComponentProps<"button">): import("react/jsx-runtime").JSX.Element;
|
|
19
19
|
declare function AttachmentTrigger({ className, asChild, type, ...props }: React.ComponentProps<"button"> & {
|
|
20
20
|
asChild?: boolean;
|
|
21
|
-
}):
|
|
22
|
-
declare function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">):
|
|
21
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
declare function AttachmentGroup({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
23
23
|
export { Attachment, AttachmentGroup, AttachmentMedia, AttachmentContent, AttachmentTitle, AttachmentDescription, AttachmentActions, AttachmentAction, AttachmentTrigger, attachmentVariants, attachmentMediaVariants, };
|
package/dist/ui/bubble.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
|
-
declare function BubbleGroup({ className, ...props }: React.ComponentProps<"div">):
|
|
3
|
+
declare function BubbleGroup({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
declare const bubbleVariants: (props?: ({
|
|
5
5
|
variant?: "default" | "secondary" | "muted" | "tinted" | "outline" | "ghost" | "destructive" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
7
|
declare function Bubble({ variant, align, className, ...props }: React.ComponentProps<"div"> & VariantProps<typeof bubbleVariants> & {
|
|
8
8
|
align?: "start" | "end";
|
|
9
|
-
}):
|
|
9
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
10
10
|
declare function BubbleContent({ asChild, className, ...props }: React.ComponentProps<"div"> & {
|
|
11
11
|
asChild?: boolean;
|
|
12
|
-
}):
|
|
12
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
13
13
|
declare function BubbleReactions({ side, align, className, ...props }: React.ComponentProps<"div"> & {
|
|
14
14
|
align?: "start" | "end";
|
|
15
15
|
side?: "top" | "bottom";
|
|
16
|
-
}):
|
|
16
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
17
17
|
export { BubbleGroup, Bubble, BubbleContent, BubbleReactions, bubbleVariants };
|
package/dist/ui/index.cjs
CHANGED
|
@@ -104,7 +104,8 @@ function createComposerFile(file) {
|
|
|
104
104
|
type: "file",
|
|
105
105
|
url: URL.createObjectURL(file),
|
|
106
106
|
filename: file.name || "attachment",
|
|
107
|
-
mediaType: file.type || "application/octet-stream"
|
|
107
|
+
mediaType: file.type || "application/octet-stream",
|
|
108
|
+
source: file
|
|
108
109
|
};
|
|
109
110
|
}
|
|
110
111
|
function revokeComposerFiles(files) {
|
|
@@ -120,7 +121,7 @@ function formatFileCount(files) {
|
|
|
120
121
|
return `${files.length} files`;
|
|
121
122
|
}
|
|
122
123
|
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";
|
|
123
|
-
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-
|
|
124
|
+
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-[background-color,color,opacity,transform] 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";
|
|
124
125
|
function AgentChatComposer({
|
|
125
126
|
accept,
|
|
126
127
|
allowAttachments = true,
|
|
@@ -132,7 +133,7 @@ function AgentChatComposer({
|
|
|
132
133
|
onAttachmentCountChange,
|
|
133
134
|
onStop,
|
|
134
135
|
onSubmit,
|
|
135
|
-
placeholder = "Send follow-up",
|
|
136
|
+
placeholder = "Send follow-up\u2026",
|
|
136
137
|
textareaRef
|
|
137
138
|
}) {
|
|
138
139
|
const fileInputRef = React.useRef(null);
|
|
@@ -206,19 +207,20 @@ function AgentChatComposer({
|
|
|
206
207
|
void submit();
|
|
207
208
|
}
|
|
208
209
|
};
|
|
209
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("relative mx-auto w-full max-w-3xl overflow-visible", className), children: [
|
|
210
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: cn("a24-composer relative mx-auto w-full max-w-3xl overflow-visible", className), children: [
|
|
210
211
|
files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
211
212
|
"div",
|
|
212
213
|
{
|
|
213
214
|
"data-testid": "agent-chat-composer-attachments",
|
|
215
|
+
"data-layout": attachmentLayout,
|
|
214
216
|
className: cn(
|
|
215
|
-
"flex min-w-0 gap-2 py-1",
|
|
217
|
+
"a24-composer__attachments flex min-w-0 gap-2 py-1",
|
|
216
218
|
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"
|
|
217
219
|
),
|
|
218
220
|
children: files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
219
221
|
"div",
|
|
220
222
|
{
|
|
221
|
-
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",
|
|
223
|
+
className: "a24-composer__attachment 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",
|
|
222
224
|
children: [
|
|
223
225
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex size-5 shrink-0 items-center justify-center rounded bg-background text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Paperclip, { className: "size-3" }) }),
|
|
224
226
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "min-w-0 flex-1 truncate", children: file.filename }),
|
|
@@ -226,7 +228,7 @@ function AgentChatComposer({
|
|
|
226
228
|
"button",
|
|
227
229
|
{
|
|
228
230
|
"aria-label": `Remove ${file.filename}`,
|
|
229
|
-
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",
|
|
231
|
+
className: "a24-composer__attachment-remove 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",
|
|
230
232
|
onClick: () => removeFile(file.id),
|
|
231
233
|
type: "button",
|
|
232
234
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "size-3" })
|
|
@@ -241,14 +243,15 @@ function AgentChatComposer({
|
|
|
241
243
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
242
244
|
"div",
|
|
243
245
|
{
|
|
246
|
+
"data-expanded": isExpanded ? "" : void 0,
|
|
244
247
|
className: cn(
|
|
245
|
-
"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",
|
|
248
|
+
"a24-composer__surface 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",
|
|
246
249
|
isExpanded ? "rounded-[18px] p-2 pb-1.5" : "rounded-full px-2 py-[3px]"
|
|
247
250
|
),
|
|
248
251
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
249
252
|
"div",
|
|
250
253
|
{
|
|
251
|
-
className: "w-full",
|
|
254
|
+
className: "a24-composer__grid w-full",
|
|
252
255
|
style: {
|
|
253
256
|
alignItems: "center",
|
|
254
257
|
display: "grid",
|
|
@@ -257,7 +260,7 @@ function AgentChatComposer({
|
|
|
257
260
|
gap: isExpanded ? "3px 10px" : "8px"
|
|
258
261
|
},
|
|
259
262
|
children: [
|
|
260
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { gridArea: "plus" }, className: "flex shrink-0 items-center justify-center", children: [
|
|
263
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { gridArea: "plus" }, className: "a24-composer__attach-slot flex shrink-0 items-center justify-center", children: [
|
|
261
264
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
262
265
|
"input",
|
|
263
266
|
{
|
|
@@ -266,6 +269,7 @@ function AgentChatComposer({
|
|
|
266
269
|
"aria-label": "Attach files",
|
|
267
270
|
className: "hidden",
|
|
268
271
|
multiple: true,
|
|
272
|
+
name: "attachments",
|
|
269
273
|
onChange: handleFilesChange,
|
|
270
274
|
type: "file"
|
|
271
275
|
}
|
|
@@ -274,7 +278,7 @@ function AgentChatComposer({
|
|
|
274
278
|
"button",
|
|
275
279
|
{
|
|
276
280
|
"aria-label": "Attach files",
|
|
277
|
-
className: pillButtonClass,
|
|
281
|
+
className: cn("a24-composer__attach", pillButtonClass),
|
|
278
282
|
disabled: disabled || isSubmitting || isRunning || !allowAttachments,
|
|
279
283
|
onClick: () => fileInputRef.current?.click(),
|
|
280
284
|
title: "Attach files",
|
|
@@ -283,16 +287,18 @@ function AgentChatComposer({
|
|
|
283
287
|
}
|
|
284
288
|
)
|
|
285
289
|
] }),
|
|
286
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "textarea" }, className: "min-w-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
290
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "textarea" }, className: "a24-composer__textarea-slot min-w-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
287
291
|
"textarea",
|
|
288
292
|
{
|
|
289
293
|
ref: setTextareaRef,
|
|
290
294
|
"aria-label": "Message",
|
|
295
|
+
autoComplete: "off",
|
|
291
296
|
className: cn(
|
|
292
|
-
"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",
|
|
297
|
+
"a24-composer__textarea 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",
|
|
293
298
|
isExpanded ? "min-h-9 max-h-[224px] py-1" : "min-h-9 h-9 max-h-9 py-2"
|
|
294
299
|
),
|
|
295
300
|
disabled: disabled || isSubmitting || isRunning,
|
|
301
|
+
name: "message",
|
|
296
302
|
onChange: (event) => setText(event.target.value),
|
|
297
303
|
onKeyDown: handleKeyDown,
|
|
298
304
|
placeholder,
|
|
@@ -300,14 +306,14 @@ function AgentChatComposer({
|
|
|
300
306
|
value: text
|
|
301
307
|
}
|
|
302
308
|
) }),
|
|
303
|
-
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "toolbar" }, className: "flex min-w-0 items-center gap-1.5", children: inputToolbarContent }) : null,
|
|
309
|
+
isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "toolbar" }, className: "a24-composer__toolbar flex min-w-0 items-center gap-1.5", children: inputToolbarContent }) : null,
|
|
304
310
|
!isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "composer" }, className: "flex min-w-0 items-center gap-1.5" }) : null,
|
|
305
311
|
!isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "mic" }, className: "flex shrink-0 items-center justify-end" }) : null,
|
|
306
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "submit" }, className: "flex shrink-0 items-center justify-end", children: isRunning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { gridArea: "submit" }, className: "a24-composer__submit-slot flex shrink-0 items-center justify-end", children: isRunning ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
307
313
|
"button",
|
|
308
314
|
{
|
|
309
315
|
"aria-label": "Stop generating",
|
|
310
|
-
className: submitButtonClass,
|
|
316
|
+
className: cn("a24-composer__submit", submitButtonClass),
|
|
311
317
|
disabled: disabled || !onStop,
|
|
312
318
|
onClick: onStop,
|
|
313
319
|
title: "Stop",
|
|
@@ -318,7 +324,7 @@ function AgentChatComposer({
|
|
|
318
324
|
"button",
|
|
319
325
|
{
|
|
320
326
|
"aria-label": files.length > 0 ? `Send ${formatFileCount(files)}` : "Send message",
|
|
321
|
-
className: cn(submitButtonClass, text.trim().length > 0 && "hover:scale-105"),
|
|
327
|
+
className: cn("a24-composer__submit", submitButtonClass, text.trim().length > 0 && "hover:scale-105"),
|
|
322
328
|
disabled: !canSubmit,
|
|
323
329
|
onClick: () => void submit(),
|
|
324
330
|
title: "Send",
|
|
@@ -331,7 +337,7 @@ function AgentChatComposer({
|
|
|
331
337
|
)
|
|
332
338
|
}
|
|
333
339
|
),
|
|
334
|
-
!isExpanded && inputToolbarContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mt-2 flex items-center gap-2 px-1", children: inputToolbarContent }) : null
|
|
340
|
+
!isExpanded && inputToolbarContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "a24-composer__toolbar a24-composer__toolbar--external mt-2 flex items-center gap-2 px-1", children: inputToolbarContent }) : null
|
|
335
341
|
] });
|
|
336
342
|
}
|
|
337
343
|
|
|
@@ -615,8 +621,8 @@ function ChatMessage(input) {
|
|
|
615
621
|
const messageProps = Object.assign({}, props);
|
|
616
622
|
messageProps.align = resolvedAlign;
|
|
617
623
|
messageProps.className = cn(
|
|
618
|
-
"group flex w-full
|
|
619
|
-
isUser ? cn("is-user justify-end", isRtl ? "mr-auto" : "ml-auto") : "is-assistant",
|
|
624
|
+
"group flex w-full flex-col gap-2",
|
|
625
|
+
isUser ? cn("is-user max-w-[80%] justify-end", isRtl ? "mr-auto" : "ml-auto") : "is-assistant max-w-full",
|
|
620
626
|
className
|
|
621
627
|
);
|
|
622
628
|
return React2.createElement(Message, messageProps);
|
|
@@ -627,13 +633,13 @@ function ChatMessageContent({
|
|
|
627
633
|
}) {
|
|
628
634
|
return React2.createElement("div", {
|
|
629
635
|
className: cn(
|
|
630
|
-
"is-user:dark flex w-
|
|
636
|
+
"is-user:dark flex w-full max-w-full min-w-0 flex-col gap-2 overflow-hidden text-sm group-[.is-user]:w-fit group-[.is-user]:overflow-visible",
|
|
631
637
|
"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",
|
|
632
638
|
"group-[.is-assistant]:w-full group-[.is-assistant]:max-w-full group-[.is-assistant]:text-foreground",
|
|
633
639
|
props.dir === "rtl" ? "group-[.is-user]:mr-auto" : "group-[.is-user]:ml-auto",
|
|
634
640
|
className
|
|
635
641
|
),
|
|
636
|
-
"data-slot": "
|
|
642
|
+
"data-slot": "bubble-content",
|
|
637
643
|
...props
|
|
638
644
|
});
|
|
639
645
|
}
|
|
@@ -804,6 +810,27 @@ var import_lucide_react3 = require("lucide-react");
|
|
|
804
810
|
var React3 = __toESM(require("react"), 1);
|
|
805
811
|
var import_streamdown = require("streamdown");
|
|
806
812
|
|
|
813
|
+
// src/active-content.ts
|
|
814
|
+
var CHAT_MARKDOWN_HARDEN_OPTIONS = Object.freeze({
|
|
815
|
+
allowDataImages: false,
|
|
816
|
+
allowedImagePrefixes: [],
|
|
817
|
+
allowedLinkPrefixes: ["*"],
|
|
818
|
+
allowedProtocols: [],
|
|
819
|
+
defaultOrigin: void 0,
|
|
820
|
+
imageBlockPolicy: "text-only",
|
|
821
|
+
linkBlockPolicy: "text-only"
|
|
822
|
+
});
|
|
823
|
+
function safeChatMarkdownHref(value) {
|
|
824
|
+
if (!value) return void 0;
|
|
825
|
+
if (value.startsWith("#")) return value;
|
|
826
|
+
try {
|
|
827
|
+
const url = new URL(value);
|
|
828
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : void 0;
|
|
829
|
+
} catch {
|
|
830
|
+
return void 0;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
807
834
|
// src/streaming-text.ts
|
|
808
835
|
var import_react = require("react");
|
|
809
836
|
var DEFAULT_COMPLETED_TEXT_CACHE_SIZE = 200;
|
|
@@ -830,7 +857,7 @@ function useStreamingText({
|
|
|
830
857
|
const cacheAdapter = cache === false ? null : cache;
|
|
831
858
|
const [displayedText, setDisplayedText] = (0, import_react.useState)(() => {
|
|
832
859
|
const cachedText = cacheAdapter?.get(id);
|
|
833
|
-
return
|
|
860
|
+
return cachedText && text.startsWith(cachedText) ? cachedText : text;
|
|
834
861
|
});
|
|
835
862
|
const targetRef = (0, import_react.useRef)(text);
|
|
836
863
|
const displayedRef = (0, import_react.useRef)(displayedText);
|
|
@@ -849,7 +876,7 @@ function useStreamingText({
|
|
|
849
876
|
if (idRef.current === id) return;
|
|
850
877
|
idRef.current = id;
|
|
851
878
|
const cachedText = cacheAdapter?.get(id);
|
|
852
|
-
const initial =
|
|
879
|
+
const initial = cachedText && text.startsWith(cachedText) ? cachedText : text;
|
|
853
880
|
shouldAnimateRef.current = isStreaming && initial !== text;
|
|
854
881
|
displayedRef.current = initial;
|
|
855
882
|
setDisplayedText(initial);
|
|
@@ -935,6 +962,17 @@ function useStreamingText({
|
|
|
935
962
|
|
|
936
963
|
// src/ui/message-response.tsx
|
|
937
964
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
965
|
+
function SafeMarkdownLink({ children, href, ...props }) {
|
|
966
|
+
const domProps = { ...props };
|
|
967
|
+
delete domProps.node;
|
|
968
|
+
const safeHref = safeChatMarkdownHref(href);
|
|
969
|
+
if (!safeHref) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children });
|
|
970
|
+
if (safeHref.startsWith("#")) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { ...domProps, href: safeHref, children });
|
|
971
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { ...domProps, href: safeHref, rel: "noopener noreferrer", target: "_blank", children });
|
|
972
|
+
}
|
|
973
|
+
function BlockedMarkdownImage({ alt }) {
|
|
974
|
+
return alt ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-label": `Image blocked: ${alt}`, role: "img", children: alt }) : null;
|
|
975
|
+
}
|
|
938
976
|
var BLOCK_MARKDOWN_TAGS = /* @__PURE__ */ new Set([
|
|
939
977
|
"blockquote",
|
|
940
978
|
"div",
|
|
@@ -985,6 +1023,8 @@ function MessageMarkdownParagraph({
|
|
|
985
1023
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { ...domProps, children });
|
|
986
1024
|
}
|
|
987
1025
|
var MESSAGE_RESPONSE_COMPONENTS = {
|
|
1026
|
+
a: SafeMarkdownLink,
|
|
1027
|
+
img: BlockedMarkdownImage,
|
|
988
1028
|
p: MessageMarkdownParagraph
|
|
989
1029
|
};
|
|
990
1030
|
var streamdownDefaultRehypePlugins = import_streamdown.defaultRehypePlugins || {};
|
|
@@ -996,13 +1036,7 @@ var MESSAGE_RESPONSE_REHYPE_PLUGINS = [
|
|
|
996
1036
|
...streamdownHardenPlugin ? [
|
|
997
1037
|
[
|
|
998
1038
|
streamdownHardenPlugin,
|
|
999
|
-
|
|
1000
|
-
allowDataImages: true,
|
|
1001
|
-
allowedImagePrefixes: ["*"],
|
|
1002
|
-
allowedLinkPrefixes: ["*"],
|
|
1003
|
-
allowedProtocols: ["*", "reshet:", "source:"],
|
|
1004
|
-
defaultOrigin: void 0
|
|
1005
|
-
}
|
|
1039
|
+
CHAT_MARKDOWN_HARDEN_OPTIONS
|
|
1006
1040
|
]
|
|
1007
1041
|
] : []
|
|
1008
1042
|
];
|
|
@@ -1031,7 +1065,7 @@ var MessageResponse = React3.memo(
|
|
|
1031
1065
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1032
1066
|
import_streamdown.Streamdown,
|
|
1033
1067
|
{
|
|
1034
|
-
className: cn("
|
|
1068
|
+
className: cn("a24-message-response", className),
|
|
1035
1069
|
components: streamdownComponents,
|
|
1036
1070
|
rehypePlugins: rehypePlugins || MESSAGE_RESPONSE_REHYPE_PLUGINS,
|
|
1037
1071
|
...props,
|
|
@@ -1056,7 +1090,10 @@ function hitlActionLabel(part, action) {
|
|
|
1056
1090
|
function hitlTitle(part) {
|
|
1057
1091
|
const presentation = part.presentation || {};
|
|
1058
1092
|
if (part.hitlKind === "tool_review") return `Run ${optionalString(presentation.tool_name) || "this tool"}?`;
|
|
1059
|
-
if (part.hitlKind === "mcp_auth")
|
|
1093
|
+
if (part.hitlKind === "mcp_auth") {
|
|
1094
|
+
const serverName = optionalString(presentation.server_name);
|
|
1095
|
+
return serverName ? `Connect ${serverName} to continue` : part.message;
|
|
1096
|
+
}
|
|
1060
1097
|
if (part.hitlKind === "app_data_permission") return "Allow this data change?";
|
|
1061
1098
|
return part.message;
|
|
1062
1099
|
}
|
|
@@ -1065,7 +1102,7 @@ function resolvedHitlLabel(part) {
|
|
|
1065
1102
|
return {
|
|
1066
1103
|
approved: part.hitlKind === "user_approval" ? "Approved" : "Allowed",
|
|
1067
1104
|
rejected: part.hitlKind === "user_approval" ? "Rejected" : "Not allowed",
|
|
1068
|
-
connected: "
|
|
1105
|
+
connected: "connected",
|
|
1069
1106
|
skipped: "Skipped",
|
|
1070
1107
|
timeout: "Timed out",
|
|
1071
1108
|
expired: "Timed out",
|
|
@@ -1183,30 +1220,39 @@ function HitlPartRow({
|
|
|
1183
1220
|
const presentation = part.presentation || {};
|
|
1184
1221
|
const requireComment = presentation.require_comment === true;
|
|
1185
1222
|
const isTerminal = part.status !== "pending";
|
|
1223
|
+
const resolvedRef = React4.useRef(null);
|
|
1224
|
+
const wasTerminal = React4.useRef(isTerminal);
|
|
1225
|
+
React4.useEffect(() => {
|
|
1226
|
+
if (isTerminal && !wasTerminal.current) resolvedRef.current?.focus();
|
|
1227
|
+
wasTerminal.current = isTerminal;
|
|
1228
|
+
}, [isTerminal]);
|
|
1186
1229
|
if (isTerminal) {
|
|
1187
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-1 py-1 text-sm text-muted-foreground", children: resolvedHitlLabel(part) });
|
|
1230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-hitl a24-hitl--resolved px-1 py-1 text-sm text-muted-foreground", ref: resolvedRef, role: "status", tabIndex: -1, children: resolvedHitlLabel(part) });
|
|
1188
1231
|
}
|
|
1189
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-2.5
|
|
1190
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm font-medium text-foreground text-pretty", children: hitlTitle(part) }),
|
|
1232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "a24-hitl space-y-2.5 px-1 py-2", children: [
|
|
1233
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-hitl__title text-sm font-medium text-foreground text-pretty", children: hitlTitle(part) }),
|
|
1191
1234
|
requireComment ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1192
1235
|
"textarea",
|
|
1193
1236
|
{
|
|
1194
1237
|
"aria-label": "Approval comment",
|
|
1195
|
-
|
|
1238
|
+
autoComplete: "off",
|
|
1239
|
+
className: "a24-hitl__comment min-h-20 w-full resize-y rounded-md border border-border/60 bg-background px-3 py-2 text-sm outline-none focus-visible:border-neutral-300 focus-visible:ring-0 dark:focus-visible:border-neutral-600",
|
|
1240
|
+
name: "hitl-comment",
|
|
1196
1241
|
onChange: (event) => setComment(event.target.value),
|
|
1197
|
-
placeholder: "Comment required",
|
|
1242
|
+
placeholder: "Comment required\u2026",
|
|
1198
1243
|
value: comment
|
|
1199
1244
|
}
|
|
1200
1245
|
) : null,
|
|
1201
|
-
state?.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", children: state.error }) : null,
|
|
1202
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap items-center gap-1.5", children: part.allowedActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1246
|
+
state?.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-hitl__error text-sm text-destructive", children: state.error }) : null,
|
|
1247
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-hitl__actions flex flex-wrap items-center gap-1.5", children: part.allowedActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1203
1248
|
"button",
|
|
1204
1249
|
{
|
|
1205
1250
|
"aria-label": hitlActionLabel(part, action),
|
|
1206
1251
|
className: cn(
|
|
1207
|
-
"min-h-10 rounded-md px-3 text-sm font-medium transition-[background-color,color,opacity,transform] duration-150 ease-out active:scale-[0.96] disabled:pointer-events-none disabled:opacity-60",
|
|
1252
|
+
"a24-hitl__action min-h-10 rounded-md px-3 text-sm font-medium transition-[background-color,color,opacity,transform] duration-150 ease-out active:scale-[0.96] disabled:pointer-events-none disabled:opacity-60",
|
|
1208
1253
|
action === "approve" || action === "connect" ? "bg-neutral-900 text-white hover:bg-neutral-800 dark:bg-neutral-100 dark:text-neutral-900 dark:hover:bg-white" : "bg-transparent text-muted-foreground hover:bg-background/80 hover:text-foreground"
|
|
1209
1254
|
),
|
|
1255
|
+
"data-primary": action === "approve" || action === "connect" ? "" : void 0,
|
|
1210
1256
|
disabled: !onHitlAction || isLoading || state?.status === "connecting" || state?.status === "resuming" || requireComment && !comment.trim(),
|
|
1211
1257
|
onClick: () => onHitlAction?.(part, action, comment.trim() || void 0),
|
|
1212
1258
|
type: "button",
|
|
@@ -1234,7 +1280,7 @@ function DefaultPartRow({
|
|
|
1234
1280
|
if (part.state === "output-error") {
|
|
1235
1281
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", children: part.errorText || "Failed to render UI content." });
|
|
1236
1282
|
}
|
|
1237
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CompactTask, { label: part.state === "input-streaming" ? "Rendering UI block" : "Rendered UI block", loading: part.state === "input-streaming" });
|
|
1283
|
+
return part.bundle ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SafeUiBlocks, { bundle: part.bundle }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CompactTask, { label: part.state === "input-streaming" ? "Rendering UI block" : "Rendered UI block", loading: part.state === "input-streaming" });
|
|
1238
1284
|
}
|
|
1239
1285
|
if (part.kind === "hitl") {
|
|
1240
1286
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -1247,10 +1293,58 @@ function DefaultPartRow({
|
|
|
1247
1293
|
}
|
|
1248
1294
|
);
|
|
1249
1295
|
}
|
|
1250
|
-
if (part.kind === "error") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", children: part.errorText });
|
|
1296
|
+
if (part.kind === "error") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "text-sm text-destructive", role: "alert", children: part.errorText });
|
|
1297
|
+
if (part.kind === "source") {
|
|
1298
|
+
const href = safeExternalUrl(part.url);
|
|
1299
|
+
return href ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { className: "a24-source-link", href, rel: "noopener noreferrer", target: "_blank", children: part.title }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "a24-source-link", children: part.title });
|
|
1300
|
+
}
|
|
1301
|
+
if (part.kind === "citation") {
|
|
1302
|
+
const href = safeExternalUrl(part.url);
|
|
1303
|
+
const label = part.label || "Citation";
|
|
1304
|
+
return href ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { className: "a24-citation", href, rel: "noopener noreferrer", target: "_blank", children: label }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "a24-citation", children: label });
|
|
1305
|
+
}
|
|
1306
|
+
if (part.kind === "attachment") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-output-attachment", children: part.attachment.filename || "Attachment" });
|
|
1251
1307
|
if (part.kind === "data") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-agents24-data-part": part.name, className: "hidden", children: message.id });
|
|
1252
1308
|
return null;
|
|
1253
1309
|
}
|
|
1310
|
+
function safeExternalUrl(value) {
|
|
1311
|
+
if (!value) return null;
|
|
1312
|
+
try {
|
|
1313
|
+
const url = new URL(value);
|
|
1314
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.href : null;
|
|
1315
|
+
} catch {
|
|
1316
|
+
return null;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
function SafeUiBlocks({ bundle }) {
|
|
1320
|
+
const rows = Array.isArray(bundle.rows) ? bundle.rows : [];
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { "aria-label": typeof bundle.title === "string" ? bundle.title : "Agent result", className: "a24-ui-blocks", children: [
|
|
1322
|
+
typeof bundle.title === "string" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: bundle.title }) : null,
|
|
1323
|
+
rows.map((rawRow, rowIndex) => {
|
|
1324
|
+
const row = rawRow && typeof rawRow === "object" && !Array.isArray(rawRow) ? rawRow : {};
|
|
1325
|
+
const blocks = Array.isArray(row.blocks) ? row.blocks : [];
|
|
1326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-ui-blocks__row", children: blocks.map((rawBlock, blockIndex) => {
|
|
1327
|
+
const block = rawBlock && typeof rawBlock === "object" && !Array.isArray(rawBlock) ? rawBlock : {};
|
|
1328
|
+
const title = typeof block.title === "string" ? block.title : "Result";
|
|
1329
|
+
const kind = String(block.kind || "note");
|
|
1330
|
+
if (kind === "table" && Array.isArray(block.columns) && Array.isArray(block.rows)) {
|
|
1331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "a24-ui-block", children: [
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h4", { children: title }),
|
|
1333
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "a24-ui-table-scroll", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { children: [
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: block.columns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { children: String(column) }, index)) }) }),
|
|
1335
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { children: block.rows.map((rawCells, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: (Array.isArray(rawCells) ? rawCells : []).map((cell, cellIndex) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { children: String(cell) }, cellIndex)) }, index)) })
|
|
1336
|
+
] }) })
|
|
1337
|
+
] }, String(block.id || blockIndex));
|
|
1338
|
+
}
|
|
1339
|
+
const value = block.value ?? block.text ?? "";
|
|
1340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "a24-ui-block", children: [
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h4", { children: title }),
|
|
1342
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: String(value) })
|
|
1343
|
+
] }, String(block.id || blockIndex));
|
|
1344
|
+
}) }, `row-${rowIndex}`);
|
|
1345
|
+
})
|
|
1346
|
+
] });
|
|
1347
|
+
}
|
|
1254
1348
|
function AgentResponseTimeline({
|
|
1255
1349
|
getHitlActionState,
|
|
1256
1350
|
isLoading = false,
|