agent-yes 1.57.0 → 1.58.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.
@@ -49,7 +49,10 @@
49
49
  {
50
50
  "type": "object",
51
51
  "properties": {
52
- "powershell": { "type": "string", "description": "PowerShell install command (Windows)" },
52
+ "powershell": {
53
+ "type": "string",
54
+ "description": "PowerShell install command (Windows)"
55
+ },
53
56
  "bash": { "type": "string", "description": "Bash install command (Unix/macOS)" },
54
57
  "npm": { "type": "string", "description": "npm install command (fallback)" },
55
58
  "unix": { "type": "string", "description": "Unix-specific install command" },
@@ -9797,7 +9797,7 @@ function tryCatch(catchFn, fn) {
9797
9797
  //#endregion
9798
9798
  //#region package.json
9799
9799
  var name = "agent-yes";
9800
- var version = "1.57.0";
9800
+ var version = "1.58.0";
9801
9801
 
9802
9802
  //#endregion
9803
9803
  //#region ts/pty-fix.ts
@@ -10646,21 +10646,21 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10646
10646
  const dataHandler = (chunk) => {
10647
10647
  try {
10648
10648
  controller.enqueue(chunk);
10649
- } catch (err) {}
10649
+ } catch {}
10650
10650
  };
10651
10651
  const endHandler = () => {
10652
10652
  if (closed) return;
10653
10653
  closed = true;
10654
10654
  try {
10655
10655
  controller.close();
10656
- } catch (err) {}
10656
+ } catch {}
10657
10657
  };
10658
10658
  const errorHandler = (err) => {
10659
10659
  if (closed) return;
10660
10660
  closed = true;
10661
10661
  try {
10662
10662
  controller.error(err);
10663
- } catch (err) {}
10663
+ } catch {}
10664
10664
  };
10665
10665
  process.stdin.on("data", dataHandler);
10666
10666
  process.stdin.on("end", endHandler);
@@ -10844,4 +10844,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
10844
10844
 
10845
10845
  //#endregion
10846
10846
  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 };
10847
- //# sourceMappingURL=SUPPORTED_CLIS-DNBWqwwx.js.map
10847
+ //# sourceMappingURL=SUPPORTED_CLIS-Kash6b_w.js.map
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  import { c as __toESM, i as __commonJSMin, r as require_ms, t as logger } from "./logger-DH1Rx9HI.js";
3
3
  import "./agent-yes.config-Dr2p5kBW.js";
4
- import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DNBWqwwx.js";
4
+ import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-Kash6b_w.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { argv } from "process";
7
7
  import { spawn } from "child_process";
@@ -4690,7 +4690,7 @@ async function fetchLatestVersion() {
4690
4690
  const response = await fetch(`https://registry.npmjs.org/${name}/latest`, { signal: AbortSignal.timeout(3e3) });
4691
4691
  if (!response.ok) return null;
4692
4692
  return (await response.json()).version;
4693
- } catch (error) {
4693
+ } catch {
4694
4694
  return null;
4695
4695
  }
4696
4696
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./logger-DH1Rx9HI.js";
2
- import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-DNBWqwwx.js";
2
+ import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-Kash6b_w.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.57.0",
3
+ "version": "1.58.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",
@@ -30,29 +30,29 @@
30
30
  },
31
31
  "bin": {
32
32
  "agent-yes": "./dist/agent-yes.js",
33
- "ay": "./dist/agent-yes.js",
34
33
  "amp-yes": "./dist/amp-yes.js",
35
34
  "auggie-yes": "./dist/auggie-yes.js",
35
+ "ay": "./dist/agent-yes.js",
36
36
  "claude-yes": "./dist/claude-yes.js",
37
37
  "codex-yes": "./dist/codex-yes.js",
38
38
  "copilot-yes": "./dist/copilot-yes.js",
39
39
  "cursor-yes": "./dist/cursor-yes.js",
40
40
  "gemini-yes": "./dist/gemini-yes.js",
41
41
  "grok-yes": "./dist/grok-yes.js",
42
- "qwen-yes": "./dist/qwen-yes.js",
43
- "opencode-yes": "./dist/opencode-yes.js"
42
+ "opencode-yes": "./dist/opencode-yes.js",
43
+ "qwen-yes": "./dist/qwen-yes.js"
44
44
  },
45
45
  "directories": {
46
46
  "doc": "docs"
47
47
  },
48
48
  "files": [
49
+ "agent-yes.config.schema.json",
50
+ "bin",
51
+ "examples",
49
52
  "scripts",
50
53
  "ts/*.ts",
51
54
  "!dist/**/*.map",
52
- "dist/**/*.js",
53
- "bin",
54
- "agent-yes.config.schema.json",
55
- "examples"
55
+ "dist/**/*.js"
56
56
  ],
57
57
  "type": "module",
58
58
  "module": "ts/index.ts",
@@ -3,10 +3,10 @@
3
3
  * Pre-publish verification script
4
4
  * Checks that critical runtime dependencies are properly configured
5
5
  */
6
- import { readFileSync, existsSync } from 'fs';
7
- import { join } from 'path';
8
- import { fileURLToPath } from 'url';
9
- import { dirname } from 'path';
6
+ import { readFileSync, existsSync } from "fs";
7
+ import { join } from "path";
8
+ import { fileURLToPath } from "url";
9
+ import { dirname } from "path";
10
10
 
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = dirname(__filename);
@@ -15,10 +15,10 @@ const errors = [];
15
15
  const warnings = [];
