@cntyclub/agent-react 0.5.0 → 0.6.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/dist/api-client.d.ts +1 -1
- package/dist/api-client.d.ts.map +1 -1
- package/dist/components/agent-composer.d.ts +23 -0
- package/dist/components/agent-composer.d.ts.map +1 -0
- package/dist/components/agent-panel.d.ts.map +1 -1
- package/dist/components/document-card.d.ts +11 -0
- package/dist/components/document-card.d.ts.map +1 -0
- package/dist/components/message-item.d.ts.map +1 -1
- package/dist/components/task-checklist.d.ts +11 -0
- package/dist/components/task-checklist.d.ts.map +1 -0
- package/dist/components/tool-activity-group.d.ts.map +1 -1
- package/dist/file-support.d.ts +13 -0
- package/dist/file-support.d.ts.map +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +463 -66
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +47 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/use-agent-chat.d.ts +1 -1
- package/dist/use-agent-chat.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ChatMessage, ChatMessageBubble, Markdown, Collapsible, CollapsibleTrigger, ChatToolChip,
|
|
2
|
-
import { ChevronDownIcon, CheckIcon, ShieldAlertIcon, CheckCheckIcon, HistoryIcon, SquarePenIcon, Minimize2Icon,
|
|
3
|
-
import * as
|
|
1
|
+
import { Button, cn, ChatMessage, ChatMessageBubble, Markdown, Spinner, Checkbox, Collapsible, CollapsibleTrigger, ChatToolChip, CollapsiblePanel, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Group, Menu, MenuTrigger, MenuPopup, MenuItem, ChatHeader, ChatHeaderAvatar, ChatHeaderTitle, ChatHeaderActions, Tooltip, TooltipTrigger, TooltipContent, Chat, ChatMessages, ChatEmptyState, ChatEmptyStateIcon, ChatEmptyStateTitle, ChatEmptyStateDescription, ChatSuggestions, ChatSuggestion, ChatTypingIndicator, useMediaQuery, TooltipProvider, Fab, DataTablePaged } from '@cntyclub/ui-react';
|
|
2
|
+
import { FileTextIcon, XIcon, PaperclipIcon, ArrowUpIcon, Maximize2Icon, ListChecksIcon, ChevronDownIcon, CheckIcon, ShieldAlertIcon, CheckCheckIcon, UploadCloudIcon, HistoryIcon, SquarePenIcon, Minimize2Icon, Trash2Icon, SparklesIcon, DownloadIcon, CodeIcon } from 'lucide-react';
|
|
3
|
+
import * as React5 from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/api-client.ts
|
|
@@ -25,13 +25,15 @@ var AgentApiClient = class {
|
|
|
25
25
|
const base = this.config.apiBaseUrl.replace(/\/$/, "");
|
|
26
26
|
const separator = path.includes("?") ? "&" : "?";
|
|
27
27
|
const url = `${base}${path}${separator}client_id=${encodeURIComponent(this.config.clientId)}`;
|
|
28
|
+
const isFormData = typeof FormData !== "undefined" && options.body instanceof FormData;
|
|
29
|
+
const headers = {
|
|
30
|
+
Authorization: `Bearer ${token}`,
|
|
31
|
+
"X-Agent-Client-Id": this.config.clientId
|
|
32
|
+
};
|
|
33
|
+
if (!isFormData) headers["Content-Type"] = "application/json";
|
|
28
34
|
const response = await fetch(url, {
|
|
29
|
-
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
30
|
-
headers
|
|
31
|
-
Authorization: `Bearer ${token}`,
|
|
32
|
-
"Content-Type": "application/json",
|
|
33
|
-
"X-Agent-Client-Id": this.config.clientId
|
|
34
|
-
},
|
|
35
|
+
body: options.body === void 0 ? void 0 : isFormData ? options.body : JSON.stringify(options.body),
|
|
36
|
+
headers,
|
|
35
37
|
method: options.method ?? "GET"
|
|
36
38
|
});
|
|
37
39
|
if (response.status === 204) return void 0;
|
|
@@ -49,7 +51,15 @@ var AgentApiClient = class {
|
|
|
49
51
|
getConfig() {
|
|
50
52
|
return this.request("/agent-mode/config/");
|
|
51
53
|
}
|
|
52
|
-
sendMessage(message, conversationId) {
|
|
54
|
+
sendMessage(message, conversationId, files) {
|
|
55
|
+
if (files && files.length > 0) {
|
|
56
|
+
const form = new FormData();
|
|
57
|
+
form.append("client_id", this.config.clientId);
|
|
58
|
+
form.append("message", message);
|
|
59
|
+
if (conversationId) form.append("conversation_id", conversationId);
|
|
60
|
+
for (const file of files) form.append("files", file, file.name);
|
|
61
|
+
return this.request("/agent-mode/chat/", { body: form, method: "POST" });
|
|
62
|
+
}
|
|
53
63
|
return this.request("/agent-mode/chat/", {
|
|
54
64
|
body: {
|
|
55
65
|
client_id: this.config.clientId,
|
|
@@ -78,6 +88,176 @@ var AgentApiClient = class {
|
|
|
78
88
|
}
|
|
79
89
|
};
|
|
80
90
|
|
|
91
|
+
// src/file-support.ts
|
|
92
|
+
var DEFAULT_ACCEPT = [".txt", ".md", ".markdown", ".csv", ".tsv", ".log", ".docx"];
|
|
93
|
+
var DEFAULT_MAX_SIZE_MB = 5;
|
|
94
|
+
function fileUploadEnabled(config) {
|
|
95
|
+
return config.fileUpload?.enabled !== false;
|
|
96
|
+
}
|
|
97
|
+
function acceptedExtensions(config) {
|
|
98
|
+
const accept = config.fileUpload?.accept;
|
|
99
|
+
return accept && accept.length > 0 ? accept.map((ext) => ext.toLowerCase()) : DEFAULT_ACCEPT;
|
|
100
|
+
}
|
|
101
|
+
function maxSizeMb(config) {
|
|
102
|
+
return config.fileUpload?.maxSizeMb ?? DEFAULT_MAX_SIZE_MB;
|
|
103
|
+
}
|
|
104
|
+
function acceptAttribute(config) {
|
|
105
|
+
return acceptedExtensions(config).join(",");
|
|
106
|
+
}
|
|
107
|
+
function extensionOf(filename) {
|
|
108
|
+
const dot = filename.lastIndexOf(".");
|
|
109
|
+
return dot >= 0 ? filename.slice(dot).toLowerCase() : "";
|
|
110
|
+
}
|
|
111
|
+
function validateFile(config, file) {
|
|
112
|
+
const extensions = acceptedExtensions(config);
|
|
113
|
+
if (!extensions.includes(extensionOf(file.name))) {
|
|
114
|
+
return `\u201C${file.name}\u201D isn\u2019t a supported text file. Allowed: ${extensions.join(", ")}.`;
|
|
115
|
+
}
|
|
116
|
+
const limit = maxSizeMb(config);
|
|
117
|
+
if (file.size > limit * 1024 * 1024) {
|
|
118
|
+
return `\u201C${file.name}\u201D is too large (max ${limit} MB).`;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
function formatBytes(bytes) {
|
|
123
|
+
if (!bytes && bytes !== 0) return "";
|
|
124
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
125
|
+
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
|
|
126
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
127
|
+
}
|
|
128
|
+
function AgentComposer({
|
|
129
|
+
acceptAttribute: acceptAttribute2,
|
|
130
|
+
className,
|
|
131
|
+
disabled,
|
|
132
|
+
files,
|
|
133
|
+
onPickFiles,
|
|
134
|
+
onRemoveFile,
|
|
135
|
+
onSubmit,
|
|
136
|
+
onValueChange,
|
|
137
|
+
placeholder = "Ask anything\u2026",
|
|
138
|
+
value
|
|
139
|
+
}) {
|
|
140
|
+
const textareaRef = React5.useRef(null);
|
|
141
|
+
const inputRef = React5.useRef(null);
|
|
142
|
+
const canSubmit = !disabled && (value.trim().length > 0 || files.length > 0);
|
|
143
|
+
const submit = React5.useCallback(() => {
|
|
144
|
+
if (!canSubmit) return;
|
|
145
|
+
onSubmit(value.trim());
|
|
146
|
+
}, [canSubmit, onSubmit, value]);
|
|
147
|
+
React5.useEffect(() => {
|
|
148
|
+
const textarea = textareaRef.current;
|
|
149
|
+
if (!textarea) return;
|
|
150
|
+
textarea.style.height = "auto";
|
|
151
|
+
textarea.style.height = `${Math.min(textarea.scrollHeight, 144)}px`;
|
|
152
|
+
}, [value]);
|
|
153
|
+
const handlePick = (event) => {
|
|
154
|
+
const picked = Array.from(event.target.files ?? []);
|
|
155
|
+
if (picked.length) onPickFiles?.(picked);
|
|
156
|
+
event.target.value = "";
|
|
157
|
+
};
|
|
158
|
+
return /* @__PURE__ */ jsx(
|
|
159
|
+
"form",
|
|
160
|
+
{
|
|
161
|
+
className: cn("shrink-0 bg-background p-3 pt-1.5", className),
|
|
162
|
+
"data-slot": "agent-composer",
|
|
163
|
+
onSubmit: (event) => {
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
submit();
|
|
166
|
+
},
|
|
167
|
+
children: /* @__PURE__ */ jsxs(
|
|
168
|
+
"div",
|
|
169
|
+
{
|
|
170
|
+
className: cn(
|
|
171
|
+
"flex flex-col gap-1.5 rounded-2xl border border-input bg-popover p-1.5 shadow-xs transition-[border-color,box-shadow] duration-150 focus-within:border-ring/64 focus-within:ring-2 focus-within:ring-ring/24 dark:bg-input/32",
|
|
172
|
+
disabled && "opacity-64"
|
|
173
|
+
),
|
|
174
|
+
children: [
|
|
175
|
+
files.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5 px-1 pt-1", children: files.map((file, index) => /* @__PURE__ */ jsxs(
|
|
176
|
+
"span",
|
|
177
|
+
{
|
|
178
|
+
className: "flex max-w-52 items-center gap-1.5 rounded-lg border border-border/72 bg-muted/48 py-1 pr-1 pl-2 text-xs",
|
|
179
|
+
children: [
|
|
180
|
+
/* @__PURE__ */ jsx(FileTextIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }),
|
|
181
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: file.name }),
|
|
182
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: formatBytes(file.size) }),
|
|
183
|
+
onRemoveFile ? /* @__PURE__ */ jsx(
|
|
184
|
+
"button",
|
|
185
|
+
{
|
|
186
|
+
"aria-label": `Remove ${file.name}`,
|
|
187
|
+
className: "flex size-4 shrink-0 cursor-pointer items-center justify-center rounded-full text-muted-foreground hover:bg-background hover:text-foreground [&_svg]:size-3",
|
|
188
|
+
onClick: () => onRemoveFile(index),
|
|
189
|
+
type: "button",
|
|
190
|
+
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
191
|
+
}
|
|
192
|
+
) : null
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
`${file.name}-${index}`
|
|
196
|
+
)) }) : null,
|
|
197
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1.5", children: [
|
|
198
|
+
onPickFiles ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
199
|
+
/* @__PURE__ */ jsx(
|
|
200
|
+
"input",
|
|
201
|
+
{
|
|
202
|
+
accept: acceptAttribute2,
|
|
203
|
+
className: "hidden",
|
|
204
|
+
multiple: true,
|
|
205
|
+
onChange: handlePick,
|
|
206
|
+
ref: inputRef,
|
|
207
|
+
type: "file"
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
/* @__PURE__ */ jsx(
|
|
211
|
+
Button,
|
|
212
|
+
{
|
|
213
|
+
"aria-label": "Attach files",
|
|
214
|
+
className: "shrink-0",
|
|
215
|
+
disabled,
|
|
216
|
+
onClick: () => inputRef.current?.click(),
|
|
217
|
+
size: "icon-sm",
|
|
218
|
+
type: "button",
|
|
219
|
+
variant: "ghost",
|
|
220
|
+
children: /* @__PURE__ */ jsx(PaperclipIcon, {})
|
|
221
|
+
}
|
|
222
|
+
)
|
|
223
|
+
] }) : null,
|
|
224
|
+
/* @__PURE__ */ jsx(
|
|
225
|
+
"textarea",
|
|
226
|
+
{
|
|
227
|
+
className: "max-h-36 min-h-8 flex-1 resize-none self-center bg-transparent py-1.5 pl-1.5 text-sm outline-none placeholder:text-muted-foreground",
|
|
228
|
+
disabled,
|
|
229
|
+
onChange: (event) => onValueChange(event.target.value),
|
|
230
|
+
onKeyDown: (event) => {
|
|
231
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
232
|
+
event.preventDefault();
|
|
233
|
+
submit();
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
placeholder,
|
|
237
|
+
ref: textareaRef,
|
|
238
|
+
rows: 1,
|
|
239
|
+
value
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
/* @__PURE__ */ jsx(
|
|
243
|
+
Button,
|
|
244
|
+
{
|
|
245
|
+
"aria-label": "Send message",
|
|
246
|
+
className: "shrink-0 rounded-full before:rounded-full",
|
|
247
|
+
disabled: !canSubmit,
|
|
248
|
+
size: "icon-sm",
|
|
249
|
+
type: "submit",
|
|
250
|
+
children: /* @__PURE__ */ jsx(ArrowUpIcon, {})
|
|
251
|
+
}
|
|
252
|
+
)
|
|
253
|
+
] })
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
81
261
|
// src/message-group.ts
|
|
82
262
|
function groupMessages(messages) {
|
|
83
263
|
const items = [];
|
|
@@ -147,7 +327,21 @@ function groupMessages(messages) {
|
|
|
147
327
|
}
|
|
148
328
|
function MessageItem({ message }) {
|
|
149
329
|
if (message.role === "user") {
|
|
150
|
-
|
|
330
|
+
const attachments = message.attachments ?? [];
|
|
331
|
+
return /* @__PURE__ */ jsxs(ChatMessage, { from: "user", children: [
|
|
332
|
+
attachments.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-wrap justify-end gap-1.5", children: attachments.map((attachment) => /* @__PURE__ */ jsxs(
|
|
333
|
+
"span",
|
|
334
|
+
{
|
|
335
|
+
className: "flex max-w-52 items-center gap-1.5 rounded-lg border border-border/72 bg-muted/48 px-2 py-1 text-muted-foreground text-xs",
|
|
336
|
+
children: [
|
|
337
|
+
/* @__PURE__ */ jsx(FileTextIcon, { className: "size-3.5 shrink-0" }),
|
|
338
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: attachment.filename })
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
attachment.id
|
|
342
|
+
)) }) : null,
|
|
343
|
+
message.content ? /* @__PURE__ */ jsx(ChatMessageBubble, { from: "user", children: message.content }) : null
|
|
344
|
+
] });
|
|
151
345
|
}
|
|
152
346
|
if (message.role === "assistant") {
|
|
153
347
|
if (!message.content || !message.content.trim()) return null;
|
|
@@ -355,20 +549,146 @@ function resolveToolPresentation(describe, toolName, args) {
|
|
|
355
549
|
}
|
|
356
550
|
return { details, summary, title };
|
|
357
551
|
}
|
|
358
|
-
function
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
552
|
+
function DownloadButton({ block, size = "sm" }) {
|
|
553
|
+
if (!block.download_url) {
|
|
554
|
+
return /* @__PURE__ */ jsx(Button, { disabled: true, size, variant: "outline", children: size === "icon-sm" ? /* @__PURE__ */ jsx(DownloadIcon, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
555
|
+
/* @__PURE__ */ jsx(DownloadIcon, {}),
|
|
556
|
+
" Download"
|
|
557
|
+
] }) });
|
|
558
|
+
}
|
|
559
|
+
return /* @__PURE__ */ jsxs(
|
|
560
|
+
Button,
|
|
561
|
+
{
|
|
562
|
+
render: (
|
|
563
|
+
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
|
564
|
+
/* @__PURE__ */ jsx("a", { download: block.filename, href: block.download_url, rel: "noopener noreferrer", target: "_blank" })
|
|
565
|
+
),
|
|
566
|
+
size,
|
|
567
|
+
variant: size === "icon-sm" ? "outline" : "default",
|
|
568
|
+
children: [
|
|
569
|
+
/* @__PURE__ */ jsx(DownloadIcon, {}),
|
|
570
|
+
size === "icon-sm" ? null : "Download"
|
|
571
|
+
]
|
|
572
|
+
}
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
function DocumentViewer({ block, onClose }) {
|
|
576
|
+
React5.useEffect(() => {
|
|
577
|
+
const onKey = (event) => event.key === "Escape" && onClose();
|
|
578
|
+
window.addEventListener("keydown", onKey);
|
|
579
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
580
|
+
}, [onClose]);
|
|
581
|
+
return /* @__PURE__ */ jsxs("div", { "aria-modal": "true", className: "fixed inset-0 z-[60] flex flex-col bg-background", role: "dialog", children: [
|
|
582
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 border-border/72 border-b px-4 py-3", children: [
|
|
583
|
+
/* @__PURE__ */ jsx(FileTextIcon, { className: "size-4 shrink-0 text-muted-foreground" }),
|
|
584
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
585
|
+
/* @__PURE__ */ jsx("div", { className: "truncate font-medium text-sm", children: block.title || block.filename }),
|
|
586
|
+
/* @__PURE__ */ jsxs("div", { className: "text-muted-foreground text-xs uppercase", children: [
|
|
587
|
+
block.format,
|
|
588
|
+
block.size_bytes ? ` \xB7 ${formatBytes(block.size_bytes)}` : ""
|
|
589
|
+
] })
|
|
590
|
+
] }),
|
|
591
|
+
/* @__PURE__ */ jsx(DownloadButton, { block }),
|
|
592
|
+
/* @__PURE__ */ jsx(Button, { "aria-label": "Close preview", onClick: onClose, size: "icon-sm", variant: "ghost", children: /* @__PURE__ */ jsx(XIcon, {}) })
|
|
593
|
+
] }),
|
|
594
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto p-4", children: /* @__PURE__ */ jsxs("pre", { className: "mx-auto max-w-3xl whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-foreground", children: [
|
|
595
|
+
block.preview || "(no preview available \u2014 download to view)",
|
|
596
|
+
block.preview_truncated ? "\n\n\u2026 preview truncated. Download for the full file." : ""
|
|
597
|
+
] }) })
|
|
598
|
+
] });
|
|
599
|
+
}
|
|
600
|
+
function DocumentCard({ block }) {
|
|
601
|
+
const [open, setOpen] = React5.useState(false);
|
|
602
|
+
const previewLines = (block.preview || "").split("\n").slice(0, 6).join("\n");
|
|
603
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-full overflow-hidden rounded-xl border border-border bg-card shadow-xs", children: [
|
|
604
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-border/72 border-b px-3 py-2", children: [
|
|
605
|
+
/* @__PURE__ */ jsx("span", { className: "flex size-7 shrink-0 items-center justify-center rounded-lg bg-primary/8 text-primary [&_svg]:size-4", children: /* @__PURE__ */ jsx(FileTextIcon, {}) }),
|
|
606
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
607
|
+
/* @__PURE__ */ jsx("div", { className: "truncate font-medium text-sm", children: block.title || block.filename }),
|
|
608
|
+
/* @__PURE__ */ jsxs("div", { className: "text-muted-foreground text-xs uppercase", children: [
|
|
609
|
+
block.format,
|
|
610
|
+
block.size_bytes ? ` \xB7 ${formatBytes(block.size_bytes)}` : ""
|
|
611
|
+
] })
|
|
612
|
+
] }),
|
|
613
|
+
/* @__PURE__ */ jsx(Button, { "aria-label": "Preview", onClick: () => setOpen(true), size: "icon-sm", variant: "ghost", children: /* @__PURE__ */ jsx(Maximize2Icon, {}) }),
|
|
614
|
+
/* @__PURE__ */ jsx(DownloadButton, { block, size: "icon-sm" })
|
|
615
|
+
] }),
|
|
616
|
+
previewLines ? /* @__PURE__ */ jsx(
|
|
617
|
+
"button",
|
|
618
|
+
{
|
|
619
|
+
className: cn(
|
|
620
|
+
"block w-full cursor-pointer px-3 py-2 text-left transition-colors hover:bg-accent/40"
|
|
621
|
+
),
|
|
622
|
+
onClick: () => setOpen(true),
|
|
623
|
+
type: "button",
|
|
624
|
+
children: /* @__PURE__ */ jsx("pre", { className: "max-h-28 overflow-hidden whitespace-pre-wrap break-words font-mono text-[11px] leading-snug text-muted-foreground", children: previewLines })
|
|
625
|
+
}
|
|
626
|
+
) : null,
|
|
627
|
+
open ? /* @__PURE__ */ jsx(DocumentViewer, { block, onClose: () => setOpen(false) }) : null
|
|
628
|
+
] });
|
|
629
|
+
}
|
|
630
|
+
function TaskChecklist({ tasks }) {
|
|
631
|
+
if (!tasks || tasks.length === 0) return null;
|
|
632
|
+
const done = tasks.filter((task) => task.status === "done").length;
|
|
633
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-full rounded-xl border border-border bg-card p-3 shadow-xs", children: [
|
|
634
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-1.5 font-medium text-sm", children: [
|
|
635
|
+
/* @__PURE__ */ jsx(ListChecksIcon, { className: "size-4 text-muted-foreground" }),
|
|
636
|
+
"Tasks",
|
|
637
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-auto text-muted-foreground text-xs", children: [
|
|
638
|
+
done,
|
|
639
|
+
"/",
|
|
640
|
+
tasks.length
|
|
641
|
+
] })
|
|
642
|
+
] }),
|
|
643
|
+
/* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: tasks.map((task, index) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2 text-sm", children: [
|
|
644
|
+
task.status === "in_progress" ? /* @__PURE__ */ jsx("span", { className: "flex size-4 shrink-0 items-center justify-center [&_svg]:size-3.5", children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(
|
|
645
|
+
Checkbox,
|
|
646
|
+
{
|
|
647
|
+
"aria-hidden": true,
|
|
648
|
+
checked: task.status === "done",
|
|
649
|
+
className: "pointer-events-none shrink-0",
|
|
650
|
+
readOnly: true,
|
|
651
|
+
tabIndex: -1
|
|
652
|
+
}
|
|
653
|
+
),
|
|
654
|
+
/* @__PURE__ */ jsx(
|
|
655
|
+
"span",
|
|
656
|
+
{
|
|
657
|
+
className: cn(
|
|
658
|
+
"min-w-0",
|
|
659
|
+
task.status === "done" && "text-muted-foreground line-through",
|
|
660
|
+
task.status === "in_progress" && "font-medium"
|
|
661
|
+
),
|
|
662
|
+
children: task.title
|
|
663
|
+
}
|
|
664
|
+
)
|
|
665
|
+
] }, `${index}-${task.title}`)) })
|
|
666
|
+
] });
|
|
667
|
+
}
|
|
668
|
+
function StepBlocks({ blocks, stepKey }) {
|
|
669
|
+
const visible = (blocks ?? []).filter(
|
|
670
|
+
(block) => block.type === "table" || block.type === "document" || block.type === "tasks"
|
|
671
|
+
);
|
|
672
|
+
if (visible.length === 0) return null;
|
|
673
|
+
return /* @__PURE__ */ jsx(Fragment, { children: visible.map((block, index) => {
|
|
674
|
+
const key = `${stepKey}-block-${index}`;
|
|
675
|
+
if (block.type === "document") {
|
|
676
|
+
return /* @__PURE__ */ jsx(DocumentCard, { block }, key);
|
|
677
|
+
}
|
|
678
|
+
if (block.type === "tasks") {
|
|
679
|
+
return /* @__PURE__ */ jsx(TaskChecklist, { tasks: block.tasks }, key);
|
|
680
|
+
}
|
|
681
|
+
const table = block;
|
|
682
|
+
const { columns, rows } = toDisplayTable(table);
|
|
363
683
|
return /* @__PURE__ */ jsx("div", { className: "w-full max-w-full", children: /* @__PURE__ */ jsx(
|
|
364
684
|
DataTablePaged,
|
|
365
685
|
{
|
|
366
686
|
columns,
|
|
367
687
|
pageSize: 8,
|
|
368
688
|
rows,
|
|
369
|
-
totalCount: typeof
|
|
689
|
+
totalCount: typeof table.pagination?.count === "number" ? table.pagination.count : table.row_count
|
|
370
690
|
}
|
|
371
|
-
) },
|
|
691
|
+
) }, key);
|
|
372
692
|
}) });
|
|
373
693
|
}
|
|
374
694
|
function RawJsonDisclosure({ result }) {
|
|
@@ -400,7 +720,7 @@ function StepDetail({
|
|
|
400
720
|
] });
|
|
401
721
|
}
|
|
402
722
|
function ToolActivityGroup({ describeToolCall, steps }) {
|
|
403
|
-
const [open, setOpen] =
|
|
723
|
+
const [open, setOpen] = React5.useState(false);
|
|
404
724
|
if (steps.length === 0) return null;
|
|
405
725
|
const last = steps[steps.length - 1];
|
|
406
726
|
const anyRunning = steps.some((step) => step.status === "running");
|
|
@@ -430,7 +750,7 @@ function ToolActivityGroup({ describeToolCall, steps }) {
|
|
|
430
750
|
),
|
|
431
751
|
/* @__PURE__ */ jsx(CollapsiblePanel, { children: /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-col gap-1.5", children: steps.map((step) => /* @__PURE__ */ jsx(StepDetail, { describeToolCall, step }, step.callId)) }) })
|
|
432
752
|
] }),
|
|
433
|
-
steps.map((step) => /* @__PURE__ */ jsx(
|
|
753
|
+
steps.map((step) => /* @__PURE__ */ jsx(StepBlocks, { blocks: step.blocks, stepKey: step.callId }, `${step.callId}-blocks`))
|
|
434
754
|
] });
|
|
435
755
|
}
|
|
436
756
|
function ToolApprovalCard({
|
|
@@ -503,21 +823,73 @@ function AgentPanel({
|
|
|
503
823
|
onClose,
|
|
504
824
|
onToggleAgentMode
|
|
505
825
|
}) {
|
|
506
|
-
const [draft, setDraft] =
|
|
507
|
-
const [view, setView] =
|
|
826
|
+
const [draft, setDraft] = React5.useState("");
|
|
827
|
+
const [view, setView] = React5.useState("chat");
|
|
828
|
+
const [files, setFiles] = React5.useState([]);
|
|
829
|
+
const [uploadError, setUploadError] = React5.useState(null);
|
|
830
|
+
const [dragging, setDragging] = React5.useState(false);
|
|
831
|
+
const dragDepth = React5.useRef(0);
|
|
508
832
|
const agentName = config.agentName ?? chat.agentInfo?.name ?? "Assistant";
|
|
833
|
+
const uploadEnabled = fileUploadEnabled(config);
|
|
509
834
|
const suggestions = config.suggestions ?? [
|
|
510
835
|
"What can you help me with?",
|
|
511
836
|
"Give me a quick summary of my data."
|
|
512
837
|
];
|
|
513
|
-
const
|
|
838
|
+
const addFiles = React5.useCallback(
|
|
839
|
+
(incoming) => {
|
|
840
|
+
const accepted = [];
|
|
841
|
+
let rejection = null;
|
|
842
|
+
for (const file of incoming) {
|
|
843
|
+
const error = validateFile(config, file);
|
|
844
|
+
if (error) {
|
|
845
|
+
rejection = error;
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
accepted.push(file);
|
|
849
|
+
}
|
|
850
|
+
setUploadError(rejection);
|
|
851
|
+
if (accepted.length) setFiles((current) => [...current, ...accepted].slice(0, 10));
|
|
852
|
+
},
|
|
853
|
+
[config]
|
|
854
|
+
);
|
|
855
|
+
const removeFile = React5.useCallback((index) => {
|
|
856
|
+
setFiles((current) => current.filter((_, i) => i !== index));
|
|
857
|
+
}, []);
|
|
858
|
+
const handleSubmit = React5.useCallback(
|
|
514
859
|
(text) => {
|
|
860
|
+
const staged = files;
|
|
515
861
|
setDraft("");
|
|
516
|
-
|
|
862
|
+
setFiles([]);
|
|
863
|
+
setUploadError(null);
|
|
864
|
+
void chat.send(text, staged);
|
|
517
865
|
},
|
|
518
|
-
[chat]
|
|
866
|
+
[chat, files]
|
|
519
867
|
);
|
|
520
|
-
const
|
|
868
|
+
const onDragEnter = React5.useCallback(
|
|
869
|
+
(event) => {
|
|
870
|
+
if (!uploadEnabled || !event.dataTransfer?.types?.includes("Files")) return;
|
|
871
|
+
dragDepth.current += 1;
|
|
872
|
+
setDragging(true);
|
|
873
|
+
},
|
|
874
|
+
[uploadEnabled]
|
|
875
|
+
);
|
|
876
|
+
const onDragLeave = React5.useCallback((event) => {
|
|
877
|
+
if (!event.dataTransfer?.types?.includes("Files")) return;
|
|
878
|
+
dragDepth.current = Math.max(0, dragDepth.current - 1);
|
|
879
|
+
if (dragDepth.current === 0) setDragging(false);
|
|
880
|
+
}, []);
|
|
881
|
+
const onDrop = React5.useCallback(
|
|
882
|
+
(event) => {
|
|
883
|
+
if (!uploadEnabled) return;
|
|
884
|
+
event.preventDefault();
|
|
885
|
+
dragDepth.current = 0;
|
|
886
|
+
setDragging(false);
|
|
887
|
+
const dropped = Array.from(event.dataTransfer?.files ?? []);
|
|
888
|
+
if (dropped.length) addFiles(dropped);
|
|
889
|
+
},
|
|
890
|
+
[addFiles, uploadEnabled]
|
|
891
|
+
);
|
|
892
|
+
const openHistory = React5.useCallback(() => {
|
|
521
893
|
setView("history");
|
|
522
894
|
void chat.refreshConversations();
|
|
523
895
|
}, [chat]);
|
|
@@ -526,11 +898,20 @@ function AgentPanel({
|
|
|
526
898
|
"div",
|
|
527
899
|
{
|
|
528
900
|
className: cn(
|
|
529
|
-
"flex min-h-0 flex-col overflow-hidden bg-background text-foreground",
|
|
901
|
+
"relative flex min-h-0 flex-col overflow-hidden bg-background text-foreground",
|
|
530
902
|
className
|
|
531
903
|
),
|
|
532
904
|
"data-slot": "agent-panel",
|
|
905
|
+
onDragEnter,
|
|
906
|
+
onDragLeave,
|
|
907
|
+
onDragOver: uploadEnabled ? (event) => event.preventDefault() : void 0,
|
|
908
|
+
onDrop,
|
|
533
909
|
children: [
|
|
910
|
+
dragging && view === "chat" ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-40 flex flex-col items-center justify-center gap-2 bg-background/85 backdrop-blur-sm", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 rounded-2xl border-2 border-primary/40 border-dashed px-8 py-6 text-center", children: [
|
|
911
|
+
/* @__PURE__ */ jsx(UploadCloudIcon, { className: "size-8 text-primary" }),
|
|
912
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-sm", children: "Drop text files to attach" }),
|
|
913
|
+
/* @__PURE__ */ jsx("div", { className: "text-muted-foreground text-xs", children: acceptAttribute(config).replaceAll(",", " \xB7 ") })
|
|
914
|
+
] }) }) : null,
|
|
534
915
|
/* @__PURE__ */ jsxs(ChatHeader, { children: [
|
|
535
916
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
|
|
536
917
|
/* @__PURE__ */ jsx(ChatHeaderAvatar, {}),
|
|
@@ -671,15 +1052,30 @@ function AgentPanel({
|
|
|
671
1052
|
)),
|
|
672
1053
|
busy ? /* @__PURE__ */ jsx(ChatTypingIndicator, {}) : null
|
|
673
1054
|
] }) }),
|
|
674
|
-
chat.error ? /* @__PURE__ */ jsxs("div", { className: "mx-3 mb-1 flex items-center justify-between gap-2 rounded-lg bg-destructive/10 px-3 py-2 text-destructive text-xs", children: [
|
|
675
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: chat.error }),
|
|
676
|
-
/* @__PURE__ */ jsx(
|
|
1055
|
+
chat.error || uploadError ? /* @__PURE__ */ jsxs("div", { className: "mx-3 mb-1 flex items-center justify-between gap-2 rounded-lg bg-destructive/10 px-3 py-2 text-destructive text-xs", children: [
|
|
1056
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: chat.error ?? uploadError }),
|
|
1057
|
+
/* @__PURE__ */ jsx(
|
|
1058
|
+
"button",
|
|
1059
|
+
{
|
|
1060
|
+
className: "shrink-0 cursor-pointer font-medium",
|
|
1061
|
+
onClick: () => {
|
|
1062
|
+
chat.clearError();
|
|
1063
|
+
setUploadError(null);
|
|
1064
|
+
},
|
|
1065
|
+
type: "button",
|
|
1066
|
+
children: "Dismiss"
|
|
1067
|
+
}
|
|
1068
|
+
)
|
|
677
1069
|
] }) : null,
|
|
678
1070
|
/* @__PURE__ */ jsx(
|
|
679
|
-
|
|
1071
|
+
AgentComposer,
|
|
680
1072
|
{
|
|
1073
|
+
acceptAttribute: acceptAttribute(config),
|
|
681
1074
|
className: cn(agentMode && "mx-auto w-full max-w-3xl"),
|
|
682
1075
|
disabled: busy || chat.pendingApprovals.length > 0,
|
|
1076
|
+
files,
|
|
1077
|
+
onPickFiles: uploadEnabled ? addFiles : void 0,
|
|
1078
|
+
onRemoveFile: removeFile,
|
|
683
1079
|
onSubmit: handleSubmit,
|
|
684
1080
|
onValueChange: setDraft,
|
|
685
1081
|
placeholder: chat.pendingApprovals.length > 0 ? "Approve or decline the pending action first\u2026" : `Ask ${agentName}\u2026`,
|
|
@@ -692,16 +1088,16 @@ function AgentPanel({
|
|
|
692
1088
|
);
|
|
693
1089
|
}
|
|
694
1090
|
function useAgentChat(config) {
|
|
695
|
-
const client =
|
|
696
|
-
const [agentInfo, setAgentInfo] =
|
|
697
|
-
const [conversationId, setConversationId] =
|
|
698
|
-
const [conversations, setConversations] =
|
|
699
|
-
const [messages, setMessages] =
|
|
700
|
-
const [pendingApprovals, setPendingApprovals] =
|
|
701
|
-
const [sending, setSending] =
|
|
702
|
-
const [resolvingApprovalId, setResolvingApprovalId] =
|
|
703
|
-
const [error, setError] =
|
|
704
|
-
|
|
1091
|
+
const client = React5.useMemo(() => new AgentApiClient(config), [config]);
|
|
1092
|
+
const [agentInfo, setAgentInfo] = React5.useState(null);
|
|
1093
|
+
const [conversationId, setConversationId] = React5.useState(null);
|
|
1094
|
+
const [conversations, setConversations] = React5.useState([]);
|
|
1095
|
+
const [messages, setMessages] = React5.useState([]);
|
|
1096
|
+
const [pendingApprovals, setPendingApprovals] = React5.useState([]);
|
|
1097
|
+
const [sending, setSending] = React5.useState(false);
|
|
1098
|
+
const [resolvingApprovalId, setResolvingApprovalId] = React5.useState(null);
|
|
1099
|
+
const [error, setError] = React5.useState(null);
|
|
1100
|
+
React5.useEffect(() => {
|
|
705
1101
|
let cancelled = false;
|
|
706
1102
|
client.getConfig().then((info) => {
|
|
707
1103
|
if (!cancelled) setAgentInfo(info);
|
|
@@ -711,11 +1107,11 @@ function useAgentChat(config) {
|
|
|
711
1107
|
cancelled = true;
|
|
712
1108
|
};
|
|
713
1109
|
}, [client]);
|
|
714
|
-
const handleFailure =
|
|
1110
|
+
const handleFailure = React5.useCallback((err) => {
|
|
715
1111
|
const message = err instanceof AgentApiError ? err.message : "Something went wrong. Please try again.";
|
|
716
1112
|
setError(message);
|
|
717
1113
|
}, []);
|
|
718
|
-
const applyResponse =
|
|
1114
|
+
const applyResponse = React5.useCallback(
|
|
719
1115
|
(response) => {
|
|
720
1116
|
if (response.status === "error" && !response.messages?.length) {
|
|
721
1117
|
setError(response.message ?? "The assistant could not answer.");
|
|
@@ -736,13 +1132,14 @@ function useAgentChat(config) {
|
|
|
736
1132
|
},
|
|
737
1133
|
[]
|
|
738
1134
|
);
|
|
739
|
-
const send =
|
|
740
|
-
async (text) => {
|
|
1135
|
+
const send = React5.useCallback(
|
|
1136
|
+
async (text, files) => {
|
|
741
1137
|
if (sending) return;
|
|
1138
|
+
if (!text.trim() && !(files && files.length)) return;
|
|
742
1139
|
setSending(true);
|
|
743
1140
|
setError(null);
|
|
744
1141
|
try {
|
|
745
|
-
const response = await client.sendMessage(text, conversationId);
|
|
1142
|
+
const response = await client.sendMessage(text, conversationId, files);
|
|
746
1143
|
applyResponse(response);
|
|
747
1144
|
} catch (err) {
|
|
748
1145
|
handleFailure(err);
|
|
@@ -752,7 +1149,7 @@ function useAgentChat(config) {
|
|
|
752
1149
|
},
|
|
753
1150
|
[applyResponse, client, conversationId, handleFailure, sending]
|
|
754
1151
|
);
|
|
755
|
-
const resolveApproval =
|
|
1152
|
+
const resolveApproval = React5.useCallback(
|
|
756
1153
|
async (callId, approve) => {
|
|
757
1154
|
if (resolvingApprovalId) return;
|
|
758
1155
|
setResolvingApprovalId(callId);
|
|
@@ -768,13 +1165,13 @@ function useAgentChat(config) {
|
|
|
768
1165
|
},
|
|
769
1166
|
[applyResponse, client, handleFailure, resolvingApprovalId]
|
|
770
1167
|
);
|
|
771
|
-
const newChat =
|
|
1168
|
+
const newChat = React5.useCallback(() => {
|
|
772
1169
|
setConversationId(null);
|
|
773
1170
|
setMessages([]);
|
|
774
1171
|
setPendingApprovals([]);
|
|
775
1172
|
setError(null);
|
|
776
1173
|
}, []);
|
|
777
|
-
const refreshConversations =
|
|
1174
|
+
const refreshConversations = React5.useCallback(async () => {
|
|
778
1175
|
try {
|
|
779
1176
|
const { conversations: list } = await client.listConversations();
|
|
780
1177
|
setConversations(list);
|
|
@@ -782,7 +1179,7 @@ function useAgentChat(config) {
|
|
|
782
1179
|
handleFailure(err);
|
|
783
1180
|
}
|
|
784
1181
|
}, [client, handleFailure]);
|
|
785
|
-
const openConversation =
|
|
1182
|
+
const openConversation = React5.useCallback(
|
|
786
1183
|
async (id) => {
|
|
787
1184
|
setError(null);
|
|
788
1185
|
try {
|
|
@@ -796,7 +1193,7 @@ function useAgentChat(config) {
|
|
|
796
1193
|
},
|
|
797
1194
|
[client, handleFailure]
|
|
798
1195
|
);
|
|
799
|
-
const deleteConversation =
|
|
1196
|
+
const deleteConversation = React5.useCallback(
|
|
800
1197
|
async (id) => {
|
|
801
1198
|
try {
|
|
802
1199
|
await client.deleteConversation(id);
|
|
@@ -808,7 +1205,7 @@ function useAgentChat(config) {
|
|
|
808
1205
|
},
|
|
809
1206
|
[client, conversationId, handleFailure, newChat]
|
|
810
1207
|
);
|
|
811
|
-
const clearError =
|
|
1208
|
+
const clearError = React5.useCallback(() => setError(null), []);
|
|
812
1209
|
return {
|
|
813
1210
|
agentInfo,
|
|
814
1211
|
clearError,
|
|
@@ -843,11 +1240,11 @@ function readStored(clientId) {
|
|
|
843
1240
|
}
|
|
844
1241
|
}
|
|
845
1242
|
function useAlwaysApprove(clientId) {
|
|
846
|
-
const [approved, setApproved] =
|
|
847
|
-
|
|
1243
|
+
const [approved, setApproved] = React5.useState(() => /* @__PURE__ */ new Set());
|
|
1244
|
+
React5.useEffect(() => {
|
|
848
1245
|
setApproved(readStored(clientId));
|
|
849
1246
|
}, [clientId]);
|
|
850
|
-
const persist =
|
|
1247
|
+
const persist = React5.useCallback(
|
|
851
1248
|
(next) => {
|
|
852
1249
|
setApproved(next);
|
|
853
1250
|
if (typeof window === "undefined") return;
|
|
@@ -858,8 +1255,8 @@ function useAlwaysApprove(clientId) {
|
|
|
858
1255
|
},
|
|
859
1256
|
[clientId]
|
|
860
1257
|
);
|
|
861
|
-
const isAlwaysApproved =
|
|
862
|
-
const setAlwaysApprove =
|
|
1258
|
+
const isAlwaysApproved = React5.useCallback((toolName) => approved.has(toolName), [approved]);
|
|
1259
|
+
const setAlwaysApprove = React5.useCallback(
|
|
863
1260
|
(toolName) => {
|
|
864
1261
|
if (approved.has(toolName)) return;
|
|
865
1262
|
const next = new Set(approved);
|
|
@@ -868,7 +1265,7 @@ function useAlwaysApprove(clientId) {
|
|
|
868
1265
|
},
|
|
869
1266
|
[approved, persist]
|
|
870
1267
|
);
|
|
871
|
-
const clearAlwaysApprove =
|
|
1268
|
+
const clearAlwaysApprove = React5.useCallback(
|
|
872
1269
|
(toolName) => {
|
|
873
1270
|
if (!approved.has(toolName)) return;
|
|
874
1271
|
const next = new Set(approved);
|
|
@@ -880,16 +1277,16 @@ function useAlwaysApprove(clientId) {
|
|
|
880
1277
|
return { clearAlwaysApprove, isAlwaysApproved, setAlwaysApprove };
|
|
881
1278
|
}
|
|
882
1279
|
function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
883
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
1280
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React5.useState(false);
|
|
884
1281
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
885
|
-
const setOpen =
|
|
1282
|
+
const setOpen = React5.useCallback(
|
|
886
1283
|
(next) => {
|
|
887
1284
|
setUncontrolledOpen(next);
|
|
888
1285
|
onOpenChange?.(next);
|
|
889
1286
|
},
|
|
890
1287
|
[onOpenChange]
|
|
891
1288
|
);
|
|
892
|
-
const [agentMode, setAgentMode] =
|
|
1289
|
+
const [agentMode, setAgentMode] = React5.useState(false);
|
|
893
1290
|
const isDesktop = useMediaQuery("(min-width: 640px)", {
|
|
894
1291
|
defaultSSRValue: true,
|
|
895
1292
|
ssr: true
|
|
@@ -899,14 +1296,14 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
899
1296
|
const alwaysApprove = useAlwaysApprove(config.clientId);
|
|
900
1297
|
const { pendingApprovals, resolveApproval, resolvingApprovalId } = chat;
|
|
901
1298
|
const { isAlwaysApproved } = alwaysApprove;
|
|
902
|
-
|
|
1299
|
+
React5.useEffect(() => {
|
|
903
1300
|
if (!open || resolvingApprovalId) return;
|
|
904
1301
|
const target = pendingApprovals.find((approval) => isAlwaysApproved(approval.tool_name));
|
|
905
1302
|
if (target) void resolveApproval(target.id, true);
|
|
906
1303
|
}, [open, pendingApprovals, resolvingApprovalId, isAlwaysApproved, resolveApproval]);
|
|
907
|
-
const lastNavigatedMessageId =
|
|
1304
|
+
const lastNavigatedMessageId = React5.useRef(null);
|
|
908
1305
|
const { messages } = chat;
|
|
909
|
-
|
|
1306
|
+
React5.useEffect(() => {
|
|
910
1307
|
if (!open || fullscreen || !config.navigate || !config.pages?.length) return;
|
|
911
1308
|
const toolMessages = messages.filter((message) => message.role === "tool");
|
|
912
1309
|
const latest = toolMessages[toolMessages.length - 1];
|
|
@@ -918,7 +1315,7 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
918
1315
|
const path = mapping.buildRoute ? mapping.buildRoute(args) : mapping.route;
|
|
919
1316
|
if (path) config.navigate(path);
|
|
920
1317
|
}, [config, fullscreen, messages, open]);
|
|
921
|
-
const closePanel =
|
|
1318
|
+
const closePanel = React5.useCallback(() => {
|
|
922
1319
|
setOpen(false);
|
|
923
1320
|
setAgentMode(false);
|
|
924
1321
|
}, [setOpen]);
|
|
@@ -997,6 +1394,6 @@ function defineAgentConfig(config) {
|
|
|
997
1394
|
return config;
|
|
998
1395
|
}
|
|
999
1396
|
|
|
1000
|
-
export { AgentApiClient, AgentApiError, AgentPanel, AgentWidget, MessageItem, ToolActivityGroup, ToolApprovalCard, defineAgentConfig, deriveDetails, groupMessages, humanizeToolName, resolveToolPresentation, useAgentChat, useAlwaysApprove };
|
|
1397
|
+
export { AgentApiClient, AgentApiError, AgentComposer, AgentPanel, AgentWidget, DEFAULT_ACCEPT, DocumentCard, MessageItem, TaskChecklist, ToolActivityGroup, ToolApprovalCard, acceptAttribute, acceptedExtensions, defineAgentConfig, deriveDetails, fileUploadEnabled, formatBytes, groupMessages, humanizeToolName, resolveToolPresentation, useAgentChat, useAlwaysApprove, validateFile };
|
|
1001
1398
|
//# sourceMappingURL=index.js.map
|
|
1002
1399
|
//# sourceMappingURL=index.js.map
|