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.
Files changed (56) hide show
  1. package/default.config.yaml +106 -0
  2. package/dist/{SUPPORTED_CLIS-BHowMgMY.js → SUPPORTED_CLIS-BlgVWZrM.js} +2 -2
  3. package/dist/{SUPPORTED_CLIS-ChhJyq4h.js → SUPPORTED_CLIS-C65PuIs6.js} +3 -3
  4. package/dist/{agentShare-T3RskvDT.js → agentShare-Cm15-dfZ.js} +3 -3
  5. package/dist/{callback-CuohbCJA.js → callback-Bbplrsbv.js} +3 -3
  6. package/dist/{callback-DeaETuHt.js → callback-Dwnkeqpz.js} +3 -3
  7. package/dist/cli.js +11 -11
  8. package/dist/cmdPs-BYBZQ0Vc.js +331 -0
  9. package/dist/{cwdConflictWarn-DIPD6HH5.js → cwdConflictWarn-BgXN56Jc.js} +1 -1
  10. package/dist/{cwdPassthroughHint-C0tfZlgZ.js → cwdPassthroughHint-CDEGVteh.js} +1 -1
  11. package/dist/{expose-Ds9aUFsq.js → expose-BlddYYx9.js} +1 -1
  12. package/dist/{forkNested-Dt5XP8ZH.js → forkNested-CJ7lQQCe.js} +1 -1
  13. package/dist/{hist-DSYaJEd3.js → hist-DZxq7NMA.js} +1 -1
  14. package/dist/index.js +2 -2
  15. package/dist/{initMsg-CeF4QNOM.js → initMsg-DoltWTZj.js} +1 -1
  16. package/dist/{initMsg-DejbYYjX.js → initMsg-axyQAPLK.js} +1 -1
  17. package/dist/{nodeRuntime-_zeWDISM.js → nodeRuntime-CipjIwfO.js} +1 -1
  18. package/dist/{notifyDaemon-BORqPeAl.js → notifyDaemon-Q3FF-WEZ.js} +47 -39
  19. package/dist/{openBrowser-BNP8xByu.js → openBrowser-THOzOGNm.js} +1 -1
  20. package/dist/{parentLink-Bv8ihRcu.js → parentLink-bpDGuQi6.js} +1 -1
  21. package/dist/{parentLink-HWunrH1s.js → parentLink-fdiuB13i.js} +1 -1
  22. package/dist/{parentPingLoop-COePRYr9.js → parentPingLoop-Dc7co5D7.js} +4 -4
  23. package/dist/{cmdPs-Bm4JG7hi.js → procStats-CyD8h5nx.js} +2 -329
  24. package/dist/{remotes-b6reVXzo.js → remotes-BjsglpjL.js} +2 -2
  25. package/dist/{remotes-BlHTR9ow.js → remotes-CAqtL_Ib.js} +1 -1
  26. package/dist/{rustBinary-BmXzqj5z.js → rustBinary-B57oRftk.js} +2 -2
  27. package/dist/{rustBinary-D12k7iOD.js → rustBinary-Dq0AytZ7.js} +2 -2
  28. package/dist/{schedule-DLoUmyJh.js → schedule-pim0Izhs.js} +6 -6
  29. package/dist/{serve-DaDlOtss.js → serve-CMsvjqPU.js} +174 -27
  30. package/dist/{setup-Cqy8nRrq.js → setup-BmxYINCx.js} +4 -4
  31. package/dist/{spawnGate-B2hA_2NQ.js → spawnGate-B26UnzqP.js} +2 -2
  32. package/dist/{spawnGate-FLwTAPW6.js → spawnGate-C8MSRt7X.js} +1 -1
  33. package/dist/{subcommands-DKTa3E6O.js → subcommands-CJBV06rg.js} +2 -2
  34. package/dist/{subcommands-BfiOyfz7.js → subcommands-CWDqhKQe.js} +21 -21
  35. package/dist/{systemPathLink-Dl2gJqeg.js → systemPathLink-BVdk48Vz.js} +1 -1
  36. package/dist/{terminal-C0tnGnrZ.js → terminal-CcmBzB3G.js} +2 -2
  37. package/dist/{todoCli-MWrejmdM.js → todoCli-azqbjBtz.js} +1 -1
  38. package/dist/{tray-BhPVpP_r.js → tray-CIt9mCKZ.js} +1 -1
  39. package/dist/trayApp-BovAZs7m.js +5 -0
  40. package/dist/{trayApp-DvL9qW6V.js → trayApp-DuZBkGl_.js} +2 -2
  41. package/dist/{ts-DJLp2_bv.js → ts-CSp4mJ7Z.js} +23 -9
  42. package/dist/{versionChecker-CkO7wYyV.js → versionChecker-CWCN4vwm.js} +2 -2
  43. package/dist/{webrtcRemote-H9Hok0_R.js → webrtcRemote-Bevc5ogS.js} +1 -1
  44. package/dist/{widget-CJqpScCG.js → widget-D2cCC8nz.js} +3 -3
  45. package/dist/{workspaceConfig-D6QndOCz.js → workspaceConfig-DTvPtr5j.js} +1 -1
  46. package/dist/{ws-DGENGNrr.js → ws-B5Qb2c-1.js} +3 -3
  47. package/dist/{ws-DzCKvzWD.js → ws-CyO9r4jx.js} +3 -3
  48. package/package.json +1 -1
  49. package/ts/agentNice.spec.ts +42 -2
  50. package/ts/index.ts +5 -4
  51. package/ts/notifyDaemon.spec.ts +16 -0
  52. package/ts/notifyDaemon.ts +22 -0
  53. package/ts/serve.ts +14 -0
  54. package/ts/serveSampler.spec.ts +390 -0
  55. package/ts/serveSampler.ts +218 -0
  56. package/dist/trayApp-BrAMlCY7.js +0 -5
