@cntyclub/agent-react 0.9.0 → 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/agent-composer.d.ts +7 -1
- package/dist/components/agent-composer.d.ts.map +1 -1
- package/dist/components/agent-panel.d.ts.map +1 -1
- package/dist/components/chat-scroller.d.ts +17 -0
- package/dist/components/chat-scroller.d.ts.map +1 -0
- 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 +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +149 -66
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,13 @@ export interface AgentComposerProps {
|
|
|
4
4
|
onValueChange: (value: string) => void;
|
|
5
5
|
/** Submit the trimmed text plus any staged files. */
|
|
6
6
|
onSubmit: (text: string) => void;
|
|
7
|
+
/** Hard-disable the input entirely (e.g. a pending approval must be resolved). */
|
|
7
8
|
disabled?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* A reply is in progress. The textarea stays enabled and focused so the user
|
|
11
|
+
* can start writing their next message, but submitting is blocked until done.
|
|
12
|
+
*/
|
|
13
|
+
busy?: boolean;
|
|
8
14
|
placeholder?: string;
|
|
9
15
|
className?: string;
|
|
10
16
|
/** File upload wiring. Omit `onPickFiles` to hide the attach button. */
|
|
@@ -19,5 +25,5 @@ export interface AgentComposerProps {
|
|
|
19
25
|
* Shift+Enter inserts a newline. Submitting is allowed when there is text OR at
|
|
20
26
|
* least one staged file.
|
|
21
27
|
*/
|
|
22
|
-
export declare function AgentComposer({ acceptAttribute, className, disabled, files, onPickFiles, onRemoveFile, onSubmit, onValueChange, placeholder, value, }: AgentComposerProps): React.JSX.Element;
|
|
28
|
+
export declare function AgentComposer({ acceptAttribute, busy, className, disabled, files, onPickFiles, onRemoveFile, onSubmit, onValueChange, placeholder, value, }: AgentComposerProps): React.JSX.Element;
|
|
23
29
|
//# sourceMappingURL=agent-composer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-composer.d.ts","sourceRoot":"","sources":["../../src/components/agent-composer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,qDAAqD;IACrD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,eAAe,EACf,SAAS,EACT,QAAQ,EACR,KAAK,EACL,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,WAA6B,EAC7B,KAAK,GACN,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"agent-composer.d.ts","sourceRoot":"","sources":["../../src/components/agent-composer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,qDAAqD;IACrD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,eAAe,EACf,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,KAAK,EACL,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,WAA6B,EAC7B,KAAK,GACN,EAAE,kBAAkB,qBA6HpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-panel.d.ts","sourceRoot":"","sources":["../../src/components/agent-panel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agent-panel.d.ts","sourceRoot":"","sources":["../../src/components/agent-panel.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,cAAc,GAAG,gBAAgB,CAAC;IACxC,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,iEAAiE;IACjE,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,kBAAkB,EAClB,IAAI,EACJ,SAAS,EACT,MAAM,EACN,eAAe,EACf,OAAO,EACP,iBAAiB,GAClB,EAAE,eAAe,qBAkTjB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type ChatScrollerProps = React.ComponentProps<"div">;
|
|
3
|
+
/**
|
|
4
|
+
* Scrollable message viewport that stays pinned to the bottom while content
|
|
5
|
+
* grows — including token-by-token streaming, where text is appended to the
|
|
6
|
+
* SAME message rather than adding new ones.
|
|
7
|
+
*
|
|
8
|
+
* Why not the UI kit's ChatMessages autoScroll: that container uses CSS
|
|
9
|
+
* `scroll-smooth`, so a programmatic jump to the bottom emits intermediate
|
|
10
|
+
* `scroll` events mid-animation whose distance-from-bottom is large, which
|
|
11
|
+
* flips its "pinned" flag to false — after the first delta it stops following.
|
|
12
|
+
* Here we scroll INSTANTLY (no smooth), so the only resulting scroll event is
|
|
13
|
+
* at the true bottom and the pin holds for the whole stream. The user can still
|
|
14
|
+
* scroll up to read history (that unpins), and scrolling back down re-pins.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ChatScroller({ children, className, ...props }: ChatScrollerProps): React.JSX.Element;
|
|
17
|
+
//# sourceMappingURL=chat-scroller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-scroller.d.ts","sourceRoot":"","sources":["../../src/components/chat-scroller.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,iBAAiB,GAAG,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAE5D;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB,qBA8BhF"}
|
|
@@ -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
|
@@ -2,6 +2,8 @@ export { AgentApiClient, AgentApiError } from "./api-client";
|
|
|
2
2
|
export { AgentComposer, type AgentComposerProps } from "./components/agent-composer";
|
|
3
3
|
export { AgentPanel, type AgentPanelProps } from "./components/agent-panel";
|
|
4
4
|
export { AgentWidget, type AgentWidgetProps } from "./components/agent-widget";
|
|
5
|
+
export { ChatScroller, type ChatScrollerProps } from "./components/chat-scroller";
|
|
6
|
+
export { CopyButton, type CopyButtonProps } from "./components/copy-button";
|
|
5
7
|
export { DocumentCard } from "./components/document-card";
|
|
6
8
|
export { MessageItem } from "./components/message-item";
|
|
7
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,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
|
|
@@ -219,6 +219,7 @@ function formatBytes(bytes) {
|
|
|
219
219
|
}
|
|
220
220
|
function AgentComposer({
|
|
221
221
|
acceptAttribute: acceptAttribute2,
|
|
222
|
+
busy,
|
|
222
223
|
className,
|
|
223
224
|
disabled,
|
|
224
225
|
files,
|
|
@@ -229,14 +230,18 @@ function AgentComposer({
|
|
|
229
230
|
placeholder = "Ask anything\u2026",
|
|
230
231
|
value
|
|
231
232
|
}) {
|
|
232
|
-
const textareaRef =
|
|
233
|
-
const inputRef =
|
|
234
|
-
const canSubmit = !disabled && (value.trim().length > 0 || files.length > 0);
|
|
235
|
-
const submit =
|
|
233
|
+
const textareaRef = React8.useRef(null);
|
|
234
|
+
const inputRef = React8.useRef(null);
|
|
235
|
+
const canSubmit = !disabled && !busy && (value.trim().length > 0 || files.length > 0);
|
|
236
|
+
const submit = React8.useCallback(() => {
|
|
236
237
|
if (!canSubmit) return;
|
|
237
238
|
onSubmit(value.trim());
|
|
239
|
+
textareaRef.current?.focus();
|
|
238
240
|
}, [canSubmit, onSubmit, value]);
|
|
239
|
-
|
|
241
|
+
React8.useEffect(() => {
|
|
242
|
+
if (!disabled) textareaRef.current?.focus();
|
|
243
|
+
}, [disabled]);
|
|
244
|
+
React8.useEffect(() => {
|
|
240
245
|
const textarea = textareaRef.current;
|
|
241
246
|
if (!textarea) return;
|
|
242
247
|
textarea.style.height = "auto";
|
|
@@ -417,6 +422,71 @@ function groupMessages(messages) {
|
|
|
417
422
|
flush();
|
|
418
423
|
return items;
|
|
419
424
|
}
|
|
425
|
+
function ChatScroller({ children, className, ...props }) {
|
|
426
|
+
const viewportRef = React8.useRef(null);
|
|
427
|
+
const pinnedRef = React8.useRef(true);
|
|
428
|
+
const handleScroll = React8.useCallback(() => {
|
|
429
|
+
const viewport = viewportRef.current;
|
|
430
|
+
if (!viewport) return;
|
|
431
|
+
const distanceFromBottom = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
|
|
432
|
+
pinnedRef.current = distanceFromBottom < 64;
|
|
433
|
+
}, []);
|
|
434
|
+
React8.useEffect(() => {
|
|
435
|
+
const viewport = viewportRef.current;
|
|
436
|
+
if (!viewport || !pinnedRef.current) return;
|
|
437
|
+
viewport.scrollTop = viewport.scrollHeight;
|
|
438
|
+
});
|
|
439
|
+
return /* @__PURE__ */ jsx(
|
|
440
|
+
"div",
|
|
441
|
+
{
|
|
442
|
+
className: cn("flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-4", className),
|
|
443
|
+
"data-slot": "chat-scroller",
|
|
444
|
+
onScroll: handleScroll,
|
|
445
|
+
ref: viewportRef,
|
|
446
|
+
...props,
|
|
447
|
+
children
|
|
448
|
+
}
|
|
449
|
+
);
|
|
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
|
+
}
|
|
420
490
|
function MessageItem({ message }) {
|
|
421
491
|
if (message.role === "user") {
|
|
422
492
|
const attachments = message.attachments ?? [];
|
|
@@ -437,7 +507,19 @@ function MessageItem({ message }) {
|
|
|
437
507
|
}
|
|
438
508
|
if (message.role === "assistant") {
|
|
439
509
|
if (!message.content || !message.content.trim()) return null;
|
|
440
|
-
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
|
+
] });
|
|
441
523
|
}
|
|
442
524
|
return null;
|
|
443
525
|
}
|
|
@@ -451,8 +533,8 @@ var DEFAULT_PHRASES = [
|
|
|
451
533
|
];
|
|
452
534
|
function ThinkingIndicator({ className, intervalMs = 1800, phrases }) {
|
|
453
535
|
const words = phrases && phrases.length ? phrases : DEFAULT_PHRASES;
|
|
454
|
-
const [index, setIndex] =
|
|
455
|
-
|
|
536
|
+
const [index, setIndex] = React8.useState(0);
|
|
537
|
+
React8.useEffect(() => {
|
|
456
538
|
setIndex(0);
|
|
457
539
|
const timer = setInterval(() => {
|
|
458
540
|
setIndex((current) => (current + 1) % words.length);
|
|
@@ -481,7 +563,7 @@ function ThinkingIndicator({ className, intervalMs = 1800, phrases }) {
|
|
|
481
563
|
className: "fade-in-0 animate-in text-muted-foreground text-xs duration-300",
|
|
482
564
|
children: [
|
|
483
565
|
words[index],
|
|
484
|
-
"\u2026"
|
|
566
|
+
" \u2026"
|
|
485
567
|
]
|
|
486
568
|
},
|
|
487
569
|
index
|
|
@@ -714,7 +796,7 @@ function DownloadButton({ block, size = "sm" }) {
|
|
|
714
796
|
);
|
|
715
797
|
}
|
|
716
798
|
function DocumentViewer({ block, onClose }) {
|
|
717
|
-
|
|
799
|
+
React8.useEffect(() => {
|
|
718
800
|
const onKey = (event) => event.key === "Escape" && onClose();
|
|
719
801
|
window.addEventListener("keydown", onKey);
|
|
720
802
|
return () => window.removeEventListener("keydown", onKey);
|
|
@@ -739,7 +821,7 @@ function DocumentViewer({ block, onClose }) {
|
|
|
739
821
|
] });
|
|
740
822
|
}
|
|
741
823
|
function DocumentCard({ block }) {
|
|
742
|
-
const [open, setOpen] =
|
|
824
|
+
const [open, setOpen] = React8.useState(false);
|
|
743
825
|
const previewLines = (block.preview || "").split("\n").slice(0, 6).join("\n");
|
|
744
826
|
return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-full overflow-hidden rounded-xl border border-border bg-card shadow-xs", children: [
|
|
745
827
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-border/72 border-b px-3 py-2", children: [
|
|
@@ -861,7 +943,7 @@ function StepDetail({
|
|
|
861
943
|
] });
|
|
862
944
|
}
|
|
863
945
|
function ToolActivityGroup({ describeToolCall, steps }) {
|
|
864
|
-
const [open, setOpen] =
|
|
946
|
+
const [open, setOpen] = React8.useState(false);
|
|
865
947
|
if (steps.length === 0) return null;
|
|
866
948
|
const last = steps[steps.length - 1];
|
|
867
949
|
const anyRunning = steps.some((step) => step.status === "running");
|
|
@@ -964,19 +1046,19 @@ function AgentPanel({
|
|
|
964
1046
|
onClose,
|
|
965
1047
|
onToggleAgentMode
|
|
966
1048
|
}) {
|
|
967
|
-
const [draft, setDraft] =
|
|
968
|
-
const [view, setView] =
|
|
969
|
-
const [files, setFiles] =
|
|
970
|
-
const [uploadError, setUploadError] =
|
|
971
|
-
const [dragging, setDragging] =
|
|
972
|
-
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);
|
|
973
1055
|
const agentName = config.agentName ?? chat.agentInfo?.name ?? "Assistant";
|
|
974
1056
|
const uploadEnabled = fileUploadEnabled(config);
|
|
975
1057
|
const suggestions = config.suggestions ?? [
|
|
976
1058
|
"What can you help me with?",
|
|
977
1059
|
"Give me a quick summary of my data."
|
|
978
1060
|
];
|
|
979
|
-
const addFiles =
|
|
1061
|
+
const addFiles = React8.useCallback(
|
|
980
1062
|
(incoming) => {
|
|
981
1063
|
const accepted = [];
|
|
982
1064
|
let rejection = null;
|
|
@@ -993,10 +1075,10 @@ function AgentPanel({
|
|
|
993
1075
|
},
|
|
994
1076
|
[config]
|
|
995
1077
|
);
|
|
996
|
-
const removeFile =
|
|
1078
|
+
const removeFile = React8.useCallback((index) => {
|
|
997
1079
|
setFiles((current) => current.filter((_, i) => i !== index));
|
|
998
1080
|
}, []);
|
|
999
|
-
const handleSubmit =
|
|
1081
|
+
const handleSubmit = React8.useCallback(
|
|
1000
1082
|
(text) => {
|
|
1001
1083
|
const staged = files;
|
|
1002
1084
|
setDraft("");
|
|
@@ -1006,7 +1088,7 @@ function AgentPanel({
|
|
|
1006
1088
|
},
|
|
1007
1089
|
[chat, files]
|
|
1008
1090
|
);
|
|
1009
|
-
const onDragEnter =
|
|
1091
|
+
const onDragEnter = React8.useCallback(
|
|
1010
1092
|
(event) => {
|
|
1011
1093
|
if (!uploadEnabled || !event.dataTransfer?.types?.includes("Files")) return;
|
|
1012
1094
|
dragDepth.current += 1;
|
|
@@ -1014,12 +1096,12 @@ function AgentPanel({
|
|
|
1014
1096
|
},
|
|
1015
1097
|
[uploadEnabled]
|
|
1016
1098
|
);
|
|
1017
|
-
const onDragLeave =
|
|
1099
|
+
const onDragLeave = React8.useCallback((event) => {
|
|
1018
1100
|
if (!event.dataTransfer?.types?.includes("Files")) return;
|
|
1019
1101
|
dragDepth.current = Math.max(0, dragDepth.current - 1);
|
|
1020
1102
|
if (dragDepth.current === 0) setDragging(false);
|
|
1021
1103
|
}, []);
|
|
1022
|
-
const onDrop =
|
|
1104
|
+
const onDrop = React8.useCallback(
|
|
1023
1105
|
(event) => {
|
|
1024
1106
|
if (!uploadEnabled) return;
|
|
1025
1107
|
event.preventDefault();
|
|
@@ -1030,7 +1112,7 @@ function AgentPanel({
|
|
|
1030
1112
|
},
|
|
1031
1113
|
[addFiles, uploadEnabled]
|
|
1032
1114
|
);
|
|
1033
|
-
const openHistory =
|
|
1115
|
+
const openHistory = React8.useCallback(() => {
|
|
1034
1116
|
setView("history");
|
|
1035
1117
|
void chat.refreshConversations();
|
|
1036
1118
|
}, [chat]);
|
|
@@ -1160,7 +1242,7 @@ function AgentPanel({
|
|
|
1160
1242
|
},
|
|
1161
1243
|
conversation.id
|
|
1162
1244
|
)) }) : /* @__PURE__ */ jsxs(Chat, { children: [
|
|
1163
|
-
/* @__PURE__ */ jsx(
|
|
1245
|
+
/* @__PURE__ */ jsx(ChatScroller, { className: cn(agentMode && "mx-auto w-full max-w-3xl"), children: chat.messages.length === 0 && !chat.sending ? /* @__PURE__ */ jsxs(ChatEmptyState, { children: [
|
|
1164
1246
|
/* @__PURE__ */ jsx(ChatEmptyStateIcon, {}),
|
|
1165
1247
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1166
1248
|
/* @__PURE__ */ jsxs(ChatEmptyStateTitle, { children: [
|
|
@@ -1215,8 +1297,9 @@ function AgentPanel({
|
|
|
1215
1297
|
AgentComposer,
|
|
1216
1298
|
{
|
|
1217
1299
|
acceptAttribute: acceptAttribute(config),
|
|
1300
|
+
busy,
|
|
1218
1301
|
className: cn(agentMode && "mx-auto w-full max-w-3xl"),
|
|
1219
|
-
disabled:
|
|
1302
|
+
disabled: chat.pendingApprovals.length > 0,
|
|
1220
1303
|
files,
|
|
1221
1304
|
onPickFiles: uploadEnabled ? addFiles : void 0,
|
|
1222
1305
|
onRemoveFile: removeFile,
|
|
@@ -1252,16 +1335,16 @@ function buildOptimisticUserMessage(text, files) {
|
|
|
1252
1335
|
};
|
|
1253
1336
|
}
|
|
1254
1337
|
function useAgentChat(config) {
|
|
1255
|
-
const client =
|
|
1256
|
-
const [agentInfo, setAgentInfo] =
|
|
1257
|
-
const [conversationId, setConversationId] =
|
|
1258
|
-
const [conversations, setConversations] =
|
|
1259
|
-
const [messages, setMessages] =
|
|
1260
|
-
const [pendingApprovals, setPendingApprovals] =
|
|
1261
|
-
const [sending, setSending] =
|
|
1262
|
-
const [resolvingApprovalId, setResolvingApprovalId] =
|
|
1263
|
-
const [error, setError] =
|
|
1264
|
-
|
|
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(() => {
|
|
1265
1348
|
let cancelled = false;
|
|
1266
1349
|
client.getConfig().then((info) => {
|
|
1267
1350
|
if (!cancelled) setAgentInfo(info);
|
|
@@ -1271,11 +1354,11 @@ function useAgentChat(config) {
|
|
|
1271
1354
|
cancelled = true;
|
|
1272
1355
|
};
|
|
1273
1356
|
}, [client]);
|
|
1274
|
-
const handleFailure =
|
|
1357
|
+
const handleFailure = React8.useCallback((err) => {
|
|
1275
1358
|
const message = err instanceof AgentApiError ? err.message : "Something went wrong. Please try again.";
|
|
1276
1359
|
setError(message);
|
|
1277
1360
|
}, []);
|
|
1278
|
-
const applyResponse =
|
|
1361
|
+
const applyResponse = React8.useCallback(
|
|
1279
1362
|
(response) => {
|
|
1280
1363
|
if (response.status === "error" && !response.messages?.length) {
|
|
1281
1364
|
setError(response.message ?? "The assistant could not answer.");
|
|
@@ -1297,7 +1380,7 @@ function useAgentChat(config) {
|
|
|
1297
1380
|
},
|
|
1298
1381
|
[]
|
|
1299
1382
|
);
|
|
1300
|
-
const handleStreamEvent =
|
|
1383
|
+
const handleStreamEvent = React8.useCallback(
|
|
1301
1384
|
(event, ctx) => {
|
|
1302
1385
|
switch (event.type) {
|
|
1303
1386
|
case "conversation":
|
|
@@ -1362,7 +1445,7 @@ function useAgentChat(config) {
|
|
|
1362
1445
|
[]
|
|
1363
1446
|
);
|
|
1364
1447
|
const streamingEnabled = config.streaming !== false && typeof ReadableStream !== "undefined";
|
|
1365
|
-
const send =
|
|
1448
|
+
const send = React8.useCallback(
|
|
1366
1449
|
async (text, files) => {
|
|
1367
1450
|
if (sending) return;
|
|
1368
1451
|
if (!text.trim() && !(files && files.length)) return;
|
|
@@ -1393,7 +1476,7 @@ function useAgentChat(config) {
|
|
|
1393
1476
|
},
|
|
1394
1477
|
[applyResponse, client, conversationId, handleFailure, handleStreamEvent, sending, streamingEnabled]
|
|
1395
1478
|
);
|
|
1396
|
-
const resolveApproval =
|
|
1479
|
+
const resolveApproval = React8.useCallback(
|
|
1397
1480
|
async (callId, approve) => {
|
|
1398
1481
|
if (resolvingApprovalId) return;
|
|
1399
1482
|
setResolvingApprovalId(callId);
|
|
@@ -1422,13 +1505,13 @@ function useAgentChat(config) {
|
|
|
1422
1505
|
},
|
|
1423
1506
|
[applyResponse, client, handleFailure, handleStreamEvent, resolvingApprovalId, streamingEnabled]
|
|
1424
1507
|
);
|
|
1425
|
-
const newChat =
|
|
1508
|
+
const newChat = React8.useCallback(() => {
|
|
1426
1509
|
setConversationId(null);
|
|
1427
1510
|
setMessages([]);
|
|
1428
1511
|
setPendingApprovals([]);
|
|
1429
1512
|
setError(null);
|
|
1430
1513
|
}, []);
|
|
1431
|
-
const refreshConversations =
|
|
1514
|
+
const refreshConversations = React8.useCallback(async () => {
|
|
1432
1515
|
try {
|
|
1433
1516
|
const { conversations: list } = await client.listConversations();
|
|
1434
1517
|
setConversations(list);
|
|
@@ -1436,7 +1519,7 @@ function useAgentChat(config) {
|
|
|
1436
1519
|
handleFailure(err);
|
|
1437
1520
|
}
|
|
1438
1521
|
}, [client, handleFailure]);
|
|
1439
|
-
const openConversation =
|
|
1522
|
+
const openConversation = React8.useCallback(
|
|
1440
1523
|
async (id) => {
|
|
1441
1524
|
setError(null);
|
|
1442
1525
|
try {
|
|
@@ -1450,7 +1533,7 @@ function useAgentChat(config) {
|
|
|
1450
1533
|
},
|
|
1451
1534
|
[client, handleFailure]
|
|
1452
1535
|
);
|
|
1453
|
-
const deleteConversation =
|
|
1536
|
+
const deleteConversation = React8.useCallback(
|
|
1454
1537
|
async (id) => {
|
|
1455
1538
|
try {
|
|
1456
1539
|
await client.deleteConversation(id);
|
|
@@ -1462,7 +1545,7 @@ function useAgentChat(config) {
|
|
|
1462
1545
|
},
|
|
1463
1546
|
[client, conversationId, handleFailure, newChat]
|
|
1464
1547
|
);
|
|
1465
|
-
const clearError =
|
|
1548
|
+
const clearError = React8.useCallback(() => setError(null), []);
|
|
1466
1549
|
return {
|
|
1467
1550
|
agentInfo,
|
|
1468
1551
|
clearError,
|
|
@@ -1497,11 +1580,11 @@ function readStored(clientId) {
|
|
|
1497
1580
|
}
|
|
1498
1581
|
}
|
|
1499
1582
|
function useAlwaysApprove(clientId) {
|
|
1500
|
-
const [approved, setApproved] =
|
|
1501
|
-
|
|
1583
|
+
const [approved, setApproved] = React8.useState(() => /* @__PURE__ */ new Set());
|
|
1584
|
+
React8.useEffect(() => {
|
|
1502
1585
|
setApproved(readStored(clientId));
|
|
1503
1586
|
}, [clientId]);
|
|
1504
|
-
const persist =
|
|
1587
|
+
const persist = React8.useCallback(
|
|
1505
1588
|
(next) => {
|
|
1506
1589
|
setApproved(next);
|
|
1507
1590
|
if (typeof window === "undefined") return;
|
|
@@ -1512,8 +1595,8 @@ function useAlwaysApprove(clientId) {
|
|
|
1512
1595
|
},
|
|
1513
1596
|
[clientId]
|
|
1514
1597
|
);
|
|
1515
|
-
const isAlwaysApproved =
|
|
1516
|
-
const setAlwaysApprove =
|
|
1598
|
+
const isAlwaysApproved = React8.useCallback((toolName) => approved.has(toolName), [approved]);
|
|
1599
|
+
const setAlwaysApprove = React8.useCallback(
|
|
1517
1600
|
(toolName) => {
|
|
1518
1601
|
if (approved.has(toolName)) return;
|
|
1519
1602
|
const next = new Set(approved);
|
|
@@ -1522,7 +1605,7 @@ function useAlwaysApprove(clientId) {
|
|
|
1522
1605
|
},
|
|
1523
1606
|
[approved, persist]
|
|
1524
1607
|
);
|
|
1525
|
-
const clearAlwaysApprove =
|
|
1608
|
+
const clearAlwaysApprove = React8.useCallback(
|
|
1526
1609
|
(toolName) => {
|
|
1527
1610
|
if (!approved.has(toolName)) return;
|
|
1528
1611
|
const next = new Set(approved);
|
|
@@ -1534,16 +1617,16 @@ function useAlwaysApprove(clientId) {
|
|
|
1534
1617
|
return { clearAlwaysApprove, isAlwaysApproved, setAlwaysApprove };
|
|
1535
1618
|
}
|
|
1536
1619
|
function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
1537
|
-
const [uncontrolledOpen, setUncontrolledOpen] =
|
|
1620
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React8.useState(false);
|
|
1538
1621
|
const open = controlledOpen ?? uncontrolledOpen;
|
|
1539
|
-
const setOpen =
|
|
1622
|
+
const setOpen = React8.useCallback(
|
|
1540
1623
|
(next) => {
|
|
1541
1624
|
setUncontrolledOpen(next);
|
|
1542
1625
|
onOpenChange?.(next);
|
|
1543
1626
|
},
|
|
1544
1627
|
[onOpenChange]
|
|
1545
1628
|
);
|
|
1546
|
-
const [agentMode, setAgentMode] =
|
|
1629
|
+
const [agentMode, setAgentMode] = React8.useState(false);
|
|
1547
1630
|
const isDesktop = useMediaQuery("(min-width: 640px)", {
|
|
1548
1631
|
defaultSSRValue: true,
|
|
1549
1632
|
ssr: true
|
|
@@ -1553,14 +1636,14 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
1553
1636
|
const alwaysApprove = useAlwaysApprove(config.clientId);
|
|
1554
1637
|
const { pendingApprovals, resolveApproval, resolvingApprovalId } = chat;
|
|
1555
1638
|
const { isAlwaysApproved } = alwaysApprove;
|
|
1556
|
-
|
|
1639
|
+
React8.useEffect(() => {
|
|
1557
1640
|
if (!open || resolvingApprovalId) return;
|
|
1558
1641
|
const target = pendingApprovals.find((approval) => isAlwaysApproved(approval.tool_name));
|
|
1559
1642
|
if (target) void resolveApproval(target.id, true);
|
|
1560
1643
|
}, [open, pendingApprovals, resolvingApprovalId, isAlwaysApproved, resolveApproval]);
|
|
1561
|
-
const firedWriteIds =
|
|
1644
|
+
const firedWriteIds = React8.useRef(/* @__PURE__ */ new Set());
|
|
1562
1645
|
const { onWriteSuccess } = config;
|
|
1563
|
-
|
|
1646
|
+
React8.useEffect(() => {
|
|
1564
1647
|
if (!onWriteSuccess) return;
|
|
1565
1648
|
for (const message of chat.messages) {
|
|
1566
1649
|
if (message.role !== "tool" || !message.is_write || message.tool_status !== "success") continue;
|
|
@@ -1570,9 +1653,9 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
1570
1653
|
onWriteSuccess({ arguments: args, toolName: message.tool_name ?? "" });
|
|
1571
1654
|
}
|
|
1572
1655
|
}, [chat.messages, onWriteSuccess]);
|
|
1573
|
-
const lastNavigatedMessageId =
|
|
1656
|
+
const lastNavigatedMessageId = React8.useRef(null);
|
|
1574
1657
|
const { messages } = chat;
|
|
1575
|
-
|
|
1658
|
+
React8.useEffect(() => {
|
|
1576
1659
|
if (!open || fullscreen || !config.navigate || !config.pages?.length) return;
|
|
1577
1660
|
const toolMessages = messages.filter((message) => message.role === "tool");
|
|
1578
1661
|
const latest = toolMessages[toolMessages.length - 1];
|
|
@@ -1584,7 +1667,7 @@ function AgentWidget({ config, onOpenChange, open: controlledOpen }) {
|
|
|
1584
1667
|
const path = mapping.buildRoute ? mapping.buildRoute(args) : mapping.route;
|
|
1585
1668
|
if (path) config.navigate(path);
|
|
1586
1669
|
}, [config, fullscreen, messages, open]);
|
|
1587
|
-
const closePanel =
|
|
1670
|
+
const closePanel = React8.useCallback(() => {
|
|
1588
1671
|
setOpen(false);
|
|
1589
1672
|
setAgentMode(false);
|
|
1590
1673
|
}, [setOpen]);
|
|
@@ -1663,6 +1746,6 @@ function defineAgentConfig(config) {
|
|
|
1663
1746
|
return config;
|
|
1664
1747
|
}
|
|
1665
1748
|
|
|
1666
|
-
export { AgentApiClient, AgentApiError, AgentComposer, AgentPanel, AgentWidget, 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 };
|
|
1667
1750
|
//# sourceMappingURL=index.js.map
|
|
1668
1751
|
//# sourceMappingURL=index.js.map
|