agent-yes 1.288.0 → 1.289.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/default.config.yaml +106 -0
- package/dist/{SUPPORTED_CLIS-BHowMgMY.js → SUPPORTED_CLIS-BlgVWZrM.js} +2 -2
- package/dist/{SUPPORTED_CLIS-ChhJyq4h.js → SUPPORTED_CLIS-C65PuIs6.js} +3 -3
- package/dist/{agentShare-T3RskvDT.js → agentShare-Cm15-dfZ.js} +3 -3
- package/dist/{callback-CuohbCJA.js → callback-Bbplrsbv.js} +3 -3
- package/dist/{callback-DeaETuHt.js → callback-Dwnkeqpz.js} +3 -3
- package/dist/cli.js +11 -11
- package/dist/cmdPs-BYBZQ0Vc.js +331 -0
- package/dist/{cwdConflictWarn-DIPD6HH5.js → cwdConflictWarn-BgXN56Jc.js} +1 -1
- package/dist/{cwdPassthroughHint-C0tfZlgZ.js → cwdPassthroughHint-CDEGVteh.js} +1 -1
- package/dist/{expose-Ds9aUFsq.js → expose-BlddYYx9.js} +1 -1
- package/dist/{forkNested-Dt5XP8ZH.js → forkNested-CJ7lQQCe.js} +1 -1
- package/dist/{hist-DSYaJEd3.js → hist-DZxq7NMA.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{initMsg-CeF4QNOM.js → initMsg-DoltWTZj.js} +1 -1
- package/dist/{initMsg-DejbYYjX.js → initMsg-axyQAPLK.js} +1 -1
- package/dist/{nodeRuntime-_zeWDISM.js → nodeRuntime-CipjIwfO.js} +1 -1
- package/dist/{notifyDaemon-BORqPeAl.js → notifyDaemon-Q3FF-WEZ.js} +47 -39
- package/dist/{openBrowser-BNP8xByu.js → openBrowser-THOzOGNm.js} +1 -1
- package/dist/{parentLink-Bv8ihRcu.js → parentLink-bpDGuQi6.js} +1 -1
- package/dist/{parentLink-HWunrH1s.js → parentLink-fdiuB13i.js} +1 -1
- package/dist/{parentPingLoop-COePRYr9.js → parentPingLoop-Dc7co5D7.js} +4 -4
- package/dist/{cmdPs-Bm4JG7hi.js → procStats-CyD8h5nx.js} +2 -329
- package/dist/{remotes-b6reVXzo.js → remotes-BjsglpjL.js} +2 -2
- package/dist/{remotes-BlHTR9ow.js → remotes-CAqtL_Ib.js} +1 -1
- package/dist/{rustBinary-BmXzqj5z.js → rustBinary-B57oRftk.js} +2 -2
- package/dist/{rustBinary-D12k7iOD.js → rustBinary-Dq0AytZ7.js} +2 -2
- package/dist/{schedule-DLoUmyJh.js → schedule-pim0Izhs.js} +6 -6
- package/dist/{serve-DaDlOtss.js → serve-CMsvjqPU.js} +174 -27
- package/dist/{setup-Cqy8nRrq.js → setup-BmxYINCx.js} +4 -4
- package/dist/{spawnGate-B2hA_2NQ.js → spawnGate-B26UnzqP.js} +2 -2
- package/dist/{spawnGate-FLwTAPW6.js → spawnGate-C8MSRt7X.js} +1 -1
- package/dist/{subcommands-DKTa3E6O.js → subcommands-CJBV06rg.js} +2 -2
- package/dist/{subcommands-BfiOyfz7.js → subcommands-CWDqhKQe.js} +21 -21
- package/dist/{systemPathLink-Dl2gJqeg.js → systemPathLink-BVdk48Vz.js} +1 -1
- package/dist/{terminal-C0tnGnrZ.js → terminal-CcmBzB3G.js} +2 -2
- package/dist/{todoCli-MWrejmdM.js → todoCli-azqbjBtz.js} +1 -1
- package/dist/{tray-BhPVpP_r.js → tray-CIt9mCKZ.js} +1 -1
- package/dist/trayApp-BovAZs7m.js +5 -0
- package/dist/{trayApp-DvL9qW6V.js → trayApp-DuZBkGl_.js} +2 -2
- package/dist/{ts-DJLp2_bv.js → ts-CSp4mJ7Z.js} +23 -9
- package/dist/{versionChecker-CkO7wYyV.js → versionChecker-CWCN4vwm.js} +2 -2
- package/dist/{webrtcRemote-H9Hok0_R.js → webrtcRemote-Bevc5ogS.js} +1 -1
- package/dist/{widget-CJqpScCG.js → widget-D2cCC8nz.js} +3 -3
- package/dist/{workspaceConfig-D6QndOCz.js → workspaceConfig-DTvPtr5j.js} +1 -1
- package/dist/{ws-DGENGNrr.js → ws-B5Qb2c-1.js} +3 -3
- package/dist/{ws-DzCKvzWD.js → ws-CyO9r4jx.js} +3 -3
- package/package.json +1 -1
- package/ts/agentNice.spec.ts +42 -2
- package/ts/index.ts +5 -4
- package/ts/notifyDaemon.spec.ts +16 -0
- package/ts/notifyDaemon.ts +22 -0
- package/ts/serve.ts +14 -0
- package/ts/serveSampler.spec.ts +390 -0
- package/ts/serveSampler.ts +218 -0
- package/dist/trayApp-BrAMlCY7.js +0 -5
|
@@ -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 { D as listRecords, I as renderLogTailLines, b as isPidAlive, u as deriveLiveState } from "./subcommands-
|
|
6
|
+
import { D as listRecords, I as renderLogTailLines, b as isPidAlive, u as deriveLiveState } from "./subcommands-CWDqhKQe.js";
|
|
7
7
|
import { f as readInbox, g as daemonLockOwnerPath, h as daemonLockDir, i as gcInboxes, l as listInboxParents, m as shouldStealLock, n as appendEvent, s as hostId, u as liveWatchers, x as notifyDir } from "./notifyStore-2SWKGwZI.js";
|
|
8
8
|
import "./webrtcLink-DLaJfTcB.js";
|
|
9
|
-
import "./remotes-
|
|
9
|
+
import "./remotes-BjsglpjL.js";
|
|
10
10
|
import { mkdir, readFile, rename, rm, stat, writeFile } from "fs/promises";
|
|
11
11
|
import { randomUUID } from "node:crypto";
|
|
12
12
|
import { execFile, execFileSync } from "node:child_process";
|
|
@@ -556,6 +556,7 @@ async function liveChildrenSnapshot() {
|
|
|
556
556
|
return m;
|
|
557
557
|
}
|
|
558
558
|
const OWNER_TTL_MS = 3e4;
|
|
559
|
+
const LOCK_WAIT_BUDGET_MS = 5e3;
|
|
559
560
|
let daemonStartedAt = 0;
|
|
560
561
|
let daemonOsStart = null;
|
|
561
562
|
let daemonToken = "";
|
|
@@ -597,46 +598,53 @@ async function writeOwner() {
|
|
|
597
598
|
* mkdir→writeOwner window of another daemon coming up), so two concurrent starts
|
|
598
599
|
* can't both "win". The liveness predicate is injectable for tests.
|
|
599
600
|
*/
|
|
600
|
-
async function acquireDaemonLock(isAlive = isPidAlive) {
|
|
601
|
+
async function acquireDaemonLock(isAlive = isPidAlive, waitBudgetMs = LOCK_WAIT_BUDGET_MS) {
|
|
601
602
|
await mkdir(notifyDir(), { recursive: true }).catch(() => {});
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if (!await writeOwner()) {
|
|
608
|
-
await rm(daemonLockDir(), {
|
|
609
|
-
recursive: true,
|
|
610
|
-
force: true
|
|
611
|
-
}).catch(() => {});
|
|
612
|
-
await new Promise((r) => setTimeout(r, 15));
|
|
613
|
-
continue;
|
|
603
|
+
const deadline = Date.now() + waitBudgetMs;
|
|
604
|
+
for (;;) {
|
|
605
|
+
if (Date.now() >= deadline) {
|
|
606
|
+
logger.warn("[notifyd] gave up acquiring the daemon lock — unverifiable live holder");
|
|
607
|
+
return false;
|
|
614
608
|
}
|
|
615
|
-
return true;
|
|
616
|
-
} catch (e) {
|
|
617
|
-
if (e.code !== "EEXIST") throw e;
|
|
618
|
-
const raw = await readFile(daemonLockOwnerPath(), "utf8").catch(() => "");
|
|
619
|
-
const now = Date.now();
|
|
620
|
-
let owner = null;
|
|
621
609
|
try {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
610
|
+
await mkdir(daemonLockDir(), { recursive: false });
|
|
611
|
+
daemonStartedAt = Date.now();
|
|
612
|
+
daemonToken = randomUUID();
|
|
613
|
+
daemonOsStart = osProcessStartToken(process.pid);
|
|
614
|
+
if (!await writeOwner()) {
|
|
615
|
+
await rm(daemonLockDir(), {
|
|
616
|
+
recursive: true,
|
|
617
|
+
force: true
|
|
618
|
+
}).catch(() => {});
|
|
619
|
+
await new Promise((r) => setTimeout(r, 15));
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
return true;
|
|
623
|
+
} catch (e) {
|
|
624
|
+
if (e.code !== "EEXIST") throw e;
|
|
625
|
+
const raw = await readFile(daemonLockOwnerPath(), "utf8").catch(() => "");
|
|
626
|
+
const now = Date.now();
|
|
627
|
+
let owner = null;
|
|
628
|
+
try {
|
|
629
|
+
owner = JSON.parse(raw);
|
|
630
|
+
} catch {}
|
|
631
|
+
const recycled = owner && typeof owner.pid === "number" && owner.pid > 0 ? osStartTokenMismatch(owner.os_start, osProcessStartToken(owner.pid)) : false;
|
|
632
|
+
if (owner && typeof owner.pid === "number" && owner.pid > 0 && owner.pid !== process.pid && typeof owner.ts === "number" && now - owner.ts <= OWNER_TTL_MS && isAlive(owner.pid) && !recycled) return false;
|
|
633
|
+
const lockAgeMs = now - await stat(daemonLockDir()).then((s) => s.mtimeMs).catch(() => now);
|
|
634
|
+
if (recycled || shouldStealLock(raw, now, {
|
|
635
|
+
staleMs: OWNER_TTL_MS,
|
|
636
|
+
lockAgeMs,
|
|
637
|
+
selfPid: process.pid,
|
|
638
|
+
isAlive
|
|
639
|
+
})) {
|
|
640
|
+
await rm(daemonLockDir(), {
|
|
641
|
+
recursive: true,
|
|
642
|
+
force: true
|
|
643
|
+
}).catch(() => {});
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
await new Promise((r) => setTimeout(r, 15));
|
|
638
647
|
}
|
|
639
|
-
await new Promise((r) => setTimeout(r, 15));
|
|
640
648
|
}
|
|
641
649
|
}
|
|
642
650
|
/**
|
|
@@ -863,4 +871,4 @@ async function ensureDaemon() {
|
|
|
863
871
|
|
|
864
872
|
//#endregion
|
|
865
873
|
export { daemonStatus, ensureDaemon, requestDaemonStop, runDaemon };
|
|
866
|
-
//# sourceMappingURL=notifyDaemon-
|
|
874
|
+
//# sourceMappingURL=notifyDaemon-Q3FF-WEZ.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
2
|
import "./globalPidIndex-DoaKEUkO.js";
|
|
3
|
-
import { n as spawnerFromRecords, t as resolveSpawner } from "./parentLink-
|
|
3
|
+
import { n as spawnerFromRecords, t as resolveSpawner } from "./parentLink-bpDGuQi6.js";
|
|
4
4
|
|
|
5
5
|
export { resolveSpawner };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as logger } from "./logger-CDIsZ-Pp.js";
|
|
2
2
|
import "./globalPidIndex-DoaKEUkO.js";
|
|
3
3
|
import { t as classifyNeedsInput } from "./needsInput-BHopZGM8.js";
|
|
4
|
-
import { n as replyTargetOf, r as shortenHome } from "./initMsg-
|
|
5
|
-
import { t as resolveSpawner } from "./parentLink-
|
|
4
|
+
import { n as replyTargetOf, r as shortenHome } from "./initMsg-axyQAPLK.js";
|
|
5
|
+
import { t as resolveSpawner } from "./parentLink-bpDGuQi6.js";
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
7
7
|
|
|
8
8
|
//#region ts/parentPing.ts
|
|
@@ -338,7 +338,7 @@ async function isParentWatching(parentWrapperPid, parentAgentPid, selfAgentPid,
|
|
|
338
338
|
logger.debug("[parent-ping] watcher lookup failed:", error);
|
|
339
339
|
}
|
|
340
340
|
try {
|
|
341
|
-
const { lastReadAt, READ_WINDOW_MS } = await import("./subcommands-
|
|
341
|
+
const { lastReadAt, READ_WINDOW_MS } = await import("./subcommands-CJBV06rg.js");
|
|
342
342
|
const last = await lastReadAt(`agent:${parentAgentPid}`, selfAgentPid);
|
|
343
343
|
if (last !== null && now - last <= READ_WINDOW_MS) return true;
|
|
344
344
|
} catch (error) {
|
|
@@ -466,4 +466,4 @@ function startParentPingLoop(opts) {
|
|
|
466
466
|
|
|
467
467
|
//#endregion
|
|
468
468
|
export { startParentPingLoop };
|
|
469
|
-
//# sourceMappingURL=parentPingLoop-
|
|
469
|
+
//# sourceMappingURL=parentPingLoop-Dc7co5D7.js.map
|
|
@@ -1,17 +1,4 @@
|
|
|
1
|
-
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./globalPidIndex-DoaKEUkO.js";
|
|
3
|
-
import "./messageLog-DdjBNqgt.js";
|
|
4
|
-
import "./e2e-z1xpwSAg.js";
|
|
5
|
-
import "./configShared-DKTgiz7K.js";
|
|
6
|
-
import { $ as buildAgentForest, D as listRecords, et as flattenForest, u as deriveLiveState } from "./subcommands-BfiOyfz7.js";
|
|
7
|
-
import "./notifyStore-2SWKGwZI.js";
|
|
8
|
-
import "./webrtcLink-DLaJfTcB.js";
|
|
9
|
-
import "./remotes-b6reVXzo.js";
|
|
10
|
-
import yargs from "yargs";
|
|
11
1
|
import { execFile } from "node:child_process";
|
|
12
|
-
import { readFileSync } from "node:fs";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
import { homedir } from "node:os";
|
|
15
2
|
import { readFile, readdir } from "node:fs/promises";
|
|
16
3
|
import { promisify } from "node:util";
|
|
17
4
|
|
|
@@ -372,319 +359,5 @@ function humanBytes(bytes) {
|
|
|
372
359
|
}
|
|
373
360
|
|
|
374
361
|
//#endregion
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
* `ay ps` — what each agent COSTS, rolled up per process tree.
|
|
378
|
-
*
|
|
379
|
-
* The split from `ay ls`: `ls` answers "what is running and what is it doing"
|
|
380
|
-
* (prompt, git, badges, forest); `ps` answers "what is this box spending on
|
|
381
|
-
* each agent, and is any of it safe to reclaim". Same rows, different question.
|
|
382
|
-
*
|
|
383
|
-
* `ps` used to be a plain alias for `ls`. It is now its own command, because the
|
|
384
|
-
* number you actually want is not in any `ps`/`htop` output: one agent is a
|
|
385
|
-
* whole subtree of wrapper + CLI + pty hosts + subagents, and only ay knows
|
|
386
|
-
* which pids collapse into which session.
|
|
387
|
-
*
|
|
388
|
-
* Deliberately local-only. Resource numbers are per-machine and there is nothing
|
|
389
|
-
* meaningful to sum across remotes; `ay ls` remains the fleet-wide view.
|
|
390
|
-
*/
|
|
391
|
-
/** Default CPU sampling window. Long enough to be meaningful, short enough to feel instant. */
|
|
392
|
-
const DEFAULT_WINDOW_MS = 1e3;
|
|
393
|
-
function shortenPath(p) {
|
|
394
|
-
const home = homedir();
|
|
395
|
-
return p.startsWith(home) ? "~" + p.slice(home.length) : p;
|
|
396
|
-
}
|
|
397
|
-
/** Trailing path segment that identifies a worktree — `/code/x/foo/tree/main` → `foo`. */
|
|
398
|
-
function repoLabel(cwd) {
|
|
399
|
-
const parts = cwd.split(/[\\/]+/).filter(Boolean);
|
|
400
|
-
const treeAt = parts.lastIndexOf("tree");
|
|
401
|
-
if (treeAt > 0) return parts[treeAt - 1];
|
|
402
|
-
return parts[parts.length - 1] ?? shortenPath(cwd);
|
|
403
|
-
}
|
|
404
|
-
/** `15.23 12.52 9.86 (8 cpu, 1.9x) mem 13.0/15Gi swap 4.8/4.8Gi FULL zombies 1440` */
|
|
405
|
-
function formatSystemLine(sys) {
|
|
406
|
-
const bits = [];
|
|
407
|
-
if (sys.load) {
|
|
408
|
-
const [one, five, fifteen] = sys.load;
|
|
409
|
-
const ratio = one / Math.max(1, sys.ncpu);
|
|
410
|
-
bits.push(`load ${one.toFixed(2)} ${five.toFixed(2)} ${fifteen.toFixed(2)} (${sys.ncpu} cpu, ${ratio.toFixed(1)}x)`);
|
|
411
|
-
}
|
|
412
|
-
if (sys.memTotalBytes !== null) {
|
|
413
|
-
const used = sys.memAvailableBytes !== null ? sys.memTotalBytes - sys.memAvailableBytes : null;
|
|
414
|
-
bits.push(`mem ${humanBytes(used)}/${humanBytes(sys.memTotalBytes)}`);
|
|
415
|
-
}
|
|
416
|
-
if (sys.swapTotalBytes !== null && sys.swapTotalBytes > 0) {
|
|
417
|
-
const usedSwap = sys.swapFreeBytes !== null ? sys.swapTotalBytes - sys.swapFreeBytes : null;
|
|
418
|
-
const full = sys.swapFreeBytes !== null && sys.swapFreeBytes <= 0 ? " FULL" : "";
|
|
419
|
-
bits.push(`swap ${humanBytes(usedSwap)}/${humanBytes(sys.swapTotalBytes)}${full}`);
|
|
420
|
-
}
|
|
421
|
-
if (sys.zombies > 0) bits.push(`zombies ${sys.zombies}`);
|
|
422
|
-
return bits.join(" ");
|
|
423
|
-
}
|
|
424
|
-
/**
|
|
425
|
-
* Roll each row up with its descendants, using the forest `depth` column: a
|
|
426
|
-
* row's descendants are the following rows with a strictly greater depth, up to
|
|
427
|
-
* the next row at or above its own level.
|
|
428
|
-
*
|
|
429
|
-
* Needed because sampleTrees attributes DEEPEST-FIRST and exclusively — a
|
|
430
|
-
* parent's own numbers deliberately omit its subagents, so without this a
|
|
431
|
-
* fan-out parent looks cheap while its real cost sits in rows below it.
|
|
432
|
-
*
|
|
433
|
-
* Returns null for a row with no descendants.
|
|
434
|
-
*/
|
|
435
|
-
function subtreeTotals(rows) {
|
|
436
|
-
return rows.map((r, i) => {
|
|
437
|
-
const depth = r.depth ?? 0;
|
|
438
|
-
const own = r.stats;
|
|
439
|
-
if (!own) return null;
|
|
440
|
-
let rss = own.rss;
|
|
441
|
-
let cpuPercent = own.cpuPercent;
|
|
442
|
-
let procs = own.procs;
|
|
443
|
-
let found = false;
|
|
444
|
-
for (let j = i + 1; j < rows.length; j++) {
|
|
445
|
-
if ((rows[j]?.depth ?? 0) <= depth) break;
|
|
446
|
-
const st = rows[j]?.stats;
|
|
447
|
-
if (!st) continue;
|
|
448
|
-
found = true;
|
|
449
|
-
rss += st.rss;
|
|
450
|
-
cpuPercent += st.cpuPercent;
|
|
451
|
-
procs += st.procs;
|
|
452
|
-
}
|
|
453
|
-
return found ? {
|
|
454
|
-
pid: own.pid,
|
|
455
|
-
rss,
|
|
456
|
-
cpuPercent,
|
|
457
|
-
procs
|
|
458
|
-
} : null;
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
function pad(s, n) {
|
|
462
|
-
return s.length >= n ? s : s + " ".repeat(n - s.length);
|
|
463
|
-
}
|
|
464
|
-
function padStart(s, n) {
|
|
465
|
-
return s.length >= n ? s : " ".repeat(n - s.length) + s;
|
|
466
|
-
}
|
|
467
|
-
function renderTable(rows, unattributed, opts = {}) {
|
|
468
|
-
const tree = opts.tree === true;
|
|
469
|
-
const showProcs = opts.procs === true;
|
|
470
|
-
const cells = rows.map((r) => ({
|
|
471
|
-
pid: (tree ? r.prefix ?? "" : "") + String(r.pid),
|
|
472
|
-
cli: r.cli,
|
|
473
|
-
status: r.status,
|
|
474
|
-
cpu: r.stats.cpuPercent.toFixed(1),
|
|
475
|
-
rss: humanBytes(r.stats.rss),
|
|
476
|
-
procs: String(r.stats.procs),
|
|
477
|
-
repo: r.repo,
|
|
478
|
-
cwd: shortenPath(r.cwd),
|
|
479
|
-
scpu: r.subtree ? r.subtree.cpuPercent.toFixed(1) : "",
|
|
480
|
-
srss: r.subtree ? humanBytes(r.subtree.rss) : "",
|
|
481
|
-
sprocs: r.subtree ? String(r.subtree.procs) : "",
|
|
482
|
-
self: r.self
|
|
483
|
-
}));
|
|
484
|
-
if (unattributed && unattributed.procs > 0) cells.push({
|
|
485
|
-
pid: "-",
|
|
486
|
-
cli: "unmanaged",
|
|
487
|
-
status: "-",
|
|
488
|
-
cpu: unattributed.cpuPercent.toFixed(1),
|
|
489
|
-
rss: humanBytes(unattributed.rss),
|
|
490
|
-
procs: String(unattributed.procs),
|
|
491
|
-
repo: "-",
|
|
492
|
-
cwd: "-",
|
|
493
|
-
scpu: "",
|
|
494
|
-
srss: "",
|
|
495
|
-
sprocs: "",
|
|
496
|
-
self: false
|
|
497
|
-
});
|
|
498
|
-
const w = {
|
|
499
|
-
pid: Math.max(3, ...cells.map((c) => c.pid.length)),
|
|
500
|
-
cli: Math.max(3, ...cells.map((c) => c.cli.length)),
|
|
501
|
-
status: Math.max(6, ...cells.map((c) => c.status.length)),
|
|
502
|
-
cpu: Math.max(5, ...cells.map((c) => c.cpu.length)),
|
|
503
|
-
rss: Math.max(5, ...cells.map((c) => c.rss.length)),
|
|
504
|
-
procs: Math.max(5, ...cells.map((c) => c.procs.length)),
|
|
505
|
-
repo: Math.max(4, ...cells.map((c) => c.repo.length)),
|
|
506
|
-
scpu: Math.max(5, ...cells.map((c) => c.scpu.length)),
|
|
507
|
-
srss: Math.max(5, ...cells.map((c) => c.srss.length)),
|
|
508
|
-
sprocs: Math.max(6, ...cells.map((c) => c.sprocs.length))
|
|
509
|
-
};
|
|
510
|
-
const line = (pid, cli, status, cpu, rss, procs, repo, cwd, scpu = "", srss = "", sprocs = "", tail = "") => `${pad(pid, w.pid)} ${pad(cli, w.cli)} ${pad(status, w.status)} ${padStart(cpu, w.cpu)} ${padStart(rss, w.rss)} ${padStart(procs, w.procs)} ` + (tree ? `${padStart(scpu, w.scpu)} ${padStart(srss, w.srss)} ${padStart(sprocs, w.sprocs)} ` : "") + `${pad(repo, w.repo)} ${cwd}${tail}`;
|
|
511
|
-
const out = [line("PID", "CLI", "STATUS", "CPU%", "RSS", "PROCS", "REPO", "CWD", "ΣCPU%", "ΣRSS", "ΣPROCS")];
|
|
512
|
-
cells.forEach((c, i) => {
|
|
513
|
-
out.push(line(c.pid, c.cli, c.status, c.cpu, c.rss, c.procs, c.repo, c.cwd, c.scpu, c.srss, c.sprocs, c.self ? " ← this session" : ""));
|
|
514
|
-
const kids = rows[i]?.procRows;
|
|
515
|
-
if (!showProcs || !kids?.length) return;
|
|
516
|
-
const indent = " ".repeat((tree ? (rows[i]?.prefix ?? "").length : 0) + 2);
|
|
517
|
-
const pw = Math.max(...kids.map((k) => String(k.pid).length));
|
|
518
|
-
const cw = Math.max(...kids.map((k) => k.comm.length));
|
|
519
|
-
for (const k of kids) out.push(`${indent}· ${padStart(String(k.pid), pw)} ${pad(k.comm, cw)} ${padStart(k.cpuPercent.toFixed(1), 5)} ${padStart(humanBytes(k.rss), 7)}` + (k.state === "Z" ? " zombie" : ""));
|
|
520
|
-
});
|
|
521
|
-
return out.join("\n");
|
|
522
|
-
}
|
|
523
|
-
async function cmdPs(rest) {
|
|
524
|
-
const y = yargs(rest).usage("Usage: ay ps [keyword] [options]\n\nPer-agent resource usage, rolled up across each agent's whole process tree\n(wrapper + CLI + pty hosts + subagents). Local-only; use `ay ls` for the\nfleet view and per-agent prompts.").option("all", {
|
|
525
|
-
type: "boolean",
|
|
526
|
-
default: false,
|
|
527
|
-
description: "Include exited agents"
|
|
528
|
-
}).option("json", {
|
|
529
|
-
type: "boolean",
|
|
530
|
-
default: false,
|
|
531
|
-
description: "Output as JSON"
|
|
532
|
-
}).option("sort", {
|
|
533
|
-
type: "string",
|
|
534
|
-
choices: [
|
|
535
|
-
"rss",
|
|
536
|
-
"cpu",
|
|
537
|
-
"procs",
|
|
538
|
-
"pid"
|
|
539
|
-
],
|
|
540
|
-
default: "rss",
|
|
541
|
-
description: "Sort rows by resource usage (default: rss, biggest first)"
|
|
542
|
-
}).option("tree", {
|
|
543
|
-
type: "boolean",
|
|
544
|
-
default: false,
|
|
545
|
-
description: "Forest order with ├─ rails, plus Σ columns rolling each agent up with its subagents"
|
|
546
|
-
}).option("procs", {
|
|
547
|
-
type: "boolean",
|
|
548
|
-
default: false,
|
|
549
|
-
description: "Expand each agent into the OS processes it owns (wrapper, CLI, shells)"
|
|
550
|
-
}).option("interval", {
|
|
551
|
-
type: "number",
|
|
552
|
-
default: DEFAULT_WINDOW_MS / 1e3,
|
|
553
|
-
description: "CPU sampling window in seconds — CPU% is a live delta, not a lifetime average"
|
|
554
|
-
}).option("cwd", {
|
|
555
|
-
type: "string",
|
|
556
|
-
description: "Restrict to agents whose cwd starts with dir"
|
|
557
|
-
}).option("help", {
|
|
558
|
-
alias: "h",
|
|
559
|
-
type: "boolean",
|
|
560
|
-
default: false,
|
|
561
|
-
description: "Show this help"
|
|
562
|
-
}).example("ay ps", "biggest agents first, with box vitals").example("ay ps --sort cpu", "who is actually burning CPU right now").example("ay ps --tree", "parent>child forest; Σ columns include each agent's subagents").example("ay ps --procs", "expand each agent into its wrapper/CLI/shell processes").example("ay ps --json", "machine-readable rollup").help(false).version(false).exitProcess(false);
|
|
563
|
-
const argv = await y.parseAsync();
|
|
564
|
-
if (argv.help || argv.h) {
|
|
565
|
-
process.stdout.write(await y.getHelp() + "\n");
|
|
566
|
-
return 0;
|
|
567
|
-
}
|
|
568
|
-
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
569
|
-
const records = await listRecords(keyword, {
|
|
570
|
-
all: argv.all,
|
|
571
|
-
active: false,
|
|
572
|
-
json: false,
|
|
573
|
-
latest: false,
|
|
574
|
-
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
575
|
-
});
|
|
576
|
-
if (records.length === 0) {
|
|
577
|
-
process.stderr.write(keyword ? `no agents matched "${keyword}"\n` : "no running agents\n");
|
|
578
|
-
return 0;
|
|
579
|
-
}
|
|
580
|
-
const flat = flattenForest(buildAgentForest(records));
|
|
581
|
-
const ordered = flat.map((r) => r.record);
|
|
582
|
-
const windowMs = Math.max(100, (Number.isFinite(argv.interval) ? argv.interval : 1) * 1e3);
|
|
583
|
-
const { trees, unattributed, members } = await sampleTrees([...ordered].reverse().map((r) => r.pid), { windowMs });
|
|
584
|
-
const states = new Map(await Promise.all(ordered.map(async (r) => [r.pid, (await deriveLiveState(r)).state])));
|
|
585
|
-
const selfPid = process.pid;
|
|
586
|
-
const rows = ordered.map((r, i) => ({
|
|
587
|
-
pid: r.pid,
|
|
588
|
-
cli: r.cli,
|
|
589
|
-
status: states.get(r.pid) ?? r.status,
|
|
590
|
-
cwd: r.cwd,
|
|
591
|
-
repo: repoLabel(r.cwd),
|
|
592
|
-
stats: trees.get(r.pid) ?? {
|
|
593
|
-
pid: r.pid,
|
|
594
|
-
rss: 0,
|
|
595
|
-
cpuPercent: 0,
|
|
596
|
-
procs: 0
|
|
597
|
-
},
|
|
598
|
-
self: trees.get(r.pid) !== void 0 && isSelfTree(r.pid, selfPid),
|
|
599
|
-
prefix: flat[i]?.prefix ?? "",
|
|
600
|
-
depth: flat[i]?.depth ?? 0
|
|
601
|
-
}));
|
|
602
|
-
if (argv.tree) {
|
|
603
|
-
const totals = subtreeTotals(rows);
|
|
604
|
-
rows.forEach((r, i) => {
|
|
605
|
-
r.subtree = totals[i] ?? null;
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
if (argv.procs) for (const r of rows) r.procRows = [...members?.get(r.pid) ?? []].sort((x, y) => y.rss - x.rss);
|
|
609
|
-
if (!argv.tree) {
|
|
610
|
-
const key = String(argv.sort);
|
|
611
|
-
rows.sort((a, b) => {
|
|
612
|
-
if (key === "cpu") return b.stats.cpuPercent - a.stats.cpuPercent;
|
|
613
|
-
if (key === "procs") return b.stats.procs - a.stats.procs;
|
|
614
|
-
if (key === "pid") return a.pid - b.pid;
|
|
615
|
-
return b.stats.rss - a.stats.rss;
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
const sys = await systemStats(await snapshotProcs());
|
|
619
|
-
if (argv.json) {
|
|
620
|
-
process.stdout.write(JSON.stringify({
|
|
621
|
-
system: sys,
|
|
622
|
-
agents: rows.map((r) => ({
|
|
623
|
-
pid: r.pid,
|
|
624
|
-
cli: r.cli,
|
|
625
|
-
status: r.status,
|
|
626
|
-
cwd: r.cwd,
|
|
627
|
-
rssBytes: r.stats.rss,
|
|
628
|
-
cpuPercent: Number(r.stats.cpuPercent.toFixed(2)),
|
|
629
|
-
procs: r.stats.procs,
|
|
630
|
-
self: r.self
|
|
631
|
-
})),
|
|
632
|
-
unattributed: {
|
|
633
|
-
rssBytes: unattributed.rss,
|
|
634
|
-
cpuPercent: Number(unattributed.cpuPercent.toFixed(2)),
|
|
635
|
-
procs: unattributed.procs
|
|
636
|
-
}
|
|
637
|
-
}, null, 2) + "\n");
|
|
638
|
-
return 0;
|
|
639
|
-
}
|
|
640
|
-
const header = formatSystemLine(sys);
|
|
641
|
-
if (header) process.stdout.write(` ${header}\n\n`);
|
|
642
|
-
process.stdout.write(renderTable(rows, unattributed, {
|
|
643
|
-
tree: argv.tree === true,
|
|
644
|
-
procs: argv.procs === true
|
|
645
|
-
}) + "\n");
|
|
646
|
-
return 0;
|
|
647
|
-
}
|
|
648
|
-
/**
|
|
649
|
-
* Is `rootPid` the wrapper of the tree this very process lives in?
|
|
650
|
-
*
|
|
651
|
-
* Walks our own ancestry rather than the snapshot: cheap, and correct even when
|
|
652
|
-
* the snapshot raced. Linux-only detail (reads /proc), returns false elsewhere —
|
|
653
|
-
* mislabelling the self row is cosmetic.
|
|
654
|
-
*/
|
|
655
|
-
function isSelfTree(rootPid, selfPid, readPpid = readPpidSync, platform = process.platform) {
|
|
656
|
-
if (platform !== "linux") return false;
|
|
657
|
-
let pid = selfPid;
|
|
658
|
-
for (let hops = 0; hops < 64 && pid > 1; hops++) {
|
|
659
|
-
if (pid === rootPid) return true;
|
|
660
|
-
const ppid = readPpid(pid);
|
|
661
|
-
if (ppid === null) return false;
|
|
662
|
-
pid = ppid;
|
|
663
|
-
}
|
|
664
|
-
return false;
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* ppid out of one `/proc/<pid>/stat` line.
|
|
668
|
-
*
|
|
669
|
-
* Split from the read so the parsing — the part that can actually be wrong — is
|
|
670
|
-
* testable on hosts without /proc. Field 2 is `comm`, wrapped in parens and NOT
|
|
671
|
-
* escaped: a process named `foo) bar (baz` is legal, so the fields after it can
|
|
672
|
-
* only be found from the LAST `)`, never by splitting on whitespace.
|
|
673
|
-
*/
|
|
674
|
-
function parsePpidFromStat(stat) {
|
|
675
|
-
const close = stat.lastIndexOf(")");
|
|
676
|
-
if (close < 0) return null;
|
|
677
|
-
const ppid = Number(stat.slice(close + 1).trim().split(/\s+/)[1]);
|
|
678
|
-
return Number.isFinite(ppid) ? ppid : null;
|
|
679
|
-
}
|
|
680
|
-
function readPpidSync(pid) {
|
|
681
|
-
try {
|
|
682
|
-
return parsePpidFromStat(readFileSync(`/proc/${pid}/stat`, "utf8"));
|
|
683
|
-
} catch {
|
|
684
|
-
return null;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
//#endregion
|
|
689
|
-
export { cmdPs };
|
|
690
|
-
//# sourceMappingURL=cmdPs-Bm4JG7hi.js.map
|
|
362
|
+
export { systemStats as i, sampleTrees as n, snapshotProcs as r, humanBytes as t };
|
|
363
|
+
//# sourceMappingURL=procStats-CyD8h5nx.js.map
|
|
@@ -93,7 +93,7 @@ async function resolveRemoteSpec(spec) {
|
|
|
93
93
|
* The bridge lives for the rest of the process (torn down on `process.exit`).
|
|
94
94
|
*/
|
|
95
95
|
async function resolveWebrtc(link, keyword, label) {
|
|
96
|
-
const { startWebrtcBridge } = await import("./webrtcRemote-
|
|
96
|
+
const { startWebrtcBridge } = await import("./webrtcRemote-Bevc5ogS.js");
|
|
97
97
|
const bridge = await startWebrtcBridge(link);
|
|
98
98
|
return {
|
|
99
99
|
url: bridge.baseUrl,
|
|
@@ -181,4 +181,4 @@ async function cmdRemote(rest) {
|
|
|
181
181
|
|
|
182
182
|
//#endregion
|
|
183
183
|
export { resolveRemoteSpec as a, readRemotes as i, deleteRemoteAlias as n, writeRemoteAlias as o, parseDirectRemoteSpec as r, cmdRemote as t };
|
|
184
|
-
//# sourceMappingURL=remotes-
|
|
184
|
+
//# sourceMappingURL=remotes-BjsglpjL.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./e2e-z1xpwSAg.js";
|
|
2
2
|
import "./webrtcLink-DLaJfTcB.js";
|
|
3
|
-
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-
|
|
3
|
+
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-BjsglpjL.js";
|
|
4
4
|
|
|
5
5
|
export { cmdRemote };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as getInstalledPackage, n as compareVersions } from "./versionChecker-
|
|
1
|
+
import { i as getInstalledPackage, n as compareVersions } from "./versionChecker-CWCN4vwm.js";
|
|
2
2
|
import { execFileSync } from "child_process";
|
|
3
3
|
import { existsSync, mkdirSync, readdirSync, rmSync, statSync, unlinkSync } from "fs";
|
|
4
4
|
import { chmod, copyFile } from "fs/promises";
|
|
@@ -310,4 +310,4 @@ async function getRustBinary(options = {}) {
|
|
|
310
310
|
|
|
311
311
|
//#endregion
|
|
312
312
|
export { gcOldBinaryDirs as a, getDownloadUrl as c, findTrayLauncher as i, getRustBinary as l, findRustBinary as n, getBinDir as o, findSpawnHiddenLauncher as r, getBinaryName as s, downloadBinary as t };
|
|
313
|
-
//# sourceMappingURL=rustBinary-
|
|
313
|
+
//# sourceMappingURL=rustBinary-B57oRftk.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./versionChecker-
|
|
2
|
-
import { a as gcOldBinaryDirs, c as getDownloadUrl, i as findTrayLauncher, l as getRustBinary, n as findRustBinary, o as getBinDir, r as findSpawnHiddenLauncher, s as getBinaryName, t as downloadBinary } from "./rustBinary-
|
|
1
|
+
import "./versionChecker-CWCN4vwm.js";
|
|
2
|
+
import { a as gcOldBinaryDirs, c as getDownloadUrl, i as findTrayLauncher, l as getRustBinary, n as findRustBinary, o as getBinDir, r as findSpawnHiddenLauncher, s as getBinaryName, t as downloadBinary } from "./rustBinary-B57oRftk.js";
|
|
3
3
|
|
|
4
4
|
export { gcOldBinaryDirs };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./versionChecker-
|
|
3
|
-
import "./ts-
|
|
2
|
+
import "./versionChecker-CWCN4vwm.js";
|
|
3
|
+
import "./ts-CSp4mJ7Z.js";
|
|
4
4
|
import "./todoAutomation-CbVVS4re.js";
|
|
5
5
|
import "./JsonlStore-BqF7AQ6E.js";
|
|
6
6
|
import "./globalPidIndex-DoaKEUkO.js";
|
|
7
7
|
import "./pidStore-B73xnAeT.js";
|
|
8
8
|
import "./messageLog-DdjBNqgt.js";
|
|
9
9
|
import "./todoStore-DF6vxHgV.js";
|
|
10
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
11
|
-
import { f as resolveSpawnCwd } from "./workspaceConfig-
|
|
12
|
-
import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-
|
|
10
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BlgVWZrM.js";
|
|
11
|
+
import { f as resolveSpawnCwd } from "./workspaceConfig-DTvPtr5j.js";
|
|
12
|
+
import { n as liveEnv, t as ensureNodeRuntime } from "./nodeRuntime-CipjIwfO.js";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
|
|
15
15
|
//#region ts/oxmgrService.ts
|
|
@@ -154,4 +154,4 @@ async function cmdSchedule(rest) {
|
|
|
154
154
|
|
|
155
155
|
//#endregion
|
|
156
156
|
export { cmdSchedule };
|
|
157
|
-
//# sourceMappingURL=schedule-
|
|
157
|
+
//# sourceMappingURL=schedule-pim0Izhs.js.map
|