agent-yes 1.284.1 → 1.285.0
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/{SUPPORTED_CLIS-DZwCkmvh.js → SUPPORTED_CLIS-CXvLHLG2.js} +3 -3
- package/dist/{SUPPORTED_CLIS-B2Jis2RD.js → SUPPORTED_CLIS-tYZC_KWR.js} +2 -2
- package/dist/{agentShare-BSh14vJq.js → agentShare-0hRw0bQn.js} +2 -2
- package/dist/{callback-nuwvhn5x.js → callback-BN6cqDjb.js} +3 -3
- package/dist/{callback-Cyr2rDek.js → callback-DCaGBxD1.js} +2 -2
- package/dist/cli.js +5 -5
- package/dist/{cmdPs-tzFiiKC5.js → cmdPs-CUkarOK7.js} +123 -18
- package/dist/index.js +2 -2
- package/dist/{notifyDaemon-BBQKDl7Q.js → notifyDaemon-DNTRkaSU.js} +2 -2
- package/dist/{parentPingLoop-CVy-ueZc.js → parentPingLoop-CovRlBFM.js} +2 -2
- package/dist/{rustBinary-CRR9Sr3R.js → rustBinary-CkKsMycJ.js} +2 -2
- package/dist/{rustBinary-C9B5hRAU.js → rustBinary-ydpdBd3-.js} +2 -2
- package/dist/{schedule-CH_evU-N.js → schedule-CgzQNLfP.js} +4 -4
- package/dist/{serve-CC074vGJ.js → serve-nk0r7fxV.js} +17 -17
- package/dist/{setup-DDZMpGsh.js → setup-P7AMLtbV.js} +2 -2
- package/dist/{subcommands-D2iZ_g0A.js → subcommands-B_Lg_zDe.js} +15 -15
- package/dist/{subcommands-DafbEv0e.js → subcommands-SeVXiezY.js} +1 -1
- package/dist/{terminal-C-UzqGmj.js → terminal-DM_kIymf.js} +2 -2
- package/dist/trayApp-BIOUrF8R.js +5 -0
- package/dist/{trayApp-Dylg_sbJ.js → trayApp-CUxqXOmu.js} +2 -2
- package/dist/{ts-BmiGlG1v.js → ts-LgWg13cL.js} +3 -3
- package/dist/{versionChecker-D59qJF9N.js → versionChecker-CbqhEGUc.js} +2 -2
- package/dist/{widget-BENlkcvI.js → widget-DUkLAsSR.js} +3 -3
- package/dist/{ws-PKok408W.js → ws-BAy7xMDI.js} +2 -2
- package/dist/{ws-DvMM1i2j.js → ws-ChkhtUQm.js} +2 -2
- package/package.json +1 -1
- package/ts/cmdPs.spec.ts +126 -1
- package/ts/cmdPs.ts +148 -12
- package/ts/procStats.spec.ts +32 -6
- package/ts/procStats.ts +77 -5
- package/dist/trayApp-D5SzLS6p.js +0 -5
|
@@ -906,7 +906,7 @@ async function runSubcommand(argv) {
|
|
|
906
906
|
switch (sub) {
|
|
907
907
|
case "ls":
|
|
908
908
|
case "list": return await cmdLs(rest);
|
|
909
|
-
case "ps": return await (await import("./cmdPs-
|
|
909
|
+
case "ps": return await (await import("./cmdPs-CUkarOK7.js")).cmdPs(rest);
|
|
910
910
|
case "status": return await cmdStatus(rest);
|
|
911
911
|
case "whoami": return await cmdWhoami(rest);
|
|
912
912
|
case "result": return await cmdResult(rest);
|
|
@@ -953,35 +953,35 @@ async function runSubcommand(argv) {
|
|
|
953
953
|
return cmdCh(rest);
|
|
954
954
|
}
|
|
955
955
|
case "term": {
|
|
956
|
-
const { cmdTerm } = await import("./terminal-
|
|
956
|
+
const { cmdTerm } = await import("./terminal-DM_kIymf.js");
|
|
957
957
|
return cmdTerm(rest);
|
|
958
958
|
}
|
|
959
959
|
case "widget": {
|
|
960
|
-
const { cmdWidget } = await import("./widget-
|
|
960
|
+
const { cmdWidget } = await import("./widget-DUkLAsSR.js");
|
|
961
961
|
return cmdWidget(rest);
|
|
962
962
|
}
|
|
963
963
|
case "mint": {
|
|
964
|
-
const { cmdMint } = await import("./widget-
|
|
964
|
+
const { cmdMint } = await import("./widget-DUkLAsSR.js");
|
|
965
965
|
return cmdMint(rest);
|
|
966
966
|
}
|
|
967
967
|
case "serve": {
|
|
968
|
-
const { cmdServe } = await import("./serve-
|
|
968
|
+
const { cmdServe } = await import("./serve-nk0r7fxV.js");
|
|
969
969
|
return cmdServe(rest);
|
|
970
970
|
}
|
|
971
971
|
case "tray": {
|
|
972
|
-
const { cmdTray } = await import("./trayApp-
|
|
972
|
+
const { cmdTray } = await import("./trayApp-BIOUrF8R.js");
|
|
973
973
|
return cmdTray(rest);
|
|
974
974
|
}
|
|
975
975
|
case "setup": {
|
|
976
|
-
const { cmdSetup } = await import("./setup-
|
|
976
|
+
const { cmdSetup } = await import("./setup-P7AMLtbV.js");
|
|
977
977
|
return cmdSetup(rest);
|
|
978
978
|
}
|
|
979
979
|
case "ws": {
|
|
980
|
-
const { cmdWs } = await import("./ws-
|
|
980
|
+
const { cmdWs } = await import("./ws-ChkhtUQm.js");
|
|
981
981
|
return cmdWs(rest);
|
|
982
982
|
}
|
|
983
983
|
case "schedule": {
|
|
984
|
-
const { cmdSchedule } = await import("./schedule-
|
|
984
|
+
const { cmdSchedule } = await import("./schedule-CgzQNLfP.js");
|
|
985
985
|
return cmdSchedule(rest);
|
|
986
986
|
}
|
|
987
987
|
case "remote": {
|
|
@@ -993,7 +993,7 @@ async function runSubcommand(argv) {
|
|
|
993
993
|
return cmdExpose(rest);
|
|
994
994
|
}
|
|
995
995
|
case "callback": {
|
|
996
|
-
const { cmdCallback } = await import("./callback-
|
|
996
|
+
const { cmdCallback } = await import("./callback-DCaGBxD1.js");
|
|
997
997
|
return cmdCallback(rest);
|
|
998
998
|
}
|
|
999
999
|
case "reap":
|
|
@@ -1004,7 +1004,7 @@ async function runSubcommand(argv) {
|
|
|
1004
1004
|
return await cmdDsh(rest);
|
|
1005
1005
|
}
|
|
1006
1006
|
case "gc": {
|
|
1007
|
-
const { gcOldBinaryDirs } = await import("./rustBinary-
|
|
1007
|
+
const { gcOldBinaryDirs } = await import("./rustBinary-CkKsMycJ.js");
|
|
1008
1008
|
const res = gcOldBinaryDirs();
|
|
1009
1009
|
if (res.removed.length === 0) process.stdout.write("no old agent-yes binary cache dirs to remove\n");
|
|
1010
1010
|
else {
|
|
@@ -3481,7 +3481,7 @@ async function cmdAttach(rest) {
|
|
|
3481
3481
|
const winsizeDir = path.join(ayHome, "winsize");
|
|
3482
3482
|
await mkdir(winsizeDir, { recursive: true });
|
|
3483
3483
|
const winsizePath = path.join(winsizeDir, String(record.pid));
|
|
3484
|
-
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-
|
|
3484
|
+
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-nk0r7fxV.js");
|
|
3485
3485
|
const daemonBase = await resolveDaemonHttpBase().catch(() => null);
|
|
3486
3486
|
const daemonToken = daemonBase ? await loadTokenReadOnly().catch(() => null) ?? "" : "";
|
|
3487
3487
|
const capViewer = `attach:${process.pid}`;
|
|
@@ -4199,7 +4199,7 @@ async function cmdNotify(rest) {
|
|
|
4199
4199
|
}
|
|
4200
4200
|
const ensure = async () => {
|
|
4201
4201
|
if (!argv["ensure-daemon"]) return;
|
|
4202
|
-
const { ensureDaemon } = await import("./notifyDaemon-
|
|
4202
|
+
const { ensureDaemon } = await import("./notifyDaemon-DNTRkaSU.js");
|
|
4203
4203
|
await ensureDaemon().catch(() => null);
|
|
4204
4204
|
};
|
|
4205
4205
|
await heartbeatWatcher(parent, selfStartedAt);
|
|
@@ -4273,7 +4273,7 @@ async function cmdNotifyCursor(args) {
|
|
|
4273
4273
|
}
|
|
4274
4274
|
async function cmdNotifyd(rest) {
|
|
4275
4275
|
const sub = rest[0] ?? "status";
|
|
4276
|
-
const daemon = await import("./notifyDaemon-
|
|
4276
|
+
const daemon = await import("./notifyDaemon-DNTRkaSU.js");
|
|
4277
4277
|
switch (sub) {
|
|
4278
4278
|
case "run": return daemon.runDaemon();
|
|
4279
4279
|
case "once": return daemon.runDaemon({ once: true });
|
|
@@ -4300,4 +4300,4 @@ async function cmdNotifyd(rest) {
|
|
|
4300
4300
|
|
|
4301
4301
|
//#endregion
|
|
4302
4302
|
export { buildAgentForest as $, readAgentPtysize as A, resolveReadWindow as B, isUnknownManagerToken as C, listRecords as D, lastStdinAt as E, recentReadEdges as F, stdinActivityPath as G, restartHintLines as H, renderLogTailLines as I, waitForLogQuiet as J, stopTipForCli as K, renderRawLog as L, readNotes as M, readPtysize as N, matchKeyword as O, recentMessageEdges as P, TYPING_BADGE as Q, renderRawLogLines as R, isSubcommand as S, lastReadAt as T, runSubcommand as U, resolveResumeArgs as V, snapshotStatus as W, writeToIpc as X, writeKeysPaced as Y, withIpcLock as Z, isAgentStuck as _, TYPING_WINDOW_MS as a, isPidAlive as b, controlCodeFromName as c, deriveLiveStatus as d, flattenForest as et, extractBadges as f, finalizedLines as g, extractTaskCounts as h, READ_WINDOW_MS as i, readLogForRender as j, menuSelectKeys as k, cursorAbs as l, extractNeedsInput as m, MAX_RENDER_BYTES as n, backoffWhileTyping as o, extractMenu as p, submitAndConfirm as q, READ_PAGE_DEFAULT as r, cmdHelp as s, GRACEFUL_EXIT_COMMANDS as t, deriveLiveState as u, isBareManagerInvocation as v, isUserTyping as w, isSlashCommand as x, isExitRequest as y, resolveOne as z };
|
|
4303
|
-
//# sourceMappingURL=subcommands-
|
|
4303
|
+
//# sourceMappingURL=subcommands-B_Lg_zDe.js.map
|
|
@@ -3,7 +3,7 @@ import "./globalPidIndex-DoaKEUkO.js";
|
|
|
3
3
|
import "./messageLog-DdjBNqgt.js";
|
|
4
4
|
import "./e2e-z1xpwSAg.js";
|
|
5
5
|
import "./configShared-DKTgiz7K.js";
|
|
6
|
-
import { A as readAgentPtysize, B as resolveReadWindow, C as isUnknownManagerToken, D as listRecords, E as lastStdinAt, F as recentReadEdges, G as stdinActivityPath, H as restartHintLines, I as renderLogTailLines, J as waitForLogQuiet, K as stopTipForCli, L as renderRawLog, M as readNotes, N as readPtysize, O as matchKeyword, P as recentMessageEdges, R as renderRawLogLines, S as isSubcommand, T as lastReadAt, U as runSubcommand, V as resolveResumeArgs, W as snapshotStatus, X as writeToIpc, Y as writeKeysPaced, _ as isAgentStuck, a as TYPING_WINDOW_MS, b as isPidAlive, c as controlCodeFromName, d as deriveLiveStatus, f as extractBadges, g as finalizedLines, h as extractTaskCounts, i as READ_WINDOW_MS, j as readLogForRender, k as menuSelectKeys, l as cursorAbs, m as extractNeedsInput, n as MAX_RENDER_BYTES, o as backoffWhileTyping, p as extractMenu, q as submitAndConfirm, r as READ_PAGE_DEFAULT, s as cmdHelp, t as GRACEFUL_EXIT_COMMANDS, u as deriveLiveState, v as isBareManagerInvocation, w as isUserTyping, x as isSlashCommand, y as isExitRequest, z as resolveOne } from "./subcommands-
|
|
6
|
+
import { A as readAgentPtysize, B as resolveReadWindow, C as isUnknownManagerToken, D as listRecords, E as lastStdinAt, F as recentReadEdges, G as stdinActivityPath, H as restartHintLines, I as renderLogTailLines, J as waitForLogQuiet, K as stopTipForCli, L as renderRawLog, M as readNotes, N as readPtysize, O as matchKeyword, P as recentMessageEdges, R as renderRawLogLines, S as isSubcommand, T as lastReadAt, U as runSubcommand, V as resolveResumeArgs, W as snapshotStatus, X as writeToIpc, Y as writeKeysPaced, _ as isAgentStuck, a as TYPING_WINDOW_MS, b as isPidAlive, c as controlCodeFromName, d as deriveLiveStatus, f as extractBadges, g as finalizedLines, h as extractTaskCounts, i as READ_WINDOW_MS, j as readLogForRender, k as menuSelectKeys, l as cursorAbs, m as extractNeedsInput, n as MAX_RENDER_BYTES, o as backoffWhileTyping, p as extractMenu, q as submitAndConfirm, r as READ_PAGE_DEFAULT, s as cmdHelp, t as GRACEFUL_EXIT_COMMANDS, u as deriveLiveState, v as isBareManagerInvocation, w as isUserTyping, x as isSlashCommand, y as isExitRequest, z as resolveOne } from "./subcommands-B_Lg_zDe.js";
|
|
7
7
|
import "./notifyStore-2SWKGwZI.js";
|
|
8
8
|
import "./webrtcLink-DLaJfTcB.js";
|
|
9
9
|
import "./remotes-b6reVXzo.js";
|
|
@@ -98,7 +98,7 @@ async function cmdTermMint(args) {
|
|
|
98
98
|
if (flags.ro && flags.interactive) throw new Error("--ro and --interactive are mutually exclusive");
|
|
99
99
|
const ttlSec = parseTtlSec(typeof flags.ttl === "string" ? flags.ttl : "15m");
|
|
100
100
|
const canSend = flags.interactive === true;
|
|
101
|
-
const { mintScopedTermToken } = await import("./serve-
|
|
101
|
+
const { mintScopedTermToken } = await import("./serve-nk0r7fxV.js");
|
|
102
102
|
const r = await mintScopedTermToken(pid, {
|
|
103
103
|
ttlSec,
|
|
104
104
|
canSend
|
|
@@ -135,4 +135,4 @@ async function cmdTerm(args) {
|
|
|
135
135
|
|
|
136
136
|
//#endregion
|
|
137
137
|
export { cmdTerm };
|
|
138
|
-
//# sourceMappingURL=terminal-
|
|
138
|
+
//# sourceMappingURL=terminal-DM_kIymf.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as findTrayLauncher } from "./rustBinary-
|
|
1
|
+
import { i as findTrayLauncher } from "./rustBinary-ydpdBd3-.js";
|
|
2
2
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
@@ -97,4 +97,4 @@ async function cmdTray(args) {
|
|
|
97
97
|
|
|
98
98
|
//#endregion
|
|
99
99
|
export { trayHiddenMarker as a, launchTray as i, hasDesktop as n, isTrayHidden as r, cmdTray as t };
|
|
100
|
-
//# sourceMappingURL=trayApp-
|
|
100
|
+
//# sourceMappingURL=trayApp-CUxqXOmu.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __esmMin, r as __exportAll } from "./chunk-cZBX9HZv.js";
|
|
2
2
|
import { n as logger, t as addTransport } from "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { i as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { i as getInstalledPackage } from "./versionChecker-CbqhEGUc.js";
|
|
4
4
|
import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
|
|
5
5
|
import { u as removeControlCharacters } from "./todoAutomation-CbVVS4re.js";
|
|
6
6
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-BOIPD_Vs.js";
|
|
@@ -2071,7 +2071,7 @@ async function agentYes({ cli, cliArgs = [], skipPermissions = false, prompt, ro
|
|
|
2071
2071
|
}, 100);
|
|
2072
2072
|
const cleanupHeartbeat = () => clearInterval(heartbeatInterval);
|
|
2073
2073
|
shell.onExit(cleanupHeartbeat);
|
|
2074
|
-
const { startParentPingLoop } = await import("./parentPingLoop-
|
|
2074
|
+
const { startParentPingLoop } = await import("./parentPingLoop-CovRlBFM.js");
|
|
2075
2075
|
const parentPingLoop = startParentPingLoop({
|
|
2076
2076
|
parentPid,
|
|
2077
2077
|
selfWrapperPid: process.pid,
|
|
@@ -2334,4 +2334,4 @@ function sleep(ms) {
|
|
|
2334
2334
|
|
|
2335
2335
|
//#endregion
|
|
2336
2336
|
export { hasTodoStore as a, permissionBadge as c, answerAsk as i, AgentContext as l, agentYes as n, listAsks as o, config as r, listAsksForProject as s, CLIS_CONFIG as t, CLAUDE_SESSION_PIN_ENV as u };
|
|
2337
|
-
//# sourceMappingURL=ts-
|
|
2337
|
+
//# sourceMappingURL=ts-LgWg13cL.js.map
|
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name = "agent-yes";
|
|
10
|
-
var version = "1.
|
|
10
|
+
var version = "1.285.0";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -215,4 +215,4 @@ async function displayVersion() {
|
|
|
215
215
|
|
|
216
216
|
//#endregion
|
|
217
217
|
export { versionString as a, getInstalledPackage as i, compareVersions as n, displayVersion as r, checkAndAutoUpdate as t };
|
|
218
|
-
//# sourceMappingURL=versionChecker-
|
|
218
|
+
//# sourceMappingURL=versionChecker-CbqhEGUc.js.map
|
|
@@ -28,7 +28,7 @@ function parseFlags(args, known) {
|
|
|
28
28
|
}
|
|
29
29
|
/** Resolve the local daemon base URL + token (flags override discovery). */
|
|
30
30
|
async function daemonTarget(flags) {
|
|
31
|
-
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-
|
|
31
|
+
const { resolveDaemonHttpBase, loadTokenReadOnly } = await import("./serve-nk0r7fxV.js");
|
|
32
32
|
const base = typeof flags.base === "string" ? flags.base : await resolveDaemonHttpBase();
|
|
33
33
|
if (!base) throw new Error("no running ay serve daemon found — start `ay serve` or pass --base <url> (e.g. http://127.0.0.1:PORT)");
|
|
34
34
|
const token = typeof flags.token === "string" ? flags.token : await loadTokenReadOnly() ?? "";
|
|
@@ -186,7 +186,7 @@ async function cmdMint(args) {
|
|
|
186
186
|
const bad = caps.filter((c) => !KNOWN_CAPS.has(c));
|
|
187
187
|
if (bad.length) throw new Error(`unknown cap(s): ${bad.join(", ")} (valid: ${[...KNOWN_CAPS].join(", ")})`);
|
|
188
188
|
const ttlSec = parseTtlSec(typeof flags.ttl === "string" ? flags.ttl : "15m");
|
|
189
|
-
const { mintScopedTermToken } = await import("./serve-
|
|
189
|
+
const { mintScopedTermToken } = await import("./serve-nk0r7fxV.js");
|
|
190
190
|
const r = await mintScopedTermToken(target, {
|
|
191
191
|
ttlSec,
|
|
192
192
|
caps
|
|
@@ -202,4 +202,4 @@ async function cmdMint(args) {
|
|
|
202
202
|
|
|
203
203
|
//#endregion
|
|
204
204
|
export { cmdMint, cmdWidget };
|
|
205
|
-
//# sourceMappingURL=widget-
|
|
205
|
+
//# sourceMappingURL=widget-DUkLAsSR.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as listRecords } from "./subcommands-
|
|
1
|
+
import { D as listRecords } from "./subcommands-B_Lg_zDe.js";
|
|
2
2
|
import { a as getProvisionRoot } from "./workspaceConfig-D6QndOCz.js";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
4
|
import { lstat, opendir } from "fs/promises";
|
|
@@ -424,4 +424,4 @@ async function cmdWs(args) {
|
|
|
424
424
|
|
|
425
425
|
//#endregion
|
|
426
426
|
export { isPathInside as a, walkWorkspaces as c, importProvisionModule as i, workspaceStatus as l, cmdWs as n, loadProvision as o, collectWorkspaces as r, resolveOperand as s, WS_JSON_SCHEMA as t };
|
|
427
|
-
//# sourceMappingURL=ws-
|
|
427
|
+
//# sourceMappingURL=ws-BAy7xMDI.js.map
|
|
@@ -3,10 +3,10 @@ import "./globalPidIndex-DoaKEUkO.js";
|
|
|
3
3
|
import "./messageLog-DdjBNqgt.js";
|
|
4
4
|
import "./e2e-z1xpwSAg.js";
|
|
5
5
|
import "./configShared-DKTgiz7K.js";
|
|
6
|
-
import "./subcommands-
|
|
6
|
+
import "./subcommands-B_Lg_zDe.js";
|
|
7
7
|
import "./notifyStore-2SWKGwZI.js";
|
|
8
8
|
import "./webrtcLink-DLaJfTcB.js";
|
|
9
9
|
import "./remotes-b6reVXzo.js";
|
|
10
|
-
import { a as isPathInside, c as walkWorkspaces, i as importProvisionModule, l as workspaceStatus, n as cmdWs, o as loadProvision, r as collectWorkspaces, s as resolveOperand, t as WS_JSON_SCHEMA } from "./ws-
|
|
10
|
+
import { a as isPathInside, c as walkWorkspaces, i as importProvisionModule, l as workspaceStatus, n as cmdWs, o as loadProvision, r as collectWorkspaces, s as resolveOperand, t as WS_JSON_SCHEMA } from "./ws-BAy7xMDI.js";
|
|
11
11
|
|
|
12
12
|
export { WS_JSON_SCHEMA, cmdWs, collectWorkspaces, isPathInside, loadProvision, walkWorkspaces, workspaceStatus };
|
package/package.json
CHANGED
package/ts/cmdPs.spec.ts
CHANGED
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
readPpidSync,
|
|
9
9
|
renderTable,
|
|
10
10
|
repoLabel,
|
|
11
|
+
subtreeTotals,
|
|
11
12
|
type PsRow,
|
|
12
13
|
} from "./cmdPs.ts";
|
|
13
|
-
import type { SystemStats, TreeStats } from "./procStats.ts";
|
|
14
|
+
import type { ProcRow, SystemStats, TreeStats } from "./procStats.ts";
|
|
14
15
|
|
|
15
16
|
const stats = (over: Partial<TreeStats> = {}): TreeStats => ({
|
|
16
17
|
pid: 1,
|
|
@@ -151,11 +152,13 @@ const fixture: {
|
|
|
151
152
|
trees: Map<number, TreeStats>;
|
|
152
153
|
unattributed: TreeStats;
|
|
153
154
|
system: SystemStats;
|
|
155
|
+
members: Map<number, ProcRow[]>;
|
|
154
156
|
} = {
|
|
155
157
|
records: [],
|
|
156
158
|
trees: new Map(),
|
|
157
159
|
unattributed: { pid: 0, rss: 0, cpuPercent: 0, procs: 0 },
|
|
158
160
|
system: sys(),
|
|
161
|
+
members: new Map(),
|
|
159
162
|
};
|
|
160
163
|
|
|
161
164
|
vi.mock("./subcommands.ts", () => ({
|
|
@@ -172,6 +175,7 @@ vi.mock("./procStats.ts", async () => {
|
|
|
172
175
|
sampleTrees: vi.fn(async () => ({
|
|
173
176
|
trees: fixture.trees,
|
|
174
177
|
unattributed: fixture.unattributed,
|
|
178
|
+
members: fixture.members ?? new Map(),
|
|
175
179
|
})),
|
|
176
180
|
};
|
|
177
181
|
});
|
|
@@ -387,3 +391,124 @@ describe("parsePpidFromStat", () => {
|
|
|
387
391
|
expect(parsePpidFromStat("1234 (bash) S notanumber 1234")).toBeNull();
|
|
388
392
|
});
|
|
389
393
|
});
|
|
394
|
+
|
|
395
|
+
describe("subtreeTotals", () => {
|
|
396
|
+
const n = (depth: number, rss: number, cpu: number, procs: number) => ({
|
|
397
|
+
depth,
|
|
398
|
+
stats: { pid: depth * 1000 + rss, rss, cpuPercent: cpu, procs },
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("returns null for a row with no descendants, so leaves render blank", () => {
|
|
402
|
+
expect(subtreeTotals([n(0, 10, 1, 1)])).toEqual([null]);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it("rolls a parent up with its children", () => {
|
|
406
|
+
const [parent, a, b] = subtreeTotals([n(0, 10, 1, 2), n(1, 5, 2, 3), n(1, 1, 4, 1)]);
|
|
407
|
+
expect(parent).toMatchObject({ rss: 16, cpuPercent: 7, procs: 6 });
|
|
408
|
+
expect(a).toBeNull();
|
|
409
|
+
expect(b).toBeNull();
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it("includes grandchildren in the grandparent's total", () => {
|
|
413
|
+
// sampleTrees attributes exclusively, so without the deep walk a fan-out
|
|
414
|
+
// parent's real cost stays invisible.
|
|
415
|
+
const out = subtreeTotals([n(0, 1, 1, 1), n(1, 2, 2, 2), n(2, 4, 4, 4)]);
|
|
416
|
+
expect(out[0]).toMatchObject({ rss: 7, cpuPercent: 7, procs: 7 });
|
|
417
|
+
expect(out[1]).toMatchObject({ rss: 6, cpuPercent: 6, procs: 6 });
|
|
418
|
+
expect(out[2]).toBeNull();
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it("stops at the next sibling — one subtree never absorbs another", () => {
|
|
422
|
+
const out = subtreeTotals([n(0, 1, 0, 1), n(1, 2, 0, 1), n(0, 100, 0, 1), n(1, 200, 0, 1)]);
|
|
423
|
+
expect(out[0]).toMatchObject({ rss: 3 });
|
|
424
|
+
expect(out[2]).toMatchObject({ rss: 300 });
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it("skips a row whose stats are missing rather than throwing", () => {
|
|
428
|
+
// Defensive: the sampler can miss an agent that exited mid-window, and a
|
|
429
|
+
// rollup must not take the whole table down with it.
|
|
430
|
+
const missing = { depth: 1, stats: undefined as unknown as ReturnType<typeof stats> };
|
|
431
|
+
const out = subtreeTotals([n(0, 1, 0, 1), missing, n(1, 4, 0, 1)]);
|
|
432
|
+
expect(out[0]).toMatchObject({ rss: 5 }); // descendants: skipped + counted
|
|
433
|
+
// And a row whose OWN stats are missing yields null instead of throwing.
|
|
434
|
+
expect(subtreeTotals([missing])).toEqual([null]);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it("treats a missing depth as a root", () => {
|
|
438
|
+
const out = subtreeTotals([{ stats: { pid: 1, rss: 1, cpuPercent: 0, procs: 1 } }, n(1, 2, 0, 1)]);
|
|
439
|
+
expect(out[0]).toMatchObject({ rss: 3 });
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
describe("renderTable --tree", () => {
|
|
444
|
+
const treeRows = [
|
|
445
|
+
row({ pid: 1, repo: "alpha", stats: stats({ rss: 100, cpuPercent: 1, procs: 2 }) }),
|
|
446
|
+
row({ pid: 2, repo: "alpha", stats: stats({ rss: 50, cpuPercent: 2, procs: 1 }) }),
|
|
447
|
+
];
|
|
448
|
+
|
|
449
|
+
it("omits the Σ columns entirely in flat mode", () => {
|
|
450
|
+
const out = renderTable(treeRows, null);
|
|
451
|
+
expect(out).not.toContain("ΣCPU%");
|
|
452
|
+
expect(out).not.toContain("ΣRSS");
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it("lists each agent's OS processes under it, but only in tree mode", () => {
|
|
456
|
+
const withProcs = [
|
|
457
|
+
{
|
|
458
|
+
...treeRows[0]!,
|
|
459
|
+
depth: 0,
|
|
460
|
+
prefix: "",
|
|
461
|
+
procRows: [
|
|
462
|
+
{ pid: 11, ppid: 1, comm: "claude", rss: 1024, cpuPercent: 2, state: "S" },
|
|
463
|
+
{ pid: 12, ppid: 11, comm: "bash", rss: 512, cpuPercent: 0, state: "S" },
|
|
464
|
+
{ pid: 13, ppid: 11, comm: "gone", rss: 0, cpuPercent: 0, state: "Z" },
|
|
465
|
+
],
|
|
466
|
+
},
|
|
467
|
+
];
|
|
468
|
+
const flat = renderTable(withProcs, null);
|
|
469
|
+
expect(flat).not.toContain("bash"); // flat mode stays a one-row-per-agent table
|
|
470
|
+
const out = renderTable(withProcs, null, { tree: true });
|
|
471
|
+
expect(out).toContain("claude");
|
|
472
|
+
expect(out).toContain("bash");
|
|
473
|
+
// A zombie is called out — it is the one process state worth acting on.
|
|
474
|
+
expect(out).toContain("zombie");
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it("renders a tree row that has no prefix at all (a lone root)", () => {
|
|
478
|
+
// prefix/depth are optional on PsRow; a row built without them must still
|
|
479
|
+
// render, and must not gain a stray indent.
|
|
480
|
+
const bare = [{ ...treeRows[0]!, subtree: null }];
|
|
481
|
+
const out = renderTable(bare, null, { tree: true });
|
|
482
|
+
const line = out.split("\n").find((l) => l.startsWith("1 ")) as string;
|
|
483
|
+
expect(line).toBeTruthy();
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
it("indents process rows relative to their agent's rails", () => {
|
|
487
|
+
const kid = { pid: 9, ppid: 1, comm: "zsh", rss: 1, cpuPercent: 0, state: "S" };
|
|
488
|
+
const nested = renderTable(
|
|
489
|
+
[{ ...treeRows[0]!, depth: 1, prefix: "└─ ", subtree: null, procRows: [kid] }],
|
|
490
|
+
null,
|
|
491
|
+
{ tree: true },
|
|
492
|
+
);
|
|
493
|
+
const root = renderTable([{ ...treeRows[0]!, subtree: null, procRows: [kid] }], null, {
|
|
494
|
+
tree: true,
|
|
495
|
+
});
|
|
496
|
+
const indentOf = (out: string) =>
|
|
497
|
+
(out.split("\n").find((l) => l.includes("zsh")) as string).match(/^ */)![0].length;
|
|
498
|
+
// A nested agent's processes sit deeper than a root agent's.
|
|
499
|
+
expect(indentOf(nested)).toBeGreaterThan(indentOf(root));
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it("adds the Σ columns and renders forest rails on the PID cell", () => {
|
|
503
|
+
const withTree = [
|
|
504
|
+
{ ...treeRows[0]!, depth: 0, prefix: "", subtree: stats({ rss: 150, cpuPercent: 3, procs: 3 }) },
|
|
505
|
+
{ ...treeRows[1]!, depth: 1, prefix: "└─ ", subtree: null },
|
|
506
|
+
];
|
|
507
|
+
const out = renderTable(withTree, null, { tree: true });
|
|
508
|
+
expect(out).toContain("ΣCPU%");
|
|
509
|
+
const child = out.split("\n").find((l) => l.includes("└─ 2")) as string;
|
|
510
|
+
expect(child).toBeTruthy();
|
|
511
|
+
// A leaf's Σ cells stay blank — repeating its own numbers would be noise.
|
|
512
|
+
expect(child).not.toMatch(/\s3\s/);
|
|
513
|
+
});
|
|
514
|
+
});
|