agent-yes 1.84.0 → 1.86.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-BdYQ3v93.js → SUPPORTED_CLIS-BlWg00sP.js} +3 -3
- package/dist/cli.js +5 -5
- package/dist/index.js +2 -2
- package/dist/remotes-CFrho898.js +131 -0
- package/dist/remotes-kfUzk-JT.js +3 -0
- package/dist/serve-D0NnTXRD.js +303 -0
- package/dist/subcommands-BDiS305D.js +6 -0
- package/dist/{subcommands-DjO8lthH.js → subcommands-BpGEGOQM.js} +440 -78
- package/dist/{tray-CH_G7aXM.js → tray-DHuD0nEk.js} +1 -1
- package/dist/{ts-DP0dIeoe.js → ts-DWuvdSWr.js} +2 -2
- package/dist/{versionChecker-DtDqoy3L.js → versionChecker-BCrJk4Zj.js} +2 -2
- package/package.json +1 -1
- package/ts/remotes.ts +161 -0
- package/ts/serve.ts +373 -0
- package/ts/subcommands.spec.ts +478 -35
- package/ts/subcommands.ts +544 -95
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import "./logger-B9h0djqx.js";
|
|
2
1
|
import { r as readGlobalPids } from "./globalPidIndex-Cr-g75QF.js";
|
|
2
|
+
import { a as resolveRemoteSpec, i as readRemotes } from "./remotes-CFrho898.js";
|
|
3
|
+
import yargs from "yargs";
|
|
3
4
|
import { appendFile, mkdir, open, readFile, stat, writeFile } from "fs/promises";
|
|
4
5
|
import { homedir } from "os";
|
|
5
6
|
import path from "path";
|
|
@@ -125,7 +126,9 @@ const SUBCOMMANDS = new Set([
|
|
|
125
126
|
"head",
|
|
126
127
|
"send",
|
|
127
128
|
"restart",
|
|
128
|
-
"note"
|
|
129
|
+
"note",
|
|
130
|
+
"serve",
|
|
131
|
+
"remote"
|
|
129
132
|
]);
|
|
130
133
|
const IDLE_THRESHOLD_MS = 60 * 1e3;
|
|
131
134
|
function isSubcommand(name) {
|
|
@@ -152,6 +155,14 @@ async function runSubcommand(argv) {
|
|
|
152
155
|
case "send": return await cmdSend(rest);
|
|
153
156
|
case "restart": return await cmdRestart(rest);
|
|
154
157
|
case "note": return await cmdNote(rest);
|
|
158
|
+
case "serve": {
|
|
159
|
+
const { cmdServe } = await import("./serve-D0NnTXRD.js");
|
|
160
|
+
return cmdServe(rest);
|
|
161
|
+
}
|
|
162
|
+
case "remote": {
|
|
163
|
+
const { cmdRemote } = await import("./remotes-kfUzk-JT.js");
|
|
164
|
+
return cmdRemote(rest);
|
|
165
|
+
}
|
|
155
166
|
default: return null;
|
|
156
167
|
}
|
|
157
168
|
} catch (err) {
|
|
@@ -160,50 +171,6 @@ async function runSubcommand(argv) {
|
|
|
160
171
|
return 1;
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
|
-
function parseArgs(rest) {
|
|
164
|
-
const flags = {};
|
|
165
|
-
const positional = [];
|
|
166
|
-
for (let i = 0; i < rest.length; i++) {
|
|
167
|
-
const arg = rest[i];
|
|
168
|
-
if (arg.startsWith("--")) {
|
|
169
|
-
const eq = arg.indexOf("=");
|
|
170
|
-
if (eq >= 0) flags[arg.slice(2, eq)] = arg.slice(eq + 1);
|
|
171
|
-
else {
|
|
172
|
-
const key = arg.slice(2);
|
|
173
|
-
const next = rest[i + 1];
|
|
174
|
-
if ([
|
|
175
|
-
"all",
|
|
176
|
-
"active",
|
|
177
|
-
"follow",
|
|
178
|
-
"json",
|
|
179
|
-
"latest",
|
|
180
|
-
"watch"
|
|
181
|
-
].includes(key) || !next || next.startsWith("-")) flags[key] = true;
|
|
182
|
-
else {
|
|
183
|
-
flags[key] = next;
|
|
184
|
-
i++;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
} else if (arg.startsWith("-") && arg.length > 1) if (arg === "-n") {
|
|
188
|
-
flags["n"] = rest[i + 1] ?? "";
|
|
189
|
-
i++;
|
|
190
|
-
} else flags[arg.slice(1)] = true;
|
|
191
|
-
else positional.push(arg);
|
|
192
|
-
}
|
|
193
|
-
return {
|
|
194
|
-
flags,
|
|
195
|
-
positional
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
function commonOpts(flags) {
|
|
199
|
-
return {
|
|
200
|
-
all: !!flags.all,
|
|
201
|
-
active: !!flags.active,
|
|
202
|
-
cwdScope: typeof flags.cwd === "string" ? path.resolve(flags.cwd) : flags.cwd === true ? process.cwd() : null,
|
|
203
|
-
latest: !!flags.latest,
|
|
204
|
-
json: !!flags.json
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
174
|
function matchKeyword(record, keyword) {
|
|
208
175
|
if (!keyword) return true;
|
|
209
176
|
const kw = keyword.toLowerCase();
|
|
@@ -242,10 +209,309 @@ async function resolveOne(keyword, opts) {
|
|
|
242
209
|
const lines = matches.slice(0, 10).map((r) => ` ${r.pid} ${r.cli} ${r.cwd}`).join("\n");
|
|
243
210
|
throw new Error(`keyword "${keyword}" matched ${matches.length} agents — disambiguate by pid or pass --latest:\n${lines}`);
|
|
244
211
|
}
|
|
212
|
+
async function remoteGet(remote, pathname) {
|
|
213
|
+
return fetch(`${remote.url}${pathname}`, { headers: { Authorization: `Bearer ${remote.token}` } });
|
|
214
|
+
}
|
|
215
|
+
async function remotePost(remote, pathname, body) {
|
|
216
|
+
return fetch(`${remote.url}${pathname}`, {
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: {
|
|
219
|
+
Authorization: `Bearer ${remote.token}`,
|
|
220
|
+
"Content-Type": "application/json"
|
|
221
|
+
},
|
|
222
|
+
body: JSON.stringify(body)
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
async function runRemoteLs(remote, opts) {
|
|
226
|
+
const params = new URLSearchParams();
|
|
227
|
+
if (remote.keyword) params.set("keyword", remote.keyword);
|
|
228
|
+
if (opts.all) params.set("all", "1");
|
|
229
|
+
if (opts.active) params.set("active", "1");
|
|
230
|
+
const res = await remoteGet(remote, `/api/ls?${params}`);
|
|
231
|
+
if (!res.ok) {
|
|
232
|
+
process.stderr.write(`remote error ${res.status}: ${await res.text()}\n`);
|
|
233
|
+
return 1;
|
|
234
|
+
}
|
|
235
|
+
const records = await res.json();
|
|
236
|
+
if (records.length === 0) {
|
|
237
|
+
process.stderr.write(remote.keyword ? `no agents matched "${remote.keyword}" on ${remote.url}\n` : `no running agents on ${remote.url}\n`);
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
process.stderr.write(`[remote ${remote.url}]\n`);
|
|
241
|
+
const termWidth = process.stdout.columns ?? 120;
|
|
242
|
+
const widths = {
|
|
243
|
+
pid: Math.max(3, ...records.map((r) => String(r.pid).length)),
|
|
244
|
+
cli: Math.max(3, ...records.map((r) => String(r.cli).length)),
|
|
245
|
+
status: Math.max(6, ...records.map((r) => String(r.status).length)),
|
|
246
|
+
cwd: Math.max(3, ...records.map((r) => String(r.cwd).length))
|
|
247
|
+
};
|
|
248
|
+
const fixedWidth = widths.pid + widths.cli + widths.status + widths.cwd + 8;
|
|
249
|
+
const promptBudget = Math.max(20, termWidth - fixedWidth - 1);
|
|
250
|
+
const header = [
|
|
251
|
+
"PID".padEnd(widths.pid),
|
|
252
|
+
"CLI".padEnd(widths.cli),
|
|
253
|
+
"STATUS".padEnd(widths.status),
|
|
254
|
+
"CWD".padEnd(widths.cwd),
|
|
255
|
+
"PROMPT"
|
|
256
|
+
].join(" ") + "\n";
|
|
257
|
+
process.stdout.write(header);
|
|
258
|
+
for (const r of records) {
|
|
259
|
+
const label = r.prompt ? truncate(`→ ${r.prompt}`, promptBudget) : "";
|
|
260
|
+
process.stdout.write([
|
|
261
|
+
String(r.pid).padEnd(widths.pid),
|
|
262
|
+
String(r.cli).padEnd(widths.cli),
|
|
263
|
+
String(r.status).padEnd(widths.status),
|
|
264
|
+
String(r.cwd).padEnd(widths.cwd),
|
|
265
|
+
label
|
|
266
|
+
].join(" ") + "\n");
|
|
267
|
+
}
|
|
268
|
+
return 0;
|
|
269
|
+
}
|
|
270
|
+
async function runRemoteRead(remote, mode, follow, n, reconnectTimeoutMs = 12e4) {
|
|
271
|
+
const keyword = remote.keyword ?? "";
|
|
272
|
+
if (!keyword) {
|
|
273
|
+
process.stderr.write("remote tail/cat/head requires a keyword (e.g. token@host:port:keyword)\n");
|
|
274
|
+
return 1;
|
|
275
|
+
}
|
|
276
|
+
if (mode === "tail" && follow) {
|
|
277
|
+
const ac = new AbortController();
|
|
278
|
+
process.on("SIGINT", () => ac.abort());
|
|
279
|
+
const deadline = Date.now() + reconnectTimeoutMs;
|
|
280
|
+
let delay = 1e3;
|
|
281
|
+
let attempt = 0;
|
|
282
|
+
process.stderr.write(`[remote ${remote.url} ${keyword}]\nfollowing... (Ctrl-C to stop, timeout: ${Math.round(reconnectTimeoutMs / 1e3)}s)\n`);
|
|
283
|
+
while (!ac.signal.aborted) try {
|
|
284
|
+
const res = await fetch(`${remote.url}/api/tail/${encodeURIComponent(keyword)}`, {
|
|
285
|
+
headers: {
|
|
286
|
+
Authorization: `Bearer ${remote.token}`,
|
|
287
|
+
Accept: "text/event-stream"
|
|
288
|
+
},
|
|
289
|
+
signal: ac.signal
|
|
290
|
+
});
|
|
291
|
+
if (!res.ok) {
|
|
292
|
+
if (res.status === 401 || res.status === 404) {
|
|
293
|
+
process.stderr.write(`remote error ${res.status}: ${await res.text()}\n`);
|
|
294
|
+
return 1;
|
|
295
|
+
}
|
|
296
|
+
throw new Error(`HTTP ${res.status}`);
|
|
297
|
+
}
|
|
298
|
+
if (attempt > 0) process.stderr.write("remote: reconnected\n");
|
|
299
|
+
delay = 1e3;
|
|
300
|
+
const reader = res.body.getReader();
|
|
301
|
+
const dec = new TextDecoder();
|
|
302
|
+
let buf = "";
|
|
303
|
+
while (true) {
|
|
304
|
+
const { done, value } = await reader.read();
|
|
305
|
+
if (done) break;
|
|
306
|
+
buf += dec.decode(value, { stream: true });
|
|
307
|
+
const lines = buf.split("\n");
|
|
308
|
+
buf = lines.pop() ?? "";
|
|
309
|
+
for (const line of lines) {
|
|
310
|
+
if (!line.startsWith("data: ")) continue;
|
|
311
|
+
try {
|
|
312
|
+
const text = JSON.parse(line.slice(6));
|
|
313
|
+
process.stdout.write(text);
|
|
314
|
+
if (!text.endsWith("\n")) process.stdout.write("\n");
|
|
315
|
+
} catch {}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
break;
|
|
319
|
+
} catch (e) {
|
|
320
|
+
if (e.name === "AbortError" || ac.signal.aborted) return 0;
|
|
321
|
+
if (Date.now() >= deadline) {
|
|
322
|
+
process.stderr.write(`remote: timeout after ${Math.round(reconnectTimeoutMs / 1e3)}s, giving up\n`);
|
|
323
|
+
return 1;
|
|
324
|
+
}
|
|
325
|
+
process.stderr.write(`remote: disconnected (${e.message}), retrying in ${delay / 1e3}s…\n`);
|
|
326
|
+
await new Promise((resolve, reject) => {
|
|
327
|
+
const t = setTimeout(resolve, delay);
|
|
328
|
+
ac.signal.addEventListener("abort", () => {
|
|
329
|
+
clearTimeout(t);
|
|
330
|
+
reject(/* @__PURE__ */ new Error("abort"));
|
|
331
|
+
});
|
|
332
|
+
}).catch(() => {});
|
|
333
|
+
if (ac.signal.aborted) return 0;
|
|
334
|
+
delay = Math.min(delay * 2, 3e4);
|
|
335
|
+
attempt++;
|
|
336
|
+
}
|
|
337
|
+
return 0;
|
|
338
|
+
}
|
|
339
|
+
const params = new URLSearchParams({
|
|
340
|
+
mode,
|
|
341
|
+
n: String(n)
|
|
342
|
+
});
|
|
343
|
+
const res = await remoteGet(remote, `/api/read/${encodeURIComponent(keyword)}?${params}`);
|
|
344
|
+
if (!res.ok) {
|
|
345
|
+
process.stderr.write(`remote error ${res.status}: ${await res.text()}\n`);
|
|
346
|
+
return 1;
|
|
347
|
+
}
|
|
348
|
+
const text = await res.text();
|
|
349
|
+
process.stderr.write(`[remote ${remote.url} ${keyword}]\n`);
|
|
350
|
+
process.stdout.write(text);
|
|
351
|
+
if (!text.endsWith("\n")) process.stdout.write("\n");
|
|
352
|
+
return 0;
|
|
353
|
+
}
|
|
354
|
+
async function runRemoteSend(remote, msg, code) {
|
|
355
|
+
const keyword = remote.keyword ?? "";
|
|
356
|
+
if (!keyword) {
|
|
357
|
+
process.stderr.write("remote send requires a keyword (e.g. token@host:port:keyword)\n");
|
|
358
|
+
return 1;
|
|
359
|
+
}
|
|
360
|
+
const res = await remotePost(remote, "/api/send", {
|
|
361
|
+
keyword,
|
|
362
|
+
msg,
|
|
363
|
+
code
|
|
364
|
+
});
|
|
365
|
+
if (!res.ok) {
|
|
366
|
+
process.stderr.write(`remote error ${res.status}: ${await res.text()}\n`);
|
|
367
|
+
return 1;
|
|
368
|
+
}
|
|
369
|
+
const data = await res.json();
|
|
370
|
+
process.stdout.write(`sent to remote pid ${data.pid} (${remote.url} ${keyword})\n`);
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
373
|
+
async function runRemoteStatus(remote) {
|
|
374
|
+
const keyword = remote.keyword ?? "";
|
|
375
|
+
if (!keyword) {
|
|
376
|
+
process.stderr.write("remote status requires a keyword (e.g. token@host:port:keyword)\n");
|
|
377
|
+
return 1;
|
|
378
|
+
}
|
|
379
|
+
const res = await remoteGet(remote, `/api/status/${encodeURIComponent(keyword)}`);
|
|
380
|
+
if (!res.ok) {
|
|
381
|
+
process.stderr.write(`remote error ${res.status}: ${await res.text()}\n`);
|
|
382
|
+
return 1;
|
|
383
|
+
}
|
|
384
|
+
process.stdout.write(JSON.stringify(await res.json(), null, 2) + "\n");
|
|
385
|
+
return 0;
|
|
386
|
+
}
|
|
387
|
+
async function fetchRemoteRecordsRaw(url, token, opts) {
|
|
388
|
+
const params = new URLSearchParams();
|
|
389
|
+
if (opts.all) params.set("all", "1");
|
|
390
|
+
if (opts.active) params.set("active", "1");
|
|
391
|
+
if (opts.keyword) params.set("keyword", opts.keyword);
|
|
392
|
+
try {
|
|
393
|
+
const res = await fetch(`${url}/api/ls?${params}`, {
|
|
394
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
395
|
+
signal: AbortSignal.timeout(5e3)
|
|
396
|
+
});
|
|
397
|
+
if (!res.ok) return [];
|
|
398
|
+
return await res.json();
|
|
399
|
+
} catch {
|
|
400
|
+
return [];
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
async function runAllRemotesLs(opts) {
|
|
404
|
+
const remotes = await readRemotes();
|
|
405
|
+
const localOpts = {
|
|
406
|
+
all: opts.all,
|
|
407
|
+
active: opts.active,
|
|
408
|
+
json: true,
|
|
409
|
+
latest: false,
|
|
410
|
+
cwdScope: null
|
|
411
|
+
};
|
|
412
|
+
const [localResult, ...remoteResults] = await Promise.allSettled([listRecords(opts.keyword, localOpts).then((recs) => ({
|
|
413
|
+
host: "local",
|
|
414
|
+
records: recs
|
|
415
|
+
})), ...Array.from(remotes.entries()).map(([alias, cfg]) => fetchRemoteRecordsRaw(cfg.url, cfg.token, opts).then((records) => ({
|
|
416
|
+
host: alias,
|
|
417
|
+
records
|
|
418
|
+
})))]);
|
|
419
|
+
const rows = [];
|
|
420
|
+
if (localResult.status === "fulfilled") for (const r of localResult.value.records) rows.push({
|
|
421
|
+
host: "local",
|
|
422
|
+
rec: r
|
|
423
|
+
});
|
|
424
|
+
for (const res of remoteResults) if (res.status === "fulfilled") for (const r of res.value.records) rows.push({
|
|
425
|
+
host: res.value.host,
|
|
426
|
+
rec: r
|
|
427
|
+
});
|
|
428
|
+
if (rows.length === 0) {
|
|
429
|
+
process.stderr.write("no running agents\n");
|
|
430
|
+
return 0;
|
|
431
|
+
}
|
|
432
|
+
const termWidth = process.stdout.columns ?? 120;
|
|
433
|
+
const hostW = Math.max(4, ...rows.map((r) => r.host.length));
|
|
434
|
+
const pidW = Math.max(3, ...rows.map((r) => String(r.rec.pid).length));
|
|
435
|
+
const cliW = Math.max(3, ...rows.map((r) => String(r.rec.cli).length));
|
|
436
|
+
const statusW = Math.max(6, ...rows.map((r) => String(r.rec.status).length));
|
|
437
|
+
const cwdW = Math.max(3, ...rows.map((r) => shortenPath(String(r.rec.cwd)).length));
|
|
438
|
+
const promptBudget = Math.max(20, termWidth - hostW - pidW - cliW - statusW - cwdW - 10 - 1);
|
|
439
|
+
process.stdout.write([
|
|
440
|
+
"HOST".padEnd(hostW),
|
|
441
|
+
"PID".padEnd(pidW),
|
|
442
|
+
"CLI".padEnd(cliW),
|
|
443
|
+
"STATUS".padEnd(statusW),
|
|
444
|
+
"CWD".padEnd(cwdW),
|
|
445
|
+
"PROMPT"
|
|
446
|
+
].join(" ") + "\n");
|
|
447
|
+
for (const { host, rec } of rows) {
|
|
448
|
+
const label = rec.prompt ? truncate(`→ ${rec.prompt}`, promptBudget) : "";
|
|
449
|
+
process.stdout.write([
|
|
450
|
+
host.padEnd(hostW),
|
|
451
|
+
String(rec.pid).padEnd(pidW),
|
|
452
|
+
String(rec.cli).padEnd(cliW),
|
|
453
|
+
String(rec.status).padEnd(statusW),
|
|
454
|
+
shortenPath(String(rec.cwd)).padEnd(cwdW),
|
|
455
|
+
label
|
|
456
|
+
].join(" ") + "\n");
|
|
457
|
+
}
|
|
458
|
+
return 0;
|
|
459
|
+
}
|
|
245
460
|
async function cmdLs(rest) {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
461
|
+
const y = yargs(rest).usage("Usage: ay ls [keyword] [options]\n ay list [keyword] [options]\n ay ps [keyword] [options]\n\nList running agents. Optionally filter by keyword (pid, cwd substring, or prompt substring).").option("all", {
|
|
462
|
+
type: "boolean",
|
|
463
|
+
default: false,
|
|
464
|
+
description: "Show all agents including exited ones"
|
|
465
|
+
}).option("active", {
|
|
466
|
+
type: "boolean",
|
|
467
|
+
default: false,
|
|
468
|
+
description: "Only show agents with an alive process"
|
|
469
|
+
}).option("json", {
|
|
470
|
+
type: "boolean",
|
|
471
|
+
default: false,
|
|
472
|
+
description: "Output as JSON array"
|
|
473
|
+
}).option("latest", {
|
|
474
|
+
type: "boolean",
|
|
475
|
+
default: false,
|
|
476
|
+
description: "Show only the most recent agent"
|
|
477
|
+
}).option("cwd", {
|
|
478
|
+
type: "string",
|
|
479
|
+
description: "Restrict to agents whose cwd starts with dir"
|
|
480
|
+
}).option("all-remotes", {
|
|
481
|
+
type: "boolean",
|
|
482
|
+
default: false,
|
|
483
|
+
description: "Include agents from all configured remotes (remotes.yaml)"
|
|
484
|
+
}).option("help", {
|
|
485
|
+
alias: "h",
|
|
486
|
+
type: "boolean",
|
|
487
|
+
default: false,
|
|
488
|
+
description: "Show this help"
|
|
489
|
+
}).example("ay ls", "list running agents").example("ay ls --all-remotes", "include all configured remote machines").example("ay ls --all", "include exited agents").example("ay ls --json", "machine-readable output").example("ay ls symval", "filter by cwd/prompt keyword").help(false).version(false).exitProcess(false);
|
|
490
|
+
const argv = await y.parseAsync();
|
|
491
|
+
if (argv.help || argv.h) {
|
|
492
|
+
process.stdout.write(await y.getHelp() + "\n");
|
|
493
|
+
return 0;
|
|
494
|
+
}
|
|
495
|
+
if (argv["all-remotes"]) return runAllRemotesLs({
|
|
496
|
+
all: argv.all,
|
|
497
|
+
active: argv.active,
|
|
498
|
+
keyword: argv._[0] !== void 0 ? String(argv._[0]) : void 0
|
|
499
|
+
});
|
|
500
|
+
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
501
|
+
if (keyword) {
|
|
502
|
+
const remote = await resolveRemoteSpec(keyword);
|
|
503
|
+
if (remote) return runRemoteLs(remote, {
|
|
504
|
+
all: argv.all,
|
|
505
|
+
active: argv.active
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
const opts = {
|
|
509
|
+
all: argv.all,
|
|
510
|
+
active: argv.active,
|
|
511
|
+
json: argv.json,
|
|
512
|
+
latest: argv.latest,
|
|
513
|
+
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
514
|
+
};
|
|
249
515
|
const records = await listRecords(keyword, opts);
|
|
250
516
|
if (opts.json) {
|
|
251
517
|
process.stdout.write(JSON.stringify(records, null, 2) + "\n");
|
|
@@ -349,11 +615,47 @@ function truncate(s, n) {
|
|
|
349
615
|
return s.slice(0, n - 1) + "…";
|
|
350
616
|
}
|
|
351
617
|
async function cmdRead(rest, { mode }) {
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
618
|
+
const argv = await yargs(rest).usage("Usage: ay read/cat/tail/head <keyword> [options]").option("follow", {
|
|
619
|
+
alias: "f",
|
|
620
|
+
type: "boolean",
|
|
621
|
+
default: false,
|
|
622
|
+
description: "Follow log output (Ctrl-C to stop)"
|
|
623
|
+
}).option("n", {
|
|
624
|
+
type: "number",
|
|
625
|
+
description: "Number of lines (default: 96 for tail/head)"
|
|
626
|
+
}).option("all", {
|
|
627
|
+
type: "boolean",
|
|
628
|
+
default: false,
|
|
629
|
+
description: "Include exited agents"
|
|
630
|
+
}).option("latest", {
|
|
631
|
+
type: "boolean",
|
|
632
|
+
default: false,
|
|
633
|
+
description: "Use most recent match when multiple match"
|
|
634
|
+
}).option("cwd", {
|
|
635
|
+
type: "string",
|
|
636
|
+
description: "Restrict to agents under this dir"
|
|
637
|
+
}).option("reconnect-timeout", {
|
|
638
|
+
type: "number",
|
|
639
|
+
default: 120,
|
|
640
|
+
description: "Seconds before giving up reconnecting remote SSE (default: 120)"
|
|
641
|
+
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
642
|
+
const opts = {
|
|
643
|
+
all: argv.all,
|
|
644
|
+
active: false,
|
|
645
|
+
json: false,
|
|
646
|
+
latest: argv.latest,
|
|
647
|
+
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
648
|
+
};
|
|
649
|
+
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
650
|
+
if (keyword) {
|
|
651
|
+
const remote = await resolveRemoteSpec(keyword);
|
|
652
|
+
const nFlag2 = argv.n;
|
|
653
|
+
const n2 = nFlag2 !== void 0 && Number.isFinite(nFlag2) && nFlag2 > 0 ? Math.floor(nFlag2) : mode === "cat" ? 0 : 96;
|
|
654
|
+
const reconnectTimeoutMs = (argv["reconnect-timeout"] ?? 120) * 1e3;
|
|
655
|
+
if (remote) return runRemoteRead(remote, mode, argv.follow, n2, reconnectTimeoutMs);
|
|
656
|
+
}
|
|
657
|
+
const follow = argv.follow;
|
|
658
|
+
const nFlag = argv.n;
|
|
357
659
|
const n = nFlag !== void 0 && Number.isFinite(nFlag) && nFlag > 0 ? Math.floor(nFlag) : mode === "cat" ? 0 : 96;
|
|
358
660
|
const record = await resolveOne(keyword, opts);
|
|
359
661
|
const logPath = record.log_file;
|
|
@@ -512,12 +814,38 @@ function extractActivityFromLines(lines) {
|
|
|
512
814
|
return null;
|
|
513
815
|
}
|
|
514
816
|
async function cmdSend(rest) {
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
817
|
+
const argv = await yargs(rest).usage("Usage: ay send <keyword> <msg|-> [options]").option("code", {
|
|
818
|
+
type: "string",
|
|
819
|
+
default: "enter",
|
|
820
|
+
description: "Trailing control code (enter|esc|ctrl-c|ctrl-y|tab|none)"
|
|
821
|
+
}).option("all", {
|
|
822
|
+
type: "boolean",
|
|
823
|
+
default: false,
|
|
824
|
+
description: "Include exited agents"
|
|
825
|
+
}).option("latest", {
|
|
826
|
+
type: "boolean",
|
|
827
|
+
default: false,
|
|
828
|
+
description: "Use most recent match"
|
|
829
|
+
}).option("cwd", {
|
|
830
|
+
type: "string",
|
|
831
|
+
description: "Restrict to agents under this dir"
|
|
832
|
+
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
833
|
+
const opts = {
|
|
834
|
+
all: argv.all,
|
|
835
|
+
active: false,
|
|
836
|
+
json: false,
|
|
837
|
+
latest: argv.latest,
|
|
838
|
+
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
839
|
+
};
|
|
840
|
+
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
841
|
+
const rawMessage = argv._.slice(1).map(String).join(" ");
|
|
519
842
|
if (!keyword) throw new Error("usage: ay send <keyword> <msg|-> [--code=enter|esc|ctrl-c|ctrl-y|tab|none]");
|
|
520
|
-
const
|
|
843
|
+
const codeName = argv.code.toLowerCase();
|
|
844
|
+
{
|
|
845
|
+
const remote = await resolveRemoteSpec(keyword);
|
|
846
|
+
if (remote) return runRemoteSend(remote, rawMessage, codeName);
|
|
847
|
+
}
|
|
848
|
+
const trailing = controlCodeFromName(codeName);
|
|
521
849
|
const record = await resolveOne(keyword, opts);
|
|
522
850
|
const fifoPath = record.fifo_file;
|
|
523
851
|
if (!fifoPath) throw new Error(`pid ${record.pid}: no fifo_file recorded — agent was not started with --stdpush (or was spawned by Rust which doesn't yet support FIFO IPC; see ROADMAP item 10)`);
|
|
@@ -594,13 +922,22 @@ async function writeToIpc(ipcPath, payload) {
|
|
|
594
922
|
}
|
|
595
923
|
}
|
|
596
924
|
async function cmdRestart(rest) {
|
|
597
|
-
const
|
|
925
|
+
const argv = await yargs(rest).usage("Usage: ay restart <keyword>").option("latest", {
|
|
926
|
+
type: "boolean",
|
|
927
|
+
default: false,
|
|
928
|
+
description: "Use most recent match"
|
|
929
|
+
}).option("cwd", {
|
|
930
|
+
type: "string",
|
|
931
|
+
description: "Restrict to agents under this dir"
|
|
932
|
+
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
598
933
|
const opts = {
|
|
599
|
-
|
|
600
|
-
|
|
934
|
+
all: true,
|
|
935
|
+
active: false,
|
|
936
|
+
json: false,
|
|
937
|
+
latest: argv.latest,
|
|
938
|
+
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
601
939
|
};
|
|
602
|
-
const
|
|
603
|
-
const record = await resolveOne(keyword, opts);
|
|
940
|
+
const record = await resolveOne(argv._[0] !== void 0 ? String(argv._[0]) : void 0, opts);
|
|
604
941
|
if (isPidAlive(record.pid)) {
|
|
605
942
|
process.stderr.write(`pid ${record.pid} is still running — stop it first or use ay send\n`);
|
|
606
943
|
return 1;
|
|
@@ -621,14 +958,16 @@ async function cmdRestart(rest) {
|
|
|
621
958
|
return 0;
|
|
622
959
|
}
|
|
623
960
|
async function cmdNote(rest) {
|
|
624
|
-
const
|
|
625
|
-
const
|
|
626
|
-
const
|
|
627
|
-
const note = positional.slice(1).join(" ");
|
|
961
|
+
const argv = await yargs(rest).usage("Usage: ay note <keyword> [\"note text\"]").help(false).version(false).exitProcess(false).parseAsync();
|
|
962
|
+
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
963
|
+
const note = argv._.slice(1).map(String).join(" ");
|
|
628
964
|
if (!keyword) throw new Error("usage: ay note <keyword> [\"note text\"] (omit text to clear)");
|
|
629
965
|
const record = await resolveOne(keyword, {
|
|
630
|
-
|
|
631
|
-
|
|
966
|
+
all: true,
|
|
967
|
+
active: false,
|
|
968
|
+
json: false,
|
|
969
|
+
latest: false,
|
|
970
|
+
cwdScope: null
|
|
632
971
|
});
|
|
633
972
|
if (!note) {
|
|
634
973
|
await writeNote(record.pid, "");
|
|
@@ -668,15 +1007,38 @@ async function snapshotStatus(record) {
|
|
|
668
1007
|
};
|
|
669
1008
|
}
|
|
670
1009
|
async function cmdStatus(rest) {
|
|
671
|
-
const
|
|
1010
|
+
const argv = await yargs(rest).usage("Usage: ay status <keyword> [options]").option("watch", {
|
|
1011
|
+
alias: "w",
|
|
1012
|
+
type: "boolean",
|
|
1013
|
+
default: false,
|
|
1014
|
+
description: "Stream changes as JSON"
|
|
1015
|
+
}).option("interval", {
|
|
1016
|
+
type: "number",
|
|
1017
|
+
default: 2,
|
|
1018
|
+
description: "Poll interval in seconds"
|
|
1019
|
+
}).option("latest", {
|
|
1020
|
+
type: "boolean",
|
|
1021
|
+
default: false,
|
|
1022
|
+
description: "Use most recent match"
|
|
1023
|
+
}).option("cwd", {
|
|
1024
|
+
type: "string",
|
|
1025
|
+
description: "Restrict to agents under this dir"
|
|
1026
|
+
}).help(false).version(false).exitProcess(false).parseAsync();
|
|
672
1027
|
const opts = {
|
|
673
|
-
|
|
674
|
-
|
|
1028
|
+
all: true,
|
|
1029
|
+
active: false,
|
|
1030
|
+
json: false,
|
|
1031
|
+
latest: argv.latest,
|
|
1032
|
+
cwdScope: typeof argv.cwd === "string" ? path.resolve(argv.cwd) : null
|
|
675
1033
|
};
|
|
676
|
-
const keyword =
|
|
1034
|
+
const keyword = argv._[0] !== void 0 ? String(argv._[0]) : void 0;
|
|
677
1035
|
if (!keyword) throw new Error("usage: ay status <keyword> [--watch] [--interval=N]");
|
|
678
|
-
|
|
679
|
-
|
|
1036
|
+
{
|
|
1037
|
+
const remote = await resolveRemoteSpec(keyword);
|
|
1038
|
+
if (remote) return runRemoteStatus(remote);
|
|
1039
|
+
}
|
|
1040
|
+
const watch = argv.watch;
|
|
1041
|
+
const intervalFlag = argv.interval;
|
|
680
1042
|
const intervalMs = Math.max(500, (Number.isFinite(intervalFlag) ? intervalFlag : 2) * 1e3);
|
|
681
1043
|
const record = await resolveOne(keyword, opts);
|
|
682
1044
|
const emit = (snap, ts) => {
|
|
@@ -715,5 +1077,5 @@ async function cmdStatus(rest) {
|
|
|
715
1077
|
}
|
|
716
1078
|
|
|
717
1079
|
//#endregion
|
|
718
|
-
export {
|
|
719
|
-
//# sourceMappingURL=subcommands-
|
|
1080
|
+
export { matchKeyword as a, resolveOne as c, writeToIpc as d, listRecords as i, runSubcommand as l, isPidAlive as n, readNotes as o, isSubcommand as r, renderRawLog as s, controlCodeFromName as t, snapshotStatus as u };
|
|
1081
|
+
//# sourceMappingURL=subcommands-BpGEGOQM.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as logger, t as addTransport } from "./logger-B9h0djqx.js";
|
|
2
|
-
import { r as getInstalledPackage } from "./versionChecker-
|
|
2
|
+
import { r as getInstalledPackage } from "./versionChecker-BCrJk4Zj.js";
|
|
3
3
|
import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-C22d9SRJ.js";
|
|
4
4
|
import { t as PidStore } from "./pidStore-C1JXxoPi.js";
|
|
5
5
|
import { r as readGlobalPids } from "./globalPidIndex-Cr-g75QF.js";
|
|
@@ -1693,4 +1693,4 @@ function sleep(ms) {
|
|
|
1693
1693
|
|
|
1694
1694
|
//#endregion
|
|
1695
1695
|
export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
|
|
1696
|
-
//# sourceMappingURL=ts-
|
|
1696
|
+
//# sourceMappingURL=ts-DWuvdSWr.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.86.0";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region ts/versionChecker.ts
|
|
@@ -221,4 +221,4 @@ async function displayVersion() {
|
|
|
221
221
|
|
|
222
222
|
//#endregion
|
|
223
223
|
export { versionString as i, displayVersion as n, getInstalledPackage as r, checkAndAutoUpdate as t };
|
|
224
|
-
//# sourceMappingURL=versionChecker-
|
|
224
|
+
//# sourceMappingURL=versionChecker-BCrJk4Zj.js.map
|
package/package.json
CHANGED