claude-yes 1.24.2 → 1.26.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/index.js CHANGED
@@ -5234,6 +5234,74 @@ class TerminalTextRender {
5234
5234
  }
5235
5235
  }
5236
5236
 
5237
+ // ts/defineConfig.ts
5238
+ async function defineCliYesConfig(cfg) {
5239
+ if (typeof cfg === "function")
5240
+ cfg = await cfg({ clis: {} });
5241
+ return cfg;
5242
+ }
5243
+
5244
+ // cli-yes.config.ts
5245
+ process.env.VERBOSE && console.log("loading cli-yes.config.ts from " + import.meta.url);
5246
+ var cli_yes_config_default = defineCliYesConfig({
5247
+ clis: {
5248
+ qwen: {
5249
+ install: "npm install -g @qwen-code/qwen-code@latest",
5250
+ version: "qwen --version"
5251
+ },
5252
+ grok: {
5253
+ install: "npm install -g @vibe-kit/grok-cli",
5254
+ ready: [/^ │ ❯ /],
5255
+ enter: [/^ 1. Yes/]
5256
+ },
5257
+ claude: {
5258
+ promptArg: "first-arg",
5259
+ install: "npm install -g @anthropic-ai/claude-code",
5260
+ restoreArgs: ["--continue"],
5261
+ ready: [/\? for shortcuts/],
5262
+ enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
5263
+ fatal: [
5264
+ /No conversation found to continue/,
5265
+ /⎿ Claude usage limit reached\./,
5266
+ /^error: unknown option/
5267
+ ],
5268
+ defaultArgs: ["--model=sonnet"]
5269
+ },
5270
+ gemini: {
5271
+ install: "npm install -g @google/gemini-cli",
5272
+ ready: [/Type your message/],
5273
+ enter: [/│ ● 1. Yes, allow once/],
5274
+ fatal: []
5275
+ },
5276
+ codex: {
5277
+ promptArg: "first-arg",
5278
+ install: "npm install -g @openai/codex-cli",
5279
+ ready: [/⏎ send/],
5280
+ enter: [
5281
+ /> 1. Yes, allow Codex to work in this folder/,
5282
+ /> 1. Approve and run now/
5283
+ ],
5284
+ fatal: [/Error: The cursor position could not be read within/],
5285
+ defaultArgs: ["--search"],
5286
+ noEOL: true
5287
+ },
5288
+ copilot: {
5289
+ promptArg: "--prompt",
5290
+ install: "npm install -g @github/copilot",
5291
+ ready: [/^ +> /, /Ctrl\+c Exit/],
5292
+ enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
5293
+ fatal: []
5294
+ },
5295
+ cursor: {
5296
+ install: "open https://cursor.com/ja/docs/cli/installation",
5297
+ binary: "cursor-agent",
5298
+ ready: [/\/ commands/],
5299
+ enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
5300
+ fatal: [/^ Error: You've hit your usage limit/]
5301
+ }
5302
+ }
5303
+ });
5304
+
5237
5305
  // ts/idleWaiter.ts
5238
5306
  class IdleWaiter {
5239
5307
  lastActivityTime = Date.now();
@@ -5487,95 +5555,106 @@ function shouldUseLock(cwd) {
5487
5555
  return true;
5488
5556
  }
5489
5557
 
5490
- // ts/index.ts
5491
- var CLI_CONFIGURES = {
5492
- grok: {
5493
- install: "npm install -g @vibe-kit/grok-cli",
5494
- ready: [/^ /],
5495
- enter: [/^ 1. Yes/]
5496
- },
5497
- claude: {
5498
- install: "npm install -g @anthropic-ai/claude-code",
5499
- ready: [/\? for shortcuts/],
5500
- enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
5501
- fatal: [
5502
- /No conversation found to continue/,
5503
- /⎿ Claude usage limit reached\./
5504
- ]
5505
- },
5506
- gemini: {
5507
- install: "npm install -g @google/gemini-cli",
5508
- ready: [/Type your message/],
5509
- enter: [/│ ● 1. Yes, allow once/],
5510
- fatal: []
5511
- },
5512
- codex: {
5513
- install: "npm install -g @openai/codex-cli",
5514
- ready: [/⏎ send/],
5515
- enter: [
5516
- /> 1. Yes, allow Codex to work in this folder/,
5517
- /> 1. Approve and run now/
5518
- ],
5519
- fatal: [/Error: The cursor position could not be read within/],
5520
- ensureArgs: (args) => {
5521
- if (!args.includes("--search"))
5522
- return ["--search", ...args];
5523
- return args;
5558
+ // ts/tryCatch.ts
5559
+ function catcher(catchFn, fn) {
5560
+ if (!fn)
5561
+ return (fn2) => catcher(catchFn, fn2);
5562
+ return (...args) => {
5563
+ try {
5564
+ return fn(...args);
5565
+ } catch (error) {
5566
+ return catchFn(error);
5524
5567
  }
5525
- },
5526
- copilot: {
5527
- install: "npm install -g @github/copilot",
5528
- ready: [/^ +> /, /Ctrl\+c Exit/],
5529
- enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
5530
- fatal: []
5531
- },
5532
- cursor: {
5533
- install: "open https://cursor.com/ja/docs/cli/installation",
5534
- binary: "cursor-agent",
5535
- ready: [/\/ commands/],
5536
- enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
5537
- fatal: [/^ Error: You've hit your usage limit/]
5538
- }
5539
- };
5540
- async function claudeYes({
5541
- cli = "claude",
5568
+ };
5569
+ }
5570
+
5571
+ // ts/yesLog.ts
5572
+ import { appendFileSync, rmSync } from "node:fs";
5573
+
5574
+ // node_modules/tsa-composer/dist/index.js
5575
+ function tsaStringJoiner(tsa, ...slots) {
5576
+ return [tsa.reduce((acc, s, i) => acc + s + (slots[i] ?? ""), "")];
5577
+ }
5578
+ function tsaComposer(parse, fn) {
5579
+ if (!parse)
5580
+ return tsaComposer(tsaStringJoiner);
5581
+ if (!fn)
5582
+ return (fn2) => tsaComposer(parse, fn2);
5583
+ const composedFn = function(...args) {
5584
+ const [tsa, ...slots] = args;
5585
+ if (!isTSA(tsa))
5586
+ return fn(...args);
5587
+ return fn(...parse(tsa, ...slots));
5588
+ };
5589
+ Object.setPrototypeOf(composedFn, fn);
5590
+ Object.getOwnPropertyNames(fn).forEach((prop2) => {
5591
+ if (prop2 !== "length" && prop2 !== "name" && prop2 !== "prototype") {
5592
+ Object.defineProperty(composedFn, prop2, Object.getOwnPropertyDescriptor(fn, prop2));
5593
+ }
5594
+ });
5595
+ return composedFn;
5596
+ }
5597
+ function isTSA(tsa) {
5598
+ return Array.isArray(tsa) && "raw" in tsa && Array.isArray(tsa.raw);
5599
+ }
5600
+
5601
+ // ts/yesLog.ts
5602
+ var initial = true;
5603
+ var yesLog = tsaComposer()(catcher((error) => {
5604
+ console.error("yesLog error:", error);
5605
+ }, function yesLog2(msg) {
5606
+ if (!process.env.VERBOSE)
5607
+ return;
5608
+ if (initial)
5609
+ rmSync("./agent-yes.log");
5610
+ initial = false;
5611
+ appendFileSync("./agent-yes.log", `${msg}
5612
+ `);
5613
+ }));
5614
+
5615
+ // ts/index.ts
5616
+ var config = await cli_yes_config_default;
5617
+ var CLIS_CONFIG = config.clis;
5618
+ var SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
5619
+ async function cliYes({
5620
+ cli,
5542
5621
  cliArgs = [],
5543
5622
  prompt,
5623
+ robust = true,
5544
5624
  cwd,
5545
5625
  env,
5546
5626
  exitOnIdle,
5547
5627
  logFile,
5548
5628
  removeControlCharactersFromStdout = false,
5549
5629
  verbose = false,
5550
- disableLock = false
5551
- } = {}) {
5552
- const continueArgs = {
5553
- codex: "resume --last".split(" "),
5554
- claude: "--continue".split(" "),
5555
- gemini: []
5556
- };
5630
+ queue = true
5631
+ }) {
5632
+ if (!cli)
5633
+ throw new Error(`cli is required`);
5634
+ const conf = CLIS_CONFIG[cli] || phpdie_default2(`Unsupported cli tool: ${cli}`);
5557
5635
  const workingDir = cwd ?? process.cwd();
5558
- if (!disableLock && shouldUseLock(workingDir)) {
5559
- await acquireLock(workingDir, prompt ?? "Interactive session");
5560
- }
5561
- const cleanupLock = async () => {
5562
- if (!disableLock && shouldUseLock(workingDir)) {
5563
- await releaseLock().catch(() => null);
5564
- }
5565
- };
5566
- process.on("exit", () => {
5567
- if (!disableLock) {
5568
- releaseLock().catch(() => null);
5636
+ if (queue) {
5637
+ if (queue && shouldUseLock(workingDir)) {
5638
+ await acquireLock(workingDir, prompt ?? "Interactive session");
5569
5639
  }
5570
- });
5571
- process.on("SIGINT", async () => {
5572
- await cleanupLock();
5573
- process.exit(130);
5574
- });
5575
- process.on("SIGTERM", async () => {
5576
- await cleanupLock();
5577
- process.exit(143);
5578
- });
5640
+ const cleanupLock = async () => {
5641
+ if (queue && shouldUseLock(workingDir)) {
5642
+ await releaseLock().catch(() => null);
5643
+ }
5644
+ };
5645
+ process.on("exit", () => {
5646
+ if (queue)
5647
+ releaseLock().catch(() => null);
5648
+ });
5649
+ process.on("SIGINT", async (code) => {
5650
+ await cleanupLock();
5651
+ process.exit(code);
5652
+ });
5653
+ process.on("SIGTERM", async (code) => {
5654
+ await cleanupLock();
5655
+ process.exit(code);
5656
+ });
5657
+ }
5579
5658
  process.stdin.setRawMode?.(true);
5580
5659
  let isFatal = false;
5581
5660
  const stdinReady = new ReadyManager;
@@ -5589,27 +5668,57 @@ async function claudeYes({
5589
5668
  cwd: cwd ?? process.cwd(),
5590
5669
  env: env ?? process.env
5591
5670
  });
5592
- const cliConf = CLI_CONFIGURES[cli] || {};
5593
- cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;
5671
+ const cliConf = CLIS_CONFIG[cli] || {};
5672
+ cliArgs = cliConf.defaultArgs ? [...cliConf.defaultArgs, ...cliArgs] : cliArgs;
5673
+ if (prompt && cliConf.promptArg) {
5674
+ if (cliConf.promptArg === "first-arg") {
5675
+ cliArgs = [prompt, ...cliArgs];
5676
+ prompt = undefined;
5677
+ } else if (cliConf.promptArg === "last-arg") {
5678
+ cliArgs = [...cliArgs, prompt];
5679
+ prompt = undefined;
5680
+ } else if (cliConf.promptArg.startsWith("--")) {
5681
+ cliArgs = [cliConf.promptArg, prompt, ...cliArgs];
5682
+ prompt = undefined;
5683
+ } else {
5684
+ console.warn(`Unknown promptArg format: ${cliConf.promptArg}`);
5685
+ }
5686
+ }
5594
5687
  const cliCommand = cliConf?.binary || cli;
5595
- let shell = tryCatch(() => pty.spawn(cliCommand, cliArgs, getPtyOptions()), (error) => {
5688
+ let shell = catcher((error) => {
5596
5689
  console.error(`Fatal: Failed to start ${cliCommand}.`);
5597
- if (cliConf?.install)
5690
+ if (cliConf?.install && isCommandNotFoundError(error))
5598
5691
  console.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
5599
5692
  throw error;
5600
- });
5693
+ function isCommandNotFoundError(e) {
5694
+ if (e instanceof Error) {
5695
+ return e.message.includes("command not found") || e.message.includes("ENOENT") || e.message.includes("spawn");
5696
+ }
5697
+ return false;
5698
+ }
5699
+ }, () => pty.spawn(cliCommand, cliArgs, getPtyOptions()))();
5601
5700
  const pendingExitCode = Promise.withResolvers();
5602
5701
  let pendingExitCodeValue = null;
5603
5702
  async function onData(data) {
5604
- nextStdout.ready();
5605
5703
  await outputWriter.write(data);
5606
5704
  }
5607
5705
  shell.onData(onData);
5608
5706
  shell.onExit(function onExit({ exitCode: exitCode2 }) {
5609
- nextStdout.ready();
5610
5707
  stdinReady.unready();
5611
5708
  const agentCrashed = exitCode2 !== 0;
5612
- const continueArg = continueArgs[cli];
5709
+ if (agentCrashed && robust && conf?.restoreArgs) {
5710
+ if (!conf.restoreArgs) {
5711
+ return console.warn(`robust is only supported for ${Object.entries(CLIS_CONFIG).filter(([_, v]) => v.restoreArgs).map(([k]) => k).join(", ")} currently, not ${cli}`);
5712
+ }
5713
+ if (isFatal) {
5714
+ return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);
5715
+ }
5716
+ console.log(`${cli} crashed, restarting...`);
5717
+ shell = pty.spawn(cli, conf.restoreArgs, getPtyOptions());
5718
+ shell.onData(onData);
5719
+ shell.onExit(onExit);
5720
+ return;
5721
+ }
5613
5722
  return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);
5614
5723
  });
5615
5724
  process.stdout.on("resize", () => {
@@ -5636,7 +5745,7 @@ async function claudeYes({
5636
5745
  }
5637
5746
  }),
5638
5747
  readable: shellOutputStream.readable
5639
- }).forEach(() => idleWaiter.ping()).forEach((text) => {
5748
+ }).forEach(() => idleWaiter.ping()).forEach(() => nextStdout.ready()).forEach(async (text) => {
5640
5749
  terminalRender.write(text);
5641
5750
  if (process.stdin.isTTY)
5642
5751
  return;
@@ -5644,24 +5753,25 @@ async function claudeYes({
5644
5753
  return;
5645
5754
  const { col, row } = terminalRender.getCursorPosition();
5646
5755
  shell.write(`\x1B[${row};${col}R`);
5756
+ await yesLog`cursor|respond position: row=${String(row)}, col=${String(col)}`;
5647
5757
  }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).by((s) => {
5648
- if (cli === "codex")
5758
+ if (conf.noEOL)
5649
5759
  return s;
5650
5760
  return s.lines({ EOL: "NONE" });
5651
- }).forEach(async (e2, i) => {
5652
- const conf = CLI_CONFIGURES[cli] || null;
5653
- if (!conf)
5654
- return;
5761
+ }).forEach((e2) => yesLog`output|${e2}`).forEach(async (e2, i) => {
5655
5762
  if (conf.ready?.some((rx) => e2.match(rx))) {
5763
+ await yesLog`ready |${e2}`;
5656
5764
  if (cli === "gemini" && i <= 80)
5657
5765
  return;
5658
5766
  stdinReady.ready();
5659
5767
  }
5660
5768
  if (conf.enter?.some((rx) => e2.match(rx))) {
5769
+ await yesLog`enter |${e2}`;
5661
5770
  await sendEnter(300);
5662
5771
  return;
5663
5772
  }
5664
5773
  if (conf.fatal?.some((rx) => e2.match(rx))) {
5774
+ await yesLog`fatal |${e2}`;
5665
5775
  isFatal = true;
5666
5776
  await exitAgent();
5667
5777
  }
@@ -5672,7 +5782,7 @@ async function claudeYes({
5672
5782
  await sendMessage(prompt);
5673
5783
  const exitCode = await pendingExitCode.promise;
5674
5784
  console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);
5675
- if (!disableLock && shouldUseLock(workingDir)) {
5785
+ if (queue && shouldUseLock(workingDir)) {
5676
5786
  await updateCurrentTaskStatus(exitCode === 0 ? "completed" : "failed").catch(() => null);
5677
5787
  await releaseLock().catch(() => null);
5678
5788
  }
@@ -5687,17 +5797,33 @@ async function claudeYes({
5687
5797
  const st = Date.now();
5688
5798
  await idleWaiter.wait(waitms);
5689
5799
  const et = Date.now();
5800
+ await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;
5801
+ nextStdout.unready();
5690
5802
  shell.write("\r");
5803
+ await Promise.race([
5804
+ nextStdout.wait(),
5805
+ new Promise((resolve) => setTimeout(() => {
5806
+ if (!nextStdout.ready) {
5807
+ shell.write("\r");
5808
+ }
5809
+ resolve();
5810
+ }, 1000))
5811
+ ]);
5691
5812
  }
5692
5813
  async function sendMessage(message) {
5693
5814
  await stdinReady.wait();
5694
- shell.write(message);
5815
+ yesLog`send |${message}`;
5695
5816
  nextStdout.unready();
5817
+ shell.write(message);
5696
5818
  idleWaiter.ping();
5819
+ yesLog`waiting next stdout|${message}`;
5697
5820
  await nextStdout.wait();
5698
- await sendEnter();
5821
+ yesLog`sending enter`;
5822
+ await sendEnter(1000);
5823
+ yesLog`sent enter`;
5699
5824
  }
5700
5825
  async function exitAgent() {
5826
+ robust = false;
5701
5827
  await sendMessage("/exit");
5702
5828
  let exited = false;
5703
5829
  await Promise.race([
@@ -5719,18 +5845,13 @@ async function claudeYes({
5719
5845
  };
5720
5846
  }
5721
5847
  }
5722
- function tryCatch(fn, catchFn) {
5723
- try {
5724
- return fn();
5725
- } catch (error) {
5726
- return catchFn(error);
5727
- }
5728
- }
5729
5848
  export {
5730
5849
  removeControlCharacters,
5731
- claudeYes as default,
5732
- CLI_CONFIGURES
5850
+ cliYes as default,
5851
+ config,
5852
+ SUPPORTED_CLIS,
5853
+ CLIS_CONFIG
5733
5854
  };
5734
5855
 
5735
- //# debugId=71BB292CF34E8BBE64756E2164756E21
5856
+ //# debugId=266F6AAC46785FCA64756E2164756E21
5736
5857
  //# sourceMappingURL=index.js.map