16
16
 
17
17
  // Load package.json
18
- const pkgPath = join(__dirname, '..', 'package.json');
19
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
18
+ const pkgPath = join(__dirname, "..", "package.json");
19
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
20
20
 
21
- console.log('🔍 Verifying agent-yes package configuration...\n');
21
+ console.log("🔍 Verifying agent-yes package configuration...\n");
22
22
 
23
23
  // Check 1: Verify critical runtime dependencies are in dependencies, not devDependencies
24
24
  const runtimeImports = [
@@ -41,16 +41,16 @@ for (const { module, reason } of runtimeImports) {
41
41
  }
42
42
 
43
43
  // Check 2: Verify build script externalizes the right dependencies
44
- const buildScript = pkg.scripts?.build || '';
44
+ const buildScript = pkg.scripts?.build || "";
45
45
  const externals = buildScript.match(/--external=[^\s]+/g) || [];
46
46
 
47
- console.log('\n📦 Build externals:');
47
+ console.log("\n📦 Build externals:");
48
48
  for (const ext of externals) {
49
49
  console.log(` ${ext}`);
50
- const modName = ext.replace('--external=', '');
50
+ const modName = ext.replace("--external=", "");
51
51
 
52
52
  // Check if externalized module is in dependencies
53
- if (modName.startsWith('@') || modName.includes('/')) {
53
+ if (modName.startsWith("@") || modName.includes("/")) {
54
54
  const inDeps = pkg.dependencies?.[modName];
55
55
  const inOptionalDeps = pkg.optionalDependencies?.[modName];
56
56
 
@@ -62,22 +62,22 @@ for (const ext of externals) {
62
62
  }
63
63
 
64
64
  // Check 3: Verify files field includes necessary runtime files
65
- console.log('\n📁 Package files configuration:');
65
+ console.log("\n📁 Package files configuration:");
66
66
  const files = pkg.files || [];
67
- console.log(` Files patterns: ${files.join(', ')}`);
67
+ console.log(` Files patterns: ${files.join(", ")}`);
68
68
 
69
- if (!files.includes('dist/**/*.js') && !files.includes('dist')) {
70
- errors.push('❌ dist directory not included in package files');
69
+ if (!files.includes("dist/**/*.js") && !files.includes("dist")) {
70
+ errors.push("❌ dist directory not included in package files");
71
71
  }
72
72
 
73
- if (!files.includes('scripts') && pkg.scripts?.postinstall?.includes('scripts/')) {
74
- warnings.push('⚠️ postinstall references scripts/ but it may not be included');
73
+ if (!files.includes("scripts") && pkg.scripts?.postinstall?.includes("scripts/")) {
74
+ warnings.push("⚠️ postinstall references scripts/ but it may not be included");
75
75
  }
76
76
 
77
77
  // Check 4: Verify bin entries point to existing files (after build)
78
- console.log('\n🔗 Binary entries:');
78
+ console.log("\n🔗 Binary entries:");
79
79
  for (const [name, path] of Object.entries(pkg.bin || {})) {
80
- const fullPath = join(__dirname, '..', path);
80
+ const fullPath = join(__dirname, "..", path);
81
81
  if (existsSync(fullPath)) {
82
82
  console.log(` ✓ ${name} → ${path}`);
83
83
  } else {
@@ -87,26 +87,26 @@ for (const [name, path] of Object.entries(pkg.bin || {})) {
87
87
  }
88
88
 
89
89
  // Summary
90
- console.log('\n' + '='.repeat(60));
90
+ console.log("\n" + "=".repeat(60));
91
91
  if (errors.length === 0 && warnings.length === 0) {
92
- console.log('✅ All checks passed! Package is ready for publish.\n');
92
+ console.log("✅ All checks passed! Package is ready for publish.\n");
93
93
  process.exit(0);
94
94
  } else {
95
95
  if (errors.length > 0) {
96
- console.error('\n❌ ERRORS FOUND:');
97
- errors.forEach(err => console.error(` ${err}`));
96
+ console.error("\n❌ ERRORS FOUND:");
97
+ errors.forEach((err) => console.error(` ${err}`));
98
98
  }
99
99
 
100
100
  if (warnings.length > 0) {
101
- console.warn('\n⚠️ WARNINGS:');
102
- warnings.forEach(warn => console.warn(` ${warn}`));
101
+ console.warn("\n⚠️ WARNINGS:");
102
+ warnings.forEach((warn) => console.warn(` ${warn}`));
103
103
  }
104
104
 
105
105
  if (errors.length > 0) {
106
- console.error('\n❌ Fix errors before publishing!\n');
106
+ console.error("\n❌ Fix errors before publishing!\n");
107
107
  process.exit(1);
108
108
  } else {
109
- console.warn('\n⚠️ Review warnings before publishing.\n');
109
+ console.warn("\n⚠️ Review warnings before publishing.\n");
110
110
  process.exit(0);
111
111
  }
112
112
  }
package/ts/JsonlStore.ts CHANGED
@@ -204,5 +204,7 @@ export class JsonlStore<T extends Record<string, any> = Record<string, any>> {
204
204
 
205
205
  let idCounter = 0;
206
206
  function generateId(): string {
207
- return Date.now().toString(36) + (idCounter++).toString(36) + Math.random().toString(36).slice(2, 6);
207
+ return (
208
+ Date.now().toString(36) + (idCounter++).toString(36) + Math.random().toString(36).slice(2, 6)
209
+ );
208
210
  }
@@ -53,7 +53,7 @@ class AgentRegistry {
53
53
  }
54
54
 
55
55
  // Split by lines and add to buffer
56
- const lines = data.split('\n');
56
+ const lines = data.split("\n");
57
57
  instance.stdoutBuffer.push(...lines);
58
58
 
59
59
  // Maintain circular buffer size
@@ -2,7 +2,18 @@
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { buildRustArgs } from "./buildRustArgs";
4
4
 
5
- const SUPPORTED_CLIS = ["claude", "gemini", "codex", "copilot", "cursor", "grok", "qwen", "auggie", "amp", "opencode"];
5
+ const SUPPORTED_CLIS = [
6
+ "claude",
7
+ "gemini",
8
+ "codex",
9
+ "copilot",
10
+ "cursor",
11
+ "grok",
12
+ "qwen",
13
+ "auggie",
14
+ "amp",
15
+ "opencode",
16
+ ];
6
17
 
7
18
  // Helper: simulate argv as [node, script, ...userArgs]
8
19
  function argv(...userArgs: string[]): string[] {
@@ -21,7 +32,11 @@ describe("buildRustArgs", () => {
21
32
  });
22
33
 
23
34
  it("appends CLI name after multiple flags", () => {
24
- const result = buildRustArgs(argv("--timeout", "30s", "--verbose", "--robust", "true"), "claude", SUPPORTED_CLIS);
35
+ const result = buildRustArgs(
36
+ argv("--timeout", "30s", "--verbose", "--robust", "true"),
37
+ "claude",
38
+ SUPPORTED_CLIS,
39
+ );
25
40
  expect(result).toEqual(["--timeout", "30s", "--verbose", "--robust", "true", "claude"]);
26
41
  });
27
42
 
@@ -89,7 +104,11 @@ describe("buildRustArgs", () => {
89
104
  });
90
105
 
91
106
  it("removes --rust regardless of position", () => {
92
- const result = buildRustArgs(argv("--verbose", "--rust", "--timeout", "5m"), "claude", SUPPORTED_CLIS);
107
+ const result = buildRustArgs(
108
+ argv("--verbose", "--rust", "--timeout", "5m"),
109
+ "claude",
110
+ SUPPORTED_CLIS,
111
+ );
93
112
  expect(result).not.toContain("--rust");
94
113
  expect(result).toEqual(["--verbose", "--timeout", "5m", "claude"]);
95
114
  });
@@ -105,13 +124,21 @@ describe("buildRustArgs", () => {
105
124
  });
106
125
 
107
126
  it("skips appending when --cli= flag is used", () => {
108
- const result = buildRustArgs(argv("--cli=gemini", "--timeout", "30s"), "claude", SUPPORTED_CLIS);
127
+ const result = buildRustArgs(
128
+ argv("--cli=gemini", "--timeout", "30s"),
129
+ "claude",
130
+ SUPPORTED_CLIS,
131
+ );
109
132
  expect(result).toEqual(["--cli=gemini", "--timeout", "30s"]);
110
133
  expect(result).not.toContain("claude");
111
134
  });
112
135
 
113
136
  it("skips appending when --cli flag is used (separate value)", () => {
114
- const result = buildRustArgs(argv("--cli", "gemini", "--timeout", "30s"), "claude", SUPPORTED_CLIS);
137
+ const result = buildRustArgs(
138
+ argv("--cli", "gemini", "--timeout", "30s"),
139
+ "claude",
140
+ SUPPORTED_CLIS,
141
+ );
115
142
  expect(result).toEqual(["--cli", "gemini", "--timeout", "30s"]);
116
143
  expect(result).not.toContain("claude");
117
144
  });
@@ -218,7 +245,11 @@ describe("buildRustArgs", () => {
218
245
  });
219
246
 
220
247
  it("claude-yes --rust --timeout 30s --verbose", () => {
221
- const result = buildRustArgs(argv("--rust", "--timeout", "30s", "--verbose"), "claude", SUPPORTED_CLIS);
248
+ const result = buildRustArgs(
249
+ argv("--rust", "--timeout", "30s", "--verbose"),
250
+ "claude",
251
+ SUPPORTED_CLIS,
252
+ );
222
253
  expect(result).toEqual(["--timeout", "30s", "--verbose", "claude"]);
223
254
  });
224
255
 
@@ -237,7 +268,11 @@ describe("buildRustArgs", () => {
237
268
  });
238
269
 
239
270
  it("agent-yes --rust claude --timeout 1h (explicit CLI in args)", () => {
240
- const result = buildRustArgs(argv("--rust", "claude", "--timeout", "1h"), undefined, SUPPORTED_CLIS);
271
+ const result = buildRustArgs(
272
+ argv("--rust", "claude", "--timeout", "1h"),
273
+ undefined,
274
+ SUPPORTED_CLIS,
275
+ );
241
276
  // cliFromScript is undefined (agent-yes), CLI already in args
242
277
  expect(result).toEqual(["claude", "--timeout", "1h"]);
243
278
  });
@@ -13,20 +13,15 @@ export function buildRustArgs(
13
13
  supportedClis: readonly string[],
14
14
  ): string[] {
15
15
  // Filter out --rust flag (already handled by TS layer)
16
- const rawRustArgs = argv
17
- .slice(2)
18
- .filter((arg) => arg !== "--rust" && !arg.startsWith("--rust="));
16
+ const rawRustArgs = argv.slice(2).filter((arg) => arg !== "--rust" && !arg.startsWith("--rust="));
19
17
 
20
18
  // Check if swarm mode is requested (don't append CLI name for swarm mode)
21
- const hasSwarmArg = rawRustArgs.some(
22
- (arg) => arg === "--swarm" || arg.startsWith("--swarm="),
23
- );
19
+ const hasSwarmArg = rawRustArgs.some((arg) => arg === "--swarm" || arg.startsWith("--swarm="));
24
20
 
25
21
  // Check if CLI is already specified in args
26
22
  const hasCliArg =
27
- rawRustArgs.some(
28
- (arg) => arg.startsWith("--cli=") || arg === "--cli",
29
- ) || rawRustArgs.some((arg) => supportedClis.includes(arg));
23
+ rawRustArgs.some((arg) => arg.startsWith("--cli=") || arg === "--cli") ||
24
+ rawRustArgs.some((arg) => supportedClis.includes(arg));
30
25
 
31
26
  // Append CLI name at the end so it doesn't trigger trailing_var_arg in clap,
32
27
  // which would cause all subsequent args (like --timeout) to be treated as positional
@@ -26,7 +26,7 @@ describe("configLoader", () => {
26
26
  defaultArgs: ["--verbose"],
27
27
  },
28
28
  },
29
- })
29
+ }),
30
30
  );
31
31
 
32
32
  const config = await loadCascadingConfig({ projectDir: testDir });
@@ -44,7 +44,7 @@ clis:
44
44
  gemini:
45
45
  defaultArgs:
46
46
  - --resume
47
- `
47
+ `,
48
48
  );
49
49
 
50
50
  const config = await loadCascadingConfig({ projectDir: testDir });
@@ -58,7 +58,7 @@ clis:
58
58
  configPath,
59
59
  `
60
60
  logsDir: /custom/logs
61
- `
61
+ `,
62
62
  );
63
63
 
64
64
  const config = await loadCascadingConfig({ projectDir: testDir });
@@ -68,12 +68,9 @@ logsDir: /custom/logs
68
68
  it("should prefer JSON over YAML when both exist", async () => {
69
69
  await writeFile(
70
70
  path.join(testDir, ".agent-yes.config.json"),
71
- JSON.stringify({ configDir: "/json/config" })
72
- );
73
- await writeFile(
74
- path.join(testDir, ".agent-yes.config.yaml"),
75
- `configDir: /yaml/config`
71
+ JSON.stringify({ configDir: "/json/config" }),
76
72
  );
73
+ await writeFile(path.join(testDir, ".agent-yes.config.yaml"), `configDir: /yaml/config`);
77
74
 
78
75
  const config = await loadCascadingConfig({ projectDir: testDir });
79
76
  expect(config.configDir).toBe("/json/config");
@@ -110,14 +107,14 @@ logsDir: /custom/logs
110
107
  JSON.stringify({
111
108
  configDir: "/home/config",
112
109
  logsDir: "/home/logs",
113
- })
110
+ }),
114
111
  );
115
112
 
116
113
  await writeFile(
117
114
  path.join(projectDir, ".agent-yes.config.json"),
118
115
  JSON.stringify({
119
116
  configDir: "/project/config",
120
- })
117
+ }),
121
118
  );
122
119
 
123
120
  const config = await loadCascadingConfig({ projectDir, homeDir });
@@ -127,10 +124,7 @@ logsDir: /custom/logs
127
124
 
128
125
  it("should add schema reference to JSON config without one", async () => {
129
126
  const configPath = path.join(testDir, ".agent-yes.config.json");
130
- await writeFile(
131
- configPath,
132
- JSON.stringify({ configDir: "/test" })
133
- );
127
+ await writeFile(configPath, JSON.stringify({ configDir: "/test" }));
134
128
 
135
129
  const result = await ensureSchemaInConfigFiles({ projectDir: testDir, homeDir: testDir });
136
130
  expect(result.modified).toContain(configPath);
@@ -150,7 +144,7 @@ clis:
150
144
  claude:
151
145
  defaultArgs:
152
146
  - --verbose
153
- `
147
+ `,
154
148
  );
155
149
 
156
150
  const result = await ensureSchemaInConfigFiles({ projectDir: testDir, homeDir: testDir });
@@ -164,10 +158,14 @@ clis:
164
158
 
165
159
  it("should skip JSON config that already has schema", async () => {
166
160
  const configPath = path.join(testDir, ".agent-yes.config.json");
167
- const originalContent = JSON.stringify({
168
- $schema: "https://example.com/schema.json",
169
- configDir: "/test",
170
- }, null, 2);
161
+ const originalContent = JSON.stringify(
162
+ {
163
+ $schema: "https://example.com/schema.json",
164
+ configDir: "/test",
165
+ },
166
+ null,
167
+ 2,
168
+ );
171
169
  await writeFile(configPath, originalContent);
172
170
 
173
171
  const result = await ensureSchemaInConfigFiles({ projectDir: testDir, homeDir: testDir });
@@ -12,7 +12,8 @@ import { deepMixin } from "./utils.ts";
12
12
 
13
13
  const CONFIG_FILENAME = ".agent-yes.config";
14
14
  const CONFIG_EXTENSIONS = [".json", ".yml", ".yaml"] as const;
15
- const SCHEMA_URL = "https://raw.githubusercontent.com/snomiao/agent-yes/main/agent-yes.config.schema.json";
15
+ const SCHEMA_URL =
16
+ "https://raw.githubusercontent.com/snomiao/agent-yes/main/agent-yes.config.schema.json";
16
17
  const YAML_SCHEMA_COMMENT = `# yaml-language-server: $schema=${SCHEMA_URL}`;
17
18
 
18
19
  /**
@@ -97,7 +98,7 @@ export interface ConfigLoadOptions {
97
98
  * Higher priority configs override lower priority ones
98
99
  */
99
100
  export async function loadCascadingConfig(
100
- options: ConfigLoadOptions = {}
101
+ options: ConfigLoadOptions = {},
101
102
  ): Promise<Partial<AgentYesConfig>> {
102
103
  const projectDir = options.projectDir ?? process.cwd();
103
104
  const homeDir = options.homeDir ?? os.homedir();
@@ -114,9 +115,7 @@ export async function loadCascadingConfig(
114
115
  ]);
115
116
 
116
117
  // Filter out empty configs and merge
117
- const nonEmptyConfigs = configs.filter(
118
- (c) => c && Object.keys(c).length > 0
119
- );
118
+ const nonEmptyConfigs = configs.filter((c) => c && Object.keys(c).length > 0);
120
119
 
121
120
  if (nonEmptyConfigs.length === 0) {
122
121
  logger.debug("[config] No config files found in any location");
@@ -212,7 +211,7 @@ function addSchemaReference(content: string, ext: string): string {
212
211
  * Modifies files in-place if they don't have a schema reference
213
212
  */
214
213
  export async function ensureSchemaInConfigFiles(
215
- options: ConfigLoadOptions = {}
214
+ options: ConfigLoadOptions = {},
216
215
  ): Promise<{ modified: string[]; skipped: string[] }> {
217
216
  const projectDir = options.projectDir ?? process.cwd();
218
217
  const homeDir = options.homeDir ?? os.homedir();
package/ts/index.ts CHANGED
@@ -178,7 +178,10 @@ export default async function agentYes({
178
178
  // Track when user sends Ctrl+C to avoid treating intentional exit as crash
179
179
  let userSentCtrlC = false;
180
180
 
181
- if (verbose) logger.debug(`[stdin] isTTY: ${process.stdin.isTTY}, setRawMode available: ${!!process.stdin.setRawMode}`);
181
+ if (verbose)
182
+ logger.debug(
183
+ `[stdin] isTTY: ${process.stdin.isTTY}, setRawMode available: ${!!process.stdin.setRawMode}`,
184
+ );
182
185
  process.stdin.setRawMode?.(true); // must be called any stdout/stdin usage
183
186
  if (verbose) logger.debug(`[stdin] Raw mode set, isRaw: ${(process.stdin as any).isRaw}`);
184
187
 
@@ -358,7 +361,7 @@ export default async function agentYes({
358
361
  cli,
359
362
  prompt,
360
363
  startTime: Date.now(),
361
- stdoutBuffer: []
364
+ stdoutBuffer: [],
362
365
  });
363
366
  } catch (error) {
364
367
  logger.warn(`[agentRegistry] Failed to register agent ${shell.pid}:`, error);
@@ -450,7 +453,7 @@ export default async function agentYes({
450
453
  cli,
451
454
  prompt,
452
455
  startTime: Date.now(),
453
- stdoutBuffer: []
456
+ stdoutBuffer: [],
454
457
  });
455
458
  } catch (error) {
456
459
  logger.warn(`[agentRegistry] Failed to register restarted agent ${shell.pid}:`, error);
@@ -522,7 +525,13 @@ export default async function agentYes({
522
525
  shell = pty.spawn(cli, restoreArgs, restorePtyOptions);
523
526
  // Register process in pidStore (non-blocking)
524
527
  try {
525
- await pidStore.registerProcess({ pid: shell.pid, cli, args: restoreArgs, prompt, cwd: workingDir });
528
+ await pidStore.registerProcess({
529
+ pid: shell.pid,
530
+ cli,
531
+ args: restoreArgs,
532
+ prompt,
533
+ cwd: workingDir,
534
+ });
526
535
  } catch (error) {
527
536
  logger.warn(`[pidStore] Failed to register restored process ${shell.pid}:`, error);
528
537
  }
@@ -537,7 +546,7 @@ export default async function agentYes({
537
546
  cli,
538
547
  prompt,
539
548
  startTime: Date.now(),
540
- stdoutBuffer: []
549
+ stdoutBuffer: [],
541
550
  });
542
551
  } catch (error) {
543
552
  logger.warn(`[agentRegistry] Failed to register restored agent ${shell.pid}:`, error);
@@ -561,7 +570,9 @@ export default async function agentYes({
561
570
  } catch (error) {
562
571
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
563
572
  }
564
- notifyWebhook("EXIT", `${exitReason} exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
573
+ notifyWebhook("EXIT", `${exitReason} exitCode=${exitCode ?? "?"}`, workingDir).catch(
574
+ () => null,
575
+ );
565
576
  return pendingExitCode.resolve(exitCode);
566
577
  });
567
578
 
@@ -687,7 +698,7 @@ export default async function agentYes({
687
698
  const dataHandler = (chunk: Buffer) => {
688
699
  try {
689
700
  controller.enqueue(chunk);
690
- } catch (err) {
701
+ } catch {
691
702
  // Ignore enqueue errors (stream may be closed)
692
703
  }
693
704
  };
@@ -698,7 +709,7 @@ export default async function agentYes({
698
709
  closed = true;
699
710
  try {
700
711
  controller.close();
701
- } catch (err) {
712
+ } catch {
702
713
  // Ignore close errors (already closed)
703
714
  }
704
715
  };
@@ -708,19 +719,19 @@ export default async function agentYes({
708
719
  closed = true;
709
720
  try {
710
721
  controller.error(err);
711
- } catch (err) {
722
+ } catch {
712
723
  // Ignore error after close
713
724
  }
714
725
  };
715
726
 
716
- process.stdin.on('data', dataHandler);
717
- process.stdin.on('end', endHandler);
718
- process.stdin.on('close', endHandler);
719
- process.stdin.on('error', errorHandler);
727
+ process.stdin.on("data", dataHandler);
728
+ process.stdin.on("end", endHandler);
729
+ process.stdin.on("close", endHandler);
730
+ process.stdin.on("error", errorHandler);
720
731
  },
721
732
  cancel(reason) {
722
733
  process.stdin.pause();
723
- }
734
+ },
724
735
  });
725
736
 
726
737
  let aborted = false;
@@ -752,63 +763,71 @@ export default async function agentYes({
752
763
  if (str === CTRL_C) {
753
764
  userSentCtrlC = true;
754
765
  // Reset flag after 2 seconds in case CLI doesn't exit immediately
755
- setTimeout(() => { userSentCtrlC = false; }, 2000);
766
+ setTimeout(() => {
767
+ userSentCtrlC = false;
768
+ }, 2000);
756
769
  }
757
770
 
758
771
  return str;
759
772
  })
760
773
 
761
774
  // Detect Ctrl+Y or /auto command to toggle auto-yes mode
762
- .map((() => {
763
- let line = "";
764
- const toggleAutoYes = () => {
765
- ctx.autoYesEnabled = !ctx.autoYesEnabled;
766
- // When switching to manual mode, mark stdin ready so user keystrokes are not blocked
767
- if (!ctx.autoYesEnabled) {
768
- ctx.stdinReady.ready();
769
- ctx.stdinFirstReady.ready();
770
- }
771
- const status = ctx.autoYesEnabled ? "\x1b[32m[auto-yes: ON]\x1b[0m" : "\x1b[33m[auto-yes: OFF]\x1b[0m";
772
- process.stderr.write(`\r${status} (Ctrl+Y to toggle)\n`);
773
- };
774
- return (data: string) => {
775
- let out = "";
776
- for (const ch of data) {
777
- // Ctrl+Y (\x19) toggles auto-yes immediately
778
- if (ch === "\x19") {
779
- toggleAutoYes();
780
- // Do not forward Ctrl+Y to the PTY
781
- continue;
775
+ .map(
776
+ (() => {
777
+ let line = "";
778
+ const toggleAutoYes = () => {
779
+ ctx.autoYesEnabled = !ctx.autoYesEnabled;
780
+ // When switching to manual mode, mark stdin ready so user keystrokes are not blocked
781
+ if (!ctx.autoYesEnabled) {
782
+ ctx.stdinReady.ready();
783
+ ctx.stdinFirstReady.ready();
782
784
  }
783
- // Handle Enter
784
- if (ch === "\r" || ch === "\n") {
785
- // Only check for /auto if line is short enough
786
- if (line.length <= 20) {
787
- const cleanLine = line.replace(/[\x00-\x1f]|\x1b\[[0-9;]*[A-Za-z]|\[[A-Z]/g, '').trim();
788
- if (cleanLine === "/auto") {
789
- out += "\x15"; // Ctrl+U to clear the /auto text from shell input
790
- toggleAutoYes();
791
- line = "";
792
- continue;
785
+ const status = ctx.autoYesEnabled
786
+ ? "\x1b[32m[auto-yes: ON]\x1b[0m"
787
+ : "\x1b[33m[auto-yes: OFF]\x1b[0m";
788
+ process.stderr.write(`\r${status} (Ctrl+Y to toggle)\n`);
789
+ };
790
+ return (data: string) => {
791
+ let out = "";
792
+ for (const ch of data) {
793
+ // Ctrl+Y (\x19) toggles auto-yes immediately
794
+ if (ch === "\x19") {
795
+ toggleAutoYes();
796
+ // Do not forward Ctrl+Y to the PTY
797
+ continue;
798
+ }
799
+ // Handle Enter
800
+ if (ch === "\r" || ch === "\n") {
801
+ // Only check for /auto if line is short enough
802
+ if (line.length <= 20) {
803
+ const cleanLine = line
804
+ .replace(/[\x00-\x1f]|\x1b\[[0-9;]*[A-Za-z]|\[[A-Z]/g, "")
805
+ .trim();
806
+ if (cleanLine === "/auto") {
807
+ out += "\x15"; // Ctrl+U to clear the /auto text from shell input
808
+ toggleAutoYes();
809
+ line = "";
810
+ continue;
811
+ }
793
812
  }
813
+ line = "";
814
+ out += ch;
815
+ continue;
794
816
  }
795
- line = "";
796
- out += ch;
797
- continue;
798
- }
799
- // Handle backspace
800
- if (ch === "\x7f" || ch === "\b") {
801
- if (line.length > 0) line = line.slice(0, -1);
817
+ // Handle backspace
818
+ if (ch === "\x7f" || ch === "\b") {
819
+ if (line.length > 0) line = line.slice(0, -1);
820
+ out += ch;
821
+ continue;
822
+ }
823
+ // Track only printable ASCII for line, with size limit
824
+ if (ch >= " " && ch <= "~" && line.length < 50) line += ch;
802
825
  out += ch;
803
- continue;
804
826
  }
805
- // Track only printable ASCII for line, with size limit
806
- if (ch >= " " && ch <= "~" && line.length < 50) line += ch;
807
- out += ch;
808
- }
809
- return out;
810
- };
811
- })())
827
+ return out;
828
+ };
829
+ })(),
830
+ )
812
831
 
813
832
  // TODO(sno): Read from IPC stream if available (FIFO on Linux, Named Pipes on Windows)
814
833
  // .by(async (s) => {
@@ -248,13 +248,29 @@ describe("CLI argument parsing", () => {
248
248
  });
249
249
 
250
250
  it("should prioritize --timeout over --exit-on-idle", () => {
251
- const result = parseCliArgs(["node", "/path/to/cli", "--timeout", "30s", "--exit-on-idle", "1m", "claude"]);
251
+ const result = parseCliArgs([
252
+ "node",
253
+ "/path/to/cli",
254
+ "--timeout",
255
+ "30s",
256
+ "--exit-on-idle",
257
+ "1m",
258
+ "claude",
259
+ ]);
252
260
 
253
261
  expect(result.exitOnIdle).toBe(30000);
254
262
  });
255
263
 
256
264
  it("should prioritize --timeout over --idle", () => {
257
- const result = parseCliArgs(["node", "/path/to/cli", "--timeout", "15s", "--idle", "1m", "claude"]);
265
+ const result = parseCliArgs([
266
+ "node",
267
+ "/path/to/cli",
268
+ "--timeout",
269
+ "15s",
270
+ "--idle",
271
+ "1m",
272
+ "claude",
273
+ ]);
258
274
 
259
275
  expect(result.exitOnIdle).toBe(15000);
260
276
  });
@@ -265,7 +281,7 @@ describe("CLI argument parsing", () => {
265
281
  parseCliArgs(["node", "/path/to/cli", "--exit-on-idle", "1m", "claude"]);
266
282
 
267
283
  expect(warnSpy).toHaveBeenCalledWith(
268
- expect.stringContaining("--exit-on-idle and -e are deprecated")
284
+ expect.stringContaining("--exit-on-idle and -e are deprecated"),
269
285
  );
270
286
 
271
287
  warnSpy.mockRestore();
@@ -277,7 +293,7 @@ describe("CLI argument parsing", () => {
277
293
  parseCliArgs(["node", "/path/to/cli", "-e", "1m", "claude"]);
278
294
 
279
295
  expect(warnSpy).toHaveBeenCalledWith(
280
- expect.stringContaining("--exit-on-idle and -e are deprecated")
296
+ expect.stringContaining("--exit-on-idle and -e are deprecated"),
281
297
  );
282
298
 
283
299
  warnSpy.mockRestore();
@@ -79,7 +79,8 @@ export function parseCliArgs(argv: string[]) {
79
79
  })
80
80
  .option("idle-action", {
81
81
  type: "string",
82
- description: 'Idle action to perform when idle time is reached, e.g., "/exit" or "check TODO.md"',
82
+ description:
83
+ 'Idle action to perform when idle time is reached, e.g., "/exit" or "check TODO.md"',
83
84
  })
84
85
  .option("queue", {
85
86
  type: "boolean",
@@ -111,7 +112,8 @@ export function parseCliArgs(argv: string[]) {
111
112
  })
112
113
  .option("auto", {
113
114
  type: "string",
114
- description: "Control auto-yes mode: 'yes' to auto-approve prompts (default), 'no' to start in manual mode. Press Ctrl+Y during the session to toggle at any time.",
115
+ description:
116
+ "Control auto-yes mode: 'yes' to auto-approve prompts (default), 'no' to start in manual mode. Press Ctrl+Y during the session to toggle at any time.",
115
117
  choices: ["yes", "no"] as const,
116
118
  default: "yes",
117
119
  })
package/ts/rustBinary.ts CHANGED
@@ -27,7 +27,7 @@ export function getBinaryName(): string {
27
27
  if (!binaryName) {
28
28
  throw new Error(
29
29
  `Unsupported platform: ${platform}-${arch}. ` +
30
- `Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`
30
+ `Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`,
31
31
  );
32
32
  }
33
33
 
@@ -49,7 +49,7 @@ export function getBinDir(): string {
49
49
  process.env.AGENT_YES_CACHE_DIR ||
50
50
  path.join(
51
51
  process.env.XDG_CACHE_HOME || path.join(process.env.HOME || "/tmp", ".cache"),
52
- "agent-yes"
52
+ "agent-yes",
53
53
  );
54
54
 
55
55
  return path.join(cacheDir, "bin");
@@ -136,8 +136,12 @@ export async function downloadBinary(verbose = false): Promise<string> {
136
136
 
137
137
  // Use PowerShell to extract zip
138
138
  const proc = Bun.spawn(
139
- ["powershell", "-Command", `Expand-Archive -Path '${tempZipPath}' -DestinationPath '${binDir}' -Force`],
140
- { cwd: binDir, stdio: ["ignore", "pipe", "pipe"] }
139
+ [
140
+ "powershell",
141
+ "-Command",
142
+ `Expand-Archive -Path '${tempZipPath}' -DestinationPath '${binDir}' -Force`,
143
+ ],
144
+ { cwd: binDir, stdio: ["ignore", "pipe", "pipe"] },
141
145
  );
142
146
  await proc.exited;
143
147
 
@@ -191,10 +195,12 @@ export async function downloadBinary(verbose = false): Promise<string> {
191
195
  /**
192
196
  * Get or download the Rust binary
193
197
  */
194
- export async function getRustBinary(options: {
195
- verbose?: boolean;
196
- forceDownload?: boolean;
197
- } = {}): Promise<string> {
198
+ export async function getRustBinary(
199
+ options: {
200
+ verbose?: boolean;
201
+ forceDownload?: boolean;
202
+ } = {},
203
+ ): Promise<string> {
198
204
  const { verbose = false, forceDownload = false } = options;
199
205
 
200
206
  // First try to find existing binary
@@ -218,7 +224,7 @@ export async function getRustBinary(options: {
218
224
  } catch (err) {
219
225
  throw new Error(
220
226
  `Failed to get Rust binary: ${err instanceof Error ? err.message : err}\n` +
221
- `You can build manually with: cd rs && cargo build --release`
227
+ `You can build manually with: cd rs && cargo build --release`,
222
228
  );
223
229
  }
224
230
  }
@@ -2,7 +2,6 @@ import { describe, expect, it } from "vitest";
2
2
  import { tryCatch } from "./tryCatch";
3
3
 
4
4
  describe("tryCatch", () => {
5
-
6
5
  describe("direct overload", () => {
7
6
  it("should catch errors and call catchFn with error, attempts, robustFn, and args", () => {
8
7
  let catchedError: unknown;
@@ -213,11 +212,11 @@ describe("tryCatch", () => {
213
212
  };
214
213
 
215
214
  const wrappedFn = tryCatch(catchFn, sometimesFails);
216
- expect(wrappedFn()).toBe(1); // attempt 1, success
217
- expect(wrappedFn()).toBe(-1); // attempt 2, fail
215
+ expect(wrappedFn()).toBe(1); // attempt 1, success
216
+ expect(wrappedFn()).toBe(-1); // attempt 2, fail
218
217
  expect(lastAttempts).toBe(2);
219
- expect(wrappedFn()).toBe(3); // attempt 3, success
220
- expect(wrappedFn()).toBe(-1); // attempt 4, fail
218
+ expect(wrappedFn()).toBe(3); // attempt 3, success
219
+ expect(wrappedFn()).toBe(-1); // attempt 4, fail
221
220
  expect(lastAttempts).toBe(4);
222
221
  });
223
222
 
@@ -242,7 +241,8 @@ describe("tryCatch", () => {
242
241
 
243
242
  describe("type safety", () => {
244
243
  it("should maintain function signature", () => {
245
- const catchFn = (_error: unknown, _attempts: number, _fn: unknown, ..._args: unknown[]) => "error";
244
+ const catchFn = (_error: unknown, _attempts: number, _fn: unknown, ..._args: unknown[]) =>
245
+ "error";
246
246
  const originalFn = (a: number, b: string): string => `${a}-${b}`;
247
247
 
248
248
  const wrappedFn = tryCatch(catchFn, originalFn);
@@ -13,9 +13,9 @@ export async function fetchLatestVersion(): Promise<string | null> {
13
13
  return null;
14
14
  }
15
15
 
16
- const data = await response.json() as { version: string };
16
+ const data = (await response.json()) as { version: string };
17
17
  return data.version;
18
- } catch (error) {
18
+ } catch {
19
19
  // Silently fail if network is unavailable or request times out
20
20
  return null;
21
21
  }
@@ -26,8 +26,8 @@ export async function fetchLatestVersion(): Promise<string | null> {
26
26
  * Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal
27
27
  */
28
28
  export function compareVersions(v1: string, v2: string): number {
29
- const parts1 = v1.split('.').map(Number);
30
- const parts2 = v2.split('.').map(Number);
29
+ const parts1 = v1.split(".").map(Number);
30
+ const parts2 = v2.split(".").map(Number);
31
31
 
32
32
  for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
33
33
  const part1 = parts1[i] || 0;