agenttop 0.9.1 → 0.9.3
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.js +134 -43
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -608,7 +608,7 @@ var SessionList = React2.memo(
|
|
|
608
608
|
}
|
|
609
609
|
const indicator = isSelected ? "\u25B8" : " ";
|
|
610
610
|
const nameColor = isSelected ? colors.bright : isActive ? colors.secondary : colors.text;
|
|
611
|
-
const
|
|
611
|
+
const getDisplayName = (s) => {
|
|
612
612
|
if (s.nickname) return s.nickname;
|
|
613
613
|
if (s.cwd) {
|
|
614
614
|
const parts = s.cwd.replace(/\/+$/, "").split("/");
|
|
@@ -620,7 +620,7 @@ var SessionList = React2.memo(
|
|
|
620
620
|
}
|
|
621
621
|
return s.slug;
|
|
622
622
|
};
|
|
623
|
-
const displayName = truncate(
|
|
623
|
+
const displayName = truncate(getDisplayName(session), INNER_WIDTH - 4);
|
|
624
624
|
return /* @__PURE__ */ jsxs2(
|
|
625
625
|
Box2,
|
|
626
626
|
{
|
|
@@ -660,16 +660,7 @@ var SessionList = React2.memo(
|
|
|
660
660
|
import React3 from "react";
|
|
661
661
|
import { Box as Box3, Text as Text3 } from "ink";
|
|
662
662
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
663
|
-
var TAG_COLORS = [
|
|
664
|
-
"#61AFEF",
|
|
665
|
-
"#98C379",
|
|
666
|
-
"#C678DD",
|
|
667
|
-
"#E5C07B",
|
|
668
|
-
"#E06C75",
|
|
669
|
-
"#56B6C2",
|
|
670
|
-
"#D19A66",
|
|
671
|
-
"#BE5046"
|
|
672
|
-
];
|
|
663
|
+
var TAG_COLORS = ["#61AFEF", "#98C379", "#C678DD", "#E5C07B", "#E06C75", "#56B6C2", "#D19A66", "#BE5046"];
|
|
673
664
|
var formatTime = (ts) => {
|
|
674
665
|
const d = new Date(ts);
|
|
675
666
|
return d.toLocaleTimeString("en-GB", { hour12: false });
|
|
@@ -1938,11 +1929,10 @@ var SplitPanel = React14.memo(
|
|
|
1938
1929
|
);
|
|
1939
1930
|
|
|
1940
1931
|
// src/ui/hooks/useSessions.ts
|
|
1941
|
-
import { useState as useState8, useEffect as useEffect5, useCallback as useCallback2, useRef as useRef3 } from "react";
|
|
1932
|
+
import { useState as useState8, useEffect as useEffect5, useCallback as useCallback2, useRef as useRef3, useMemo as useMemo2 } from "react";
|
|
1942
1933
|
var ACTIVE_POLL_MS = 1e4;
|
|
1943
1934
|
var IDLE_POLL_MS = 3e4;
|
|
1944
|
-
var
|
|
1945
|
-
if (session.nickname) return session.nickname;
|
|
1935
|
+
var getGroupKey = (session) => {
|
|
1946
1936
|
if (session.cwd) {
|
|
1947
1937
|
const parts = session.cwd.replace(/\/+$/, "").split("/");
|
|
1948
1938
|
return parts[parts.length - 1] || session.slug;
|
|
@@ -1954,20 +1944,17 @@ var getDisplayName = (session) => {
|
|
|
1954
1944
|
return session.slug;
|
|
1955
1945
|
};
|
|
1956
1946
|
var buildGroups = (sessions, expandedKeys) => {
|
|
1957
|
-
const
|
|
1947
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
1958
1948
|
for (const s of sessions) {
|
|
1959
|
-
const
|
|
1960
|
-
const
|
|
1961
|
-
if (
|
|
1962
|
-
else
|
|
1949
|
+
const key = getGroupKey(s);
|
|
1950
|
+
const existing = byKey.get(key);
|
|
1951
|
+
if (existing) existing.push(s);
|
|
1952
|
+
else byKey.set(key, [s]);
|
|
1963
1953
|
}
|
|
1964
1954
|
const groups = [];
|
|
1965
|
-
for (const [key, list] of
|
|
1955
|
+
for (const [key, list] of byKey) {
|
|
1966
1956
|
list.sort((a, b) => b.lastActivity - a.lastActivity);
|
|
1967
|
-
const totalIn = list.reduce(
|
|
1968
|
-
(sum, s) => sum + s.usage.inputTokens + s.usage.cacheReadTokens,
|
|
1969
|
-
0
|
|
1970
|
-
);
|
|
1957
|
+
const totalIn = list.reduce((sum, s) => sum + s.usage.inputTokens + s.usage.cacheReadTokens, 0);
|
|
1971
1958
|
const totalOut = list.reduce((sum, s) => sum + s.usage.outputTokens, 0);
|
|
1972
1959
|
groups.push({
|
|
1973
1960
|
key,
|
|
@@ -2045,14 +2032,16 @@ var useSessions = (allUsers, filter, archivedIds, viewingArchive) => {
|
|
|
2045
2032
|
const interval = setInterval(refresh, pollMs);
|
|
2046
2033
|
return () => clearInterval(interval);
|
|
2047
2034
|
}, [refresh, sessions.length > 0]);
|
|
2048
|
-
const groups = buildGroups(sessions, expandedKeys);
|
|
2049
|
-
const visibleItems = buildVisibleItems(groups);
|
|
2035
|
+
const groups = useMemo2(() => buildGroups(sessions, expandedKeys), [sessions, expandedKeys]);
|
|
2036
|
+
const visibleItems = useMemo2(() => buildVisibleItems(groups), [groups]);
|
|
2037
|
+
const itemCountRef = useRef3(visibleItems.length);
|
|
2038
|
+
itemCountRef.current = visibleItems.length;
|
|
2050
2039
|
const selectedItem = visibleItems[selectedIndex] ?? null;
|
|
2051
2040
|
const selectedSession = selectedItem?.type === "ungrouped" ? selectedItem.session : selectedItem?.type === "session" ? selectedItem.session : null;
|
|
2052
2041
|
const selectedGroup = selectedItem?.type === "group" ? selectedItem.group : null;
|
|
2053
2042
|
const selectNext = useCallback2(() => {
|
|
2054
|
-
setSelectedIndex((i) => Math.min(i + 1, Math.max(0,
|
|
2055
|
-
}, [
|
|
2043
|
+
setSelectedIndex((i) => Math.min(i + 1, Math.max(0, itemCountRef.current - 1)));
|
|
2044
|
+
}, []);
|
|
2056
2045
|
const selectPrev = useCallback2(() => {
|
|
2057
2046
|
setSelectedIndex((i) => Math.max(i - 1, 0));
|
|
2058
2047
|
}, []);
|
|
@@ -2137,7 +2126,7 @@ var useActivityStream = (session, allUsers) => {
|
|
|
2137
2126
|
};
|
|
2138
2127
|
|
|
2139
2128
|
// src/ui/hooks/useFilteredEvents.ts
|
|
2140
|
-
import { useMemo as
|
|
2129
|
+
import { useMemo as useMemo3 } from "react";
|
|
2141
2130
|
var applyFilter = (events, filter) => {
|
|
2142
2131
|
if (!filter) return events;
|
|
2143
2132
|
const lower = filter.toLowerCase();
|
|
@@ -2145,7 +2134,7 @@ var applyFilter = (events, filter) => {
|
|
|
2145
2134
|
(e) => e.toolName.toLowerCase().includes(lower) || JSON.stringify(e.toolInput).toLowerCase().includes(lower)
|
|
2146
2135
|
);
|
|
2147
2136
|
};
|
|
2148
|
-
var useFilteredEvents = (rawEvents, filter) =>
|
|
2137
|
+
var useFilteredEvents = (rawEvents, filter) => useMemo3(() => applyFilter(rawEvents, filter), [rawEvents, filter]);
|
|
2149
2138
|
|
|
2150
2139
|
// src/ui/hooks/useAlerts.ts
|
|
2151
2140
|
import { useState as useState10, useEffect as useEffect7, useRef as useRef5 } from "react";
|
|
@@ -2859,14 +2848,30 @@ var App = ({ options, config: initialConfig, version, firstRun }) => {
|
|
|
2859
2848
|
const [updateStatus, setUpdateStatus] = useState15("");
|
|
2860
2849
|
const [showDetail, setShowDetail] = useState15(false);
|
|
2861
2850
|
const [viewingArchive, setViewingArchive] = useState15(false);
|
|
2862
|
-
const [confirmAction, setConfirmAction] = useState15(
|
|
2851
|
+
const [confirmAction, setConfirmAction] = useState15(
|
|
2852
|
+
null
|
|
2853
|
+
);
|
|
2863
2854
|
const [archivedIds, setArchivedIds] = useState15(() => new Set(Object.keys(getArchived())));
|
|
2864
2855
|
const refreshArchived = useCallback6(() => setArchivedIds(new Set(Object.keys(getArchived()))), []);
|
|
2865
|
-
const updateInfo = useUpdateChecker(
|
|
2856
|
+
const updateInfo = useUpdateChecker(
|
|
2857
|
+
options.noUpdates,
|
|
2858
|
+
setup.liveConfig.updates.checkOnLaunch,
|
|
2859
|
+
setup.liveConfig.updates.checkInterval
|
|
2860
|
+
);
|
|
2866
2861
|
useEffect9(() => {
|
|
2867
2862
|
applyTheme(resolveTheme(setup.liveConfig.theme, setup.liveConfig.customThemes));
|
|
2868
2863
|
}, [setup.liveConfig.theme, setup.liveConfig.customThemes]);
|
|
2869
|
-
const {
|
|
2864
|
+
const {
|
|
2865
|
+
sessions,
|
|
2866
|
+
visibleItems,
|
|
2867
|
+
selectedSession,
|
|
2868
|
+
selectedGroup,
|
|
2869
|
+
selectedIndex,
|
|
2870
|
+
selectNext,
|
|
2871
|
+
selectPrev,
|
|
2872
|
+
toggleExpand,
|
|
2873
|
+
refresh
|
|
2874
|
+
} = useSessions(options.allUsers, filter || void 0, archivedIds, viewingArchive);
|
|
2870
2875
|
const activityTarget = split.splitMode ? null : selectedGroup ? selectedGroup.sessions : selectedSession;
|
|
2871
2876
|
const rawEvents = useActivityStream(activityTarget, options.allUsers);
|
|
2872
2877
|
const leftRawEvents = useActivityStream(split.splitMode ? split.leftSession : null, options.allUsers);
|
|
@@ -2911,7 +2916,10 @@ var App = ({ options, config: initialConfig, version, firstRun }) => {
|
|
|
2911
2916
|
const alertHeight = options.noSecurity ? 0 : 6;
|
|
2912
2917
|
const mainHeight = termHeight - 3 - alertHeight - 1 - (inputMode !== "normal" ? 1 : 0);
|
|
2913
2918
|
const viewportRows = mainHeight - 2;
|
|
2914
|
-
const switchPanel = useCallback6(
|
|
2919
|
+
const switchPanel = useCallback6(
|
|
2920
|
+
(dir) => split.switchPanel(dir, setActivePanel),
|
|
2921
|
+
[split.switchPanel]
|
|
2922
|
+
);
|
|
2915
2923
|
const clearSplitState = useCallback6(() => {
|
|
2916
2924
|
split.clearSplitState();
|
|
2917
2925
|
setActivePanel("sessions");
|
|
@@ -3018,8 +3026,18 @@ var App = ({ options, config: initialConfig, version, firstRun }) => {
|
|
|
3018
3026
|
});
|
|
3019
3027
|
if (setup.showSetup) {
|
|
3020
3028
|
const steps = [
|
|
3021
|
-
...setup.liveConfig.prompts.hook === "pending" ? [
|
|
3022
|
-
|
|
3029
|
+
...setup.liveConfig.prompts.hook === "pending" ? [
|
|
3030
|
+
{
|
|
3031
|
+
title: "Install Claude Code hook?",
|
|
3032
|
+
description: "Adds a PostToolUse hook that blocks prompt injection attempts in real-time."
|
|
3033
|
+
}
|
|
3034
|
+
] : [],
|
|
3035
|
+
...setup.liveConfig.prompts.mcp === "pending" ? [
|
|
3036
|
+
{
|
|
3037
|
+
title: "Install MCP server?",
|
|
3038
|
+
description: "Registers agenttop as an MCP server so Claude Code can query session status and alerts."
|
|
3039
|
+
}
|
|
3040
|
+
] : []
|
|
3023
3041
|
];
|
|
3024
3042
|
if (steps.length === 0) {
|
|
3025
3043
|
setup.setShowSetup(false);
|
|
@@ -3027,20 +3045,85 @@ var App = ({ options, config: initialConfig, version, firstRun }) => {
|
|
|
3027
3045
|
}
|
|
3028
3046
|
return /* @__PURE__ */ jsx15(SetupModal, { steps, onComplete: setup.handleSetupComplete });
|
|
3029
3047
|
}
|
|
3030
|
-
if (setup.showThemePicker)
|
|
3048
|
+
if (setup.showThemePicker)
|
|
3049
|
+
return /* @__PURE__ */ jsx15(
|
|
3050
|
+
ThemePickerModal,
|
|
3051
|
+
{
|
|
3052
|
+
onSelect: setup.handleThemePickerSelect,
|
|
3053
|
+
onSkip: setup.handleThemePickerSkip,
|
|
3054
|
+
onDismiss: setup.handleThemePickerDismiss
|
|
3055
|
+
}
|
|
3056
|
+
);
|
|
3031
3057
|
if (setup.showTour) return /* @__PURE__ */ jsx15(GuidedTour, { onComplete: setup.handleTourComplete, onSkip: setup.handleTourSkip });
|
|
3032
3058
|
if (setup.showThemeMenu) return /* @__PURE__ */ jsx15(ThemeMenu, { config: setup.liveConfig, onClose: setup.handleThemeMenuClose });
|
|
3033
|
-
if (setup.showSettings)
|
|
3059
|
+
if (setup.showSettings)
|
|
3060
|
+
return /* @__PURE__ */ jsx15(
|
|
3061
|
+
SettingsMenu,
|
|
3062
|
+
{
|
|
3063
|
+
config: setup.liveConfig,
|
|
3064
|
+
onClose: setup.handleSettingsClose,
|
|
3065
|
+
onOpenThemeMenu: setup.handleOpenThemeMenu
|
|
3066
|
+
}
|
|
3067
|
+
);
|
|
3034
3068
|
if (confirmAction) {
|
|
3035
|
-
return /* @__PURE__ */ jsx15(Box15, { flexDirection: "column", height: termHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx15(
|
|
3069
|
+
return /* @__PURE__ */ jsx15(Box15, { flexDirection: "column", height: termHeight, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx15(
|
|
3070
|
+
ConfirmModal,
|
|
3071
|
+
{
|
|
3072
|
+
title: confirmAction.title,
|
|
3073
|
+
message: confirmAction.message,
|
|
3074
|
+
onConfirm: confirmAction.onConfirm,
|
|
3075
|
+
onCancel: () => setConfirmAction(null)
|
|
3076
|
+
}
|
|
3077
|
+
) });
|
|
3036
3078
|
}
|
|
3037
3079
|
const activitySlug = selectedGroup ? selectedGroup.key : selectedSession?.slug ?? null;
|
|
3038
3080
|
const isMerged = selectedGroup !== null;
|
|
3039
|
-
const rightPanel = split.splitMode ? /* @__PURE__ */ jsx15(
|
|
3081
|
+
const rightPanel = split.splitMode ? /* @__PURE__ */ jsx15(
|
|
3082
|
+
SplitPanel,
|
|
3083
|
+
{
|
|
3084
|
+
activePanel,
|
|
3085
|
+
leftSession: split.leftSession,
|
|
3086
|
+
rightSession: split.rightSession,
|
|
3087
|
+
leftEvents,
|
|
3088
|
+
rightEvents,
|
|
3089
|
+
leftScroll: split.leftScroll,
|
|
3090
|
+
rightScroll: split.rightScroll,
|
|
3091
|
+
leftFilter: split.leftFilter,
|
|
3092
|
+
rightFilter: split.rightFilter,
|
|
3093
|
+
leftShowDetail: split.leftShowDetail,
|
|
3094
|
+
rightShowDetail: split.rightShowDetail,
|
|
3095
|
+
height: mainHeight
|
|
3096
|
+
}
|
|
3097
|
+
) : showDetail && selectedSession ? /* @__PURE__ */ jsx15(SessionDetail, { session: selectedSession, focused: activePanel === "activity", height: mainHeight }) : /* @__PURE__ */ jsx15(
|
|
3098
|
+
ActivityFeed,
|
|
3099
|
+
{
|
|
3100
|
+
events,
|
|
3101
|
+
sessionSlug: activitySlug,
|
|
3102
|
+
sessionId: selectedSession?.sessionId,
|
|
3103
|
+
isActive: selectedGroup ? selectedGroup.isActive : selectedSession ? selectedSession.pid !== null : void 0,
|
|
3104
|
+
focused: activePanel === "activity",
|
|
3105
|
+
height: mainHeight,
|
|
3106
|
+
scrollOffset: activityScroll,
|
|
3107
|
+
filter: activityFilter || void 0,
|
|
3108
|
+
merged: isMerged,
|
|
3109
|
+
mergedSessions: selectedGroup?.sessions
|
|
3110
|
+
}
|
|
3111
|
+
);
|
|
3040
3112
|
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: termHeight, children: [
|
|
3041
3113
|
/* @__PURE__ */ jsx15(StatusBar, { sessionCount: sessions.length, alertCount: alerts.length, version, updateInfo }),
|
|
3042
3114
|
/* @__PURE__ */ jsxs15(Box15, { flexGrow: 1, height: mainHeight, children: [
|
|
3043
|
-
/* @__PURE__ */ jsx15(
|
|
3115
|
+
/* @__PURE__ */ jsx15(
|
|
3116
|
+
SessionList,
|
|
3117
|
+
{
|
|
3118
|
+
visibleItems,
|
|
3119
|
+
selectedIndex,
|
|
3120
|
+
focused: activePanel === "sessions",
|
|
3121
|
+
height: mainHeight,
|
|
3122
|
+
filter: filter || void 0,
|
|
3123
|
+
viewingArchive,
|
|
3124
|
+
totalSessions: sessions.length
|
|
3125
|
+
}
|
|
3126
|
+
),
|
|
3044
3127
|
rightPanel
|
|
3045
3128
|
] }),
|
|
3046
3129
|
!options.noSecurity && /* @__PURE__ */ jsx15(AlertBar, { alerts }),
|
|
@@ -3055,7 +3138,15 @@ var App = ({ options, config: initialConfig, version, firstRun }) => {
|
|
|
3055
3138
|
/* @__PURE__ */ jsx15(Text14, { color: colors.bright, children: filterInput.value }),
|
|
3056
3139
|
/* @__PURE__ */ jsx15(Text14, { color: colors.muted, children: "_" })
|
|
3057
3140
|
] }),
|
|
3058
|
-
inputMode === "normal" && /* @__PURE__ */ jsx15(
|
|
3141
|
+
inputMode === "normal" && /* @__PURE__ */ jsx15(
|
|
3142
|
+
FooterBar,
|
|
3143
|
+
{
|
|
3144
|
+
keybindings: kb,
|
|
3145
|
+
updateStatus,
|
|
3146
|
+
viewingArchive,
|
|
3147
|
+
splitMode: split.splitMode
|
|
3148
|
+
}
|
|
3149
|
+
)
|
|
3059
3150
|
] });
|
|
3060
3151
|
};
|
|
3061
3152
|
|