agent-yes 1.65.0 → 1.67.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.
@@ -1059,7 +1059,7 @@ function tryCatch(catchFn, fn) {
1059
1059
  //#endregion
1060
1060
  //#region package.json
1061
1061
  var name = "agent-yes";
1062
- var version = "1.65.0";
1062
+ var version = "1.67.0";
1063
1063
 
1064
1064
  //#endregion
1065
1065
  //#region ts/pty-fix.ts
@@ -1305,6 +1305,7 @@ var AgentContext = class {
1305
1305
  isFatal = false;
1306
1306
  shouldRestartWithoutContinue = false;
1307
1307
  autoYesEnabled = true;
1308
+ restartCount = 0;
1308
1309
  constructor(params) {
1309
1310
  this.shell = params.shell;
1310
1311
  this.pidStore = params.pidStore;
@@ -1515,7 +1516,7 @@ const CLIS_CONFIG = config.clis;
1515
1516
  * });
1516
1517
  * ```
1517
1518
  */
1518
- async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, exitOnIdle, logFile, removeControlCharactersFromStdout = false, verbose = false, queue = false, install = false, resume = false, useSkills = false, useStdinAppend = false, autoYes = true }) {
1519
+ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, exitOnIdle, logFile, removeControlCharactersFromStdout = false, verbose = false, queue = false, install = false, resume = false, useSkills = false, useStdinAppend = false, autoYes = true, idleAction }) {
1519
1520
  if (!cli) throw new Error(`cli is required`);
1520
1521
  const conf = CLIS_CONFIG[cli] || DIE(`Unsupported cli tool: ${cli}, current process.argv: ${process.argv.join(" ")}`);
1521
1522
  const workingDir = cwd ?? process.cwd();
@@ -1705,6 +1706,14 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1705
1706
  }
1706
1707
  ctx.shouldRestartWithoutContinue = false;
1707
1708
  ctx.isFatal = false;
1709
+ if (ctx.restartCount >= 10) {
1710
+ logger.error(`${cli} reached max restarts (10), giving up.`);
1711
+ return pendingExitCode.resolve(exitCode);
1712
+ }
1713
+ const backoffMs = 1e3 * Math.pow(2, ctx.restartCount);
1714
+ logger.info(`Restart ${ctx.restartCount + 1}/10, waiting ${backoffMs}ms before restart...`);
1715
+ await sleep(backoffMs);
1716
+ ctx.restartCount++;
1708
1717
  let [bin, ...args] = [...parseCommandString(cliConf?.binary || cli), ...cliArgs.filter((arg) => !["--continue", "--resume"].includes(arg))];
1709
1718
  logger.info(`Restarting ${cli} ${JSON.stringify([bin, ...args])}`);
1710
1719
  const restartPtyOptions = {
@@ -1764,6 +1773,15 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1764
1773
  notifyWebhook("EXIT", `fatal exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
1765
1774
  return pendingExitCode.resolve(exitCode);
1766
1775
  }