@@ -334,6 +334,112 @@ clis:
334
334
  - --search
335
335
  noEOL: true
336
336
 
337
+ # codex-ds — the `codex` binary pointed at DeepSeek V4 Pro over OpenRouter
338
+ # instead of the built-in OpenAI models. Everything the provider needs rides
339
+ # in `defaultArgs` as `-c` overrides, so this works against a stock codex
340
+ # install with no `~/.codex/*.config.toml` of your own; the only external
341
+ # requirement is `OPENROUTER_API_KEY` in the environment (same shape as glm's
342
+ # ZAI_API_KEY). Get one at https://openrouter.ai/keys.
343
+ #
344
+ # Two codex-version constraints are baked into the override:
345
+ # - `wire_api` must be "responses"; codex >= 0.147 removed the "chat"
346
+ # wire protocol, and OpenRouter serves POST /api/v1/responses.
347
+ # - the provider table is passed inline rather than as a named profile,
348
+ # because codex >= 0.147 rejects a `[profiles.X]` table in config.toml
349
+ # and wants it in a separate `<X>.config.toml`.
350
+ #
351
+ # All drive markers below are copied from the `codex` block — same binary,
352
+ # same TUI — because per-CLI config does not inherit.
353
+ codex-ds:
354
+ binary: codex
355
+ promptArg: first-arg
356
+ defaultArgs:
357
+ - -c
358
+ - model_providers.openrouter={name="OpenRouter",base_url="https://openrouter.ai/api/v1",env_key="OPENROUTER_API_KEY",wire_api="responses"}
359
+ - -c
360
+ - model_provider="openrouter"
361
+ - -c
362
+ - model="deepseek/deepseek-v4-pro-0813"
363
+ - --search
364
+ yesArgs:
365
+ - --dangerously-bypass-approvals-and-sandbox
366
+ install:
367
+ npm: "npm install -g @openai/codex@latest"
368
+ help: https://openrouter.ai/deepseek/deepseek-v4-pro
369
+ updateAvailable:
370
+ - "^✨⬆️ Update available!"
371
+ ready:
372
+ - ⏎ send
373
+ - "› "
374
+ - '\? for shortcuts'
375
+ working:
376
+ - esc to interrupt
377
+ needsInput:
378
+ - pattern: '[›>] ?\d+\.'
379
+ flags: m
380
+ enter:
381
+ - pattern: '[›>] ?1\. ?Yes'
382
+ flags: m
383
+ - pattern: '[›>] ?1\. ?Approve'
384
+ flags: m
385
+ - pattern: '[›>] ?1\. ?Allow'
386
+ flags: m
387
+ fatal:
388
+ - "Error: The cursor position could not be read within"
389
+ noEOL: true
390
+
391
+
392
+ # codex-ds-direct — same idea as codex-ds, but pointed straight at DeepSeek's
393
+ # own endpoint instead of going through OpenRouter. DeepSeek gained native
394
+ # Responses API support in the 2026-08-13 V4 Pro update
395
+ # (https://api-docs.deepseek.com/guides/responses_api/), so no translating
396
+ # proxy is needed on this path either — one less hop and no reseller margin.
397
+ # Requires `DEEPSEEK_API_KEY`; get one at https://platform.deepseek.com.
398
+ #
399
+ # Model id differs from the OpenRouter route: DeepSeek's own /models lists
400
+ # exactly `deepseek-v4-flash` and `deepseek-v4-pro` — there are no dated
401
+ # snapshot ids here, so this uses the plain `deepseek-v4-pro`.
402
+ #
403
+ # Drive markers are copied from the `codex` block, as with codex-ds.
404
+ codex-ds-direct:
405
+ binary: codex
406
+ promptArg: first-arg
407
+ defaultArgs:
408
+ - -c
409
+ - model_providers.deepseek={name="DeepSeek",base_url="https://api.deepseek.com",env_key="DEEPSEEK_API_KEY",wire_api="responses"}
410
+ - -c
411
+ - model_provider="deepseek"
412
+ - -c
413
+ - model="deepseek-v4-pro"
414
+ - --search
415
+ yesArgs:
416
+ - --dangerously-bypass-approvals-and-sandbox
417
+ install:
418
+ npm: "npm install -g @openai/codex@latest"
419
+ help: https://api-docs.deepseek.com/guides/responses_api/
420
+ updateAvailable:
421
+ - "^✨⬆️ Update available!"
422
+ ready:
423
+ - ⏎ send
424
+ - "› "
425
+ - '\? for shortcuts'
426
+ working:
427
+ - esc to interrupt
428
+ needsInput:
429
+ - pattern: '[›>] ?\d+\.'
430
+ flags: m
431
+ enter:
432
+ - pattern: '[›>] ?1\. ?Yes'
433
+ flags: m
434
+ - pattern: '[›>] ?1\. ?Approve'
435
+ flags: m
436
+ - pattern: '[›>] ?1\. ?Allow'
437
+ flags: m
438
+ fatal:
439
+ - "Error: The cursor position could not be read within"
440
+ noEOL: true
441
+
442
+
337
443
  qwen:
