@invergent/agent-chat-react 1.4.9 → 1.4.11
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/index.cjs +88 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +88 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -371,7 +371,8 @@ interface SessionTreePanelProps {
|
|
|
371
371
|
/** Treat the root as hidden, so its children appear as top-level rows. */
|
|
372
372
|
hideRoot?: boolean;
|
|
373
373
|
onSessionSelect?: (sessionId: string) => void;
|
|
374
|
+
onSessionDelete?: (sessionId: string) => void;
|
|
374
375
|
}
|
|
375
|
-
declare function SessionTreePanel({ adapter, sessionId, activeSessionId, agentId, title, sessionListLimit, hideRoot, onSessionSelect, }: SessionTreePanelProps): react_jsx_runtime.JSX.Element | null;
|
|
376
|
+
declare function SessionTreePanel({ adapter, sessionId, activeSessionId, agentId, title, sessionListLimit, hideRoot, onSessionSelect, onSessionDelete, }: SessionTreePanelProps): react_jsx_runtime.JSX.Element | null;
|
|
376
377
|
|
|
377
378
|
export { AgentChat, type AgentChatAdapter, type AgentChatAdapterContextValue, AgentChatAdapterProvider, type AgentChatArtifactKind, type AgentChatArtifactMeta, type AgentChatArtifactPayload, type AgentChatChartArtifactSpec, type AgentChatClarifyAnswer, type AgentChatClarifyArgs, type AgentChatClarifyChoice, type AgentChatClarifyQuestion, type AgentChatErrorCategory, type AgentChatErrorInfo, type AgentChatEventStream, type AgentChatEventType, type AgentChatExpertFeedbackRating, type AgentChatHtmlArtifactSpec, type AgentChatMarkdownArtifactSpec, type AgentChatMessage, type AgentChatMessageStatus, type AgentChatProps, type AgentChatRole, type AgentChatRuntimeApi, type AgentChatRuntimeEvent, type AgentChatSession, type AgentChatSessionList, type AgentChatSessionTree, type AgentChatSessionTreeNode, type AgentChatSlashCommand, type AgentChatSseMessageEvent, type AgentChatState, type AgentChatSvgArtifactSpec, type AgentChatSystemKind, type AgentChatTableArtifactSpec, type AgentChatTokenUsage, type AgentChatToolCallInfo, type AgentChatWorkspaceEntry, type AgentChatWorkspaceFile, type AgentChatWorkspaceTree, type AgentChatWorkspaceUpload, type ArtifactKind, type ArtifactPayload, type ChartArtifactSpec, type ChatMessage, type ClarifyAnswer, type ClarifyArgs, type ClarifyChoice, type ClarifyQuestion, type ErrorInfo, type HtmlArtifactSpec, type MarkdownArtifactSpec, MessageResponse, type MessageResponseProps, type RetryIndicator, type SessionTree, type SessionTreeNode, SessionTreePanel, type SessionTreePanelProps, type SvgArtifactSpec, type TableArtifactSpec, type TokenUsage, type ToolCallInfo, type WorkspaceEntry, type WorkspaceFile, type WorkspaceTree, type WorkspaceUpload, useAgentChatAdapterContext, useAgentChatRuntime };
|
package/dist/index.d.ts
CHANGED
|
@@ -371,7 +371,8 @@ interface SessionTreePanelProps {
|
|
|
371
371
|
/** Treat the root as hidden, so its children appear as top-level rows. */
|
|
372
372
|
hideRoot?: boolean;
|
|
373
373
|
onSessionSelect?: (sessionId: string) => void;
|
|
374
|
+
onSessionDelete?: (sessionId: string) => void;
|
|
374
375
|
}
|
|
375
|
-
declare function SessionTreePanel({ adapter, sessionId, activeSessionId, agentId, title, sessionListLimit, hideRoot, onSessionSelect, }: SessionTreePanelProps): react_jsx_runtime.JSX.Element | null;
|
|
376
|
+
declare function SessionTreePanel({ adapter, sessionId, activeSessionId, agentId, title, sessionListLimit, hideRoot, onSessionSelect, onSessionDelete, }: SessionTreePanelProps): react_jsx_runtime.JSX.Element | null;
|
|
376
377
|
|
|
377
378
|
export { AgentChat, type AgentChatAdapter, type AgentChatAdapterContextValue, AgentChatAdapterProvider, type AgentChatArtifactKind, type AgentChatArtifactMeta, type AgentChatArtifactPayload, type AgentChatChartArtifactSpec, type AgentChatClarifyAnswer, type AgentChatClarifyArgs, type AgentChatClarifyChoice, type AgentChatClarifyQuestion, type AgentChatErrorCategory, type AgentChatErrorInfo, type AgentChatEventStream, type AgentChatEventType, type AgentChatExpertFeedbackRating, type AgentChatHtmlArtifactSpec, type AgentChatMarkdownArtifactSpec, type AgentChatMessage, type AgentChatMessageStatus, type AgentChatProps, type AgentChatRole, type AgentChatRuntimeApi, type AgentChatRuntimeEvent, type AgentChatSession, type AgentChatSessionList, type AgentChatSessionTree, type AgentChatSessionTreeNode, type AgentChatSlashCommand, type AgentChatSseMessageEvent, type AgentChatState, type AgentChatSvgArtifactSpec, type AgentChatSystemKind, type AgentChatTableArtifactSpec, type AgentChatTokenUsage, type AgentChatToolCallInfo, type AgentChatWorkspaceEntry, type AgentChatWorkspaceFile, type AgentChatWorkspaceTree, type AgentChatWorkspaceUpload, type ArtifactKind, type ArtifactPayload, type ChartArtifactSpec, type ChatMessage, type ClarifyAnswer, type ClarifyArgs, type ClarifyChoice, type ClarifyQuestion, type ErrorInfo, type HtmlArtifactSpec, type MarkdownArtifactSpec, MessageResponse, type MessageResponseProps, type RetryIndicator, type SessionTree, type SessionTreeNode, SessionTreePanel, type SessionTreePanelProps, type SvgArtifactSpec, type TableArtifactSpec, type TokenUsage, type ToolCallInfo, type WorkspaceEntry, type WorkspaceFile, type WorkspaceTree, type WorkspaceUpload, useAgentChatAdapterContext, useAgentChatRuntime };
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import Ansi from 'ansi-to-react';
|
|
|
18
18
|
import { getUsage } from 'tokenlens';
|
|
19
19
|
import { Command as Command$1 } from 'cmdk';
|
|
20
20
|
import { nanoid } from 'nanoid';
|
|
21
|
+
import { formatDistanceToNow } from 'date-fns';
|
|
21
22
|
|
|
22
23
|
// src/agent-chat.tsx
|
|
23
24
|
var AgentChatAdapterContext = createContext(null);
|
|
@@ -7822,32 +7823,31 @@ function mergeTreeNodes(groups) {
|
|
|
7822
7823
|
}
|
|
7823
7824
|
return Array.from(byId.values());
|
|
7824
7825
|
}
|
|
7825
|
-
function
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
case "completed":
|
|
7830
|
-
return "secondary";
|
|
7831
|
-
case "failed":
|
|
7832
|
-
return "destructive";
|
|
7833
|
-
default:
|
|
7834
|
-
return "outline";
|
|
7835
|
-
}
|
|
7826
|
+
function formatSessionTime(value) {
|
|
7827
|
+
const date = new Date(value);
|
|
7828
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
7829
|
+
return formatDistanceToNow(date, { addSuffix: true });
|
|
7836
7830
|
}
|
|
7837
7831
|
function TreeNodeRow({
|
|
7838
7832
|
entry,
|
|
7839
7833
|
depth,
|
|
7840
7834
|
activeSessionId,
|
|
7841
7835
|
canStop,
|
|
7836
|
+
canDelete,
|
|
7837
|
+
deletingSessionId,
|
|
7842
7838
|
onSelect,
|
|
7843
|
-
onStop
|
|
7839
|
+
onStop,
|
|
7840
|
+
onDelete
|
|
7844
7841
|
}) {
|
|
7845
7842
|
const [expanded, setExpanded] = useState(true);
|
|
7846
7843
|
const hasChildren = entry.children.length > 0;
|
|
7847
7844
|
const isActive = entry.id === activeSessionId;
|
|
7848
7845
|
const isRunning = entry.status === "active";
|
|
7849
|
-
const
|
|
7850
|
-
const
|
|
7846
|
+
const title = entry.title ?? "New session";
|
|
7847
|
+
const subtitle = [
|
|
7848
|
+
entry.model ?? "default",
|
|
7849
|
+
formatSessionTime(entry.updatedAt)
|
|
7850
|
+
].filter(Boolean).join(" \xB7 ");
|
|
7851
7851
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7852
7852
|
/* @__PURE__ */ jsxs(
|
|
7853
7853
|
"div",
|
|
@@ -7859,16 +7859,16 @@ function TreeNodeRow({
|
|
|
7859
7859
|
if (e.key === "Enter" || e.key === " ") onSelect(entry.id);
|
|
7860
7860
|
},
|
|
7861
7861
|
className: cn(
|
|
7862
|
-
"group flex items-center gap-
|
|
7863
|
-
isActive ? "bg-line text-foreground" : "
|
|
7862
|
+
"group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
|
|
7863
|
+
isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-subtle hover:bg-input hover:text-foreground border-l-transparent"
|
|
7864
7864
|
),
|
|
7865
|
-
style: { paddingLeft: `${depth * 12 +
|
|
7865
|
+
style: { paddingLeft: `${depth * 12 + 12}px` },
|
|
7866
7866
|
children: [
|
|
7867
7867
|
hasChildren ? /* @__PURE__ */ jsx(
|
|
7868
7868
|
"button",
|
|
7869
7869
|
{
|
|
7870
7870
|
type: "button",
|
|
7871
|
-
className: "p-0.5 rounded hover:bg-line",
|
|
7871
|
+
className: "p-0.5 rounded hover:bg-line shrink-0",
|
|
7872
7872
|
onClick: (e) => {
|
|
7873
7873
|
e.stopPropagation();
|
|
7874
7874
|
setExpanded(!expanded);
|
|
@@ -7878,32 +7878,10 @@ function TreeNodeRow({
|
|
|
7878
7878
|
children: expanded ? /* @__PURE__ */ jsx(ChevronDownIcon, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-3.5 h-3.5" })
|
|
7879
7879
|
}
|
|
7880
7880
|
) : /* @__PURE__ */ jsx("span", { className: "w-4 h-4 shrink-0" }),
|
|
7881
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0
|
|
7882
|
-
/* @__PURE__ */ jsx("
|
|
7883
|
-
|
|
7884
|
-
/* @__PURE__ */ jsx(
|
|
7885
|
-
Badge,
|
|
7886
|
-
{
|
|
7887
|
-
variant: statusColor(entry.status),
|
|
7888
|
-
className: "h-4 px-1.5 text-[10px]",
|
|
7889
|
-
children: entry.status
|
|
7890
|
-
}
|
|
7891
|
-
)
|
|
7881
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
7882
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm truncate", children: title }),
|
|
7883
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-faint truncate", children: subtitle })
|
|
7892
7884
|
] }),
|
|
7893
|
-
/* @__PURE__ */ jsxs(
|
|
7894
|
-
"span",
|
|
7895
|
-
{
|
|
7896
|
-
className: "text-xs text-faint shrink-0 tabular-nums",
|
|
7897
|
-
"aria-label": `${messageCount} messages, ${toolCallCount} tool calls`,
|
|
7898
|
-
title: `${messageCount} messages, ${toolCallCount} tool calls`,
|
|
7899
|
-
children: [
|
|
7900
|
-
messageCount,
|
|
7901
|
-
"m/",
|
|
7902
|
-
toolCallCount,
|
|
7903
|
-
"t"
|
|
7904
|
-
]
|
|
7905
|
-
}
|
|
7906
|
-
),
|
|
7907
7885
|
isRunning && canStop && /* @__PURE__ */ jsx(
|
|
7908
7886
|
"button",
|
|
7909
7887
|
{
|
|
@@ -7917,6 +7895,21 @@ function TreeNodeRow({
|
|
|
7917
7895
|
title: "Stop sub-agent",
|
|
7918
7896
|
children: /* @__PURE__ */ jsx(SquareIcon, { className: "w-3 h-3", fill: "currentColor" })
|
|
7919
7897
|
}
|
|
7898
|
+
),
|
|
7899
|
+
canDelete && /* @__PURE__ */ jsx(
|
|
7900
|
+
"button",
|
|
7901
|
+
{
|
|
7902
|
+
type: "button",
|
|
7903
|
+
className: "p-1 rounded opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none disabled:opacity-50 transition-all",
|
|
7904
|
+
onClick: (e) => {
|
|
7905
|
+
e.stopPropagation();
|
|
7906
|
+
onDelete(entry.id);
|
|
7907
|
+
},
|
|
7908
|
+
"aria-label": "Delete session",
|
|
7909
|
+
title: "Delete session",
|
|
7910
|
+
disabled: deletingSessionId === entry.id,
|
|
7911
|
+
children: /* @__PURE__ */ jsx(Trash2Icon, { className: "w-3 h-3" })
|
|
7912
|
+
}
|
|
7920
7913
|
)
|
|
7921
7914
|
]
|
|
7922
7915
|
}
|
|
@@ -7928,8 +7921,11 @@ function TreeNodeRow({
|
|
|
7928
7921
|
depth: depth + 1,
|
|
7929
7922
|
activeSessionId,
|
|
7930
7923
|
canStop,
|
|
7924
|
+
canDelete,
|
|
7925
|
+
deletingSessionId,
|
|
7931
7926
|
onSelect,
|
|
7932
|
-
onStop
|
|
7927
|
+
onStop,
|
|
7928
|
+
onDelete
|
|
7933
7929
|
},
|
|
7934
7930
|
child.id
|
|
7935
7931
|
))
|
|
@@ -7943,15 +7939,20 @@ function SessionTreePanel({
|
|
|
7943
7939
|
title = "Running",
|
|
7944
7940
|
sessionListLimit = DEFAULT_SESSION_LIST_LIMIT,
|
|
7945
7941
|
hideRoot = false,
|
|
7946
|
-
onSessionSelect
|
|
7942
|
+
onSessionSelect,
|
|
7943
|
+
onSessionDelete
|
|
7947
7944
|
}) {
|
|
7948
7945
|
const [nodes, setNodes] = useState([]);
|
|
7949
7946
|
const [loading, setLoading] = useState(false);
|
|
7950
7947
|
const [error, setError] = useState(null);
|
|
7951
7948
|
const [hasEverLoaded, setHasEverLoaded] = useState(false);
|
|
7949
|
+
const [deletingSessionId, setDeletingSessionId] = useState(
|
|
7950
|
+
null
|
|
7951
|
+
);
|
|
7952
7952
|
const mounted = useRef(true);
|
|
7953
7953
|
const requestId = useRef(0);
|
|
7954
7954
|
const lastFingerprint = useRef("");
|
|
7955
|
+
const resetContext = useRef(null);
|
|
7955
7956
|
const refetch = useCallback(
|
|
7956
7957
|
async (opts) => {
|
|
7957
7958
|
const canLoadSessionList = Boolean(agentId && adapter.listSessions);
|
|
@@ -8006,12 +8007,17 @@ function SessionTreePanel({
|
|
|
8006
8007
|
};
|
|
8007
8008
|
}, []);
|
|
8008
8009
|
useEffect(() => {
|
|
8009
|
-
|
|
8010
|
+
const previous = resetContext.current;
|
|
8011
|
+
const shouldReset = !previous || previous.adapter !== adapter || previous.agentId !== agentId || previous.sessionListLimit !== sessionListLimit;
|
|
8012
|
+
resetContext.current = { adapter, agentId, sessionListLimit };
|
|
8013
|
+
if (shouldReset) {
|
|
8014
|
+
setNodes([]);
|
|
8015
|
+
setHasEverLoaded(false);
|
|
8016
|
+
lastFingerprint.current = "";
|
|
8017
|
+
}
|
|
8010
8018
|
setError(null);
|
|
8011
|
-
setHasEverLoaded(false);
|
|
8012
|
-
lastFingerprint.current = "";
|
|
8013
8019
|
void refetch();
|
|
8014
|
-
}, [refetch,
|
|
8020
|
+
}, [adapter, agentId, refetch, sessionListLimit]);
|
|
8015
8021
|
const runningCount = useMemo(
|
|
8016
8022
|
() => nodes.filter((n) => n.status === "active").length,
|
|
8017
8023
|
[nodes]
|
|
@@ -8042,17 +8048,44 @@ function SessionTreePanel({
|
|
|
8042
8048
|
},
|
|
8043
8049
|
[adapter, refetch]
|
|
8044
8050
|
);
|
|
8051
|
+
const handleDelete = useCallback(
|
|
8052
|
+
async (id) => {
|
|
8053
|
+
if (!adapter.deleteSession || deletingSessionId) return;
|
|
8054
|
+
setDeletingSessionId(id);
|
|
8055
|
+
try {
|
|
8056
|
+
await adapter.deleteSession({ sessionId: id });
|
|
8057
|
+
onSessionDelete?.(id);
|
|
8058
|
+
await refetch({ silent: true });
|
|
8059
|
+
} catch (e) {
|
|
8060
|
+
setError(e instanceof Error ? e.message : "Failed to delete session");
|
|
8061
|
+
} finally {
|
|
8062
|
+
if (mounted.current) setDeletingSessionId(null);
|
|
8063
|
+
}
|
|
8064
|
+
},
|
|
8065
|
+
[adapter, deletingSessionId, onSessionDelete, refetch]
|
|
8066
|
+
);
|
|
8045
8067
|
if (!hasEverLoaded) return null;
|
|
8046
8068
|
if (nodes.length === 0) return null;
|
|
8047
8069
|
const topLevel = hideRoot ? roots.flatMap((r) => r.children) : roots;
|
|
8048
8070
|
if (topLevel.length === 0) return null;
|
|
8049
8071
|
return /* @__PURE__ */ jsxs("div", { className: "border-t border-line", children: [
|
|
8050
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide
|
|
8072
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide", children: [
|
|
8051
8073
|
/* @__PURE__ */ jsx(UsersIcon, { className: "w-3.5 h-3.5" }),
|
|
8052
8074
|
/* @__PURE__ */ jsx("span", { children: title }),
|
|
8053
8075
|
runningCount > 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", className: "h-4 px-1.5 text-[10px] ml-auto", children: runningCount })
|
|
8054
8076
|
] }),
|
|
8055
|
-
loading && /* @__PURE__ */ jsx(
|
|
8077
|
+
loading && /* @__PURE__ */ jsx(
|
|
8078
|
+
"div",
|
|
8079
|
+
{
|
|
8080
|
+
className: "px-3 py-2",
|
|
8081
|
+
role: "status",
|
|
8082
|
+
"aria-label": "Loading sessions",
|
|
8083
|
+
children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
8084
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-28" }),
|
|
8085
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-20" })
|
|
8086
|
+
] })
|
|
8087
|
+
}
|
|
8088
|
+
),
|
|
8056
8089
|
error && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-destructive", children: error }),
|
|
8057
8090
|
!error && /* @__PURE__ */ jsx("div", { className: "px-1 pb-2", children: topLevel.map((entry) => /* @__PURE__ */ jsx(
|
|
8058
8091
|
TreeNodeRow,
|
|
@@ -8061,8 +8094,11 @@ function SessionTreePanel({
|
|
|
8061
8094
|
depth: 0,
|
|
8062
8095
|
activeSessionId: activeSessionId ?? "",
|
|
8063
8096
|
canStop: Boolean(adapter.stopSession),
|
|
8097
|
+
canDelete: Boolean(adapter.deleteSession),
|
|
8098
|
+
deletingSessionId,
|
|
8064
8099
|
onSelect: handleSelect,
|
|
8065
|
-
onStop: handleStop
|
|
8100
|
+
onStop: handleStop,
|
|
8101
|
+
onDelete: handleDelete
|
|
8066
8102
|
},
|
|
8067
8103
|
entry.id
|
|
8068
8104
|
)) })
|