agent-yes 1.140.2 → 1.142.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-BKX1tigt.js +8 -0
- package/dist/{SUPPORTED_CLIS-CTOnaXTX.js → SUPPORTED_CLIS-C03sKqhu.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/index.js +2 -2
- package/dist/{schedule-DZb7ZQgW.js → schedule-BB_gXj7p.js} +4 -4
- package/dist/{serve-BBwXw8gY.js → serve-B8tHXvH2.js} +5 -5
- package/dist/{setup-S9LoYWK5.js → setup-DKF0uPs6.js} +2 -2
- package/dist/subcommands-DyhY1zTt.js +7 -0
- package/dist/{subcommands-Cz7-sHOT.js → subcommands-OKH2CsBu.js} +143 -19
- package/dist/{ts-B1-x2rKP.js → ts-DkAVuuIK.js} +2 -2
- package/dist/{versionChecker-Bhn4NygE.js → versionChecker-Dl2LrFFo.js} +2 -2
- package/package.json +1 -1
- package/ts/lsWatch.ts +1 -1
- package/ts/needsInput.spec.ts +20 -1
- package/ts/needsInput.ts +14 -0
- package/ts/subcommands.spec.ts +147 -0
- package/ts/subcommands.ts +0 -0
- package/dist/SUPPORTED_CLIS-DYcaH-bR.js +0 -8
- package/dist/subcommands-DKizMTs9.js +0 -7
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-DkAVuuIK.js";
|
|
2
|
+
import "./logger-CDIsZ-Pp.js";
|
|
3
|
+
import "./versionChecker-Dl2LrFFo.js";
|
|
4
|
+
import "./pidStore-fqXqTKkh.js";
|
|
5
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-C03sKqhu.js";
|
|
7
|
+
|
|
8
|
+
export { SUPPORTED_CLIS };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { t as CLIS_CONFIG } from "./ts-DkAVuuIK.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-
|
|
8
|
+
//# sourceMappingURL=SUPPORTED_CLIS-C03sKqhu.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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 { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
4
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-Dl2LrFFo.js";
|
|
5
5
|
import { argv } from "process";
|
|
6
6
|
import { execFileSync, spawn } from "child_process";
|
|
7
7
|
import ms from "ms";
|
|
@@ -480,7 +480,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
480
480
|
const rawArg = process.argv[2];
|
|
481
481
|
const managerCommands = !invokedCliName(process.argv);
|
|
482
482
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
483
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
483
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-DyhY1zTt.js");
|
|
484
484
|
if (isHelpFlag && process.argv.length === 3) {
|
|
485
485
|
cmdHelp(managerCommands);
|
|
486
486
|
process.exit(0);
|
|
@@ -513,7 +513,7 @@ if (config.useRust) {
|
|
|
513
513
|
}
|
|
514
514
|
}
|
|
515
515
|
if (rustBinary) {
|
|
516
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
516
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-BKX1tigt.js");
|
|
517
517
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
518
518
|
if (config.verbose) {
|
|
519
519
|
console.log(`[rust] Using binary: ${rustBinary}`);
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-
|
|
1
|
+
import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-DkAVuuIK.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-Dl2LrFFo.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-DkAVuuIK.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-Dl2LrFFo.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-C03sKqhu.js";
|
|
7
7
|
import { n as resolveSpawnCwd } from "./workspaceConfig-BCOqRBEW.js";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
|
|
@@ -141,4 +141,4 @@ async function cmdSchedule(rest) {
|
|
|
141
141
|
|
|
142
142
|
//#endregion
|
|
143
143
|
export { cmdSchedule };
|
|
144
|
-
//# sourceMappingURL=schedule-
|
|
144
|
+
//# sourceMappingURL=schedule-BB_gXj7p.js.map
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-DkAVuuIK.js";
|
|
2
2
|
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-Dl2LrFFo.js";
|
|
4
4
|
import "./pidStore-fqXqTKkh.js";
|
|
5
5
|
import { a as updateGlobalPidStatus } from "./globalPidIndex-DlmmJlO8.js";
|
|
6
6
|
import { t as pgidForWrapper } from "./reaper-C-eWAxIj.js";
|
|
7
7
|
import "./configShared-C1C04bbq.js";
|
|
8
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
8
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-C03sKqhu.js";
|
|
9
9
|
import "./remotes-PKKjfTI1.js";
|
|
10
|
-
import { S as
|
|
10
|
+
import { S as snapshotStatus, _ as renderRawLog, c as extractTaskCounts, g as readNotes, i as controlCodeFromName, m as listRecords, o as deriveLiveStatus, w as writeToIpc, y as resolveOne } from "./subcommands-OKH2CsBu.js";
|
|
11
11
|
import yargs from "yargs";
|
|
12
12
|
import { mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
13
13
|
import { homedir, hostname, userInfo } from "os";
|
|
@@ -1175,4 +1175,4 @@ Options:
|
|
|
1175
1175
|
|
|
1176
1176
|
//#endregion
|
|
1177
1177
|
export { cmdServe };
|
|
1178
|
-
//# sourceMappingURL=serve-
|
|
1178
|
+
//# sourceMappingURL=serve-B8tHXvH2.js.map
|
|
@@ -32,7 +32,7 @@ async function cmdSetup(rest) {
|
|
|
32
32
|
if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
|
|
33
33
|
if (noShare) return 0;
|
|
34
34
|
process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
|
|
35
|
-
const { cmdServe } = await import("./serve-
|
|
35
|
+
const { cmdServe } = await import("./serve-B8tHXvH2.js");
|
|
36
36
|
return cmdServe([
|
|
37
37
|
"install",
|
|
38
38
|
"--share",
|
|
@@ -42,4 +42,4 @@ async function cmdSetup(rest) {
|
|
|
42
42
|
|
|
43
43
|
//#endregion
|
|
44
44
|
export { cmdSetup };
|
|
45
|
-
//# sourceMappingURL=setup-
|
|
45
|
+
//# sourceMappingURL=setup-DKF0uPs6.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import "./logger-CDIsZ-Pp.js";
|
|
2
|
+
import "./globalPidIndex-DlmmJlO8.js";
|
|
3
|
+
import "./configShared-C1C04bbq.js";
|
|
4
|
+
import "./remotes-PKKjfTI1.js";
|
|
5
|
+
import { C as stopTipForCli, S as snapshotStatus, _ as renderRawLog, a as cursorAbs, b as resolveReadWindow, c as extractTaskCounts, d as isExitRequest, f as isPidAlive, g as readNotes, h as matchKeyword, i as controlCodeFromName, l as finalizedLines, m as listRecords, n as READ_PAGE_DEFAULT, o as deriveLiveStatus, p as isSubcommand, r as cmdHelp, s as extractNeedsInput, t as GRACEFUL_EXIT_COMMANDS, u as isAgentStuck, v as renderRawLogLines, w as writeToIpc, x as runSubcommand, y as resolveOne } from "./subcommands-OKH2CsBu.js";
|
|
6
|
+
|
|
7
|
+
export { cmdHelp, isSubcommand, runSubcommand };
|
|
@@ -182,6 +182,19 @@ function classifyNeedsInput(lines, cfg) {
|
|
|
182
182
|
const end = Math.min(lines.length, last + 6);
|
|
183
183
|
return { question: lines.slice(start, end).map((l) => l.trim()).filter((l) => l && !isChromeLine(l)).join(" • ").slice(0, 400) };
|
|
184
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* True when the rendered screen still shows a "busy" marker (config `working`,
|
|
187
|
+
* e.g. claude's `esc to interrupt`). Paired with a long-quiet log this is the
|
|
188
|
+
* `stuck` signal: a live spinner writes to the log every frame, so a busy marker
|
|
189
|
+
* on screen WITHOUT recent output means the agent wedged mid-stream (a silent
|
|
190
|
+
* API stream stall) rather than finishing. Pure + synchronous like the rest of
|
|
191
|
+
* this module so it's trivially unit-testable.
|
|
192
|
+
*/
|
|
193
|
+
function isWorkingScreen(lines, working) {
|
|
194
|
+
if (!working?.length) return false;
|
|
195
|
+
const text = lines.join("\n");
|
|
196
|
+
return working.some((re) => reTest(re, text));
|
|
197
|
+
}
|
|
185
198
|
|
|
186
199
|
//#endregion
|
|
187
200
|
//#region ts/lsWatch.ts
|
|
@@ -488,6 +501,7 @@ const SUBCOMMANDS = new Set([
|
|
|
488
501
|
"send",
|
|
489
502
|
"attach",
|
|
490
503
|
"stop",
|
|
504
|
+
"exit",
|
|
491
505
|
"restart",
|
|
492
506
|
"note",
|
|
493
507
|
"serve",
|
|
@@ -498,6 +512,10 @@ const SUBCOMMANDS = new Set([
|
|
|
498
512
|
]);
|
|
499
513
|
const MANAGER_SUBCOMMANDS = new Set(["setup"]);
|
|
500
514
|
const IDLE_THRESHOLD_MS = 60 * 1e3;
|
|
515
|
+
const STUCK_THRESHOLD_MS = (() => {
|
|
516
|
+
const n = Number(process.env.AGENT_YES_STUCK_MS);
|
|
517
|
+
return Number.isFinite(n) && n > 0 ? n : 300 * 1e3;
|
|
518
|
+
})();
|
|
501
519
|
/**
|
|
502
520
|
* Whether `name` is a subcommand. `managerCommands` (default true, for the
|
|
503
521
|
* generic `ay`/`agent-yes` entry) additionally admits manager-only commands
|
|
@@ -531,18 +549,19 @@ async function runSubcommand(argv) {
|
|
|
531
549
|
case "send": return await cmdSend(rest);
|
|
532
550
|
case "attach": return await cmdAttach(rest);
|
|
533
551
|
case "stop": return await cmdStop(rest);
|
|
552
|
+
case "exit": return await cmdExit(rest);
|
|
534
553
|
case "restart": return await cmdRestart(rest);
|
|
535
554
|
case "note": return await cmdNote(rest);
|
|
536
555
|
case "serve": {
|
|
537
|
-
const { cmdServe } = await import("./serve-
|
|
556
|
+
const { cmdServe } = await import("./serve-B8tHXvH2.js");
|
|
538
557
|
return cmdServe(rest);
|
|
539
558
|
}
|
|
540
559
|
case "setup": {
|
|
541
|
-
const { cmdSetup } = await import("./setup-
|
|
560
|
+
const { cmdSetup } = await import("./setup-DKF0uPs6.js");
|
|
542
561
|
return cmdSetup(rest);
|
|
543
562
|
}
|
|
544
563
|
case "schedule": {
|
|
545
|
-
const { cmdSchedule } = await import("./schedule-
|
|
564
|
+
const { cmdSchedule } = await import("./schedule-BB_gXj7p.js");
|
|
546
565
|
return cmdSchedule(rest);
|
|
547
566
|
}
|
|
548
567
|
case "remote": {
|
|
@@ -563,7 +582,7 @@ async function runSubcommand(argv) {
|
|
|
563
582
|
}
|
|
564
583
|
function cmdHelp(managerCommands = true) {
|
|
565
584
|
const setupLine = managerCommands ? ` ay setup guided setup: pick a workspace, share to agent-yes.com\n` : ``;
|
|
566
|
-
process.stdout.write("ay - agent-yes CLI\n\nManagement:\n ay ls [keyword] list running agents\n ay tail [-f] [-n N] <keyword> last N lines (96), -f to follow\n ay read <keyword> [page opts] paginate: --last/--head N, --range A:B,\n --before-line L [--limit N]\n ay cat <keyword> full log\n ay head <keyword> first N lines\n ay send <keyword> <msg> send a message\n ay attach <keyword> interactive attach (detach: Ctrl-\\)\n ay stop <keyword> graceful shutdown (/exit for claude/codex)\n ay status <keyword> agent status snapshot\n ay result <keyword> [--wait] pull an agent's structured result envelope\n ay result set '<json>' (inside an agent) deposit your result envelope\n ay reap kill process groups leaked by dead agents\n\nRemote:\n" + setupLine + " ay schedule <when> <cli> -- <msg> run an agent on a schedule (HH:MM or cron)\n ay serve [--port N] start HTTP API server (prints token)\n ay serve status show serve daemon/server status\n ay remote add <alias> http://<token>@<host>:<port>\n ay remote ls / rm <alias> manage saved remotes\n ay ls <token>@<host>:<port> connect inline (no alias needed)\n ay send <token>@<host>:<port>:<kw> <msg>\n\nRun an agent:\n ay [claude|codex|gemini|...] [options] -- [prompt]\n ay claude -- \"fix the bug in auth.ts\"\n ay claude --help full agent-runner options\n\nLabs (examples at https://github.com/snomiao/agent-yes/tree/main/lab):\n local-role-play/ designer + builder on one machine\n http-remote/ ay serve remote access demo\n p2p-pairing/ libp2p P2P (needs: cargo build --features swarm)\n");
|
|
585
|
+
process.stdout.write("ay - agent-yes CLI\n\nManagement:\n ay ls [keyword] list running agents\n ay tail [-f] [-n N] <keyword> last N lines (96), -f to follow\n ay read <keyword> [page opts] paginate: --last/--head N, --range A:B,\n --before-line L [--limit N]\n ay cat <keyword> full log\n ay head <keyword> first N lines\n ay send <keyword> <msg> send a message\n ay attach <keyword> interactive attach (detach: Ctrl-\\)\n ay stop <keyword> graceful shutdown (/exit for claude/codex)\n ay exit <keyword> [reason] graceful shutdown, recording who/why (= 'ay send <kw> exit')\n ay status <keyword> agent status snapshot\n ay result <keyword> [--wait] pull an agent's structured result envelope\n ay result set '<json>' (inside an agent) deposit your result envelope\n ay reap kill process groups leaked by dead agents\n\nRemote:\n" + setupLine + " ay schedule <when> <cli> -- <msg> run an agent on a schedule (HH:MM or cron)\n ay serve [--port N] start HTTP API server (prints token)\n ay serve status show serve daemon/server status\n ay remote add <alias> http://<token>@<host>:<port>\n ay remote ls / rm <alias> manage saved remotes\n ay ls <token>@<host>:<port> connect inline (no alias needed)\n ay send <token>@<host>:<port>:<kw> <msg>\n\nRun an agent:\n ay [claude|codex|gemini|...] [options] -- [prompt]\n ay claude -- \"fix the bug in auth.ts\"\n ay claude --help full agent-runner options\n\nLabs (examples at https://github.com/snomiao/agent-yes/tree/main/lab):\n local-role-play/ designer + builder on one machine\n http-remote/ ay serve remote access demo\n p2p-pairing/ libp2p P2P (needs: cargo build --features swarm)\n");
|
|
567
586
|
return 0;
|
|
568
587
|
}
|
|
569
588
|
function matchKeyword(record, keyword) {
|
|
@@ -977,6 +996,10 @@ async function deriveLiveState(r) {
|
|
|
977
996
|
state: "needs_input",
|
|
978
997
|
question: ni.question
|
|
979
998
|
};
|
|
999
|
+
if (base === "idle" && await isAgentStuck(r)) return {
|
|
1000
|
+
state: "stuck",
|
|
1001
|
+
question: null
|
|
1002
|
+
};
|
|
980
1003
|
}
|
|
981
1004
|
return {
|
|
982
1005
|
state: base,
|
|
@@ -1000,7 +1023,7 @@ async function cmdLs(rest) {
|
|
|
1000
1023
|
alias: "w",
|
|
1001
1024
|
type: "boolean",
|
|
1002
1025
|
default: false,
|
|
1003
|
-
description: "Stream agent state transitions (needs_input | idle | active | stopped) as NDJSON across all matched agents — one event stream for a whole fan-out, instead of N per-pid `ay status --watch`es. Runs until Ctrl-C."
|
|
1026
|
+
description: "Stream agent state transitions (needs_input | idle | active | stuck | stopped) as NDJSON across all matched agents — one event stream for a whole fan-out, instead of N per-pid `ay status --watch`es. Runs until Ctrl-C."
|
|
1004
1027
|
}).option("interval", {
|
|
1005
1028
|
type: "number",
|
|
1006
1029
|
default: 2,
|
|
@@ -1646,9 +1669,12 @@ function cliDefaults() {
|
|
|
1646
1669
|
* and renders it through xterm, then runs the CLI's `needsInput`/`working`
|
|
1647
1670
|
* patterns. Returns null when no menu is detected (or the CLI defines none).
|
|
1648
1671
|
*/
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1672
|
+
/**
|
|
1673
|
+
* Render the last `n` lines of a raw PTY log (reads only the final 32KB). Returns
|
|
1674
|
+
* null on any read/render error or an empty log. Shared by the needs_input and
|
|
1675
|
+
* stuck classifiers so they don't each re-implement the tail read.
|
|
1676
|
+
*/
|
|
1677
|
+
async function renderLogTailLines(logPath, n = 40) {
|
|
1652
1678
|
const TAIL_BYTES = 32 * 1024;
|
|
1653
1679
|
let buf;
|
|
1654
1680
|
try {
|
|
@@ -1671,17 +1697,41 @@ async function extractNeedsInput(logPath, cli) {
|
|
|
1671
1697
|
return null;
|
|
1672
1698
|
}
|
|
1673
1699
|
try {
|
|
1674
|
-
return
|
|
1700
|
+
return (await renderRawLog(buf, {
|
|
1675
1701
|
mode: "tail",
|
|
1676
|
-
n
|
|
1677
|
-
})).split("\n")
|
|
1678
|
-
needsInput: cfg.needsInput,
|
|
1679
|
-
working: cfg.working
|
|
1680
|
-
});
|
|
1702
|
+
n
|
|
1703
|
+
})).split("\n");
|
|
1681
1704
|
} catch {
|
|
1682
1705
|
return null;
|
|
1683
1706
|
}
|
|
1684
1707
|
}
|
|
1708
|
+
async function extractNeedsInput(logPath, cli) {
|
|
1709
|
+
const cfg = (await cliDefaults())[cli];
|
|
1710
|
+
if (!cfg?.needsInput?.length) return null;
|
|
1711
|
+
const lines = await renderLogTailLines(logPath, 40);
|
|
1712
|
+
if (!lines) return null;
|
|
1713
|
+
return classifyNeedsInput(lines, {
|
|
1714
|
+
needsInput: cfg.needsInput,
|
|
1715
|
+
working: cfg.working
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
/**
|
|
1719
|
+
* Whether an alive agent is wedged: its log has been silent for at least
|
|
1720
|
+
* STUCK_THRESHOLD_MS yet its screen still shows a `working` busy marker (a live
|
|
1721
|
+
* spinner keeps writing, so busy + long-silent = a mid-stream stall). Pass the
|
|
1722
|
+
* already-stat'd log mtime to skip a redundant stat. Returns false when the CLI
|
|
1723
|
+
* has no `working` markers configured (nothing to key off).
|
|
1724
|
+
*/
|
|
1725
|
+
async function isAgentStuck(record, logMtimeMs) {
|
|
1726
|
+
if (!record.log_file) return false;
|
|
1727
|
+
const cfg = (await cliDefaults())[record.cli];
|
|
1728
|
+
if (!cfg?.working?.length) return false;
|
|
1729
|
+
const mtime = logMtimeMs ?? await stat(record.log_file).then((s) => s.mtimeMs).catch(() => null);
|
|
1730
|
+
if (mtime === null || Date.now() - mtime < STUCK_THRESHOLD_MS) return false;
|
|
1731
|
+
const lines = await renderLogTailLines(record.log_file, 40);
|
|
1732
|
+
if (!lines) return false;
|
|
1733
|
+
return isWorkingScreen(lines, cfg.working);
|
|
1734
|
+
}
|
|
1685
1735
|
function extractActivityFromLines(lines) {
|
|
1686
1736
|
const isChrome = (l) => {
|
|
1687
1737
|
const s = l.trim();
|
|
@@ -1776,6 +1826,12 @@ async function cmdSend(rest) {
|
|
|
1776
1826
|
if (sender.agent) throw new Error(`${what}.\n Confirm it's the right agent first: ay tail ${record.pid}\n then resend, or pass --force to override.`);
|
|
1777
1827
|
process.stderr.write(`warning: ${what} — make sure this is the agent you meant (ay tail ${record.pid}).\n`);
|
|
1778
1828
|
}
|
|
1829
|
+
if (isExitRequest(body)) {
|
|
1830
|
+
const reason = sender.agent ? `requested by ${sender.agent.cli} #${sender.agent.pid} @ ${shortenPath(sender.agent.cwd)}` : `requested via 'ay send ${keyword} exit'`;
|
|
1831
|
+
const { strategy } = await gracefulExitAgent(record, reason);
|
|
1832
|
+
process.stdout.write(`pid ${record.pid} (${record.cli}): exit requested — sent ${strategy} (${reason})\n`);
|
|
1833
|
+
return 0;
|
|
1834
|
+
}
|
|
1779
1835
|
const fullBody = (sender.agent ? `[from ${sender.agent.cli} #${sender.agent.pid} @ ${shortenPath(sender.agent.cwd)} — reply: ay send ${sender.agent.pid} "..."]\n` : "") + body;
|
|
1780
1836
|
if (fullBody && trailing) {
|
|
1781
1837
|
await writeToIpc(fifoPath, fullBody);
|
|
@@ -1938,6 +1994,74 @@ async function cmdStop(rest) {
|
|
|
1938
1994
|
process.stderr.write(`\n ay status ${record.pid} # confirm it exited\n ay ls --all # see exit codes\n`);
|
|
1939
1995
|
return 0;
|
|
1940
1996
|
}
|
|
1997
|
+
/** A `send` body that is exactly the exit word (not a sentence that merely
|
|
1998
|
+
* contains it). Bare "exit" and the literal "/exit" both qualify. */
|
|
1999
|
+
function isExitRequest(body) {
|
|
2000
|
+
const t = body.trim().toLowerCase();
|
|
2001
|
+
return t === "exit" || t === "/exit";
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
2004
|
+
* Gracefully terminate a live agent and record WHY in its note (the audit trail
|
|
2005
|
+
* shown by `ay ls`). Sends the CLI's graceful-exit command (e.g. claude's
|
|
2006
|
+
* `/exit`) or a double-Ctrl+C fallback. `reason` is agent-yes metadata — claude's
|
|
2007
|
+
* `/exit` takes no argument, so the reason is the note, not appended to `/exit`.
|
|
2008
|
+
* Shared by `ay exit` and by `ay send <kw> exit`'s routing.
|
|
2009
|
+
*/
|
|
2010
|
+
async function gracefulExitAgent(record, reason) {
|
|
2011
|
+
if (!record.fifo_file) throw new Error(`pid ${record.pid}: no fifo_file — cannot send shutdown command`);
|
|
2012
|
+
await writeNote(record.pid, `↩ exit — ${reason}`).catch(() => {});
|
|
2013
|
+
const fifoPath = record.fifo_file;
|
|
2014
|
+
const graceful = GRACEFUL_EXIT_COMMANDS[record.cli];
|
|
2015
|
+
if (graceful) {
|
|
2016
|
+
await writeToIpc(fifoPath, graceful);
|
|
2017
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
2018
|
+
await writeToIpc(fifoPath, "\r");
|
|
2019
|
+
return { strategy: `'${graceful}' + Enter` };
|
|
2020
|
+
}
|
|
2021
|
+
await writeToIpc(fifoPath, "");
|
|
2022
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
2023
|
+
await writeToIpc(fifoPath, "");
|
|
2024
|
+
return { strategy: `double Ctrl+C (no known /exit for cli "${record.cli}")` };
|
|
2025
|
+
}
|
|
2026
|
+
async function cmdExit(rest) {
|
|
2027
|
+
const argv = await yargs(rest).usage("Usage: ay exit <keyword> [reason]").option("all", {
|
|
2028
|
+
type: "boolean",
|
|
2029
|
+
default: false,
|
|
2030
|
+
description: "Include exited agents"
|
|
2031
|
+
}).option("latest", {
|
|
2032
|
+
type: "boolean",
|
|
2033
|
+
default: false,
|
|
2034
|
+
description: "Use most recent match"
|
|
2035
|
+
}).option("cwd", {
|
|
2036
|
+
type: "string",
|
|
2037
|
+
description: "Restrict to agents under this dir"
|
|
2038
|
+
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
2039
|
+
const opts = {
|
|
2040
|
+
all: argv.all,
|
|
2041
|
+
active: false,
|
|
2042
|
+
json: false,
|
|
2043
|
+
latest: argv.latest,
|
|
2044
|
+
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
2045
|
+
};
|
|
2046
|
+
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
2047
|
+
if (!keyword) throw new Error("usage: ay exit <keyword> [reason]");
|
|
2048
|
+
const reasonArg = argv._.slice(1).map(String).join(" ").trim();
|
|
2049
|
+
const record = await resolveOne(keyword, opts);
|
|
2050
|
+
if (!isPidAlive(record.pid)) {
|
|
2051
|
+
await updateGlobalPidStatus(record.pid, {
|
|
2052
|
+
status: "exited",
|
|
2053
|
+
exit_reason: "already-stopped"
|
|
2054
|
+
}).catch(() => {});
|
|
2055
|
+
process.stdout.write(`pid ${record.pid} (${record.cli}) already stopped — marked exited\n`);
|
|
2056
|
+
return 0;
|
|
2057
|
+
}
|
|
2058
|
+
const sender = await senderContext();
|
|
2059
|
+
const reason = reasonArg || (sender.agent ? `requested by ${sender.agent.cli} #${sender.agent.pid} @ ${shortenPath(sender.agent.cwd)}` : "manual");
|
|
2060
|
+
const { strategy } = await gracefulExitAgent(record, reason);
|
|
2061
|
+
process.stdout.write(`exiting pid ${record.pid} (${record.cli}) via ${strategy} — ${reason}\n`);
|
|
2062
|
+
process.stderr.write(`\n ay status ${record.pid} # confirm it exited\n`);
|
|
2063
|
+
return 0;
|
|
2064
|
+
}
|
|
1941
2065
|
async function cmdAttach(rest) {
|
|
1942
2066
|
const argv = await yargs(rest).usage("Usage: ay attach <keyword> [--escape ctrl-\\]").option("escape", {
|
|
1943
2067
|
type: "string",
|
|
@@ -2189,7 +2313,7 @@ async function snapshotStatus(record) {
|
|
|
2189
2313
|
if (ni) {
|
|
2190
2314
|
state = "needs_input";
|
|
2191
2315
|
question = ni.question;
|
|
2192
|
-
}
|
|
2316
|
+
} else if (state === "idle" && await isAgentStuck(record, logMtimeMs)) state = "stuck";
|
|
2193
2317
|
}
|
|
2194
2318
|
const note = (await readNotes()).get(record.pid) ?? null;
|
|
2195
2319
|
return {
|
|
@@ -2269,7 +2393,7 @@ async function cmdStatus(rest) {
|
|
|
2269
2393
|
const startedAt = Date.now();
|
|
2270
2394
|
for (;;) {
|
|
2271
2395
|
const snap = await snapshotStatus(record);
|
|
2272
|
-
if (snap.state === "needs_input" || snap.state === "idle" || snap.state === "stopped") {
|
|
2396
|
+
if (snap.state === "needs_input" || snap.state === "idle" || snap.state === "stuck" || snap.state === "stopped") {
|
|
2273
2397
|
emit(snap);
|
|
2274
2398
|
return 0;
|
|
2275
2399
|
}
|
|
@@ -2284,7 +2408,7 @@ async function cmdStatus(rest) {
|
|
|
2284
2408
|
const startedAt = Date.now();
|
|
2285
2409
|
for (;;) {
|
|
2286
2410
|
const snap = await snapshotStatus(record);
|
|
2287
|
-
if (snap.state === "idle") {
|
|
2411
|
+
if (snap.state === "idle" || snap.state === "stuck") {
|
|
2288
2412
|
emit(snap);
|
|
2289
2413
|
return 0;
|
|
2290
2414
|
}
|
|
@@ -2456,5 +2580,5 @@ async function cmdResultSet(rest) {
|
|
|
2456
2580
|
}
|
|
2457
2581
|
|
|
2458
2582
|
//#endregion
|
|
2459
|
-
export {
|
|
2460
|
-
//# sourceMappingURL=subcommands-
|
|
2583
|
+
export { stopTipForCli as C, snapshotStatus as S, renderRawLog as _, cursorAbs as a, resolveReadWindow as b, extractTaskCounts as c, isExitRequest as d, isPidAlive as f, readNotes as g, matchKeyword as h, controlCodeFromName as i, finalizedLines as l, listRecords as m, READ_PAGE_DEFAULT as n, deriveLiveStatus as o, isSubcommand as p, cmdHelp as r, extractNeedsInput as s, GRACEFUL_EXIT_COMMANDS as t, isAgentStuck as u, renderRawLogLines as v, writeToIpc as w, runSubcommand as x, resolveOne as y };
|
|
2584
|
+
//# sourceMappingURL=subcommands-OKH2CsBu.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-Dl2LrFFo.js";
|
|
3
3
|
import { t as agentYesHome } from "./agentYesHome-_eJa3DaX.js";
|
|
4
4
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-V4qvXgAw.js";
|
|
5
5
|
import { t as PidStore } from "./pidStore-fqXqTKkh.js";
|
|
@@ -1788,4 +1788,4 @@ function sleep(ms) {
|
|
|
1788
1788
|
|
|
1789
1789
|
//#endregion
|
|
1790
1790
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1791
|
-
//# sourceMappingURL=ts-
|
|
1791
|
+
//# sourceMappingURL=ts-DkAVuuIK.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.142.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 i, displayVersion as n, getInstalledPackage as r, checkAndAutoUpdate as t };
|
|
218
|
-
//# sourceMappingURL=versionChecker-
|
|
218
|
+
//# sourceMappingURL=versionChecker-Dl2LrFFo.js.map
|
package/package.json
CHANGED
package/ts/lsWatch.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* `needsInput.ts`.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
export type LiveState = "active" | "idle" | "stopped" | "needs_input";
|
|
13
|
+
export type LiveState = "active" | "idle" | "stopped" | "needs_input" | "stuck";
|
|
14
14
|
|
|
15
15
|
/** The observable state of one agent at a single tick. */
|
|
16
16
|
export interface LsAgentState {
|
package/ts/needsInput.spec.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { expect, test } from "vitest";
|
|
2
|
-
import { classifyNeedsInput } from "./needsInput.ts";
|
|
2
|
+
import { classifyNeedsInput, isWorkingScreen } from "./needsInput.ts";
|
|
3
3
|
import { loadSharedCliDefaults } from "./configShared.ts";
|
|
4
4
|
|
|
5
5
|
// Use the REAL shipped claude/codex patterns so the test guards the actual config.
|
|
@@ -11,6 +11,25 @@ test("claude config actually ships a needsInput pattern", () => {
|
|
|
11
11
|
expect(claude.needsInput?.length).toBeGreaterThan(0);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
+
test("claude config ships a working busy marker (the stuck detector keys off it)", () => {
|
|
15
|
+
expect(claude.working?.length).toBeGreaterThan(0);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("isWorkingScreen: true when the shipped claude busy marker is on screen", () => {
|
|
19
|
+
const screen = ["⏺ Running the test suite…", "", "esc to interrupt · ← for agents"];
|
|
20
|
+
expect(isWorkingScreen(screen, claude.working)).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("isWorkingScreen: false at a finished/idle prompt (no busy marker)", () => {
|
|
24
|
+
const screen = ["⏺ Done — all tests pass.", "", "❯", "", "? for shortcuts"];
|
|
25
|
+
expect(isWorkingScreen(screen, claude.working)).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("isWorkingScreen: false when no working patterns are configured", () => {
|
|
29
|
+
expect(isWorkingScreen(["esc to interrupt"], undefined)).toBe(false);
|
|
30
|
+
expect(isWorkingScreen(["esc to interrupt"], [])).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
|
|
14
33
|
test("detects a claude AskUserQuestion selection menu", () => {
|
|
15
34
|
const screen = [
|
|
16
35
|
"Which auth method should we use?",
|
package/ts/needsInput.ts
CHANGED
|
@@ -66,3 +66,17 @@ export function classifyNeedsInput(
|
|
|
66
66
|
.filter((l) => l && !isChromeLine(l));
|
|
67
67
|
return { question: block.join(" • ").slice(0, 400) };
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* True when the rendered screen still shows a "busy" marker (config `working`,
|
|
72
|
+
* e.g. claude's `esc to interrupt`). Paired with a long-quiet log this is the
|
|
73
|
+
* `stuck` signal: a live spinner writes to the log every frame, so a busy marker
|
|
74
|
+
* on screen WITHOUT recent output means the agent wedged mid-stream (a silent
|
|
75
|
+
* API stream stall) rather than finishing. Pure + synchronous like the rest of
|
|
76
|
+
* this module so it's trivially unit-testable.
|
|
77
|
+
*/
|
|
78
|
+
export function isWorkingScreen(lines: string[], working?: RegExp[]): boolean {
|
|
79
|
+
if (!working?.length) return false;
|
|
80
|
+
const text = lines.join("\n");
|
|
81
|
+
return working.some((re) => reTest(re, text));
|
|
82
|
+
}
|
package/ts/subcommands.spec.ts
CHANGED
|
@@ -717,6 +717,82 @@ describe("subcommands.cmdSend writes bytes to FIFO", () => {
|
|
|
717
717
|
const { controlCodeFromName } = await loadModule();
|
|
718
718
|
expect(controlCodeFromName("none")).toBe("");
|
|
719
719
|
});
|
|
720
|
+
|
|
721
|
+
it.skipIf(!itUnix)(
|
|
722
|
+
"routes a bare 'exit' to the graceful /exit, not the literal word",
|
|
723
|
+
async () => {
|
|
724
|
+
const { runSubcommand } = await loadModule();
|
|
725
|
+
const { appendGlobalPid } = await import("./globalPidIndex.ts");
|
|
726
|
+
const { spawnSync } = await import("child_process");
|
|
727
|
+
const tmp = await mkdtemp(path.join(tmpdir(), "ay-fifo-"));
|
|
728
|
+
try {
|
|
729
|
+
const fifo = path.join(tmp, "exit.fifo");
|
|
730
|
+
if (spawnSync("mkfifo", [fifo]).status !== 0) return;
|
|
731
|
+
const fs = await import("fs");
|
|
732
|
+
const rdwrFd = fs.openSync(fifo, fs.constants.O_RDWR);
|
|
733
|
+
await appendGlobalPid({
|
|
734
|
+
pid: process.pid,
|
|
735
|
+
cli: "claude",
|
|
736
|
+
prompt: null,
|
|
737
|
+
cwd: process.cwd(),
|
|
738
|
+
log_file: null,
|
|
739
|
+
fifo_file: fifo,
|
|
740
|
+
status: "active",
|
|
741
|
+
exit_code: null,
|
|
742
|
+
exit_reason: null,
|
|
743
|
+
started_at: Date.now(),
|
|
744
|
+
});
|
|
745
|
+
const stdout: string[] = [];
|
|
746
|
+
const orig = process.stdout.write.bind(process.stdout);
|
|
747
|
+
(process.stdout as any).write = (s: any) => (stdout.push(String(s)), true);
|
|
748
|
+
const savedAyPid = process.env.AGENT_YES_PID;
|
|
749
|
+
delete process.env.AGENT_YES_PID;
|
|
750
|
+
try {
|
|
751
|
+
const code = await runSubcommand([
|
|
752
|
+
"bun",
|
|
753
|
+
"cli.js",
|
|
754
|
+
"send",
|
|
755
|
+
String(process.pid),
|
|
756
|
+
"exit",
|
|
757
|
+
"--force",
|
|
758
|
+
]);
|
|
759
|
+
expect(code).toBe(0);
|
|
760
|
+
expect(stdout.join("")).toMatch(/exit requested/);
|
|
761
|
+
} finally {
|
|
762
|
+
process.stdout.write = orig;
|
|
763
|
+
if (savedAyPid !== undefined) process.env.AGENT_YES_PID = savedAyPid;
|
|
764
|
+
}
|
|
765
|
+
const buf = Buffer.alloc(4096);
|
|
766
|
+
const n = fs.readSync(rdwrFd, buf, 0, buf.length, null);
|
|
767
|
+
// The real `/exit` command + Enter — NOT the literal "exit\r" that claude ignores.
|
|
768
|
+
expect(buf.subarray(0, n).toString()).toBe("/exit\r");
|
|
769
|
+
fs.closeSync(rdwrFd);
|
|
770
|
+
} finally {
|
|
771
|
+
await rm(tmp, { recursive: true, force: true }).catch(() => null);
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
describe("subcommands.isExitRequest", () => {
|
|
778
|
+
it("matches the bare exit word and the literal /exit (any case, trimmed)", async () => {
|
|
779
|
+
const { isExitRequest } = await loadModule();
|
|
780
|
+
for (const s of ["exit", "/exit", " exit ", "EXIT", "/Exit", "\nexit\n"]) {
|
|
781
|
+
expect(isExitRequest(s)).toBe(true);
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
it("does NOT match a sentence that merely contains 'exit'", async () => {
|
|
785
|
+
const { isExitRequest } = await loadModule();
|
|
786
|
+
for (const s of [
|
|
787
|
+
"please exit now",
|
|
788
|
+
"exit the loop after step 3",
|
|
789
|
+
"do not exit",
|
|
790
|
+
"exiting",
|
|
791
|
+
"",
|
|
792
|
+
]) {
|
|
793
|
+
expect(isExitRequest(s)).toBe(false);
|
|
794
|
+
}
|
|
795
|
+
});
|
|
720
796
|
});
|
|
721
797
|
|
|
722
798
|
describe("subcommands.writeToIpc reliable delivery", () => {
|
|
@@ -1571,3 +1647,74 @@ describe("subcommands.deriveLiveStatus", () => {
|
|
|
1571
1647
|
}
|
|
1572
1648
|
});
|
|
1573
1649
|
});
|
|
1650
|
+
|
|
1651
|
+
describe("subcommands.isAgentStuck / stuck state", () => {
|
|
1652
|
+
const rec = (over: any) => ({
|
|
1653
|
+
pid: process.pid,
|
|
1654
|
+
cli: "claude",
|
|
1655
|
+
prompt: null,
|
|
1656
|
+
cwd: "/tmp",
|
|
1657
|
+
log_file: null,
|
|
1658
|
+
fifo_file: null,
|
|
1659
|
+
status: "active",
|
|
1660
|
+
exit_code: null,
|
|
1661
|
+
exit_reason: null,
|
|
1662
|
+
started_at: 0,
|
|
1663
|
+
...over,
|
|
1664
|
+
});
|
|
1665
|
+
// A log whose rendered tail shows claude's shipped `working` busy marker.
|
|
1666
|
+
const BUSY = "⏺ Cogitating…\r\nesc to interrupt · ← for agents\r\n";
|
|
1667
|
+
const tenMinAgo = () => new Date(Date.now() - 10 * 60 * 1000);
|
|
1668
|
+
|
|
1669
|
+
it("isAgentStuck: true when a busy marker is on screen and the log is long-silent", async () => {
|
|
1670
|
+
const dir = await mkdtemp(path.join(tmpdir(), "ay-stuck-"));
|
|
1671
|
+
try {
|
|
1672
|
+
const log = path.join(dir, "a.log");
|
|
1673
|
+
await writeFile(log, BUSY);
|
|
1674
|
+
await utimes(log, tenMinAgo(), tenMinAgo());
|
|
1675
|
+
const mod = await loadModule();
|
|
1676
|
+
expect(await mod.isAgentStuck(rec({ log_file: log }))).toBe(true);
|
|
1677
|
+
} finally {
|
|
1678
|
+
await rm(dir, { recursive: true, force: true }).catch(() => null);
|
|
1679
|
+
}
|
|
1680
|
+
});
|
|
1681
|
+
|
|
1682
|
+
it("isAgentStuck: false when the busy log was written recently (still working)", async () => {
|
|
1683
|
+
const dir = await mkdtemp(path.join(tmpdir(), "ay-stuck-"));
|
|
1684
|
+
try {
|
|
1685
|
+
const log = path.join(dir, "a.log");
|
|
1686
|
+
await writeFile(log, BUSY); // fresh mtime — under the stuck threshold
|
|
1687
|
+
const mod = await loadModule();
|
|
1688
|
+
expect(await mod.isAgentStuck(rec({ log_file: log }))).toBe(false);
|
|
1689
|
+
} finally {
|
|
1690
|
+
await rm(dir, { recursive: true, force: true }).catch(() => null);
|
|
1691
|
+
}
|
|
1692
|
+
});
|
|
1693
|
+
|
|
1694
|
+
it("isAgentStuck: false when long-silent but no busy marker on screen (genuinely idle)", async () => {
|
|
1695
|
+
const dir = await mkdtemp(path.join(tmpdir(), "ay-stuck-"));
|
|
1696
|
+
try {
|
|
1697
|
+
const log = path.join(dir, "a.log");
|
|
1698
|
+
await writeFile(log, "⏺ Done — all green.\r\n❯\r\n");
|
|
1699
|
+
await utimes(log, tenMinAgo(), tenMinAgo());
|
|
1700
|
+
const mod = await loadModule();
|
|
1701
|
+
expect(await mod.isAgentStuck(rec({ log_file: log }))).toBe(false);
|
|
1702
|
+
} finally {
|
|
1703
|
+
await rm(dir, { recursive: true, force: true }).catch(() => null);
|
|
1704
|
+
}
|
|
1705
|
+
});
|
|
1706
|
+
|
|
1707
|
+
it("snapshotStatus: reports 'stuck' for a long-silent busy agent (not 'idle')", async () => {
|
|
1708
|
+
const dir = await mkdtemp(path.join(tmpdir(), "ay-stuck-"));
|
|
1709
|
+
try {
|
|
1710
|
+
const log = path.join(dir, "a.log");
|
|
1711
|
+
await writeFile(log, BUSY);
|
|
1712
|
+
await utimes(log, tenMinAgo(), tenMinAgo());
|
|
1713
|
+
const mod = await loadModule();
|
|
1714
|
+
const snap = await mod.snapshotStatus(rec({ log_file: log }));
|
|
1715
|
+
expect(snap.state).toBe("stuck");
|
|
1716
|
+
} finally {
|
|
1717
|
+
await rm(dir, { recursive: true, force: true }).catch(() => null);
|
|
1718
|
+
}
|
|
1719
|
+
});
|
|
1720
|
+
});
|
package/ts/subcommands.ts
CHANGED
|
Binary file
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import "./ts-B1-x2rKP.js";
|
|
2
|
-
import "./logger-CDIsZ-Pp.js";
|
|
3
|
-
import "./versionChecker-Bhn4NygE.js";
|
|
4
|
-
import "./pidStore-fqXqTKkh.js";
|
|
5
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CTOnaXTX.js";
|
|
7
|
-
|
|
8
|
-
export { SUPPORTED_CLIS };
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import "./logger-CDIsZ-Pp.js";
|
|
2
|
-
import "./globalPidIndex-DlmmJlO8.js";
|
|
3
|
-
import "./configShared-C1C04bbq.js";
|
|
4
|
-
import "./remotes-PKKjfTI1.js";
|
|
5
|
-
import { S as writeToIpc, _ as resolveOne, a as cursorAbs, b as snapshotStatus, c as extractTaskCounts, d as isSubcommand, f as listRecords, g as renderRawLogLines, h as renderRawLog, i as controlCodeFromName, l as finalizedLines, m as readNotes, n as READ_PAGE_DEFAULT, o as deriveLiveStatus, p as matchKeyword, r as cmdHelp, s as extractNeedsInput, t as GRACEFUL_EXIT_COMMANDS, u as isPidAlive, v as resolveReadWindow, x as stopTipForCli, y as runSubcommand } from "./subcommands-Cz7-sHOT.js";
|
|
6
|
-
|
|
7
|
-
export { cmdHelp, isSubcommand, runSubcommand };
|