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.
@@ -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 { flags, positional } = parseArgs(rest);
247
- const opts = commonOpts(flags);
248
- const keyword = positional[0];
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 { flags, positional } = parseArgs(rest);
353
- const opts = commonOpts(flags);
354
- const keyword = positional[0];
355
- const follow = !!(flags.f || flags.follow);
356
- const nFlag = typeof flags.n === "string" ? Number(flags.n) : void 0;
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 { flags, positional } = parseArgs(rest);
516
- const opts = commonOpts(flags);
517
- const keyword = positional[0];
518
- const rawMessage = positional.slice(1).join(" ");
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 trailing = controlCodeFromName(typeof flags.code === "string" ? flags.code.toLowerCase() : "enter");
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 { flags, positional } = parseArgs(rest);
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
- ...commonOpts(flags),
600
- all: true
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 keyword = positional[0];
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 { flags, positional } = parseArgs(rest);
625
- const opts = commonOpts(flags);
626
- const keyword = positional[0];
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
- ...opts,
631
- all: true
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 { flags, positional } = parseArgs(rest);
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
- ...commonOpts(flags),
674
- all: true
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 = positional[0];
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
- const watch = !!(flags.watch || flags.w);
679
- const intervalFlag = typeof flags.interval === "string" ? Number(flags.interval) : 2;
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 { isSubcommand, runSubcommand };
719
- //# sourceMappingURL=subcommands-DjO8lthH.js.map
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
@@ -175,4 +175,4 @@ async function startTray() {
175
175
 
176
176
  //#endregion
177
177
  export { ensureTray, startTray };
178
- //# sourceMappingURL=tray-CH_G7aXM.js.map
178
+ //# sourceMappingURL=tray-DHuD0nEk.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-DtDqoy3L.js";
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-DP0dIeoe.js.map
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.84.0";
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-DtDqoy3L.js.map
224
+ //# sourceMappingURL=versionChecker-BCrJk4Zj.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-yes",
3
- "version": "1.84.0",
3
+ "version": "1.86.0",
4
4
  "description": "A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses.",
5
5
  "keywords": [
6
6
  "ai",