@cntyclub/agent-react 0.9.1 → 0.9.2
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/components/copy-button.d.ts +9 -0
- package/dist/components/copy-button.d.ts.map +1 -0
- package/dist/components/message-item.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -67
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface CopyButtonProps {
|
|
3
|
+
/** The text copied to the clipboard (the assistant reply's raw markdown). */
|
|
4
|
+
text: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Small ghost icon button that copies `text` and briefly flips to a check. */
|
|
8
|
+
export declare function CopyButton({ className, text }: CopyButtonProps): React.JSX.Element;
|
|
9
|
+
//# sourceMappingURL=copy-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-button.d.ts","sourceRoot":"","sources":["../../src/components/copy-button.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,eAAe,qBAwC9D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-item.d.ts","sourceRoot":"","sources":["../../src/components/message-item.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"message-item.d.ts","sourceRoot":"","sources":["../../src/components/message-item.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,4BA8CjE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { AgentComposer, type AgentComposerProps } from "./components/agent-compo
|
|
|
3
3
|
export { AgentPanel, type AgentPanelProps } from "./components/agent-panel";
|
|
4
4
|
export { AgentWidget, type AgentWidgetProps } from "./components/agent-widget";
|
|
5
5
|
export { ChatScroller, type ChatScrollerProps } from "./components/chat-scroller";
|
|
6
|
+
export { CopyButton, type CopyButtonProps } from "./components/copy-button";
|
|
6
7
|
export { DocumentCard } from "./components/document-card";
|
|
7
8
|
export { MessageItem } from "./components/message-item";
|
|
8
9
|
export { TaskChecklist } from "./components/task-checklist";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAClG,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACjF,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,UAAU,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,UAAU,IAAI,mBAAmB,EACjC,UAAU,IAAI,mBAAmB,EACjC,KAAK,IAAI,cAAc,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACjG,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAClG,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChF,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACjF,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,eAAe,EACf,UAAU,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,iBAAiB,GAClB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,UAAU,IAAI,mBAAmB,EACjC,UAAU,IAAI,mBAAmB,EACjC,KAAK,IAAI,cAAc,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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,
|
|
2
|
-
import { FileTextIcon, XIcon, PaperclipIcon, ArrowUpIcon, Maximize2Icon, ListChecksIcon, ChevronDownIcon,
|
|
3
|
-
import * as
|
|
1
|
+
import { Button, cn, Tooltip, TooltipTrigger, TooltipContent, ChatMessage, ChatMessageBubble, Markdown, Spinner, Checkbox, Collapsible, CollapsibleTrigger, ChatToolChip, CollapsiblePanel, ChatToolCard, ChatToolCardHeader, ChatToolCardActions, Group, Menu, MenuTrigger, MenuPopup, MenuItem, ChatHeader, ChatHeaderAvatar, ChatHeaderTitle, ChatHeaderActions, Chat, ChatEmptyState, ChatEmptyStateIcon, ChatEmptyStateTitle, ChatEmptyStateDescription, ChatSuggestions, ChatSuggestion, useMediaQuery, TooltipProvider, Fab, DataTablePaged } from '@cntyclub/ui-react';
|
|
2
|
+
import { FileTextIcon, XIcon, PaperclipIcon, ArrowUpIcon, CheckIcon, CopyIcon, Maximize2Icon, ListChecksIcon, ChevronDownIcon, ShieldAlertIcon, CheckCheckIcon, UploadCloudIcon, HistoryIcon, SquarePenIcon, Minimize2Icon, Trash2Icon, SparklesIcon, DownloadIcon, CodeIcon } from 'lucide-react';
|
|
3
|
+
import * as React8 from 'react';
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
// src/api-client.ts
|
|
@@ -230,18 +230,18 @@ function AgentComposer({
|
|
|
230
230
|
placeholder = "Ask anything\u2026",
|
|
231
231
|
value
|
|
232
232
|
}) {
|
|
233
|
-
const textareaRef =
|
|
234
|
-
const inputRef =
|
|
233
|
+
const textareaRef = React8.useRef(null);
|
|
234
|
+
const inputRef = React8.useRef(null);
|
|
235
235
|
const canSubmit = !disabled && !busy && (value.trim().length > 0 || files.length > 0);
|
|
236
|
-
const submit =
|
|
236
|
+
const submit = React8.useCallback(() => {
|
|
237
237
|
if (!canSubmit) return;
|
|
238
238
|
onSubmit(value.trim());
|
|
239
239
|
textareaRef.current?.focus();
|
|
240
240
|
}, [canSubmit, onSubmit, value]);
|
|
241
|
-
|
|
241
|
+
React8.useEffect(() => {
|
|
242
242
|
if (!disabled) textareaRef.current?.focus();
|
|
243
243
|
}, [disabled]);
|
|
244
|
-
|
|
244
|
+
React8.useEffect(() => {
|
|
245
245
|
const textarea = textareaRef.current;
|
|
246
246
|
if (!textarea) return;
|
|
247
247
|
textarea.style.height = "auto";
|
|
@@ -423,15 +423,15 @@ function groupMessages(messages) {
|
|
|
423
423
|
return items;
|
|
424
424
|
}
|
|
425
425
|
function ChatScroller({ children, className, ...props }) {
|
|
426
|
-
const viewportRef =
|
|
427
|
-
const pinnedRef =
|
|
428
|
-
const handleScroll =
|
|
426
|
+
const viewportRef = React8.useRef(null);
|
|
427
|
+
const pinnedRef = React8.useRef(true);
|
|
428
|
+
const handleScroll = React8.useCallback(() => {
|
|
429
429
|
const viewport = viewportRef.current;
|
|
430
430
|
if (!viewport) return;
|
|
431
431
|
const distanceFromBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
|
|
432
432
|
pinnedRef.current = distanceFromBottom < 64;
|
|
433
433
|
}, []);
|
|
434
|
-
|
|
434
|
+
React8.useEffect(() => {
|
|
435
435
|
const viewport = viewportRef.current;
|
|
436
436
|
if (!viewport || !pinnedRef.current) return;
|
|
437
437
|
viewport.scrollTop = viewport.scrollHeight;
|
|
@@ -448,6 +448,45 @@ function ChatScroller({ children, className, ...props }) {
|
|
|
448
448
|
}
|
|
449
449
|
);
|
|
450
450
|
}
|
|
451
|
+
function CopyButton({ className, text }) {
|
|
452
|
+
const [copied, setCopied] = React8.useState(false);
|
|
453
|
+
const timerRef = React8.useRef(null);
|
|
454
|
+
React8.useEffect(() => {
|
|
455
|
+
return () => {
|
|
456
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
457
|
+
};
|
|
458
|
+
}, []);
|
|
459
|
+
const copy = React8.useCallback(async () => {
|
|
460
|
+
try {
|
|
461
|
+
await navigator.clipboard.writeText(text);
|
|
462
|
+
} catch {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
setCopied(true);
|
|
466
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
467
|
+
timerRef.current = setTimeout(() => setCopied(false), 1500);
|
|
468
|
+
}, [text]);
|
|
469
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
470
|
+
/* @__PURE__ */ jsx(
|
|
471
|
+
TooltipTrigger,
|
|
472
|
+
{
|
|
473
|
+
render: /* @__PURE__ */ jsx(
|
|
474
|
+
Button,
|
|
475
|
+
{
|
|
476
|
+
"aria-label": copied ? "Copied" : "Copy message",
|
|
477
|
+
className: cn("text-muted-foreground", className),
|
|
478
|
+
onClick: copy,
|
|
479
|
+
size: "icon-xs",
|
|
480
|
+
type: "button",
|
|
481
|
+
variant: "ghost",
|
|
482
|
+
children: copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-success" }) : /* @__PURE__ */ jsx(CopyIcon, {})
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
}
|
|
486
|
+
),
|
|
487
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: copied ? "Copied!" : "Copy" })
|
|
488
|
+
] });
|
|
489
|
+
}
|
|
451
490
|
function MessageItem({ message }) {
|
|
452
491
|
if (message.role === "user") {
|
|
453
492
|
const attachments = message.attachments ?? [];
|
|
@@ -468,7 +507,19 @@ function MessageItem({ message }) {
|
|
|
468
507
|
}
|
|
469
508
|
if (message.role === "assistant") {
|
|
470
509
|
if (!message.content || !message.content.trim()) return null;
|
|
471
|
-
return /* @__PURE__ */
|
|
510
|
+
return /* @__PURE__ */ jsxs(ChatMessage, { className: "group", from: "assistant", children: [
|
|
511
|
+
/* @__PURE__ */ jsx(ChatMessageBubble, { from: "assistant", children: /* @__PURE__ */ jsx(Markdown, { children: message.content }) }),
|
|
512
|
+
/* @__PURE__ */ jsx(
|
|
513
|
+
"div",
|
|
514
|
+
{
|
|
515
|
+
className: cn(
|
|
516
|
+
"mt-0.5 flex opacity-0 transition-opacity",
|
|
517
|
+
"group-hover:opacity-100 focus-within:opacity-100"
|
|
518
|
+
),
|
|
519
|
+
children: /* @__PURE__ */ jsx(CopyButton, { text: message.content })
|
|
520
|
+
}
|
|
521
|
+
)
|
|
522
|
+
] });
|
|
472
523
|
}
|
|
473
524
|
return null;
|
|
474
525
|
}
|
|
@@ -482,8 +533,8 @@ var DEFAULT_PHRASES = [
|
|
|
482
533
|
];
|
|
483
534
|
function ThinkingIndicator({ className, intervalMs = 1800, phrases }) {
|
|
484
535
|
const words = phrases && phrases.length ? phrases : DEFAULT_PHRASES;
|
|
485
|
-
const [index, setIndex] =
|
|
486
|
-
|
|
536
|
+
const [index, setIndex] = React8.useState(0);
|
|
537
|
+
React8.useEffect(() => {
|
|
487
538
|
setIndex(0);
|
|
488
539
|
const timer = setInterval(() => {
|
|
489
540
|
setIndex((current) => (current + 1) % words.length);
|
|
@@ -745,7 +796,7 @@ function DownloadButton({ block, size = "sm" }) {
|
|
|
745
796
|
);
|
|
746
797
|
}
|
|
747
798
|
function DocumentViewer({ block, onClose }) {
|
|
748
|
-
|
|
799
|
+
React8.useEffect(() => {
|
|
749
800
|
const onKey = (event) => event.key === "Escape" && onClose();
|
|
750
801
|
window.addEventListener("keydown", onKey);
|
|
751
802
|
return () => window.removeEventListener("keydown", onKey);
|
|
@@ -770,7 +821,7 @@ function DocumentViewer({ block, onClose }) {
|
|
|
770
821
|
] });
|
|
771
822
|
}
|
|
772
823
|
function DocumentCard({ block }) {
|
|
773
|
-
const [open, setOpen] =
|
|
824
|
+
const [open, setOpen] = React8.useState(false);
|
|
774
825
|
const previewLines = (block.preview || "").split("\n").slice(0, 6).join("\n");
|
|
775
826
|
return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-full overflow-hidden rounded-xl border border-border bg-card shadow-xs", children: [
|
|
776
827
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-border/72 border-b px-3 py-2", children: [
|
|
@@ -892,7 +943,7 @@ function StepDetail({
|
|
|
892
943
|
] });
|
|
893
944
|
}
|
|
894
945
|
function ToolActivityGroup({ describeToolCall, steps }) {
|
|
895
|
-
const [open, setOpen] =
|
|
946
|
+
const [open, setOpen] = React8.useState(false);
|
|
896
947
|
if (steps.length === 0) return null;
|
|
897
948
|
const last = steps[steps.length - 1];
|
|
898
949
|
const anyRunning = steps.some((step) => step.status === "running");
|
|
@@ -995,19 +1046,19 @@ function AgentPanel({
|
|
|
995
1046
|
onClose,
|
|
996
1047
|
onToggleAgentMode
|
|
997
1048
|
}) {
|
|
998
|
-
const [draft, setDraft] =
|
|
999
|
-
const [view, setView] =
|
|
1000
|
-
const [files, setFiles] =
|
|
1001
|
-
const [uploadError, setUploadError] =
|
|
1002
|
-
const [dragging, setDragging] =
|
|
1003
|
-
const dragDepth =
|
|
1049
|
+
const [draft, setDraft] = React8.useState("");
|
|
1050
|
+
const [view, setView] = React8.useState("chat");
|
|
1051
|
+
const [files, setFiles] = React8.useState([]);
|
|
1052
|
+
const [uploadError, setUploadError] = React8.useState(null);
|
|
1053
|
+
const [dragging, setDragging] = React8.useState(false);
|
|
1054
|
+
const dragDepth = React8.useRef(0);
|
|
1004
1055
|
const agentName = config.agentName ?? chat.agentInfo?.name ?? "Assistant";
|
|
1005
1056
|
const uploadEnabled = fileUploadEnabled(config);
|
|
1006
1057
|
const suggestions = config.suggestions ?? [
|
|
1007
1058
|
"What can you help me with?",
|
|
1008
1059
|
"Give me a quick summary of my data."
|
|
1009
1060
|
];
|
|
1010
|
-
const addFiles =
|
|
1061
|
+
const addFiles = React8.useCallback(
|
|
1011
1062
|
(incoming) => {
|
|
1012
1063
|
const accepted = [];
|
|
1013
1064
|
let rejection = null;
|
|
@@ -1024,10 +1075,10 @@ function AgentPanel({
|
|
|
1024
1075
|
},
|
|
1025
1076
|
[config]
|
|
1026
1077
|
);
|
|
1027
|
-
const removeFile =
|
|
1078
|
+
const removeFile = React8.useCallback((index) => {
|
|
1028
1079
|
setFiles((current) => current.filter((_, i) => i !== index));
|
|
1029
1080
|
}, []);
|
|
1030
|
-
const handleSubmit =
|
|
1081
|
+
const handleSubmit = React8.useCallback(
|
|
1031
1082
|
(text) => {
|
|
1032
1083
|
const staged = files;
|
|
1033
1084
|
setDraft("");
|
|
@@ -1037,7 +1088,7 @@ function AgentPanel({
|
|
|
1037
1088
|
},
|
|
1038
1089
|
[chat, files]
|
|
1039
1090
|
);
|
|
1040
|
-
const onDragEnter =
|
|
1091
|
+
const onDragEnter = React8.useCallback(
|
|
1041
1092
|
(event) => {
|
|
1042
1093
|
if (!uploadEnabled || !event.dataTransfer?.types?.includes("Files")) return;
|
|
1043
1094
|
dragDepth.current += 1;
|
|
@@ -1045,12 +1096,12 @@ function AgentPanel({
|
|
|
1045
1096
|
},
|
|
1046
1097
|
[uploadEnabled]
|
|
1047
1098
|
);
|
|
1048
|
-
const onDragLeave =
|
|
1099
|
+
const onDragLeave = React8.useCallback((event) => {
|
|
1049
1100
|
if (!event.dataTransfer?.types?.includes("Files")) return;
|
|
1050
1101
|
dragDepth.current = Math.max(0, dragDepth.current - 1);
|
|
1051
1102
|
if (dragDepth.current === 0) setDragging(false);
|
|
1052
1103
|
}, []);
|
|
1053
|
-
const onDrop =
|
|
1104
|
+
const onDrop = React8.useCallback(
|
|
1054
1105
|
(event) => {
|
|
1055
1106
|
if (!uploadEnabled) return;
|
|
1056
1107
|
event.preventDefault();
|
|
@@ -1061,7 +1112,7 @@ function AgentPanel({
|
|
|
1061
1112
|
},
|
|
1062
1113
|
[addFiles, uploadEnabled]
|
|
1063
1114
|
);
|
|
1064
|
-
const openHistory =
|
|
1115
|
+
const openHistory = React8.useCallback(() => {
|
|
1065
1116
|
setView("history");
|
|
1066
1117
|
void chat.refreshConversations();
|
|
1067
1118
|
}, [chat]);
|
|
@@ -1284,16 +1335,16 @@ function buildOptimisticUserMessage(text, files) {
|
|
|
1284
1335
|
};
|
|
1285
1336
|
}
|
|
1286
1337
|
function useAgentChat(config) {
|
|
1287
|
-
const client =
|
|
1288
|
-
const [agentInfo, setAgentInfo] =
|
|
1289
|
-
const [conversationId, setConversationId] =
|
|
1290
|
-
const [conversations, setConversations] =
|
|
1291
|
-
const [messages, setMessages] =
|
|
1292
|
-
const [pendingApprovals, setPendingApprovals] =
|
|
1293
|
-
const [sending, setSending] =
|
|
1294
|
-
const [resolvingApprovalId, setResolvingApprovalId] =
|
|
1295
|
-
const [error, setError] =
|
|
1296
|
-
|
|
1338
|
+
const client = React8.useMemo(() => new AgentApiClient(config), [config]);
|
|
1339
|
+
const [agentInfo, setAgentInfo] = React8.useState(null);
|
|
1340
|
+
const [conversationId, setConversationId] = React8.useState(null);
|
|
1341
|
+
const [conversations, setConversations] = React8.useState([]);
|
|
1342
|
+
const [messages, setMessages] = React8.useState([]);
|
|
1343
|
+
const [pendingApprovals, setPendingApprovals] = React8.useState([]);
|
|
1344
|
+
const [sending, setSending] = React8.useState(false);
|
|
1345
|
+
const [resolvingApprovalId, setResolvingApprovalId] = React8.useState(null);
|
|
1346
|
+
const [error, setError] = React8.useState(null);
|
|
1347
|
+
React8.useEffect(() => {
|
|
1297
1348
|
let cancelled = false;
|
|
1298
1349
|
client.getConfig().then((info) => {
|
|
1299
1350
|
if (!cancelled) setAgentInfo(info);
|
|
@@ -1303,11 +1354,11 @@ function useAgentChat(config) {
|
|
|
1303
1354
|
cancelled = true;
|
|
1304
1355
|
};
|
|
1305
1356
|
}, [client]);
|
|
1306
|
-
const handleFailure =
|
|
1357
|
+
const handleFailure = React8.useCallback((err) => {
|
|
1307
1358
|
const message = err instanceof AgentApiError ? err.message : "Something went wrong. Please try again.";
|
|
1308
1359
|
setError(message);
|
|
1309
1360
|
}, []);
|
|
1310
|
-
const applyResponse =
|
|
1361
|
+
const applyResponse = React8.useCallback(
|
|
1311
1362
|
(response) => {
|
|
1312
1363
|
if (response.status === "error" && !response.messages?.length) {
|
|
1313
1364
|
setError(response.message ?? "The assistant could not answer.");
|
|
@@ -1329,7 +1380,7 @@ function useAgentChat(config) {
|
|
|
1329
1380
|
},
|
|
1330
1381
|
[]
|
|
1331
1382
|
);
|
|
1332
|
-
const handleStreamEvent =
|
|
1383
|
+
const handleStreamEvent = React8.useCallback(
|
|
1333
1384
|
(event, ctx) => {
|
|
1334
1385
|
switch (event.type) {
|
|
1335
1386
|
case "conversation":
|
|
@@ -1394,7 +1445,7 @@ function useAgentChat(config) {
|
|
|
1394
1445
|
[]
|
|
1395
1446
|
);
|
|
1396
1447
|
const streamingEnabled = config.streaming !== false && typeof ReadableStream !== "undefined";
|
|
1397
|
-
const send =
|
|
1448
|
+
const send = React8.useCallback(
|
|
1398
1449
|
async (text, files) => {
|
|
1399
1450
|
if (sending) return;
|
|
1400
1451
|
if (!text.trim() && !(files && files.length)) return;
|
|
@@ -1425,7 +1476,7 @@ function useAgentChat(config) {
|
|
|
1425
1476
|
},
|
|
1426
1477
|
[applyResponse, client, conversationId, handleFailure, handleStreamEvent, sending, streamingEnabled]
|
|
1427
1478
|
);
|
|
1428
|
-
const resolveApproval =
|
|
1479
|
+
const resolveApproval = React8.useCallback(
|
|
1429
1480
|
async (callId, approve) => {
|
|
1430
1481
|
if (resolvingApprovalId) return;
|
|
1431
1482
|
setResolvingApprovalId(callId);
|
|
@@ -1454,13 +1505,13 @@ function useAgentChat(config) {
|
|
|
1454
1505
|
},
|
|
1455
1506
|
[applyResponse, client, handleFailure, handleStreamEvent, resolvingApprovalId, streamingEnabled]
|
|
1456
1507
|
);
|
|
1457
|
-
const newChat =
|
|
1508
|
+
const newChat = React8.useCallback(() => {
|
|
1458
1509
|
setConversationId(null);
|
|
1459
1510
|
setMessages([]);
|
|
1460
1511
|
setPendingApprovals([]);
|
|
1461
1512
|
setError(null);
|
|
1462
1513
|
}, []);
|
|
1463
|
-
const refreshConversations =
|
|
1514
|
+
const refreshConversations = React8.useCallback(async () => {
|
|
1464
1515
|
try {
|
|
1465
1516
|
const { conversations: list } = await client.listConversations();
|
|
1466
1517
|
setConversations(list);
|
|
@@ -1468,7 +1519,7 @@ function useAgentChat(config) {
|
|
|
1468
1519
|
handleFailure(err);
|
|
1469
1520
|
}
|
|
1470
1521
|
}, [client, handleFailure]);
|
|
1471
|
-
const openConversation =
|
|
1522
|
+
const openConversation = React8.useCallback(
|
|
1472
1523
|
async (id) => {
|
|
1473
1524
|
setError(null);
|
|
1474
1525
|
try {
|
|
@@ -1482,7 +1533,7 @@ function useAgentChat(config) {
|
|
|
1482
1533
|
},
|
|
1483
1534
|
[client, handleFailure]
|
|
1484
1535
|
);
|
|
1485
|
-
const deleteConversation =
|
|
1536
|
+
const deleteConversation = React8.useCallback(
|
|
1486
1537
|
async (id) => {
|
|
1487
1538
|
try {
|
|
1488
1539
|
await client.deleteConversation(id);
|
|
@@ -1494,7 +1545,7 @@ function useAgentChat(config) {
|
|
|
1494
1545
|
},
|
|
1495
1546
|
[client, conversationId, handleFailure, newChat]
|
|
1496
1547
|
);
|
|
1497
|
-
const clearError =
|
|
1548
|
+
const clearError = React8.useCallback(() => setError(null), []);
|
|
1498
1549
|
return {
|
|
1499
1550
|
agentInfo,
|
|
1500
1551
|
clearError,
|
|
@@ -1529,11 +1580,11 @@ function readStored(clientId) {
|
|
|
1529
1580
|
}
|
|
1530
1581
|
}
|
|
1531
1582
|
function useAlwaysApprove(clientId) {
|
|
1532
|
-
const [approved, setApproved] =
|
|
1533
|
-
|
|
1583
|
+
const [approved, setApproved] = React8.useState(() => /* @__PURE__ */ new Set());
|
|
1584
|
+
React8.useEffect(() => {
|
|
1534
1585
|
setApproved(readStored(clientId));
|
|
1535
1586
|
}, [clientId]);
|
|
1536
|
-
const persist =
|
|
1587
|
+
const persist = React8.useCallback(
|
|
1537
1588
|
(next) => {
|
|
1538
1589
|
setApproved(next);
|
|
1539
1590
|
if (typeof window === "undefined") return;
|
|
@@ -1544,8 +1595,8 @@ function useAlwaysApprove(clientId) {
|
|
|
1544
1595
|
},
|
|
1545
1596
|
[clientId]
|
|
1546
1597
|
);
|
|
1547
|
-
const isAlwaysApproved =
|
|
1548
|
-
const setAlwaysApprove =
|
|
1598
|
+
const isAlwaysApproved = React8.useCallback((toolName) => approved.has(toolName), [approved]);
|
|
1599
|
+
const setAlwaysApprove = React8.useCallback(
|
|
1549
1600
|
(toolName) => {
|
|
1550
1601
|
if (approved.has(toolName)) return;
|
|
1551
1602
|
const next = new Set(approved);
|
|
@@ -1554,7 +1605,7 @@ function useAlwaysApprove(clientId) {
|
|
|
1554
1605
|
},
|
|
1555
1606
|
[approved, persist]
|
|
1556
1607
|
);
|
|
1557
|
-
const clearAlwaysApprove =
|
|
1608
|
+
const clearAlwaysApprove = React8.useCallback(
|
|
1558
1609
|
(toolName) => {
|
|
1559
1610
|
if (!approved.has(toolName)) return;
|
|
1560
1611
|
const next = new Set(approved);
|
|
@@ -1566,16 +1617,16 @@ function useAlwaysApprove(clientId) {
|
|
|
1566
1617
|
return { clearAlwaysApprove, isAlwaysApproved, setAlwaysApprove };
|
|
1567
1618
|
}
|
|
1568
1619
|
function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
1569
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
1620
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React8.useState(false);
|
|
1570
1621
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
1571
|
-
const setOpen =
|
|
1622
|
+
const setOpen = React8.useCallback(
|
|
1572
1623
|
(next) => {
|
|
1573
1624
|
setUncontrolledOpen(next);
|
|
1574
1625
|
onOpenChange?.(next);
|
|
1575
1626
|
},
|
|
1576
1627
|
[onOpenChange]
|
|
1577
1628
|
);
|
|
1578
|
-
const [agentMode, setAgentMode] =
|
|
1629
|
+
const [agentMode, setAgentMode] = React8.useState(false);
|
|
1579
1630
|
const isDesktop = useMediaQuery("(min-width: 640px)", {
|
|
1580
1631
|
defaultSSRValue: true,
|
|
1581
1632
|
ssr: true
|
|
@@ -1585,14 +1636,14 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
1585
1636
|
const alwaysApprove = useAlwaysApprove(config.clientId);
|
|
1586
1637
|
const { pendingApprovals, resolveApproval, resolvingApprovalId } = chat;
|
|
1587
1638
|
const { isAlwaysApproved } = alwaysApprove;
|
|
1588
|
-
|
|
1639
|
+
React8.useEffect(() => {
|
|
1589
1640
|
if (!open || resolvingApprovalId) return;
|
|
1590
1641
|
const target = pendingApprovals.find((approval) => isAlwaysApproved(approval.tool_name));
|
|
1591
1642
|
if (target) void resolveApproval(target.id, true);
|
|
1592
1643
|
}, [open, pendingApprovals, resolvingApprovalId, isAlwaysApproved, resolveApproval]);
|
|
1593
|
-
const firedWriteIds =
|
|
1644
|
+
const firedWriteIds = React8.useRef(/* @__PURE__ */ new Set());
|
|
1594
1645
|
const { onWriteSuccess } = config;
|
|
1595
|
-
|
|
1646
|
+
React8.useEffect(() => {
|
|
1596
1647
|
if (!onWriteSuccess) return;
|
|
1597
1648
|
for (const message of chat.messages) {
|
|
1598
1649
|
if (message.role !== "tool" || !message.is_write || message.tool_status !== "success") continue;
|
|
@@ -1602,9 +1653,9 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
1602
1653
|
onWriteSuccess({ arguments: args, toolName: message.tool_name ?? "" });
|
|
1603
1654
|
}
|
|
1604
1655
|
}, [chat.messages, onWriteSuccess]);
|
|
1605
|
-
const lastNavigatedMessageId =
|
|
1656
|
+
const lastNavigatedMessageId = React8.useRef(null);
|
|
1606
1657
|
const { messages } = chat;
|
|
1607
|
-
|
|
1658
|
+
React8.useEffect(() => {
|
|
1608
1659
|
if (!open || fullscreen || !config.navigate || !config.pages?.length) return;
|
|
1609
1660
|
const toolMessages = messages.filter((message) => message.role === "tool");
|
|
1610
1661
|
const latest = toolMessages[toolMessages.length - 1];
|
|
@@ -1616,7 +1667,7 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
1616
1667
|
const path = mapping.buildRoute ? mapping.buildRoute(args) : mapping.route;
|
|
1617
1668
|
if (path) config.navigate(path);
|
|
1618
1669
|
}, [config, fullscreen, messages, open]);
|
|
1619
|
-
const closePanel =
|
|
1670
|
+
const closePanel = React8.useCallback(() => {
|
|
1620
1671
|
setOpen(false);
|
|
1621
1672
|
setAgentMode(false);
|
|
1622
1673
|
}, [setOpen]);
|
|
@@ -1695,6 +1746,6 @@ function defineAgentConfig(config) {
|
|
|
1695
1746
|
return config;
|
|
1696
1747
|
}
|
|
1697
1748
|
|
|
1698
|
-
export { AgentApiClient, AgentApiError, AgentComposer, AgentPanel, AgentWidget, ChatScroller, DEFAULT_ACCEPT, DocumentCard, MessageItem, TaskChecklist, ThinkingIndicator, ToolActivityGroup, ToolApprovalCard, acceptAttribute, acceptedExtensions, defineAgentConfig, deriveDetails, fileUploadEnabled, formatBytes, groupMessages, humanizeToolName, resolveToolPresentation, useAgentChat, useAlwaysApprove, validateFile };
|
|
1749
|
+
export { AgentApiClient, AgentApiError, AgentComposer, AgentPanel, AgentWidget, ChatScroller, CopyButton, DEFAULT_ACCEPT, DocumentCard, MessageItem, TaskChecklist, ThinkingIndicator, ToolActivityGroup, ToolApprovalCard, acceptAttribute, acceptedExtensions, defineAgentConfig, deriveDetails, fileUploadEnabled, formatBytes, groupMessages, humanizeToolName, resolveToolPresentation, useAgentChat, useAlwaysApprove, validateFile };
|
|
1699
1750
|
//# sourceMappingURL=index.js.map
|
|
1700
1751
|
//# sourceMappingURL=index.js.map
|