@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.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var Ansi = require('ansi-to-react');
|
|
|
22
22
|
var tokenlens = require('tokenlens');
|
|
23
23
|
var cmdk = require('cmdk');
|
|
24
24
|
var nanoid = require('nanoid');
|
|
25
|
+
var dateFns = require('date-fns');
|
|
25
26
|
|
|
26
27
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
28
|
|
|
@@ -7927,32 +7928,31 @@ function mergeTreeNodes(groups) {
|
|
|
7927
7928
|
}
|
|
7928
7929
|
return Array.from(byId.values());
|
|
7929
7930
|
}
|
|
7930
|
-
function
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
case "completed":
|
|
7935
|
-
return "secondary";
|
|
7936
|
-
case "failed":
|
|
7937
|
-
return "destructive";
|
|
7938
|
-
default:
|
|
7939
|
-
return "outline";
|
|
7940
|
-
}
|
|
7931
|
+
function formatSessionTime(value) {
|
|
7932
|
+
const date = new Date(value);
|
|
7933
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
7934
|
+
return dateFns.formatDistanceToNow(date, { addSuffix: true });
|
|
7941
7935
|
}
|
|
7942
7936
|
function TreeNodeRow({
|
|
7943
7937
|
entry,
|
|
7944
7938
|
depth,
|
|
7945
7939
|
activeSessionId,
|
|
7946
7940
|
canStop,
|
|
7941
|
+
canDelete,
|
|
7942
|
+
deletingSessionId,
|
|
7947
7943
|
onSelect,
|
|
7948
|
-
onStop
|
|
7944
|
+
onStop,
|
|
7945
|
+
onDelete
|
|
7949
7946
|
}) {
|
|
7950
7947
|
const [expanded, setExpanded] = react.useState(true);
|
|
7951
7948
|
const hasChildren = entry.children.length > 0;
|
|
7952
7949
|
const isActive = entry.id === activeSessionId;
|
|
7953
7950
|
const isRunning = entry.status === "active";
|
|
7954
|
-
const
|
|
7955
|
-
const
|
|
7951
|
+
const title = entry.title ?? "New session";
|
|
7952
|
+
const subtitle = [
|
|
7953
|
+
entry.model ?? "default",
|
|
7954
|
+
formatSessionTime(entry.updatedAt)
|
|
7955
|
+
].filter(Boolean).join(" \xB7 ");
|
|
7956
7956
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
7957
7957
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7958
7958
|
"div",
|
|
@@ -7964,16 +7964,16 @@ function TreeNodeRow({
|
|
|
7964
7964
|
if (e.key === "Enter" || e.key === " ") onSelect(entry.id);
|
|
7965
7965
|
},
|
|
7966
7966
|
className: cn(
|
|
7967
|
-
"group flex items-center gap-
|
|
7968
|
-
isActive ? "bg-line text-foreground" : "
|
|
7967
|
+
"group flex items-center gap-2 w-full py-2 pr-2 text-left cursor-pointer transition-colors border-l-2",
|
|
7968
|
+
isActive ? "bg-line text-foreground border-l-primary" : "bg-transparent text-subtle hover:bg-input hover:text-foreground border-l-transparent"
|
|
7969
7969
|
),
|
|
7970
|
-
style: { paddingLeft: `${depth * 12 +
|
|
7970
|
+
style: { paddingLeft: `${depth * 12 + 12}px` },
|
|
7971
7971
|
children: [
|
|
7972
7972
|
hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
7973
7973
|
"button",
|
|
7974
7974
|
{
|
|
7975
7975
|
type: "button",
|
|
7976
|
-
className: "p-0.5 rounded hover:bg-line",
|
|
7976
|
+
className: "p-0.5 rounded hover:bg-line shrink-0",
|
|
7977
7977
|
onClick: (e) => {
|
|
7978
7978
|
e.stopPropagation();
|
|
7979
7979
|
setExpanded(!expanded);
|
|
@@ -7983,32 +7983,10 @@ function TreeNodeRow({
|
|
|
7983
7983
|
children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "w-3.5 h-3.5" })
|
|
7984
7984
|
}
|
|
7985
7985
|
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-4 h-4 shrink-0" }),
|
|
7986
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0
|
|
7987
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
7988
|
-
|
|
7989
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7990
|
-
Badge,
|
|
7991
|
-
{
|
|
7992
|
-
variant: statusColor(entry.status),
|
|
7993
|
-
className: "h-4 px-1.5 text-[10px]",
|
|
7994
|
-
children: entry.status
|
|
7995
|
-
}
|
|
7996
|
-
)
|
|
7986
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
7987
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm truncate", children: title }),
|
|
7988
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-faint truncate", children: subtitle })
|
|
7997
7989
|
] }),
|
|
7998
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7999
|
-
"span",
|
|
8000
|
-
{
|
|
8001
|
-
className: "text-xs text-faint shrink-0 tabular-nums",
|
|
8002
|
-
"aria-label": `${messageCount} messages, ${toolCallCount} tool calls`,
|
|
8003
|
-
title: `${messageCount} messages, ${toolCallCount} tool calls`,
|
|
8004
|
-
children: [
|
|
8005
|
-
messageCount,
|
|
8006
|
-
"m/",
|
|
8007
|
-
toolCallCount,
|
|
8008
|
-
"t"
|
|
8009
|
-
]
|
|
8010
|
-
}
|
|
8011
|
-
),
|
|
8012
7990
|
isRunning && canStop && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8013
7991
|
"button",
|
|
8014
7992
|
{
|
|
@@ -8022,6 +8000,21 @@ function TreeNodeRow({
|
|
|
8022
8000
|
title: "Stop sub-agent",
|
|
8023
8001
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SquareIcon, { className: "w-3 h-3", fill: "currentColor" })
|
|
8024
8002
|
}
|
|
8003
|
+
),
|
|
8004
|
+
canDelete && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8005
|
+
"button",
|
|
8006
|
+
{
|
|
8007
|
+
type: "button",
|
|
8008
|
+
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",
|
|
8009
|
+
onClick: (e) => {
|
|
8010
|
+
e.stopPropagation();
|
|
8011
|
+
onDelete(entry.id);
|
|
8012
|
+
},
|
|
8013
|
+
"aria-label": "Delete session",
|
|
8014
|
+
title: "Delete session",
|
|
8015
|
+
disabled: deletingSessionId === entry.id,
|
|
8016
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2Icon, { className: "w-3 h-3" })
|
|
8017
|
+
}
|
|
8025
8018
|
)
|
|
8026
8019
|
]
|
|
8027
8020
|
}
|
|
@@ -8033,8 +8026,11 @@ function TreeNodeRow({
|
|
|
8033
8026
|
depth: depth + 1,
|
|
8034
8027
|
activeSessionId,
|
|
8035
8028
|
canStop,
|
|
8029
|
+
canDelete,
|
|
8030
|
+
deletingSessionId,
|
|
8036
8031
|
onSelect,
|
|
8037
|
-
onStop
|
|
8032
|
+
onStop,
|
|
8033
|
+
onDelete
|
|
8038
8034
|
},
|
|
8039
8035
|
child.id
|
|
8040
8036
|
))
|
|
@@ -8048,15 +8044,20 @@ function SessionTreePanel({
|
|
|
8048
8044
|
title = "Running",
|
|
8049
8045
|
sessionListLimit = DEFAULT_SESSION_LIST_LIMIT,
|
|
8050
8046
|
hideRoot = false,
|
|
8051
|
-
onSessionSelect
|
|
8047
|
+
onSessionSelect,
|
|
8048
|
+
onSessionDelete
|
|
8052
8049
|
}) {
|
|
8053
8050
|
const [nodes, setNodes] = react.useState([]);
|
|
8054
8051
|
const [loading, setLoading] = react.useState(false);
|
|
8055
8052
|
const [error, setError] = react.useState(null);
|
|
8056
8053
|
const [hasEverLoaded, setHasEverLoaded] = react.useState(false);
|
|
8054
|
+
const [deletingSessionId, setDeletingSessionId] = react.useState(
|
|
8055
|
+
null
|
|
8056
|
+
);
|
|
8057
8057
|
const mounted = react.useRef(true);
|
|
8058
8058
|
const requestId = react.useRef(0);
|
|
8059
8059
|
const lastFingerprint = react.useRef("");
|
|
8060
|
+
const resetContext = react.useRef(null);
|
|
8060
8061
|
const refetch = react.useCallback(
|
|
8061
8062
|
async (opts) => {
|
|
8062
8063
|
const canLoadSessionList = Boolean(agentId && adapter.listSessions);
|
|
@@ -8111,12 +8112,17 @@ function SessionTreePanel({
|
|
|
8111
8112
|
};
|
|
8112
8113
|
}, []);
|
|
8113
8114
|
react.useEffect(() => {
|
|
8114
|
-
|
|
8115
|
+
const previous = resetContext.current;
|
|
8116
|
+
const shouldReset = !previous || previous.adapter !== adapter || previous.agentId !== agentId || previous.sessionListLimit !== sessionListLimit;
|
|
8117
|
+
resetContext.current = { adapter, agentId, sessionListLimit };
|
|
8118
|
+
if (shouldReset) {
|
|
8119
|
+
setNodes([]);
|
|
8120
|
+
setHasEverLoaded(false);
|
|
8121
|
+
lastFingerprint.current = "";
|
|
8122
|
+
}
|
|
8115
8123
|
setError(null);
|
|
8116
|
-
setHasEverLoaded(false);
|
|
8117
|
-
lastFingerprint.current = "";
|
|
8118
8124
|
void refetch();
|
|
8119
|
-
}, [refetch,
|
|
8125
|
+
}, [adapter, agentId, refetch, sessionListLimit]);
|
|
8120
8126
|
const runningCount = react.useMemo(
|
|
8121
8127
|
() => nodes.filter((n) => n.status === "active").length,
|
|
8122
8128
|
[nodes]
|
|
@@ -8147,17 +8153,44 @@ function SessionTreePanel({
|
|
|
8147
8153
|
},
|
|
8148
8154
|
[adapter, refetch]
|
|
8149
8155
|
);
|
|
8156
|
+
const handleDelete = react.useCallback(
|
|
8157
|
+
async (id) => {
|
|
8158
|
+
if (!adapter.deleteSession || deletingSessionId) return;
|
|
8159
|
+
setDeletingSessionId(id);
|
|
8160
|
+
try {
|
|
8161
|
+
await adapter.deleteSession({ sessionId: id });
|
|
8162
|
+
onSessionDelete?.(id);
|
|
8163
|
+
await refetch({ silent: true });
|
|
8164
|
+
} catch (e) {
|
|
8165
|
+
setError(e instanceof Error ? e.message : "Failed to delete session");
|
|
8166
|
+
} finally {
|
|
8167
|
+
if (mounted.current) setDeletingSessionId(null);
|
|
8168
|
+
}
|
|
8169
|
+
},
|
|
8170
|
+
[adapter, deletingSessionId, onSessionDelete, refetch]
|
|
8171
|
+
);
|
|
8150
8172
|
if (!hasEverLoaded) return null;
|
|
8151
8173
|
if (nodes.length === 0) return null;
|
|
8152
8174
|
const topLevel = hideRoot ? roots.flatMap((r) => r.children) : roots;
|
|
8153
8175
|
if (topLevel.length === 0) return null;
|
|
8154
8176
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-line", children: [
|
|
8155
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide
|
|
8177
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 px-3 py-2 text-xs font-semibold uppercase tracking-wide", children: [
|
|
8156
8178
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.UsersIcon, { className: "w-3.5 h-3.5" }),
|
|
8157
8179
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
|
|
8158
8180
|
runningCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", className: "h-4 px-1.5 text-[10px] ml-auto", children: runningCount })
|
|
8159
8181
|
] }),
|
|
8160
|
-
loading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8182
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8183
|
+
"div",
|
|
8184
|
+
{
|
|
8185
|
+
className: "px-3 py-2",
|
|
8186
|
+
role: "status",
|
|
8187
|
+
"aria-label": "Loading sessions",
|
|
8188
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
|
|
8189
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-3.5 w-28" }),
|
|
8190
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-3 w-20" })
|
|
8191
|
+
] })
|
|
8192
|
+
}
|
|
8193
|
+
),
|
|
8161
8194
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 text-xs text-destructive", children: error }),
|
|
8162
8195
|
!error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-1 pb-2", children: topLevel.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8163
8196
|
TreeNodeRow,
|
|
@@ -8166,8 +8199,11 @@ function SessionTreePanel({
|
|
|
8166
8199
|
depth: 0,
|
|
8167
8200
|
activeSessionId: activeSessionId ?? "",
|
|
8168
8201
|
canStop: Boolean(adapter.stopSession),
|
|
8202
|
+
canDelete: Boolean(adapter.deleteSession),
|
|
8203
|
+
deletingSessionId,
|
|
8169
8204
|
onSelect: handleSelect,
|
|
8170
|
-
onStop: handleStop
|
|
8205
|
+
onStop: handleStop,
|
|
8206
|
+
onDelete: handleDelete
|
|
8171
8207
|
},
|
|
8172
8208
|
entry.id
|
|
8173
8209
|
)) })
|