1776
+ if (ctx.restartCount >= 10) {
1777
+ logger.error(`${cli} reached max restarts (10), giving up.`);
1778
+ notifyWebhook("EXIT", `max-restarts exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
1779
+ return pendingExitCode.resolve(exitCode);
1780
+ }
1781
+ const backoffMs = 1e3 * Math.pow(2, ctx.restartCount);
1782
+ logger.info(`${cli} crashed (exit code: ${exitCode}), restart ${ctx.restartCount + 1}/10 in ${backoffMs}ms...`);
1783
+ await sleep(backoffMs);
1784
+ ctx.restartCount++;
1767
1785
  try {
1768
1786
  await pidStore.updateStatus(exitedPid, "exited", {
1769
1787
  exitReason: "restarted",
@@ -1772,7 +1790,6 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1772
1790
  } catch (error) {
1773
1791
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
1774
1792
  }
1775
- logger.info(`${cli} crashed (exit code: ${exitCode}), restarting...`);
1776
1793
  let restoreArgs = conf.restoreArgs;
1777
1794
  if (cli === "codex") {
1778
1795
  const storedSessionId = await getSessionForCwd(workingDir);
@@ -1891,16 +1908,26 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1891
1908
  }, 800);
1892
1909
  const cleanupHeartbeat = () => clearInterval(heartbeatInterval);
1893
1910
  shell.onExit(cleanupHeartbeat);
1894
- if (exitOnIdle) ctx.idleWaiter.wait(exitOnIdle).then(async () => {
1895
- await pidStore.updateStatus(shell.pid, "idle").catch(() => null);
1896
- if (isStillWorkingQ()) {
1897
- logger.warn(`[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet`);
1898
- return;
1911
+ if (exitOnIdle) (async () => {
1912
+ while (true) {
1913
+ await ctx.idleWaiter.wait(exitOnIdle);
1914
+ await pidStore.updateStatus(shell.pid, "idle").catch(() => null);
1915
+ if (isStillWorkingQ()) {
1916
+ logger.warn(`[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet`);
1917
+ continue;
1918
+ }
1919
+ if (idleAction) {
1920
+ logger.info(`[${cli}-yes] ${cli} is idle, performing idle action: ${idleAction}`);
1921
+ notifyWebhook("IDLE", `action=${idleAction}`, workingDir).catch(() => null);
1922
+ await sendMessage(ctx.messageContext, idleAction);
1923
+ continue;
1924
+ }
1925
+ logger.info(`[${cli}-yes] ${cli} is idle, exiting...`);
1926
+ notifyWebhook("IDLE", "", workingDir).catch(() => null);
1927
+ await exitAgent();
1928
+ break;
1899
1929
  }
1900
- logger.info(`[${cli}-yes] ${cli} is idle, exiting...`);
1901
- notifyWebhook("IDLE", "", workingDir).catch(() => null);
1902
- await exitAgent();
1903
- });
1930
+ })();
1904
1931
  const stdinStream = new ReadableStream({
1905
1932
  start(controller) {
1906
1933
  process.stdin.resume();
@@ -2112,4 +2139,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
2112
2139
 
2113
2140
  //#endregion
2114
2141
  export { AgentContext as a, PidStore as c, config as i, removeControlCharacters as l, CLIS_CONFIG as n, name as o, agentYes as r, version as s, SUPPORTED_CLIS as t };
2115
- //# sourceMappingURL=SUPPORTED_CLIS-CWEfLDO6.js.map
2142
+ //# sourceMappingURL=SUPPORTED_CLIS-CmSMCHW2.js.map
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CWEfLDO6.js";
2
+ import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-CmSMCHW2.js";
3
3
  import { t as logger } from "./logger-CX77vJDA.js";
4
4
  import { argv } from "process";
5
5
  import { spawn } from "child_process";
@@ -56,7 +56,8 @@ function parseCliArgs(argv) {
56
56
  alias: "i"
57
57
  }).option("idle-action", {
58
58
  type: "string",
59
- description: "Idle action to perform when idle time is reached, e.g., \"/exit\" or \"check TODO.md\""
59
+ description: "Idle action to perform when idle time is reached, e.g., \"/exit\" or \"check TODO.md\"",
60
+ alias: "ia"
60
61
  }).option("queue", {
61
62
  type: "boolean",
62
63
  description: "Queue Agent Commands when spawning multiple agents in the same directory/repo, can be disabled with --no-queue",
@@ -189,6 +190,7 @@ function parseCliArgs(argv) {
189
190
  useStdinAppend: Boolean(parsedArgv.stdpush || parsedArgv.ipc || parsedArgv.fifo),
190
191
  showVersion: parsedArgv.version,
191
192
  autoYes: parsedArgv.auto !== "no",
193
+ idleAction: parsedArgv.idleAction,
192
194
  useRust: parsedArgv.rust,
193
195
  swarm: parsedArgv.swarm ?? (parsedArgv.experimentalSwarm ? parsedArgv.swarmTopic : void 0),
194
196
  experimentalSwarm: parsedArgv.experimentalSwarm,
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-CWEfLDO6.js";
1
+ import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-CmSMCHW2.js";
2
2
  import "./logger-CX77vJDA.js";
3
3
 
4
4
  export { AgentContext, CLIS_CONFIG, config, agentYes as default, removeControlCharacters };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-yes",
3
- "version": "1.65.0",
3
+ "version": "1.67.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",
package/ts/index.ts CHANGED
@@ -119,6 +119,7 @@ export default async function agentYes({
119
119
  useSkills = false,
120
120
  useStdinAppend = false,
121
121
  autoYes = true,
122
+ idleAction,
122
123
  }: {
123
124
  cli: SUPPORTED_CLIS;
124
125
  cliArgs?: string[];
@@ -136,6 +137,7 @@ export default async function agentYes({
136
137
  useSkills?: boolean; // if true, prepend SKILL.md header to the prompt for non-Claude agents
137
138
  useStdinAppend?: boolean; // if true, enable FIFO input stream on Linux, for additional stdin input
138
139
  autoYes?: boolean; // if true, auto-yes is enabled (default), toggle with Ctrl+Y during session
140
+ idleAction?: string; // if set, type this message when idle instead of exiting
139
141
  }) {
140
142
  if (!cli) throw new Error(`cli is required`);
141
143
  const conf =
@@ -420,6 +422,16 @@ export default async function agentYes({
420
422
  ctx.shouldRestartWithoutContinue = false; // reset flag
421
423
  ctx.isFatal = false; // reset fatal flag to allow restart
422
424
 
425
+ // Enforce restart limit with exponential backoff
426
+ if (ctx.restartCount >= 10) {
427
+ logger.error(`${cli} reached max restarts (10), giving up.`);
428
+ return pendingExitCode.resolve(exitCode);
429
+ }
430
+ const backoffMs = 1000 * Math.pow(2, ctx.restartCount);
431
+ logger.info(`Restart ${ctx.restartCount + 1}/10, waiting ${backoffMs}ms before restart...`);
432
+ await sleep(backoffMs);
433
+ ctx.restartCount++;
434
+
423
435
  // Restart without continue args - use original cliArgs without restoreArgs
424
436
  const cliCommand = cliConf?.binary || cli;
425
437
  let [bin, ...args] = [
@@ -491,6 +503,21 @@ export default async function agentYes({
491
503
  return pendingExitCode.resolve(exitCode);
492
504
  }
493
505
 
506
+ // Enforce restart limit with exponential backoff
507
+ if (ctx.restartCount >= 10) {
508
+ logger.error(`${cli} reached max restarts (10), giving up.`);
509
+ notifyWebhook("EXIT", `max-restarts exitCode=${exitCode ?? "?"}`, workingDir).catch(
510
+ () => null,
511
+ );
512
+ return pendingExitCode.resolve(exitCode);
513
+ }
514
+ const backoffMs = 1000 * Math.pow(2, ctx.restartCount);
515
+ logger.info(
516
+ `${cli} crashed (exit code: ${exitCode}), restart ${ctx.restartCount + 1}/10 in ${backoffMs}ms...`,
517
+ );
518
+ await sleep(backoffMs);
519
+ ctx.restartCount++;
520
+
494
521
  // Update status (non-blocking)
495
522
  try {
496
523
  await pidStore.updateStatus(exitedPid, "exited", {
@@ -500,7 +527,6 @@ export default async function agentYes({
500
527
  } catch (error) {
501
528
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
502
529
  }
503
- logger.info(`${cli} crashed (exit code: ${exitCode}), restarting...`);
504
530
 
505
531
  // For codex, try to use stored session ID for this directory
506
532
  let restoreArgs = conf.restoreArgs;
@@ -665,17 +691,26 @@ export default async function agentYes({
665
691
  shell.onExit(cleanupHeartbeat);
666
692
 
667
693
  if (exitOnIdle)
668
- ctx.idleWaiter.wait(exitOnIdle).then(async () => {
669
- await pidStore.updateStatus(shell.pid, "idle").catch(() => null);
670
- if (isStillWorkingQ()) {
671
- logger.warn(`[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet`);
672
- return;
694
+ (async () => {
695
+ while (true) {
696
+ await ctx.idleWaiter.wait(exitOnIdle);
697
+ await pidStore.updateStatus(shell.pid, "idle").catch(() => null);
698
+ if (isStillWorkingQ()) {
699
+ logger.warn(`[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet`);
700
+ continue;
701
+ }
702
+ if (idleAction) {
703
+ logger.info(`[${cli}-yes] ${cli} is idle, performing idle action: ${idleAction}`);
704
+ notifyWebhook("IDLE", `action=${idleAction}`, workingDir).catch(() => null);
705
+ await sendMessage(ctx.messageContext, idleAction);
706
+ continue;
707
+ }
708
+ logger.info(`[${cli}-yes] ${cli} is idle, exiting...`);
709
+ notifyWebhook("IDLE", "", workingDir).catch(() => null);
710
+ await exitAgent();
711
+ break;
673
712
  }
674
-
675
- logger.info(`[${cli}-yes] ${cli} is idle, exiting...`);
676
- notifyWebhook("IDLE", "", workingDir).catch(() => null);
677
- await exitAgent();
678
- });
713
+ })();
679
714
 
680
715
  // Message streaming
681
716
 
@@ -83,6 +83,7 @@ export function parseCliArgs(argv: string[]) {
83
83
  type: "string",
84
84
  description:
85
85
  'Idle action to perform when idle time is reached, e.g., "/exit" or "check TODO.md"',
86
+ alias: "ia",
86
87
  })
87
88
  .option("queue", {
88
89
  type: "boolean",
@@ -273,6 +274,7 @@ export function parseCliArgs(argv: string[]) {
273
274
  useStdinAppend: Boolean(parsedArgv.stdpush || parsedArgv.ipc || parsedArgv.fifo), // Support --stdpush, --ipc, and --fifo (backward compatibility)
274
275
  showVersion: parsedArgv.version,
275
276
  autoYes: parsedArgv.auto !== "no", // auto-yes enabled by default, disabled with --auto=no
277
+ idleAction: parsedArgv.idleAction as string | undefined,
276
278
  useRust: parsedArgv.rust,
277
279
  // New unified --swarm flag (takes precedence over deprecated flags)
278
280
  swarm: parsedArgv.swarm ?? (parsedArgv.experimentalSwarm ? parsedArgv.swarmTopic : undefined),