agenttop 0.11.3 → 0.11.5

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 CHANGED
@@ -612,6 +612,7 @@ var deriveSeverityColors = (c) => ({
612
612
  // src/updates.ts
613
613
  import { execFile, spawn } from "child_process";
614
614
  import { readFile } from "fs/promises";
615
+ import { existsSync } from "fs";
615
616
  import { join, dirname } from "path";
616
617
  import { fileURLToPath } from "url";
617
618
  var getPackageVersion = async () => {
@@ -628,6 +629,17 @@ var getNpmPath = () => {
628
629
  const nodeDir = dirname(process.execPath);
629
630
  return join(nodeDir, process.platform === "win32" ? "npm.cmd" : "npm");
630
631
  };
632
+ var detectInstallMethod = () => {
633
+ const execPath = process.execPath;
634
+ const thisFile = fileURLToPath(import.meta.url);
635
+ if (thisFile.includes("/Cellar/") || thisFile.includes("/homebrew/") || existsSync("/usr/local/Cellar/agenttop") || existsSync("/opt/homebrew/Cellar/agenttop")) {
636
+ return "homebrew";
637
+ }
638
+ if (process.platform === "win32" && (execPath.includes("\\scoop\\") || thisFile.includes("\\scoop\\"))) {
639
+ return "scoop";
640
+ }
641
+ return "npm";
642
+ };
631
643
  var checkForUpdate = () => new Promise((resolve) => {
632
644
  const npm = getNpmPath();
633
645
  getPackageVersion().then((current) => {
@@ -646,14 +658,34 @@ var checkForUpdate = () => new Promise((resolve) => {
646
658
  });
647
659
  });
648
660
  var installUpdate = () => {
661
+ const method = detectInstallMethod();
662
+ if (method === "homebrew") {
663
+ return new Promise((resolve, reject) => {
664
+ execFile("brew", ["upgrade", "agenttop"], { timeout: 12e4 }, (err, stdout) => {
665
+ if (err) {
666
+ execFile("brew", ["reinstall", "agenttop"], { timeout: 12e4 }, (err2, stdout2) => {
667
+ if (err2) reject(err2);
668
+ else resolve(stdout2.trim());
669
+ });
670
+ } else {
671
+ resolve(stdout.trim());
672
+ }
673
+ });
674
+ });
675
+ }
676
+ if (method === "scoop") {
677
+ return new Promise((resolve, reject) => {
678
+ execFile("scoop", ["update", "agenttop"], { timeout: 12e4, shell: true }, (err, stdout) => {
679
+ if (err) reject(err);
680
+ else resolve(stdout.trim());
681
+ });
682
+ });
683
+ }
649
684
  const npm = getNpmPath();
650
685
  return new Promise((resolve, reject) => {
651
- execFile(npm, ["install", "-g", "--force", "agenttop@latest"], { timeout: 6e4 }, (err, stdout) => {
652
- if (err) {
653
- reject(err);
654
- } else {
655
- resolve(stdout.trim());
656
- }
686
+ execFile(npm, ["install", "-g", "agenttop@latest"], { timeout: 6e4 }, (err, stdout) => {
687
+ if (err) reject(err);
688
+ else resolve(stdout.trim());
657
689
  });
658
690
  });
659
691
  };
@@ -3050,7 +3082,18 @@ var sessions = [];
3050
3082
  var refreshInFlight = false;
3051
3083
  var listeners = /* @__PURE__ */ new Set();
3052
3084
  var getCachedSessions = () => sessions;
3085
+ var hashSessions = (list) => {
3086
+ let h = "";
3087
+ for (const s of list) {
3088
+ h += `${s.sessionId}:${s.status}:${s.pid}:${s.lastActivity}:${s.usage.inputTokens}:${s.usage.outputTokens};`;
3089
+ }
3090
+ return h;
3091
+ };
3092
+ var lastHash = "";
3053
3093
  var setCachedSessions = (next) => {
3094
+ const nextHash = hashSessions(next);
3095
+ if (nextHash === lastHash) return;
3096
+ lastHash = nextHash;
3054
3097
  sessions = next;
3055
3098
  for (const fn of listeners) fn(next);
3056
3099
  };
@@ -3556,26 +3599,37 @@ var useSessions = (allUsers, filter, archivedIds, viewingArchive) => {
3556
3599
  const [selectedIndex, setSelectedIndex] = useState11(0);
3557
3600
  const [expandedKeys, setExpandedKeys] = useState11(/* @__PURE__ */ new Set());
3558
3601
  const usageOverrides = useRef5(/* @__PURE__ */ new Map());
3559
- const refresh = useCallback3(() => {
3560
- const found = getCachedSessions();
3561
- const filtered = enrichAndFilter(found, usageOverrides.current, filter, archivedIds, viewingArchive);
3562
- setSessions(filtered);
3563
- triggerRefresh(allUsers);
3564
- }, [allUsers, filter, archivedIds, viewingArchive]);
3565
- useEffect6(() => {
3566
- const unsubscribe = subscribe(() => {
3602
+ const lastSessionIdsRef = useRef5("");
3603
+ const updateSessions = useCallback3(
3604
+ (force) => {
3567
3605
  const found = getCachedSessions();
3568
3606
  const filtered = enrichAndFilter(found, usageOverrides.current, filter, archivedIds, viewingArchive);
3607
+ const key = filtered.map((s) => `${s.sessionId}:${s.status}:${s.lastActivity}`).join(",");
3608
+ if (!force && key === lastSessionIdsRef.current) return;
3609
+ lastSessionIdsRef.current = key;
3569
3610
  setSessions(filtered);
3570
- });
3611
+ },
3612
+ [filter, archivedIds, viewingArchive]
3613
+ );
3614
+ const refresh = useCallback3(() => {
3615
+ updateSessions(true);
3616
+ triggerRefresh(allUsers);
3617
+ }, [allUsers, updateSessions]);
3618
+ useEffect6(() => {
3619
+ const unsubscribe = subscribe(() => updateSessions());
3571
3620
  return unsubscribe;
3572
- }, [filter, archivedIds, viewingArchive]);
3621
+ }, [updateSessions]);
3622
+ const hasSessions = sessions2.length > 0;
3623
+ const refreshRef = useRef5(refresh);
3624
+ refreshRef.current = refresh;
3625
+ useEffect6(() => {
3626
+ refreshRef.current();
3627
+ }, []);
3573
3628
  useEffect6(() => {
3574
- refresh();
3575
- const pollMs = sessions2.length > 0 ? ACTIVE_POLL_MS : IDLE_POLL_MS;
3629
+ const pollMs = hasSessions ? ACTIVE_POLL_MS : IDLE_POLL_MS;
3576
3630
  const interval = setInterval(() => triggerRefresh(allUsers), pollMs);
3577
3631
  return () => clearInterval(interval);
3578
- }, [refresh, sessions2.length > 0]);
3632
+ }, [allUsers, hasSessions]);
3579
3633
  const groups = useMemo2(() => buildGroups(sessions2, expandedKeys), [sessions2, expandedKeys]);
3580
3634
  const visibleItems = useMemo2(() => buildVisibleItems(groups), [groups]);
3581
3635
  const itemCountRef = useRef5(visibleItems.length);
@@ -4193,7 +4247,7 @@ var useUpdateChecker = (disabled, checkOnLaunch, checkInterval) => {
4193
4247
  import { useState as useState16, useCallback as useCallback6 } from "react";
4194
4248
 
4195
4249
  // src/hooks/installer.ts
4196
- import { existsSync, readFileSync, writeFileSync, copyFileSync, mkdirSync as mkdirSync2, chmodSync } from "fs";
4250
+ import { existsSync as existsSync2, readFileSync, writeFileSync, copyFileSync, mkdirSync as mkdirSync2, chmodSync } from "fs";
4197
4251
  import { join as join3, dirname as dirname3 } from "path";
4198
4252
  import { homedir } from "os";
4199
4253
  import { fileURLToPath as fileURLToPath2 } from "url";
@@ -4205,10 +4259,10 @@ var getHookSource = () => {
4205
4259
  const distHooksDir = join3(dirname3(thisFile), "hooks");
4206
4260
  for (const dir of [distHooksDir, srcHooksDir]) {
4207
4261
  const path = join3(dir, HOOK_FILENAME);
4208
- if (existsSync(path)) return path;
4262
+ if (existsSync2(path)) return path;
4209
4263
  }
4210
4264
  const npmGlobalPath = join3(dirname3(thisFile), "..", "hooks", HOOK_FILENAME);
4211
- if (existsSync(npmGlobalPath)) return npmGlobalPath;
4265
+ if (existsSync2(npmGlobalPath)) return npmGlobalPath;
4212
4266
  throw new Error(`cannot find ${HOOK_FILENAME} \u2014 is agenttop installed correctly?`);
4213
4267
  };
4214
4268
  var getHookTarget = () => {
@@ -4217,7 +4271,7 @@ var getHookTarget = () => {
4217
4271
  return join3(claudeHooksDir, HOOK_FILENAME);
4218
4272
  };
4219
4273
  var readSettings = () => {
4220
- if (!existsSync(SETTINGS_PATH)) {
4274
+ if (!existsSync2(SETTINGS_PATH)) {
4221
4275
  return {};
4222
4276
  }
4223
4277
  try {