claude-yes 1.78.0 → 1.79.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,6 +1,6 @@
1
- import { t as CLIS_CONFIG } from "./ts-B2M_r506.js";
1
+ import { t as CLIS_CONFIG } from "./ts-DCMrcZpL.js";
2
2
  import "./logger-B9h0djqx.js";
3
- import "./versionChecker-CoV20GQ7.js";
3
+ import "./versionChecker-CEkbd2dm.js";
4
4
  import "./pidStore-C1JXxoPi.js";
5
5
  import "./globalPidIndex-Cr-g75QF.js";
6
6
 
@@ -9,4 +9,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
9
9
 
10
10
  //#endregion
11
11
  export { SUPPORTED_CLIS };
12
- //# sourceMappingURL=SUPPORTED_CLIS-eyTIFAJl.js.map
12
+ //# sourceMappingURL=SUPPORTED_CLIS-BcN2aqoM.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-CoV20GQ7.js";
3
+ import { i as versionString, n as displayVersion, r as getInstalledPackage, t as checkAndAutoUpdate } from "./versionChecker-CEkbd2dm.js";
4
4
  import { argv } from "process";
5
5
  import { execFileSync, spawn } from "child_process";
6
6
  import ms from "ms";
@@ -475,7 +475,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
475
475
  }
476
476
  }