338
444
  install:
339
445
  npm: "npm install -g @qwen-code/qwen-code@latest"
@@ -1,8 +1,8 @@
1
- import { t as CLIS_CONFIG } from "./ts-DJLp2_bv.js";
1
+ import { t as CLIS_CONFIG } from "./ts-CSp4mJ7Z.js";
2
2
 
3
3
  //#region ts/SUPPORTED_CLIS.ts
4
4
  const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
5
5
 
6
6
  //#endregion
7
7
  export { SUPPORTED_CLIS as t };
8
- //# sourceMappingURL=SUPPORTED_CLIS-BHowMgMY.js.map
8
+ //# sourceMappingURL=SUPPORTED_CLIS-BlgVWZrM.js.map
@@ -1,12 +1,12 @@
1
1
  import "./logger-CDIsZ-Pp.js";
2
- import "./versionChecker-CkO7wYyV.js";
3
- import "./ts-DJLp2_bv.js";
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-BHowMgMY.js";
10
+ import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BlgVWZrM.js";
11
11
 
12
12
  export { SUPPORTED_CLIS };
@@ -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 { z as resolveOne } from "./subcommands-BfiOyfz7.js";
6
+ import { z as resolveOne } from "./subcommands-CWDqhKQe.js";
7
7
  import "./notifyStore-2SWKGwZI.js";
8
8
  import "./webrtcLink-DLaJfTcB.js";
9
- import "./remotes-b6reVXzo.js";
9
+ import "./remotes-BjsglpjL.js";
10
10
  import { a as startShare } from "./share-DTlaFn6s.js";
11
11
 
12
12
  //#region ts/agentShare.ts
