agent-yes 1.121.0 → 1.122.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 +27 -4
- package/dist/SUPPORTED_CLIS-BVqe3k7F.js +8 -0
- package/dist/{SUPPORTED_CLIS-O57LGUEG.js → SUPPORTED_CLIS-DFYbm2uk.js} +2 -2
- package/dist/{agent-yes.config-kmtJKJHk.js → agent-yes.config-z-IPzH5U.js} +3 -2
- package/dist/cli.js +5 -5
- package/dist/index.js +2 -2
- package/dist/reaper-Dj8R7ltI.js +64 -0
- package/dist/reaper-HqcUms2d.js +3 -0
- package/dist/{remotes-DavR4Hca.js → remotes-CpGcTr7A.js} +1 -1
- package/dist/{remotes-BufkGk0e.js → remotes-D2fqaRU8.js} +1 -1
- package/dist/schedule-CJaNc82S.js +144 -0
- package/dist/{serve-D2czcYNC.js → serve-VczpuYDk.js} +121 -26
- package/dist/{setup-f1FIFcZm.js → setup-DveWqmSR.js} +5 -42
- package/dist/{share-B6QVr5D1.js → share-ClsUSd_0.js} +69 -9
- package/dist/{subcommands-CzpZQHO6.js → subcommands-CmNGbbIA.js} +15 -6
- package/dist/{subcommands-DobVXouH.js → subcommands-CzZ4uBIa.js} +2 -2
- package/dist/{tray-B8_rx1iu.js → tray-DjCIyakK.js} +22 -10
- package/dist/{ts-D91dm1E0.js → ts-7kSDmCpQ.js} +76 -7
- package/dist/{versionChecker-CAtpgnoQ.js → versionChecker-B5vxV_hH.js} +13 -19
- package/dist/workspaceConfig-XP2NEWmV.js +56 -0
- package/lab/ui/index.html +63 -32
- package/package.json +1 -1
- package/ts/autoRetry.spec.ts +19 -0
- package/ts/autoRetry.ts +16 -0
- package/ts/configShared.ts +4 -0
- package/ts/index.ts +102 -0
- package/ts/oxmgrService.ts +36 -0
- package/ts/pty.ts +19 -1
- package/ts/reaper.spec.ts +45 -0
- package/ts/reaper.ts +77 -0
- package/ts/schedule.spec.ts +30 -0
- package/ts/schedule.ts +161 -0
- package/ts/serve.ts +174 -19
- package/ts/share.ts +81 -10
- package/ts/subcommands.ts +0 -0
- package/ts/tray.spec.ts +9 -1
- package/ts/tray.ts +30 -14
- package/ts/versionChecker.ts +24 -27
- package/dist/SUPPORTED_CLIS-CegJgoEf.js +0 -8
package/default.config.yaml
CHANGED
|
@@ -36,8 +36,20 @@ clis:
|
|
|
36
36
|
- pattern: Press Enter to continue
|
|
37
37
|
flags: m
|
|
38
38
|
fatal:
|
|
39
|
-
- Claude usage limit reached
|
|
40
39
|
- "^error: unknown option"
|
|
40
|
+
# Recoverable API errors: instead of exiting, agent-yes types "retry" with
|
|
41
|
+
# exponential backoff (8s, 16, 32 … capped) for up to 8h (claude's usage
|
|
42
|
+
# limit window is ~5h). Checked before `fatal`, so these never kill the run.
|
|
43
|
+
autoRetry:
|
|
44
|
+
- pattern: "API Error.*Overloaded"
|
|
45
|
+
flags: i
|
|
46
|
+
- Overloaded
|
|
47
|
+
- Claude usage limit reached
|
|
48
|
+
- hit your usage limit
|
|
49
|
+
- pattern: "rate.?limit"
|
|
50
|
+
flags: i
|
|
51
|
+
- pattern: "session limit"
|
|
52
|
+
flags: i
|
|
41
53
|
restoreArgs:
|
|
42
54
|
- --continue
|
|
43
55
|
restartWithoutContinueArg:
|
|
@@ -78,10 +90,21 @@ clis:
|
|
|
78
90
|
- ⏎ send
|
|
79
91
|
- "› "
|
|
80
92
|
- '\? for shortcuts'
|
|
93
|
+
working:
|
|
94
|
+
# codex shows "• Working (… • esc to interrupt)" while streaming/running.
|
|
95
|
+
# (Approval dialogs say "esc to cancel", so this only marks real work.)
|
|
96
|
+
- esc to interrupt
|
|
81
97
|
enter:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
98
|
+
# codex highlights the selected option with "›" (U+203A), NOT ASCII ">".
|
|
99
|
+
# Match the affirmative first option (Yes / Approve / Allow) when it is the
|
|
100
|
+
# highlighted choice. The "[›>]" class keeps matching the old ASCII bullet
|
|
101
|
+
# too, in case an older/newer codex reverts the glyph.
|
|
102
|
+
- pattern: '[›>] ?1\. ?Yes'
|
|
103
|
+
flags: m
|
|
104
|
+
- pattern: '[›>] ?1\. ?Approve'
|
|
105
|
+
flags: m
|
|
106
|
+
- pattern: '[›>] ?1\. ?Allow'
|
|
107
|
+
flags: m
|
|
85
108
|
fatal:
|
|
86
109
|
- "Error: The cursor position could not be read within"
|
|
87
110
|
defaultArgs:
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import "./ts-7kSDmCpQ.js";
|
|
2
|
+
import "./logger-B9h0djqx.js";
|
|
3
|
+
import "./versionChecker-B5vxV_hH.js";
|
|
4
|
+
import "./pidStore-B5vBu8Px.js";
|
|
5
|
+
import "./globalPidIndex-gZuTvTBs.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DFYbm2uk.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-7kSDmCpQ.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-DFYbm2uk.js.map
|
|
@@ -26,7 +26,7 @@ function compileTypingRespond(typingRespond) {
|
|
|
26
26
|
return Object.fromEntries(Object.entries(typingRespond).map(([message, patterns]) => [message, patterns.map(compileRegexSource)]));
|
|
27
27
|
}
|
|
28
28
|
function normalizeCliConfig(raw) {
|
|
29
|
-
const { ready, fatal, working, enter, enterExclude, typingRespond, restartWithoutContinueArg, updateAvailable, exitCommands, exitCommand, ...rest } = raw;
|
|
29
|
+
const { ready, fatal, working, enter, enterExclude, typingRespond, restartWithoutContinueArg, updateAvailable, autoRetry, exitCommands, exitCommand, ...rest } = raw;
|
|
30
30
|
return {
|
|
31
31
|
...rest,
|
|
32
32
|
ready: compileRegexList(ready),
|
|
@@ -37,6 +37,7 @@ function normalizeCliConfig(raw) {
|
|
|
37
37
|
typingRespond: compileTypingRespond(typingRespond),
|
|
38
38
|
restartWithoutContinueArg: compileRegexList(restartWithoutContinueArg),
|
|
39
39
|
updateAvailable: compileRegexList(updateAvailable),
|
|
40
|
+
autoRetry: compileRegexList(autoRetry),
|
|
40
41
|
exitCommands: exitCommands ?? exitCommand
|
|
41
42
|
};
|
|
42
43
|
}
|
|
@@ -288,4 +289,4 @@ async function getDefaultConfig() {
|
|
|
288
289
|
|
|
289
290
|
//#endregion
|
|
290
291
|
export { agent_yes_config_default as default };
|
|
291
|
-
//# sourceMappingURL=agent-yes.config-
|
|
292
|
+
//# sourceMappingURL=agent-yes.config-z-IPzH5U.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { n as logger } from "./logger-B9h0djqx.js";
|
|
3
|
-
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-
|
|
3
|
+
import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-B5vxV_hH.js";
|
|
4
4
|
import { argv } from "process";
|
|
5
5
|
import { execFileSync, spawn } from "child_process";
|
|
6
6
|
import ms from "ms";
|
|
@@ -482,7 +482,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
|
|
|
482
482
|
{
|
|
483
483
|
const rawArg = process.argv[2];
|
|
484
484
|
const isHelpFlag = rawArg === "-h" || rawArg === "--help";
|
|
485
|
-
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-
|
|
485
|
+
const { isSubcommand, runSubcommand, cmdHelp } = await import("./subcommands-CzZ4uBIa.js");
|
|
486
486
|
if (isHelpFlag && process.argv.length === 3) {
|
|
487
487
|
cmdHelp();
|
|
488
488
|
process.exit(0);
|
|
@@ -496,12 +496,12 @@ await checkAndAutoUpdate();
|
|
|
496
496
|
logger.info(versionString());
|
|
497
497
|
const config = parseCliArgs(process.argv);
|
|
498
498
|
if (config.tray) {
|
|
499
|
-
const { startTray } = await import("./tray-
|
|
499
|
+
const { startTray } = await import("./tray-DjCIyakK.js");
|
|
500
500
|
await startTray();
|
|
501
501
|
await new Promise(() => {});
|
|
502
502
|
}
|
|
503
503
|
{
|
|
504
|
-
const { ensureTray } = await import("./tray-
|
|
504
|
+
const { ensureTray } = await import("./tray-DjCIyakK.js");
|
|
505
505
|
ensureTray();
|
|
506
506
|
}
|
|
507
507
|
if (config.useRust) {
|
|
@@ -515,7 +515,7 @@ if (config.useRust) {
|
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
if (rustBinary) {
|
|
518
|
-
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-
|
|
518
|
+
const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-BVqe3k7F.js");
|
|
519
519
|
const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
|
|
520
520
|
if (config.verbose) {
|
|
521
521
|
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-7kSDmCpQ.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import "./versionChecker-
|
|
3
|
+
import "./versionChecker-B5vxV_hH.js";
|
|
4
4
|
import "./pidStore-B5vBu8Px.js";
|
|
5
5
|
import "./globalPidIndex-gZuTvTBs.js";
|
|
6
6
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { t as agentYesHome } from "./agentYesHome-BvaUOzCV.js";
|
|
2
|
+
import { appendFile, mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
//#region ts/reaper.ts
|
|
6
|
+
const registryPath = () => path.join(agentYesHome(), "reaper.jsonl");
|
|
7
|
+
function isAlive(pid) {
|
|
8
|
+
if (pid <= 1) return false;
|
|
9
|
+
try {
|
|
10
|
+
process.kill(pid, 0);
|
|
11
|
+
return true;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return e.code === "EPERM";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Record this wrapper + its agent's process group for later sweeping. */
|
|
17
|
+
async function register(wrapperPid, pgid) {
|
|
18
|
+
if (pgid <= 1) return;
|
|
19
|
+
try {
|
|
20
|
+
await mkdir(agentYesHome(), { recursive: true });
|
|
21
|
+
await appendFile(registryPath(), JSON.stringify({
|
|
22
|
+
wpid: wrapperPid,
|
|
23
|
+
pgid
|
|
24
|
+
}) + "\n");
|
|
25
|
+
} catch {}
|
|
26
|
+
}
|
|
27
|
+
/** SIGKILL the recorded group of every agent whose wrapper has exited, and
|
|
28
|
+
* rewrite the registry keeping only still-running agents. Best-effort. */
|
|
29
|
+
async function sweep() {
|
|
30
|
+
let content;
|
|
31
|
+
try {
|
|
32
|
+
content = await readFile(registryPath(), "utf8");
|
|
33
|
+
} catch {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const keep = [];
|
|
37
|
+
for (const line of content.split("\n")) {
|
|
38
|
+
const t = line.trim();
|
|
39
|
+
if (!t) continue;
|
|
40
|
+
let entry;
|
|
41
|
+
try {
|
|
42
|
+
entry = JSON.parse(t);
|
|
43
|
+
} catch {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (typeof entry.wpid !== "number" || typeof entry.pgid !== "number") continue;
|
|
47
|
+
if (isAlive(entry.wpid)) {
|
|
48
|
+
keep.push(t);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (process.platform !== "win32" && entry.pgid > 1) try {
|
|
52
|
+
process.kill(-entry.pgid, "SIGKILL");
|
|
53
|
+
} catch {}
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const tmp = registryPath() + ".tmp";
|
|
57
|
+
await writeFile(tmp, keep.join("\n"));
|
|
58
|
+
await rename(tmp, registryPath());
|
|
59
|
+
} catch {}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
export { sweep as n, register as t };
|
|
64
|
+
//# sourceMappingURL=reaper-Dj8R7ltI.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-
|
|
1
|
+
import { a as resolveRemoteSpec, i as readRemotes, n as deleteRemoteAlias, o as writeRemoteAlias, r as parseDirectRemoteSpec, t as cmdRemote } from "./remotes-D2fqaRU8.js";
|
|
2
2
|
|
|
3
3
|
export { cmdRemote };
|
|
@@ -147,4 +147,4 @@ async function cmdRemote(rest) {
|
|
|
147
147
|
|
|
148
148
|
//#endregion
|
|
149
149
|
export { resolveRemoteSpec as a, readRemotes as i, deleteRemoteAlias as n, writeRemoteAlias as o, parseDirectRemoteSpec as r, cmdRemote as t };
|
|
150
|
-
//# sourceMappingURL=remotes-
|
|
150
|
+
//# sourceMappingURL=remotes-D2fqaRU8.js.map
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import "./ts-7kSDmCpQ.js";
|
|
2
|
+
import "./logger-B9h0djqx.js";
|
|
3
|
+
import "./versionChecker-B5vxV_hH.js";
|
|
4
|
+
import "./pidStore-B5vBu8Px.js";
|
|
5
|
+
import "./globalPidIndex-gZuTvTBs.js";
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DFYbm2uk.js";
|
|
7
|
+
import { n as resolveSpawnCwd } from "./workspaceConfig-XP2NEWmV.js";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
|
|
10
|
+
//#region ts/oxmgrService.ts
|
|
11
|
+
async function ensureBootAutostart(oxmgrBin) {
|
|
12
|
+
try {
|
|
13
|
+
if (await Bun.spawn([
|
|
14
|
+
oxmgrBin,
|
|
15
|
+
"service",
|
|
16
|
+
"status"
|
|
17
|
+
], { stdio: [
|
|
18
|
+
"ignore",
|
|
19
|
+
"ignore",
|
|
20
|
+
"ignore"
|
|
21
|
+
] }).exited === 0) return true;
|
|
22
|
+
return await Bun.spawn([
|
|
23
|
+
oxmgrBin,
|
|
24
|
+
"service",
|
|
25
|
+
"install"
|
|
26
|
+
], { stdio: [
|
|
27
|
+
"ignore",
|
|
28
|
+
"ignore",
|
|
29
|
+
"ignore"
|
|
30
|
+
] }).exited === 0;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region ts/schedule.ts
|
|
38
|
+
const SCHED_PREFIX = "agent-yes-cron-";
|
|
39
|
+
/** `HH:MM` → a daily cron; otherwise a raw 5-field cron passes through. null if neither. */
|
|
40
|
+
function toCron(spec) {
|
|
41
|
+
const s = spec.trim();
|
|
42
|
+
const hm = /^(\d{1,2}):(\d{2})$/.exec(s);
|
|
43
|
+
if (hm) {
|
|
44
|
+
const h = Number(hm[1]), m = Number(hm[2]);
|
|
45
|
+
return h < 24 && m < 60 ? `${m} ${h} * * *` : null;
|
|
46
|
+
}
|
|
47
|
+
return /^\S+(\s+\S+){4}$/.test(s) ? s : null;
|
|
48
|
+
}
|
|
49
|
+
/** Single-quote for oxmgr's shell-style command parsing (verified: it respects quotes). */
|
|
50
|
+
function shellQuote(s) {
|
|
51
|
+
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
52
|
+
}
|
|
53
|
+
function schedName(explicit, cli, key) {
|
|
54
|
+
if (explicit) return explicit.startsWith(SCHED_PREFIX) ? explicit : SCHED_PREFIX + explicit;
|
|
55
|
+
return SCHED_PREFIX + cli + "-" + createHash("sha1").update(key).digest("hex").slice(0, 6);
|
|
56
|
+
}
|
|
57
|
+
async function run(cmd, capture = false) {
|
|
58
|
+
const p = Bun.spawn(cmd, {
|
|
59
|
+
stdin: "ignore",
|
|
60
|
+
stdout: capture ? "pipe" : "inherit",
|
|
61
|
+
stderr: capture ? "pipe" : "inherit"
|
|
62
|
+
});
|
|
63
|
+
const out = capture ? await new Response(p.stdout).text() : "";
|
|
64
|
+
return {
|
|
65
|
+
code: await p.exited ?? 1,
|
|
66
|
+
out
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async function cmdSchedule(rest) {
|
|
70
|
+
const oxmgrBin = Bun.which("oxmgr");
|
|
71
|
+
if (!oxmgrBin) {
|
|
72
|
+
process.stderr.write("ay schedule: oxmgr not found\n install with: cargo install oxmgr\n or: bun add -g oxmgr\n");
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
const sub = rest[0];
|
|
76
|
+
if (!sub || sub === "-h" || sub === "--help") {
|
|
77
|
+
process.stdout.write("Usage:\n ay schedule <when> <cli> [--cwd DIR] [--name N] [-- <prompt>]\n schedule a recurring agent\n ay schedule list list scheduled agents\n ay schedule remove <name> remove one\n\n<when> is a daily HH:MM (e.g. 10:00) or a 5-field cron (\"0 10 * * *\").\nThe agent runs once now and then on every tick, and survives reboot.\n\nExample — a 10am daily QA pass:\n ay schedule 10:00 claude --cwd ~/ws/product -- \"run a full QA pass and write a report\"\n");
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
if (sub === "list" || sub === "ls") {
|
|
81
|
+
process.stdout.write(`scheduled agents are named '${SCHED_PREFIX}*':\n`);
|
|
82
|
+
return (await run([oxmgrBin, "list"])).code;
|
|
83
|
+
}
|
|
84
|
+
if (sub === "remove" || sub === "rm" || sub === "delete") {
|
|
85
|
+
const name = rest[1];
|
|
86
|
+
if (!name) {
|
|
87
|
+
process.stderr.write("usage: ay schedule remove <name>\n");
|
|
88
|
+
return 1;
|
|
89
|
+
}
|
|
90
|
+
return (await run([
|
|
91
|
+
oxmgrBin,
|
|
92
|
+
"delete",
|
|
93
|
+
name.startsWith(SCHED_PREFIX) ? name : SCHED_PREFIX + name
|
|
94
|
+
])).code;
|
|
95
|
+
}
|
|
96
|
+
const dashIdx = rest.indexOf("--");
|
|
97
|
+
const head = dashIdx >= 0 ? rest.slice(0, dashIdx) : rest;
|
|
98
|
+
const prompt = dashIdx >= 0 ? rest.slice(dashIdx + 1).join(" ") : "";
|
|
99
|
+
let nameFlag;
|
|
100
|
+
let cwdFlag;
|
|
101
|
+
const pos = [];
|
|
102
|
+
for (let i = 0; i < head.length; i++) if (head[i] === "--name") nameFlag = head[++i];
|
|
103
|
+
else if (head[i] === "--cwd") cwdFlag = head[++i];
|
|
104
|
+
else pos.push(head[i]);
|
|
105
|
+
const [when, cli] = pos;
|
|
106
|
+
if (!when || !cli) {
|
|
107
|
+
process.stderr.write("usage: ay schedule <when> <cli> [-- <prompt>]\n");
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
110
|
+
const cron = toCron(when);
|
|
111
|
+
if (!cron) {
|
|
112
|
+
process.stderr.write(`ay schedule: bad <when> "${when}" — use HH:MM or a 5-field cron\n`);
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
if (!SUPPORTED_CLIS.includes(cli)) {
|
|
116
|
+
process.stderr.write(`ay schedule: unsupported cli "${cli}"\n`);
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
const cwd = resolveSpawnCwd(cwdFlag);
|
|
120
|
+
const ayBin = Bun.which("ay");
|
|
121
|
+
const agentCmd = `${ayBin ? `${shellQuote(process.execPath)} ${shellQuote(ayBin)}` : "ay"} ${cli}${prompt ? ` -- ${shellQuote(prompt)}` : ""}`;
|
|
122
|
+
const name = schedName(nameFlag, cli, cron + "\0" + prompt + "\0" + cwd);
|
|
123
|
+
const { code } = await run([
|
|
124
|
+
oxmgrBin,
|
|
125
|
+
"start",
|
|
126
|
+
agentCmd,
|
|
127
|
+
"--name",
|
|
128
|
+
name,
|
|
129
|
+
"--cwd",
|
|
130
|
+
cwd,
|
|
131
|
+
"--restart",
|
|
132
|
+
"never",
|
|
133
|
+
"--cron-restart",
|
|
134
|
+
cron
|
|
135
|
+
]);
|
|
136
|
+
if (code !== 0) return code;
|
|
137
|
+
const onBoot = await ensureBootAutostart(oxmgrBin);
|
|
138
|
+
process.stdout.write(`\nscheduled '${name}'\n ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}${prompt.length > 60 ? "…" : ""}"` : ""}\n when: ${cron} cwd: ${cwd}\n` + (onBoot ? ` runs now and on every tick; survives reboot.\n` : " runs now and on every tick.\n start-on-boot: not registered — run `oxmgr service install` to enable\n") + `\n ay schedule list # all scheduled agents\n ay schedule remove ${name.slice(15)}\n`);
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//#endregion
|
|
143
|
+
export { cmdSchedule };
|
|
144
|
+
//# sourceMappingURL=schedule-CJaNc82S.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import "./ts-
|
|
1
|
+
import "./ts-7kSDmCpQ.js";
|
|
2
2
|
import "./logger-B9h0djqx.js";
|
|
3
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
3
|
+
import { r as getInstalledPackage } from "./versionChecker-B5vxV_hH.js";
|
|
4
4
|
import "./pidStore-B5vBu8Px.js";
|
|
5
5
|
import "./globalPidIndex-gZuTvTBs.js";
|
|
6
|
-
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-
|
|
7
|
-
import "./remotes-
|
|
8
|
-
import { c as listRecords, d as renderRawLog, f as resolveOne, g as writeToIpc, m as snapshotStatus, r as controlCodeFromName, u as readNotes } from "./subcommands-
|
|
6
|
+
import { t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DFYbm2uk.js";
|
|
7
|
+
import "./remotes-D2fqaRU8.js";
|
|
8
|
+
import { c as listRecords, d as renderRawLog, f as resolveOne, g as writeToIpc, m as snapshotStatus, r as controlCodeFromName, u as readNotes } from "./subcommands-CmNGbbIA.js";
|
|
9
9
|
import yargs from "yargs";
|
|
10
10
|
import { mkdir, open, readFile, writeFile } from "fs/promises";
|
|
11
11
|
import { homedir, hostname, userInfo } from "os";
|
|
@@ -33,6 +33,20 @@ async function loadOrCreateToken(tokenFlag) {
|
|
|
33
33
|
return token;
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
async function loadTokenReadOnly() {
|
|
37
|
+
try {
|
|
38
|
+
return (await readFile(tokenPath(), "utf-8")).trim();
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function readShareLink() {
|
|
44
|
+
try {
|
|
45
|
+
return (await readFile(path.join(agentYesHome(), ".share-link"), "utf-8")).trim();
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
36
50
|
function tokenEqual(provided, expectedToken) {
|
|
37
51
|
const maxLen = Math.max(provided.length, expectedToken.length);
|
|
38
52
|
return timingSafeEqual(Buffer.from(provided.padEnd(maxLen, "\0")), Buffer.from(expectedToken.padEnd(maxLen, "\0"))) && provided.length === expectedToken.length;
|
|
@@ -101,20 +115,41 @@ function ayServeArgv(args) {
|
|
|
101
115
|
...args
|
|
102
116
|
];
|
|
103
117
|
}
|
|
118
|
+
const WIN_RUN_KEY = "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run";
|
|
119
|
+
const WIN_RUN_VALUE = DAEMON_NAME;
|
|
104
120
|
async function ensureBootAutostart(mgr) {
|
|
105
121
|
try {
|
|
106
|
-
if (mgr.id
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
122
|
+
if (mgr.id === "oxmgr") {
|
|
123
|
+
const installed = await spawnExit([
|
|
124
|
+
mgr.bin,
|
|
125
|
+
"service",
|
|
126
|
+
"status"
|
|
127
|
+
]) === 0 || await spawnExit([
|
|
128
|
+
mgr.bin,
|
|
129
|
+
"service",
|
|
130
|
+
"install"
|
|
131
|
+
]) === 0;
|
|
132
|
+
if (installed && process.platform === "linux") await spawnExit([
|
|
133
|
+
"loginctl",
|
|
134
|
+
"enable-linger",
|
|
135
|
+
userInfo().username
|
|
136
|
+
]);
|
|
137
|
+
return installed;
|
|
138
|
+
}
|
|
139
|
+
if (await spawnExit([mgr.bin, "save"]) !== 0) return false;
|
|
140
|
+
if (process.platform === "win32") return await spawnExit([
|
|
141
|
+
"reg",
|
|
142
|
+
"add",
|
|
143
|
+
WIN_RUN_KEY,
|
|
144
|
+
"/v",
|
|
145
|
+
WIN_RUN_VALUE,
|
|
146
|
+
"/t",
|
|
147
|
+
"REG_SZ",
|
|
148
|
+
"/d",
|
|
149
|
+
mgr.bin.includes(" ") ? `"${mgr.bin}" resurrect` : `${mgr.bin} resurrect`,
|
|
150
|
+
"/f"
|
|
111
151
|
]) === 0;
|
|
112
|
-
|
|
113
|
-
"loginctl",
|
|
114
|
-
"enable-linger",
|
|
115
|
-
userInfo().username
|
|
116
|
-
]);
|
|
117
|
-
return installed;
|
|
152
|
+
return await spawnExit([mgr.bin, "startup"]) === 0;
|
|
118
153
|
} catch {
|
|
119
154
|
return false;
|
|
120
155
|
}
|
|
@@ -240,7 +275,8 @@ async function cmdServeDaemon(sub, args) {
|
|
|
240
275
|
const httpish = effArgs.some((a) => a.startsWith("--http") || a.startsWith("--share")) || !effArgs.some((a) => a.startsWith("--webrtc"));
|
|
241
276
|
process.stdout.write(`\n${priorArgs !== null ? `rolled '${DAEMON_NAME}' forward to` : `installed '${DAEMON_NAME}' as a daemon via ${mgr.id} —`} v${current}\n`);
|
|
242
277
|
if (mgr.id === "oxmgr") process.stdout.write(onBoot ? `start-on-boot: enabled (systemd --user + linger, starts at boot)\n` : `start-on-boot: not registered — needs a user systemd session; run \`oxmgr service install\` to enable\n`);
|
|
243
|
-
else process.stdout.write(onBoot ? `start-on-login: enabled (
|
|
278
|
+
else if (process.platform === "win32") process.stdout.write(onBoot ? `start-on-login: enabled (a HKCU Run entry runs \`pm2 resurrect\`)\n` : `start-on-login: not registered — \`pm2 save\` or the registry write failed\n`);
|
|
279
|
+
else process.stdout.write(onBoot ? `start-on-boot: enabled (pm2 startup registered with the system init)\n` : `start-on-boot: not registered — run \`pm2 startup\` (may need sudo) to enable\n`);
|
|
244
280
|
process.stdout.write(`token: ${token}\n\n`);
|
|
245
281
|
if (httpish) {
|
|
246
282
|
process.stdout.write(` ay ls ${token}@<host>:${port}\n`);
|
|
@@ -262,11 +298,17 @@ async function cmdServeDaemon(sub, args) {
|
|
|
262
298
|
"inherit",
|
|
263
299
|
"inherit"
|
|
264
300
|
] }).exited ?? 1;
|
|
265
|
-
if (mgr.id === "pm2" && code === 0)
|
|
266
|
-
"
|
|
267
|
-
"
|
|
268
|
-
|
|
269
|
-
|
|
301
|
+
if (mgr.id === "pm2" && code === 0) {
|
|
302
|
+
await spawnExit([mgr.bin, "save"]);
|
|
303
|
+
if (process.platform === "win32") await spawnExit([
|
|
304
|
+
"reg",
|
|
305
|
+
"delete",
|
|
306
|
+
WIN_RUN_KEY,
|
|
307
|
+
"/v",
|
|
308
|
+
WIN_RUN_VALUE,
|
|
309
|
+
"/f"
|
|
310
|
+
]);
|
|
311
|
+
}
|
|
270
312
|
return code;
|
|
271
313
|
}
|
|
272
314
|
if (sub === "logs") return await Bun.spawn([
|
|
@@ -281,6 +323,56 @@ async function cmdServeDaemon(sub, args) {
|
|
|
281
323
|
] }).exited ?? 1;
|
|
282
324
|
return 1;
|
|
283
325
|
}
|
|
326
|
+
async function cmdServeStatus(args) {
|
|
327
|
+
const json = args.includes("--json");
|
|
328
|
+
const mgr = resolveDaemonManager();
|
|
329
|
+
const token = await loadTokenReadOnly();
|
|
330
|
+
const shareLink = await readShareLink();
|
|
331
|
+
const daemonArgs = mgr ? await readDaemonServeArgs(mgr) : null;
|
|
332
|
+
const installed = daemonArgs !== null;
|
|
333
|
+
const a = daemonArgs ?? [];
|
|
334
|
+
const port = portFromArgs(a);
|
|
335
|
+
const webrtcish = a.some((x) => x.startsWith("--webrtc") || x.startsWith("--share"));
|
|
336
|
+
const httpish = a.some((x) => x.startsWith("--http") || x.startsWith("--share")) || !a.some((x) => x.startsWith("--webrtc"));
|
|
337
|
+
const mode = httpish && webrtcish ? "http+webrtc" : webrtcish ? "webrtc" : "http";
|
|
338
|
+
const runningVersion = httpish && token ? await fetchDaemonVersion(port, token) : null;
|
|
339
|
+
const current = getInstalledPackage().version;
|
|
340
|
+
if (json) {
|
|
341
|
+
process.stdout.write(JSON.stringify({
|
|
342
|
+
manager: mgr?.id ?? null,
|
|
343
|
+
installed,
|
|
344
|
+
mode,
|
|
345
|
+
port: httpish ? port : null,
|
|
346
|
+
reachable: runningVersion !== null,
|
|
347
|
+
runningVersion,
|
|
348
|
+
currentVersion: current,
|
|
349
|
+
upToDate: runningVersion !== null && runningVersion === current,
|
|
350
|
+
args: a,
|
|
351
|
+
hasToken: !!token,
|
|
352
|
+
shareLink
|
|
353
|
+
}, null, 2) + "\n");
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
const w = (s = "") => process.stdout.write(s + "\n");
|
|
357
|
+
w(`daemon name: ${DAEMON_NAME}`);
|
|
358
|
+
w(`manager: ${mgr ? mgr.id : "none — install pm2 or oxmgr to daemonize"}`);
|
|
359
|
+
if (installed) {
|
|
360
|
+
w(`installed: yes (via ${mgr.id})`);
|
|
361
|
+
w(`mode: ${mode}${httpish ? ` (port ${port})` : ""}`);
|
|
362
|
+
if (a.length) w(`args: ${a.join(" ")}`);
|
|
363
|
+
} else w(`installed: no — start a daemon with: ay serve install [--share]`);
|
|
364
|
+
if (runningVersion !== null) w(`http api: reachable on 127.0.0.1:${port} — v${runningVersion} (${runningVersion === current ? "up to date" : `outdated (current v${current})`})`);
|
|
365
|
+
else if (mode === "webrtc") w(`http api: none (webrtc-only)`);
|
|
366
|
+
else w(`http api: not reachable on 127.0.0.1:${port} (not running)`);
|
|
367
|
+
w(`token: ${token ?? "(none yet — created on first serve)"}`);
|
|
368
|
+
if (shareLink) w(`share link: ${shareLink}`);
|
|
369
|
+
if (token && httpish) {
|
|
370
|
+
w();
|
|
371
|
+
w(`connect: ay ls ${token}@<host>:${port}`);
|
|
372
|
+
w(` ay remote add <alias> http://${token}@<host>:${port}`);
|
|
373
|
+
}
|
|
374
|
+
return 0;
|
|
375
|
+
}
|
|
284
376
|
async function cmdServe(rest) {
|
|
285
377
|
if (rest.includes("-h") || rest.includes("--help")) {
|
|
286
378
|
process.stdout.write(`Usage: ay serve [options]
|
|
@@ -298,10 +390,11 @@ Modes (default: --http):
|
|
|
298
390
|
--share [URL] Legacy alias for --http --webrtc
|
|
299
391
|
|
|
300
392
|
Options:
|
|
301
|
-
--port N Port to listen on (default: ${DEFAULT_PORT})\n --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)\n --token TOKEN Auth token (auto-generated and saved if omitted)\n -d, --daemon Install these flags as a background daemon (pm2/oxmgr)\n (same as: ay serve install <flags>)\n --allow-spawn Deprecated no-op — the console can always spawn agents\n --tls-cert FILE TLS certificate PEM\n --tls-key FILE TLS private key PEM\n\nSubcommands:\n ay serve install install as background daemon (pm2 on Windows, else oxmgr)\n ay serve uninstall remove daemon\n ay serve logs view daemon logs\n\nOnce running, connect from another machine:\n ay ls <token>@<host>:${DEFAULT_PORT}\n ay remote add <alias> http://<token>@<host>:${DEFAULT_PORT}\n`);
|
|
393
|
+
--port N Port to listen on (default: ${DEFAULT_PORT})\n --host HOST Interface to bind (default: 127.0.0.1; use 0.0.0.0 to expose)\n --token TOKEN Auth token (auto-generated and saved if omitted)\n -d, --daemon Install these flags as a background daemon (pm2/oxmgr)\n (same as: ay serve install <flags>)\n --allow-spawn Deprecated no-op — the console can always spawn agents\n --tls-cert FILE TLS certificate PEM\n --tls-key FILE TLS private key PEM\n\nSubcommands:\n ay serve install install as background daemon (pm2 on Windows, else oxmgr)\n ay serve status show daemon/server status (add --json for scripts)\n ay serve uninstall remove daemon\n ay serve logs view daemon logs\n\nOnce running, connect from another machine:\n ay ls <token>@<host>:${DEFAULT_PORT}\n ay remote add <alias> http://<token>@<host>:${DEFAULT_PORT}\n`);
|
|
302
394
|
return 0;
|
|
303
395
|
}
|
|
304
396
|
const sub = rest[0];
|
|
397
|
+
if (sub === "status") return cmdServeStatus(rest.slice(1));
|
|
305
398
|
if (sub === "install" || sub === "uninstall" || sub === "logs") return cmdServeDaemon(sub, rest.slice(1));
|
|
306
399
|
const argv = await yargs(rest).usage("Usage: ay serve [options]").option("port", {
|
|
307
400
|
type: "number",
|
|
@@ -741,9 +834,11 @@ Options:
|
|
|
741
834
|
const cwd = typeof body.cwd === "string" && body.cwd ? body.cwd : process.cwd();
|
|
742
835
|
const prompt = String(body.prompt ?? "");
|
|
743
836
|
process.stderr.write(`→ console spawned: ay ${cli}${prompt ? ` -- "${prompt.slice(0, 60)}"` : ""} (cwd: ${cwd})\n`);
|
|
837
|
+
const ayBin = Bun.which("ay") ?? process.argv[1];
|
|
838
|
+
const ayCmd = process.platform === "win32" && ayBin.toLowerCase().endsWith(".exe") ? [ayBin] : [process.execPath, ayBin];
|
|
744
839
|
try {
|
|
745
840
|
const child = Bun.spawn([
|
|
746
|
-
|
|
841
|
+
...ayCmd,
|
|
747
842
|
cli,
|
|
748
843
|
...prompt ? ["--", prompt] : []
|
|
749
844
|
], {
|
|
@@ -823,7 +918,7 @@ Options:
|
|
|
823
918
|
const webrtcVal = argv.webrtc ?? argv.share;
|
|
824
919
|
const explicitUrl = typeof webrtcVal === "string" && webrtcVal.startsWith("webrtc://") ? webrtcVal : void 0;
|
|
825
920
|
try {
|
|
826
|
-
const { startShare, loadOrCreateShareRoom } = await import("./share-
|
|
921
|
+
const { startShare, loadOrCreateShareRoom } = await import("./share-ClsUSd_0.js");
|
|
827
922
|
const { room, link, close } = await startShare({
|
|
828
923
|
url: explicitUrl ?? await loadOrCreateShareRoom(),
|
|
829
924
|
localFetch: apiFetch,
|
|
@@ -862,4 +957,4 @@ Options:
|
|
|
862
957
|
|
|
863
958
|
//#endregion
|
|
864
959
|
export { cmdServe };
|
|
865
|
-
//# sourceMappingURL=serve-
|
|
960
|
+
//# sourceMappingURL=serve-VczpuYDk.js.map
|
|
@@ -1,45 +1,8 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { existsSync as existsSync$1 } from "node:fs";
|
|
1
|
+
import { r as setWorkspaceRoot, t as getWorkspaceRoot } from "./workspaceConfig-XP2NEWmV.js";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
6
3
|
import { stdin, stdout } from "node:process";
|
|
7
4
|
import { createInterface } from "node:readline/promises";
|
|
8
5
|
|
|
9
|
-
//#region ts/workspaceConfig.ts
|
|
10
|
-
function configPath() {
|
|
11
|
-
return path.join(agentYesHome(), "config.json");
|
|
12
|
-
}
|
|
13
|
-
function readConfig() {
|
|
14
|
-
try {
|
|
15
|
-
return JSON.parse(readFileSync(configPath(), "utf-8"));
|
|
16
|
-
} catch {
|
|
17
|
-
return {};
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
/** Expand a leading `~` (`~` or `~/x`) to an absolute home-based path. */
|
|
21
|
-
function expandTilde(p) {
|
|
22
|
-
const s = p.trim();
|
|
23
|
-
if (s === "~") return homedir();
|
|
24
|
-
if (s.startsWith("~/") || s.startsWith("~\\")) return path.join(homedir(), s.slice(2));
|
|
25
|
-
return s;
|
|
26
|
-
}
|
|
27
|
-
/** The configured workspace root (absolute), or the home dir if unset. */
|
|
28
|
-
function getWorkspaceRoot() {
|
|
29
|
-
const w = readConfig().workspace;
|
|
30
|
-
return w && w.trim() ? w : homedir();
|
|
31
|
-
}
|
|
32
|
-
/** Persist the workspace root, tilde-expanded and resolved to an absolute path. */
|
|
33
|
-
function setWorkspaceRoot(dir) {
|
|
34
|
-
const abs = path.resolve(expandTilde(dir));
|
|
35
|
-
const cfg = readConfig();
|
|
36
|
-
cfg.workspace = abs;
|
|
37
|
-
mkdirSync(agentYesHome(), { recursive: true });
|
|
38
|
-
writeFileSync(configPath(), JSON.stringify(cfg, null, 2));
|
|
39
|
-
return abs;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
//#endregion
|
|
43
6
|
//#region ts/setup.ts
|
|
44
7
|
async function cmdSetup(rest) {
|
|
45
8
|
if (rest.includes("-h") || rest.includes("--help")) {
|
|
@@ -66,10 +29,10 @@ async function cmdSetup(rest) {
|
|
|
66
29
|
}
|
|
67
30
|
const abs = setWorkspaceRoot(ws);
|
|
68
31
|
process.stdout.write(`workspace root: ${abs}\n`);
|
|
69
|
-
if (!existsSync
|
|
32
|
+
if (!existsSync(abs)) process.stderr.write(` note: that directory doesn't exist yet — create it, or agents spawned there will fail\n`);
|
|
70
33
|
if (noShare) return 0;
|
|
71
34
|
process.stdout.write(`\nsharing this machine to agent-yes.com…\n`);
|
|
72
|
-
const { cmdServe } = await import("./serve-
|
|
35
|
+
const { cmdServe } = await import("./serve-VczpuYDk.js");
|
|
73
36
|
return cmdServe([
|
|
74
37
|
"install",
|
|
75
38
|
"--share",
|
|
@@ -79,4 +42,4 @@ async function cmdSetup(rest) {
|
|
|
79
42
|
|
|
80
43
|
//#endregion
|
|
81
44
|
export { cmdSetup };
|
|
82
|
-
//# sourceMappingURL=setup-
|
|
45
|
+
//# sourceMappingURL=setup-DveWqmSR.js.map
|