477
477
  {
478
- const { isSubcommand, runSubcommand } = await import("./subcommands-Ctgm4cEn.js");
478
+ const { isSubcommand, runSubcommand } = await import("./subcommands-DQY6uKK-.js");
479
479
  if (isSubcommand(process.argv[2])) {
480
480
  const code = await runSubcommand(process.argv);
481
481
  process.exit(code ?? 0);
@@ -504,7 +504,7 @@ if (config.useRust) {
504
504
  }
505
505
  }
506
506
  if (rustBinary) {
507
- const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-eyTIFAJl.js");
507
+ const { SUPPORTED_CLIS } = await import("./SUPPORTED_CLIS-BcN2aqoM.js");
508
508
  const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
509
509
  if (config.verbose) {
510
510
  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-B2M_r506.js";
1
+ import { a as removeControlCharacters, i as AgentContext, n as agentYes, r as config, t as CLIS_CONFIG } from "./ts-DCMrcZpL.js";
2
2
  import "./logger-B9h0djqx.js";
3
- import "./versionChecker-CoV20GQ7.js";
3
+ import "./versionChecker-CEkbd2dm.js";
4
4
  import "./pidStore-C1JXxoPi.js";
5
5
  import "./globalPidIndex-Cr-g75QF.js";
6
6
 
@@ -81,7 +81,8 @@ const SUBCOMMANDS = new Set([
81
81
  "cat",
82
82
  "tail",
83
83
  "head",
84
- "send"
84
+ "send",
85
+ "restart"
85
86
  ]);
86
87
  function isSubcommand(name) {
87
88
  return !!name && SUBCOMMANDS.has(name);
@@ -104,6 +105,7 @@ async function runSubcommand(argv) {
104
105
  case "tail": return await cmdRead(rest, { mode: "tail" });
105
106
  case "head": return await cmdRead(rest, { mode: "head" });
106
107
  case "send": return await cmdSend(rest);
108
+ case "restart": return await cmdRestart(rest);
107
109
  default: return null;
108
110
  }
109
111
  } catch (err) {
@@ -125,6 +127,7 @@ function parseArgs(rest) {
125
127
  const next = rest[i + 1];
126
128
  if ([
127
129
  "all",
130
+ "active",
128
131
  "json",
129
132
  "latest"
130
133
  ].includes(key) || !next || next.startsWith("-")) flags[key] = true;
@@ -147,6 +150,7 @@ function parseArgs(rest) {
147
150
  function commonOpts(flags) {
148
151
  return {
149
152
  all: !!flags.all,
153
+ active: !!flags.active,
150
154
  cwdScope: typeof flags.cwd === "string" ? path.resolve(flags.cwd) : flags.cwd === true ? process.cwd() : null,
151
155
  latest: !!flags.latest,
152
156
  json: !!flags.json
@@ -163,7 +167,8 @@ function matchKeyword(record, keyword) {
163
167
  }
164
168
  async function listRecords(keyword, opts) {
165
169
  let records = mergeRecords(await readLocalTsPids(process.cwd()), opts.cwdScope ? await readLocalTsPids(opts.cwdScope) : [], await readGlobalPids());
166
- if (!opts.all) records = records.filter((r) => r.status !== "exited" && isPidAlive(r.pid));
170
+ if (!opts.all) records = records.filter((r) => r.status !== "exited");
171
+ if (opts.active) records = records.filter((r) => isPidAlive(r.pid));
167
172
  if (opts.cwdScope) {
168
173
  const scope = opts.cwdScope;
169
174
  records = records.filter((r) => r.cwd === scope || r.cwd.startsWith(scope + path.sep));
@@ -183,7 +188,7 @@ function isPidAlive(pid) {
183
188
  async function resolveOne(keyword, opts) {
184
189
  if (!keyword) throw new Error("keyword required (pid, cwd substring, cli name, or prompt substring)");
185
190
  const matches = await listRecords(keyword, opts);
186
- if (matches.length === 0) throw new Error(`no running agent matched "${keyword}"`);
191
+ if (matches.length === 0) throw new Error(`no agent matched "${keyword}"`);
187
192
  if (matches.length === 1) return matches[0];
188
193
  if (opts.latest) return matches[0];
189
194
  const lines = matches.slice(0, 10).map((r) => ` ${r.pid} ${r.cli} ${r.cwd}`).join("\n");
@@ -215,18 +220,20 @@ async function cmdLs(rest) {
215
220
  const promptBudget = Math.max(20, termWidth - fixedWidth - 1);
216
221
  const IDLE_THRESHOLD_MS = 60 * 1e3;
217
222
  const rows = await Promise.all(records.map(async (r) => {
218
- let displayStatus = r.status;
219
- if (r.status === "active" && r.log_file) {
223
+ let displayStatus;
224
+ if (!isPidAlive(r.pid)) displayStatus = "stopped";
225
+ else if (r.log_file) {
220
226
  const mtime = await stat(r.log_file).then((s) => s.mtimeMs).catch(() => null);
221
- if (mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS) displayStatus = "idle";
222
- }
227
+ displayStatus = mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS ? "idle" : "active";
228
+ } else displayStatus = "active";
223
229
  return {
224
230
  pid: String(r.pid),
225
231
  cli: r.cli,
226
232
  status: displayStatus,
227
233
  age: humanizeAge(Date.now() - r.started_at),
228
234
  cwd: shortenPath(r.cwd),
229
- prompt: truncate(r.prompt ?? "", promptBudget)
235
+ prompt: truncate(r.prompt ?? "", promptBudget),
236
+ _alive: displayStatus !== "stopped"
230
237
  };
231
238
  }));
232
239
  const header = [
@@ -246,9 +253,18 @@ async function cmdLs(rest) {
246
253
  r.cwd.padEnd(widths.cwd),
247
254
  r.prompt
248
255
  ].join(" ") + "\n");
249
- if (!opts.json && records.length > 0) {
250
- const example = records[0].pid;
251
- process.stderr.write(`\n cy tail ${example} # view latest output\n cy read ${example} # full rendered log\n cy send ${example} "next: ..." # send a prompt\n cy send ${example} "" --code=ctrl-c # interrupt\n`);
256
+ if (!opts.json && rows.length > 0) {
257
+ const alive = rows.find((r) => r._alive);
258
+ const stopped = rows.find((r) => !r._alive);
259
+ const hints = ["\n"];
260
+ if (alive) {
261
+ hints.push(` cy tail ${alive.pid} # view latest output\n`);
262
+ hints.push(` cy send ${alive.pid} "next: ..." # send a prompt\n`);
263
+ hints.push(` cy send ${alive.pid} "" --code=ctrl-c # interrupt\n`);
264
+ }
265
+ if (stopped) hints.push(` cy restart ${stopped.pid} # restart stopped agent\n`);
266
+ if (!alive && !stopped) hints.push(` cy ls --all # show exited agents\n`);
267
+ process.stderr.write(hints.join(""));
252
268
  }
253
269
  return 0;
254
270
  }
@@ -344,8 +360,13 @@ async function cmdSend(rest) {
344
360
  const record = await resolveOne(keyword, opts);
345
361
  const fifoPath = record.fifo_file;
346
362
  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)`);
347
- const payload = (message ?? "") + trailing;
348
- await writeToIpc(fifoPath, payload);
363
+ const body = message ?? "";
364
+ if (body && trailing) {
365
+ await writeToIpc(fifoPath, body);
366
+ await new Promise((r) => setTimeout(r, 200));
367
+ await writeToIpc(fifoPath, trailing);
368
+ } else await writeToIpc(fifoPath, body + trailing);
369
+ const payload = body + trailing;
349
370
  process.stdout.write(`sent to pid ${record.pid} (${record.cli}): ${truncate(payload, 80)}\n`);
350
371
  process.stderr.write(`\n cy tail ${record.pid} # watch output\n cy ls # list all agents\n`);
351
372
  return 0;
@@ -402,7 +423,34 @@ async function writeToIpc(ipcPath, payload) {
402
423
  }
403
424
  }
404
425
  }
426
+ async function cmdRestart(rest) {
427
+ const { flags, positional } = parseArgs(rest);
428
+ const opts = {
429
+ ...commonOpts(flags),
430
+ all: true
431
+ };
432
+ const keyword = positional[0];
433
+ const record = await resolveOne(keyword, opts);
434
+ if (isPidAlive(record.pid)) {
435
+ process.stderr.write(`pid ${record.pid} is still running — stop it first or use cy send\n`);
436
+ return 1;
437
+ }
438
+ const args = ["--cli=" + record.cli];
439
+ if (record.prompt) args.push(record.prompt);
440
+ const proc = Bun.spawn(["agent-yes", ...args], {
441
+ cwd: record.cwd,
442
+ detached: true,
443
+ stdio: [
444
+ "ignore",
445
+ "ignore",
446
+ "ignore"
447
+ ]
448
+ });
449
+ process.stdout.write(`restarted ${record.cli} in ${shortenPath(record.cwd)} (new pid: ${proc.pid})\n`);
450
+ process.stderr.write(`\n cy tail ${proc.pid} # watch output\n cy ls # list all agents\n`);
451
+ return 0;
452
+ }
405
453
 
406
454
  //#endregion
407
455
  export { isSubcommand, runSubcommand };
408
- //# sourceMappingURL=subcommands-Ctgm4cEn.js.map
456
+ //# sourceMappingURL=subcommands-DQY6uKK-.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-CoV20GQ7.js";
2
+ import { r as getInstalledPackage } from "./versionChecker-CEkbd2dm.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 { arch, platform } from "process";
@@ -1679,4 +1679,4 @@ function sleep(ms) {
1679
1679
 
1680
1680
  //#endregion
1681
1681
  export { removeControlCharacters as a, AgentContext as i, agentYes as n, config as r, CLIS_CONFIG as t };
1682
- //# sourceMappingURL=ts-B2M_r506.js.map
1682
+ //# sourceMappingURL=ts-DCMrcZpL.js.map
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
7
7
 
8
8
  //#region package.json
9
9
  var name = "claude-yes";
10
- var version = "1.78.0";
10
+ var version = "1.79.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-CoV20GQ7.js.map
224
+ //# sourceMappingURL=versionChecker-CEkbd2dm.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-yes",
3
- "version": "1.78.0",
3
+ "version": "1.79.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",
@@ -206,7 +206,7 @@ describe("subcommands.runSubcommand routing", () => {
206
206
  try {
207
207
  const code = await runSubcommand(["bun", "cli.js", "read", "no-such-agent-keyword"]);
208
208
  expect(code).toBe(1);
209
- expect(stderr.join("")).toMatch(/no running agent matched/);
209
+ expect(stderr.join("")).toMatch(/no agent matched/);
210
210
  } finally {
211
211
  process.stderr.write = orig;
212
212
  }
package/ts/subcommands.ts CHANGED
@@ -76,7 +76,7 @@ function mergeRecords(...buckets: GlobalPidRecord[][]): GlobalPidRecord[] {
76
76
  return Array.from(out.values());
77
77
  }
78
78
 
79
- const SUBCOMMANDS = new Set(["ls", "list", "ps", "read", "cat", "tail", "head", "send"]);
79
+ const SUBCOMMANDS = new Set(["ls", "list", "ps", "read", "cat", "tail", "head", "send", "restart"]);
80
80
 
81
81
  export function isSubcommand(name: string | undefined): boolean {
82
82
  return !!name && SUBCOMMANDS.has(name);
@@ -107,6 +107,8 @@ export async function runSubcommand(argv: string[]): Promise<number | null> {
107
107
  return await cmdRead(rest, { mode: "head" });
108
108
  case "send":
109
109
  return await cmdSend(rest);
110
+ case "restart":
111
+ return await cmdRestart(rest);
110
112
  default:
111
113
  return null;
112
114
  }
@@ -123,6 +125,7 @@ export async function runSubcommand(argv: string[]): Promise<number | null> {
123
125
 
124
126
  interface CommonOpts {
125
127
  all: boolean;
128
+ active: boolean;
126
129
  cwdScope: string | null;
127
130
  latest: boolean;
128
131
  json: boolean;
@@ -146,7 +149,7 @@ export function parseArgs(rest: string[]): ParsedArgs {
146
149
  const key = arg.slice(2);
147
150
  const next = rest[i + 1];
148
151
  // Boolean flags: --all, --json, --latest
149
- if (["all", "json", "latest"].includes(key) || !next || next.startsWith("-")) {
152
+ if (["all", "active", "json", "latest"].includes(key) || !next || next.startsWith("-")) {
150
153
  flags[key] = true;
151
154
  } else {
152
155
  flags[key] = next;
@@ -171,6 +174,7 @@ export function parseArgs(rest: string[]): ParsedArgs {
171
174
  function commonOpts(flags: Record<string, string | boolean>): CommonOpts {
172
175
  return {
173
176
  all: !!flags.all,
177
+ active: !!flags.active,
174
178
  cwdScope:
175
179
  typeof flags.cwd === "string"
176
180
  ? path.resolve(flags.cwd)
@@ -210,7 +214,10 @@ async function listRecords(
210
214
  let records = mergeRecords(local, scopeLocal, global);
211
215
 
212
216
  if (!opts.all) {
213
- records = records.filter((r) => r.status !== "exited" && isPidAlive(r.pid));
217
+ records = records.filter((r) => r.status !== "exited");
218
+ }
219
+ if (opts.active) {
220
+ records = records.filter((r) => isPidAlive(r.pid));
214
221
  }
215
222
  if (opts.cwdScope) {
216
223
  const scope = opts.cwdScope;
@@ -237,7 +244,7 @@ async function resolveOne(keyword: string | undefined, opts: CommonOpts): Promis
237
244
  }
238
245
  const matches = await listRecords(keyword, opts);
239
246
  if (matches.length === 0) {
240
- throw new Error(`no running agent matched "${keyword}"`);
247
+ throw new Error(`no agent matched "${keyword}"`);
241
248
  }
242
249
  if (matches.length === 1) return matches[0]!;
243
250
  if (opts.latest) return matches[0]!; // already sorted newest-first
@@ -291,12 +298,17 @@ async function cmdLs(rest: string[]): Promise<number> {
291
298
  const IDLE_THRESHOLD_MS = 60 * 1000;
292
299
  const rows = await Promise.all(
293
300
  records.map(async (r) => {
294
- let displayStatus = r.status;
295
- if (r.status === "active" && r.log_file) {
301
+ let displayStatus: string;
302
+ if (!isPidAlive(r.pid)) {
303
+ displayStatus = "stopped";
304
+ } else if (r.log_file) {
296
305
  const mtime = await stat(r.log_file)
297
306
  .then((s) => s.mtimeMs)
298
307
  .catch(() => null);
299
- if (mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS) displayStatus = "idle";
308
+ displayStatus =
309
+ mtime !== null && Date.now() - mtime > IDLE_THRESHOLD_MS ? "idle" : "active";
310
+ } else {
311
+ displayStatus = "active";
300
312
  }
301
313
  return {
302
314
  pid: String(r.pid),
@@ -305,6 +317,7 @@ async function cmdLs(rest: string[]): Promise<number> {
305
317
  age: humanizeAge(Date.now() - r.started_at),
306
318
  cwd: shortenPath(r.cwd),
307
319
  prompt: truncate(r.prompt ?? "", promptBudget),
320
+ _alive: displayStatus !== "stopped",
308
321
  };
309
322
  }),
310
323
  );
@@ -333,15 +346,21 @@ async function cmdLs(rest: string[]): Promise<number> {
333
346
  );
334
347
  }
335
348
 
336
- if (!opts.json && records.length > 0) {
337
- const example = records[0]!.pid;
338
- process.stderr.write(
339
- `\n` +
340
- ` cy tail ${example} # view latest output\n` +
341
- ` cy read ${example} # full rendered log\n` +
342
- ` cy send ${example} "next: ..." # send a prompt\n` +
343
- ` cy send ${example} "" --code=ctrl-c # interrupt\n`,
344
- );
349
+ if (!opts.json && rows.length > 0) {
350
+ const alive = rows.find((r) => r._alive);
351
+ const stopped = rows.find((r) => !r._alive);
352
+ const hints: string[] = ["\n"];
353
+ if (alive) {
354
+ hints.push(` cy tail ${alive.pid} # view latest output\n`);
355
+ hints.push(` cy send ${alive.pid} "next: ..." # send a prompt\n`);
356
+ hints.push(` cy send ${alive.pid} "" --code=ctrl-c # interrupt\n`);
357
+ }
358
+ if (stopped) {
359
+ hints.push(` cy restart ${stopped.pid} # restart stopped agent\n`);
360
+ }
361
+ if (!alive && !stopped)
362
+ hints.push(` cy ls --all # show exited agents\n`);
363
+ process.stderr.write(hints.join(""));
345
364
  }
346
365
 
347
366
  return 0;
@@ -491,8 +510,15 @@ async function cmdSend(rest: string[]): Promise<number> {
491
510
  );
492
511
  }
493
512
 
494
- const payload = (message ?? "") + trailing;
495
- await writeToIpc(fifoPath, payload);
513
+ const body = message ?? "";
514
+ if (body && trailing) {
515
+ await writeToIpc(fifoPath, body);
516
+ await new Promise((r) => setTimeout(r, 200));
517
+ await writeToIpc(fifoPath, trailing);
518
+ } else {
519
+ await writeToIpc(fifoPath, body + trailing);
520
+ }
521
+ const payload = body + trailing;
496
522
  process.stdout.write(`sent to pid ${record.pid} (${record.cli}): ${truncate(payload, 80)}\n`);
497
523
 
498
524
  process.stderr.write(
@@ -564,3 +590,38 @@ async function writeToIpc(ipcPath: string, payload: string): Promise<void> {
564
590
  }
565
591
  }
566
592
  }
593
+
594
+ // ---------------------------------------------------------------------------
595
+ // cy restart
596
+ // ---------------------------------------------------------------------------
597
+
598
+ async function cmdRestart(rest: string[]): Promise<number> {
599
+ const { flags, positional } = parseArgs(rest);
600
+ const opts = { ...commonOpts(flags), all: true }; // search stopped agents too
601
+ const keyword = positional[0];
602
+ const record = await resolveOne(keyword, opts);
603
+
604
+ if (isPidAlive(record.pid)) {
605
+ process.stderr.write(`pid ${record.pid} is still running — stop it first or use cy send\n`);
606
+ return 1;
607
+ }
608
+
609
+ const args = ["--cli=" + record.cli];
610
+ if (record.prompt) args.push(record.prompt);
611
+
612
+ const proc = Bun.spawn(["agent-yes", ...args], {
613
+ cwd: record.cwd,
614
+ detached: true,
615
+ stdio: ["ignore", "ignore", "ignore"],
616
+ });
617
+
618
+ process.stdout.write(
619
+ `restarted ${record.cli} in ${shortenPath(record.cwd)} (new pid: ${proc.pid})\n`,
620
+ );
621
+ process.stderr.write(
622
+ `\n` +
623
+ ` cy tail ${proc.pid} # watch output\n` +
624
+ ` cy ls # list all agents\n`,
625
+ );
626
+ return 0;
627
+ }