@@ -230,4 +230,4 @@ function transformEvent(rawEvent, agentId, forwarded) {
230
230
 
231
231
  //#endregion
232
232
  export { createScopedShare, listShares, revokeAllShares, revokeShare };
233
- //# sourceMappingURL=agentShare-T3RskvDT.js.map
233
+ //# sourceMappingURL=agentShare-Cm15-dfZ.js.map
@@ -1,5 +1,5 @@
1
1
  import { t as agentYesHome } from "./agentYesHome-BNtn19J4.js";
2
- import { z as resolveOne } from "./subcommands-BfiOyfz7.js";
2
+ import { z as resolveOne } from "./subcommands-CWDqhKQe.js";
3
3
  import { a as mintCapability, o as parseExpires } from "./callbackCore-Bl2gGcxg.js";
4
4
  import { randomBytes } from "node:crypto";
5
5
  import { chmodSync, readFileSync, renameSync, writeFileSync } from "node:fs";
@@ -72,7 +72,7 @@ async function resolveBase(flag) {
72
72
  if (flag) return flag;
73
73
  if (process.env.AGENT_YES_CALLBACK_BASE) return process.env.AGENT_YES_CALLBACK_BASE;
74
74
  try {
75
- const { resolveLocalServeUrl } = await import("./serve-DaDlOtss.js");
75
+ const { resolveLocalServeUrl } = await import("./serve-CMsvjqPU.js");
76
76
  const url = await resolveLocalServeUrl();
77
77
  if (url) return url;
78
78
  } catch {}
@@ -187,4 +187,4 @@ async function cmdCallback(rest) {
187
187
 
188
188
  //#endregion
189
189
  export { loadOrCreateCallbackSecret as i, isCallbackRevoked as n, loadCallbackSecretReadOnly as r, cmdCallback as t };
190
- //# sourceMappingURL=callback-CuohbCJA.js.map
190
+ //# sourceMappingURL=callback-Bbplrsbv.js.map
@@ -3,11 +3,11 @@ 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-BfiOyfz7.js";
6
+ import "./subcommands-CWDqhKQe.js";
7
7
  import "./notifyStore-2SWKGwZI.js";
8
8
  import "./webrtcLink-DLaJfTcB.js";
9
- import "./remotes-b6reVXzo.js";
9
+ import "./remotes-BjsglpjL.js";
10
10
  import "./callbackCore-Bl2gGcxg.js";
11
- import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-CuohbCJA.js";
11
+ import { i as loadOrCreateCallbackSecret, n as isCallbackRevoked, r as loadCallbackSecretReadOnly, t as cmdCallback } from "./callback-Bbplrsbv.js";
12
12
 
13
13
  export { cmdCallback };
package/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import { t as invokedCliName } from "./invokedCli-zdFbz1ST.js";
3
3
  import { n as logger } from "./logger-CDIsZ-Pp.js";
4
- import { a as versionString, r as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-CkO7wYyV.js";
5
- import { l as getRustBinary } from "./rustBinary-BmXzqj5z.js";
4
+ import { a as versionString, r as displayVersion, t as checkAndAutoUpdate } from "./versionChecker-CWCN4vwm.js";
5
+ import { l as getRustBinary } from "./rustBinary-B57oRftk.js";
6
6
  import { argv } from "process";
7
7
  import { spawn } from "child_process";
8
8
  import ms from "ms";
@@ -295,7 +295,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
295
295
  const rawArg = process.argv[2];
296
296
  const managerCommands = !invokedCliName(process.argv);
297
297
  const isHelpFlag = rawArg === "-h" || rawArg === "--help";
298
- const { isSubcommand, runSubcommand, cmdHelp, isUnknownManagerToken, isBareManagerInvocation } = await import("./subcommands-DKTa3E6O.js");
298
+ const { isSubcommand, runSubcommand, cmdHelp, isUnknownManagerToken, isBareManagerInvocation } = await import("./subcommands-CJBV06rg.js");
299
299
  if (isHelpFlag && process.argv.length === 3) {
300
300
  await cmdHelp(managerCommands);
301
301
  process.exit(0);
@@ -309,7 +309,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
309
309
  process.exit(code ?? 0);
310
310
  }
311
311
  {
312
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-ChhJyq4h.js");
312
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-C65PuIs6.js");
313
313
  if (isUnknownManagerToken(rawArg, managerCommands, SUPPORTED_CLIS)) {
314
314
  process.stderr.write(`ay: unknown subcommand or CLI '${rawArg}'.\n See 'ay help' for subcommands. To run an agent, name a CLI:\n 'ay <cli> …' (e.g. 'ay claude …') or 'ay --cli <cli> …'.\n`);
315
315
  process.exit(1);
@@ -317,7 +317,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
317
317
  }
318
318
  }
319
319
  {
320
- const { detectCwdPassthrough, SUPPRESS_CWD_WARN_ENV } = await import("./cwdPassthroughHint-C0tfZlgZ.js");
320
+ const { detectCwdPassthrough, SUPPRESS_CWD_WARN_ENV } = await import("./cwdPassthroughHint-CDEGVteh.js");
321
321
  const dep = detectCwdPassthrough(process.argv);
322
322
  if (dep) {
323
323
  console.warn(dep.message);
@@ -328,16 +328,16 @@ await checkAndAutoUpdate();
328
328
  logger.info(versionString());
329
329
  const config = parseCliArgs(process.argv);
330
330
  if (config.tray) {
331
- const { startTray } = await import("./tray-BhPVpP_r.js");
331
+ const { startTray } = await import("./tray-CIt9mCKZ.js");
332
332
  await startTray();
333
333
  await new Promise(() => {});
334
334
  }
335
335
  {
336
- const { ensureTray } = await import("./tray-BhPVpP_r.js");
336
+ const { ensureTray } = await import("./tray-CIt9mCKZ.js");
337
337
  ensureTray();
338
338
  }
339
339
  if (!config.showVersion && !config.appendPrompt && !config.tray) {
340
- const { waitForSpawnCapacity } = await import("./spawnGate-FLwTAPW6.js");
340
+ const { waitForSpawnCapacity } = await import("./spawnGate-C8MSRt7X.js");
341
341
  await waitForSpawnCapacity({
342
342
  onWait: (reason, waitedMs) => {
343
343
  if (config.verbose || waitedMs === 0) console.error(`[agent-yes] spawn gate: ${reason} — waiting…`);
@@ -346,7 +346,7 @@ if (!config.showVersion && !config.appendPrompt && !config.tray) {
346
346
  });
347
347
  }
348
348
  if (!config.showVersion && !config.appendPrompt && !config.tray) {
349
- const { warnIfCwdOccupied } = await import("./cwdConflictWarn-DIPD6HH5.js");
349
+ const { warnIfCwdOccupied } = await import("./cwdConflictWarn-BgXN56Jc.js");
350
350
  await warnIfCwdOccupied(process.argv);
351
351
  }
352
352
  if (config.useRust) {
@@ -360,14 +360,14 @@ if (config.useRust) {
360
360
  }
361
361
  }
362
362
  if (rustBinary) {
363
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-ChhJyq4h.js");
363
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-C65PuIs6.js");
364
364
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
365
365
  if (config.verbose) {
366
366
  console.log(`[rust] Using binary: ${rustBinary}`);
367
367
  console.log(`[rust] Args: ${rustArgs.join(" ")}`);
368
368
  }
369
369
  const attach = config.attach || process.env.AGENT_YES_ATTACH === "1";
370
- const { shouldForkNested, buildSpawnTutorial, waitForRegistration, confirmAgentStarted, predictedLogPath } = await import("./forkNested-Dt5XP8ZH.js");
370
+ const { shouldForkNested, buildSpawnTutorial, waitForRegistration, confirmAgentStarted, predictedLogPath } = await import("./forkNested-CJ7lQQCe.js");
371
371
  if (shouldForkNested({
372
372
  isTTY: Boolean(process.stdout.isTTY),
373
373
  ayPid: process.env.AGENT_YES_PID,
@@ -0,0 +1,331 @@
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-CWDqhKQe.js";
7
+ import "./notifyStore-2SWKGwZI.js";
8
+ import "./webrtcLink-DLaJfTcB.js";
9
+ import "./remotes-BjsglpjL.js";
10
+ import { i as systemStats, n as sampleTrees, r as snapshotProcs, t as humanBytes } from "./procStats-CyD8h5nx.js";
11
+ import yargs from "yargs";
12
+ import { readFileSync } from "node:fs";
13
+ import path from "node:path";
14
+ import { homedir } from "node:os";
15
+
16
+ //#region ts/cmdPs.ts
17
+ /**
18
+ * `ay ps` — what each agent COSTS, rolled up per process tree.
19
+ *
20
+ * The split from `ay ls`: `ls` answers "what is running and what is it doing"
21
+ * (prompt, git, badges, forest); `ps` answers "what is this box spending on
22
+ * each agent, and is any of it safe to reclaim". Same rows, different question.
23
+ *
24
+ * `ps` used to be a plain alias for `ls`. It is now its own command, because the
25
+ * number you actually want is not in any `ps`/`htop` output: one agent is a
26
+ * whole subtree of wrapper + CLI + pty hosts + subagents, and only ay knows
27
+ * which pids collapse into which session.
28
+ *
29
+ * Deliberately local-only. Resource numbers are per-machine and there is nothing
30
+ * meaningful to sum across remotes; `ay ls` remains the fleet-wide view.
31
+ */
32
+ /** Default CPU sampling window. Long enough to be meaningful, short enough to feel instant. */
33
+ const DEFAULT_WINDOW_MS = 1e3;
34
+ function shortenPath(p) {
35
+ const home = homedir();
36
+ return p.startsWith(home) ? "~" + p.slice(home.length) : p;
37
+ }
38
+ /** Trailing path segment that identifies a worktree — `/code/x/foo/tree/main` → `foo`. */
39
+ function repoLabel(cwd) {
40
+ const parts = cwd.split(/[\\/]+/).filter(Boolean);
41
+ const treeAt = parts.lastIndexOf("tree");
42
+ if (treeAt > 0) return parts[treeAt - 1];
43
+ return parts[parts.length - 1] ?? shortenPath(cwd);
44
+ }
45
+ /** `15.23 12.52 9.86 (8 cpu, 1.9x) mem 13.0/15Gi swap 4.8/4.8Gi FULL zombies 1440` */
46
+ function formatSystemLine(sys) {
47
+ const bits = [];
48
+ if (sys.load) {
49
+ const [one, five, fifteen] = sys.load;
50
+ const ratio = one / Math.max(1, sys.ncpu);
51
+ bits.push(`load ${one.toFixed(2)} ${five.toFixed(2)} ${fifteen.toFixed(2)} (${sys.ncpu} cpu, ${ratio.toFixed(1)}x)`);
52
+ }
53
+ if (sys.memTotalBytes !== null) {
54
+ const used = sys.memAvailableBytes !== null ? sys.memTotalBytes - sys.memAvailableBytes : null;
55
+ bits.push(`mem ${humanBytes(used)}/${humanBytes(sys.memTotalBytes)}`);
56
+ }
57
+ if (sys.swapTotalBytes !== null && sys.swapTotalBytes > 0) {
58
+ const usedSwap = sys.swapFreeBytes !== null ? sys.swapTotalBytes - sys.swapFreeBytes : null;
59
+ const full = sys.swapFreeBytes !== null && sys.swapFreeBytes <= 0 ? " FULL" : "";
60
+ bits.push(`swap ${humanBytes(usedSwap)}/${humanBytes(sys.swapTotalBytes)}${full}`);
61
+ }
62
+ if (sys.zombies > 0) bits.push(`zombies ${sys.zombies}`);
63
+ return bits.join(" ");
64
+ }
65
+ /**
66
+ * Roll each row up with its descendants, using the forest `depth` column: a
67
+ * row's descendants are the following rows with a strictly greater depth, up to
68
+ * the next row at or above its own level.
69
+ *
70
+ * Needed because sampleTrees attributes DEEPEST-FIRST and exclusively — a
71
+ * parent's own numbers deliberately omit its subagents, so without this a
72
+ * fan-out parent looks cheap while its real cost sits in rows below it.
73
+ *
74
+ * Returns null for a row with no descendants.
75
+ */
76
+ function subtreeTotals(rows) {
77
+ return rows.map((r, i) => {
78
+ const depth = r.depth ?? 0;
79
+ const own = r.stats;
80
+ if (!own) return null;
81
+ let rss = own.rss;
82
+ let cpuPercent = own.cpuPercent;
83
+ let procs = own.procs;
84
+ let found = false;
85
+ for (let j = i + 1; j < rows.length; j++) {
86
+ if ((rows[j]?.depth ?? 0) <= depth) break;
87
+ const st = rows[j]?.stats;
88
+ if (!st) continue;
89
+ found = true;
90
+ rss += st.rss;
91
+ cpuPercent += st.cpuPercent;
92
+ procs += st.procs;
93
+ }
94
+ return found ? {
95
+ pid: own.pid,
96
+ rss,
97
+ cpuPercent,
98
+ procs
99
+ } : null;
100
+ });
101
+ }
102
+ function pad(s, n) {
103
+ return s.length >= n ? s : s + " ".repeat(n - s.length);
104
+ }
105
+ function padStart(s, n) {
106
+ return s.length >= n ? s : " ".repeat(n - s.length) + s;
107
+ }
108
+ function renderTable(rows, unattributed, opts = {}) {
109
+ const tree = opts.tree === true;
110
+ const showProcs = opts.procs === true;
111
+ const cells = rows.map((r) => ({
112
+ pid: (tree ? r.prefix ?? "" : "") + String(r.pid),
113
+ cli: r.cli,
114
+ status: r.status,
115
+ cpu: r.stats.cpuPercent.toFixed(1),
116
+ rss: humanBytes(r.stats.rss),
117
+ procs: String(r.stats.procs),
118
+ repo: r.repo,
119
+ cwd: shortenPath(r.cwd),
120
+ scpu: r.subtree ? r.subtree.cpuPercent.toFixed(1) : "",
121
+ srss: r.subtree ? humanBytes(r.subtree.rss) : "",
122
+ sprocs: r.subtree ? String(r.subtree.procs) : "",
123
+ self: r.self
124
+ }));
125
+ if (unattributed && unattributed.procs > 0) cells.push({
126
+ pid: "-",
127
+ cli: "unmanaged",
128
+ status: "-",
129
+ cpu: unattributed.cpuPercent.toFixed(1),
130
+ rss: humanBytes(unattributed.rss),
131
+ procs: String(unattributed.procs),
132
+ repo: "-",
133
+ cwd: "-",
134
+ scpu: "",
135
+ srss: "",
136
+ sprocs: "",
137
+ self: false
138
+ });
139
+ const w = {
140
+ pid: Math.max(3, ...cells.map((c) => c.pid.length)),
141
+ cli: Math.max(3, ...cells.map((c) => c.cli.length)),
142
+ status: Math.max(6, ...cells.map((c) => c.status.length)),
143
+ cpu: Math.max(5, ...cells.map((c) => c.cpu.length)),
144
+ rss: Math.max(5, ...cells.map((c) => c.rss.length)),
145
+ procs: Math.max(5, ...cells.map((c) => c.procs.length)),
146
+ repo: Math.max(4, ...cells.map((c) => c.repo.length)),
147
+ scpu: Math.max(5, ...cells.map((c) => c.scpu.length)),
148
+ srss: Math.max(5, ...cells.map((c) => c.srss.length)),
149
+ sprocs: Math.max(6, ...cells.map((c) => c.sprocs.length))
150
+ };
151
+ 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}`;
152
+ const out = [line("PID", "CLI", "STATUS", "CPU%", "RSS", "PROCS", "REPO", "CWD", "ΣCPU%", "ΣRSS", "ΣPROCS")];
153
+ cells.forEach((c, i) => {
154
+ 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" : ""));
155
+ const kids = rows[i]?.procRows;
156
+ if (!showProcs || !kids?.length) return;
157
+ const indent = " ".repeat((tree ? (rows[i]?.prefix ?? "").length : 0) + 2);
158
+ const pw = Math.max(...kids.map((k) => String(k.pid).length));
159
+ const cw = Math.max(...kids.map((k) => k.comm.length));
160
+ 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" : ""));
161
+ });
162
+ return out.join("\n");
163
+ }
164
+ async function cmdPs(rest) {
165
+ 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", {
166
+ type: "boolean",
167
+ default: false,
168
+ description: "Include exited agents"
169
+ }).option("json", {
170
+ type: "boolean",
171
+ default: false,
172
+ description: "Output as JSON"
173
+ }).option("sort", {
174
+ type: "string",
175
+ choices: [
176
+ "rss",
177
+ "cpu",
178
+ "procs",
179
+ "pid"
180
+ ],
181
+ default: "rss",
182
+ description: "Sort rows by resource usage (default: rss, biggest first)"
183
+ }).option("tree", {
184
+ type: "boolean",
185
+ default: false,
186
+ description: "Forest order with ├─ rails, plus Σ columns rolling each agent up with its subagents"
187
+ }).option("procs", {
188
+ type: "boolean",
189
+ default: false,
190
+ description: "Expand each agent into the OS processes it owns (wrapper, CLI, shells)"
191
+ }).option("interval", {
192
+ type: "number",
193
+ default: DEFAULT_WINDOW_MS / 1e3,
194
+ description: "CPU sampling window in seconds — CPU% is a live delta, not a lifetime average"
195
+ }).option("cwd", {
196
+ type: "string",
197
+ description: "Restrict to agents whose cwd starts with dir"
198
+ }).option("help", {
199
+ alias: "h",
200
+ type: "boolean",
201
+ default: false,
202
+ description: "Show this help"
203
+ }).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);
204
+ const argv = await y.parseAsync();
205
+ if (argv.help || argv.h) {
206
+ process.stdout.write(await y.getHelp() + "\n");
207
+ return 0;
208
+ }
209
+ const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
210
+ const records = await listRecords(keyword, {
211
+ all: argv.all,
212
+ active: false,
213
+ json: false,
214
+ latest: false,
215
+ cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
216
+ });
217
+ if (records.length === 0) {
218
+ process.stderr.write(keyword ? `no agents matched "${keyword}"\n` : "no running agents\n");
219
+ return 0;
220
+ }
221
+ const flat = flattenForest(buildAgentForest(records));
222
+ const ordered = flat.map((r) => r.record);
223
+ const windowMs = Math.max(100, (Number.isFinite(argv.interval) ? argv.interval : 1) * 1e3);
224
+ const { trees, unattributed, members } = await sampleTrees([...ordered].reverse().map((r) => r.pid), { windowMs });
225
+ const states = new Map(await Promise.all(ordered.map(async (r) => [r.pid, (await deriveLiveState(r)).state])));
226
+ const selfPid = process.pid;
227
+ const rows = ordered.map((r, i) => ({
228
+ pid: r.pid,
229
+ cli: r.cli,
230
+ status: states.get(r.pid) ?? r.status,
231
+ cwd: r.cwd,
232
+ repo: repoLabel(r.cwd),
233
+ stats: trees.get(r.pid) ?? {
234
+ pid: r.pid,
235
+ rss: 0,
236
+ cpuPercent: 0,
237
+ procs: 0
238
+ },
239
+ self: trees.get(r.pid) !== void 0 && isSelfTree(r.pid, selfPid),
240
+ prefix: flat[i]?.prefix ?? "",
241
+ depth: flat[i]?.depth ?? 0
242
+ }));
243
+ if (argv.tree) {
244
+ const totals = subtreeTotals(rows);
245
+ rows.forEach((r, i) => {
246
+ r.subtree = totals[i] ?? null;
247
+ });
248
+ }
249
+ if (argv.procs) for (const r of rows) r.procRows = [...members?.get(r.pid) ?? []].sort((x, y) => y.rss - x.rss);
250
+ if (!argv.tree) {
251
+ const key = String(argv.sort);
252
+ rows.sort((a, b) => {
253
+ if (key === "cpu") return b.stats.cpuPercent - a.stats.cpuPercent;
254
+ if (key === "procs") return b.stats.procs - a.stats.procs;
255
+ if (key === "pid") return a.pid - b.pid;
256
+ return b.stats.rss - a.stats.rss;
257
+ });
258
+ }
259
+ const sys = await systemStats(await snapshotProcs());
260
+ if (argv.json) {
261
+ process.stdout.write(JSON.stringify({
262
+ system: sys,
263
+ agents: rows.map((r) => ({
264
+ pid: r.pid,
265
+ cli: r.cli,
266
+ status: r.status,
267
+ cwd: r.cwd,
268
+ rssBytes: r.stats.rss,
269
+ cpuPercent: Number(r.stats.cpuPercent.toFixed(2)),
270
+ procs: r.stats.procs,
271
+ self: r.self
272
+ })),
273
+ unattributed: {
274
+ rssBytes: unattributed.rss,
275
+ cpuPercent: Number(unattributed.cpuPercent.toFixed(2)),
276
+ procs: unattributed.procs
277
+ }
278
+ }, null, 2) + "\n");
279
+ return 0;
280
+ }
281
+ const header = formatSystemLine(sys);
282
+ if (header) process.stdout.write(` ${header}\n\n`);
283
+ process.stdout.write(renderTable(rows, unattributed, {
284
+ tree: argv.tree === true,
285
+ procs: argv.procs === true
286
+ }) + "\n");
287
+ return 0;
288
+ }
289
+ /**
290
+ * Is `rootPid` the wrapper of the tree this very process lives in?
291
+ *
292
+ * Walks our own ancestry rather than the snapshot: cheap, and correct even when
293
+ * the snapshot raced. Linux-only detail (reads /proc), returns false elsewhere —
294
+ * mislabelling the self row is cosmetic.
295
+ */
296
+ function isSelfTree(rootPid, selfPid, readPpid = readPpidSync, platform = process.platform) {
297
+ if (platform !== "linux") return false;
298
+ let pid = selfPid;
299
+ for (let hops = 0; hops < 64 && pid > 1; hops++) {
300
+ if (pid === rootPid) return true;
301
+ const ppid = readPpid(pid);
302
+ if (ppid === null) return false;
303
+ pid = ppid;
304
+ }
305
+ return false;
306
+ }
307
+ /**
308
+ * ppid out of one `/proc/<pid>/stat` line.
309
+ *
310
+ * Split from the read so the parsing — the part that can actually be wrong — is
311
+ * testable on hosts without /proc. Field 2 is `comm`, wrapped in parens and NOT
312
+ * escaped: a process named `foo) bar (baz` is legal, so the fields after it can
313
+ * only be found from the LAST `)`, never by splitting on whitespace.
314
+ */
315
+ function parsePpidFromStat(stat) {
316
+ const close = stat.lastIndexOf(")");
317
+ if (close < 0) return null;
318
+ const ppid = Number(stat.slice(close + 1).trim().split(/\s+/)[1]);
319
+ return Number.isFinite(ppid) ? ppid : null;
320
+ }
321
+ function readPpidSync(pid) {
322
+ try {
323
+ return parsePpidFromStat(readFileSync(`/proc/${pid}/stat`, "utf8"));
324
+ } catch {
325
+ return null;
326
+ }
327
+ }
328
+
329
+ //#endregion
330
+ export { cmdPs };
331
+ //# sourceMappingURL=cmdPs-BYBZQ0Vc.js.map
@@ -61,4 +61,4 @@ async function warnIfCwdOccupied(rawArgv) {
61
61
 
62
62
  //#endregion
63
63
  export { warnIfCwdOccupied };
64
- //# sourceMappingURL=cwdConflictWarn-DIPD6HH5.js.map
64
+ //# sourceMappingURL=cwdConflictWarn-BgXN56Jc.js.map
@@ -85,4 +85,4 @@ function detectCwdPassthrough(argv) {
85
85
 
86
86
  //#endregion
87
87
  export { SUPPRESS_CWD_WARN_ENV, detectCwdPassthrough };
88
- //# sourceMappingURL=cwdPassthroughHint-C0tfZlgZ.js.map
88
+ //# sourceMappingURL=cwdPassthroughHint-CDEGVteh.js.map
@@ -549,4 +549,4 @@ async function cmdExpose(args) {
549
549
 
550
550
  //#endregion
551
551
  export { cmdExpose, ensureExposure, listExposures, stopExposure };
552
- //# sourceMappingURL=expose-Ds9aUFsq.js.map
552
+ //# sourceMappingURL=expose-BlddYYx9.js.map
@@ -141,4 +141,4 @@ async function confirmAgentStarted(pid, graceMs = 1500, aborted) {
141
141
 
142
142
  //#endregion
143
143
  export { buildSpawnTutorial, confirmAgentStarted, predictedLogPath, shouldForkNested, waitForRegistration };
144
- //# sourceMappingURL=forkNested-Dt5XP8ZH.js.map
144
+ //# sourceMappingURL=forkNested-CJ7lQQCe.js.map
@@ -439,4 +439,4 @@ async function cmdHist(rest) {
439
439
 
440
440
  //#endregion
441
441
  export { cmdHist };
442
- //# sourceMappingURL=hist-DSYaJEd3.js.map
442
+ //# sourceMappingURL=hist-DZxq7NMA.js.map
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./logger-CDIsZ-Pp.js";
2
- import "./versionChecker-CkO7wYyV.js";
3
- import { a as hasTodoStore, i as answerAsk, l as AgentContext, n as agentYes, o as listAsks, r as config, s as listAsksForProject, t as CLIS_CONFIG } from "./ts-DJLp2_bv.js";
2
+ import "./versionChecker-CWCN4vwm.js";
3
+ import { a as hasTodoStore, i as answerAsk, l as AgentContext, n as agentYes, o as listAsks, r as config, s as listAsksForProject, t as CLIS_CONFIG } from "./ts-CSp4mJ7Z.js";
4
4
  import { a as renderTree, c as describeBlock, i as renderDigest, l as monitorHint, o as unblockedTasks, r as openBlockers, t as reconcileTodos, u as removeControlCharacters } from "./todoAutomation-CbVVS4re.js";
5
5
  import "./JsonlStore-BqF7AQ6E.js";
6
6
  import "./globalPidIndex-DoaKEUkO.js";
@@ -1,3 +1,3 @@
1
- import { n as replyTargetOf, r as shortenHome, t as buildInitMsg } from "./initMsg-DejbYYjX.js";
1
+ import { n as replyTargetOf, r as shortenHome, t as buildInitMsg } from "./initMsg-axyQAPLK.js";
2
2
 
3
3
  export { buildInitMsg };
@@ -86,4 +86,4 @@ function buildInitMsg(prompt, spawner, nonce, identity) {
86
86
 
87
87
  //#endregion
88
88
  export { replyTargetOf as n, shortenHome as r, buildInitMsg as t };
89
- //# sourceMappingURL=initMsg-DejbYYjX.js.map
89
+ //# sourceMappingURL=initMsg-axyQAPLK.js.map