agent-yes 1.68.0 → 1.68.2

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.68.0";
1062
+ var version = "1.68.2";
1063
1063
 
1064
1064
  //#endregion
1065
1065
  //#region ts/pty-fix.ts
@@ -2139,4 +2139,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
2139
2139
 
2140
2140
  //#endregion
2141
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 };
2142
- //# sourceMappingURL=SUPPORTED_CLIS-Cl2oCgKo.js.map
2142
+ //# sourceMappingURL=SUPPORTED_CLIS-lTQa7aYE.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-Cl2oCgKo.js";
2
+ import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-lTQa7aYE.js";
3
3
  import { t as logger } from "./logger-CX77vJDA.js";
4
4
  import { argv } from "process";
5
5
  import { spawn } from "child_process";
@@ -467,7 +467,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
467
467
  const rawRustArgs = argv.slice(2).filter((arg) => arg !== "--rust" && !arg.startsWith("--rust="));
468
468
  const hasSwarmArg = rawRustArgs.some((arg) => arg === "--swarm" || arg.startsWith("--swarm="));
469
469
  const hasCliArg = rawRustArgs.some((arg) => arg.startsWith("--cli=") || arg === "--cli") || rawRustArgs.some((arg) => supportedClis.includes(arg));
470
- if (cliFromScript && !hasCliArg && !hasSwarmArg) return [...rawRustArgs, cliFromScript];
470
+ if (cliFromScript && !hasCliArg && !hasSwarmArg) return [`--cli=${cliFromScript}`, ...rawRustArgs];
471
471
  return rawRustArgs;
472
472
  }
473
473
 
@@ -480,31 +480,35 @@ if (config.useRust) {
480
480
  try {
481
481
  rustBinary = await getRustBinary({ verbose: config.verbose });
482
482
  } catch (err) {
483
- console.error(err instanceof Error ? err.message : String(err));
484
- process.exit(1);
483
+ if (config.verbose) {
484
+ console.error(`[rust] ${err instanceof Error ? err.message : String(err)}`);
485
+ console.error("[rust] Falling back to TypeScript implementation.");
486
+ }
485
487
  }
486
- const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
487
- if (config.verbose) {
488
- console.log(`[rust] Using binary: ${rustBinary}`);
489
- console.log(`[rust] Args: ${rustArgs.join(" ")}`);
488
+ if (rustBinary) {
489
+ const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
490
+ if (config.verbose) {
491
+ console.log(`[rust] Using binary: ${rustBinary}`);
492
+ console.log(`[rust] Args: ${rustArgs.join(" ")}`);
493
+ }
494
+ const child = spawn(rustBinary, rustArgs, {
495
+ stdio: "inherit",
496
+ env: process.env,
497
+ cwd: process.cwd()
498
+ });
499
+ child.on("error", (err) => {
500
+ if (err.code === "ENOENT") console.error(`Rust binary '${rustBinary}' not found. Try: npx agent-yes --rust --verbose`);
501
+ else console.error(`Failed to spawn Rust binary: ${err.message}`);
502
+ process.exit(1);
503
+ });
504
+ child.on("exit", (code, signal) => {
505
+ if (signal) process.exit(128 + (signal === "SIGINT" ? 2 : signal === "SIGTERM" ? 15 : 1));
506
+ process.exit(code ?? 1);
507
+ });
508
+ process.on("SIGINT", () => child.kill("SIGINT"));
509
+ process.on("SIGTERM", () => child.kill("SIGTERM"));
510
+ await new Promise(() => {});
490
511
  }
491
- const child = spawn(rustBinary, rustArgs, {
492
- stdio: "inherit",
493
- env: process.env,
494
- cwd: process.cwd()
495
- });
496
- child.on("error", (err) => {
497
- if (err.code === "ENOENT") console.error(`Rust binary '${rustBinary}' not found. Try: npx agent-yes --rust --verbose`);
498
- else console.error(`Failed to spawn Rust binary: ${err.message}`);
499
- process.exit(1);
500
- });
501
- child.on("exit", (code, signal) => {
502
- if (signal) process.exit(128 + (signal === "SIGINT" ? 2 : signal === "SIGTERM" ? 15 : 1));
503
- process.exit(code ?? 1);
504
- });
505
- process.on("SIGINT", () => child.kill("SIGINT"));
506
- process.on("SIGTERM", () => child.kill("SIGTERM"));
507
- await new Promise(() => {});
508
512
  }
509
513
  if (config.showVersion) {
510
514
  await displayVersion();
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-Cl2oCgKo.js";
1
+ import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-lTQa7aYE.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.68.0",
3
+ "version": "1.68.2",
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",
@@ -21,70 +21,60 @@ function argv(...userArgs: string[]): string[] {
21
21
  }
22
22
 
23
23
  describe("buildRustArgs", () => {
24
- // ─── Core: CLI name positioning ────────────────────────────────────
25
- // The CLI name MUST appear after all flags to avoid clap's trailing_var_arg
26
- // swallowing named flags as positional args.
24
+ // ─── Core: CLI name passed via --cli= flag ─────────────────────────
25
+ // The CLI name is passed via --cli= flag at the start, so it doesn't
26
+ // get mixed with trailing positional args (which are prompt text).
27
27
 
28
- describe("CLI name is always appended at the end (not prepended)", () => {
29
- it("appends CLI name after flags", () => {
28
+ describe("CLI name is passed via --cli= flag", () => {
29
+ it("prepends --cli= flag before other args", () => {
30
30
  const result = buildRustArgs(argv("--timeout", "1h"), "claude", SUPPORTED_CLIS);
31
- expect(result).toEqual(["--timeout", "1h", "claude"]);
31
+ expect(result).toEqual(["--cli=claude", "--timeout", "1h"]);
32
32
  });
33
33
 
34
- it("appends CLI name after multiple flags", () => {
34
+ it("prepends --cli= flag before multiple flags", () => {
35
35
  const result = buildRustArgs(
36
36
  argv("--timeout", "30s", "--verbose", "--robust", "true"),
37
37
  "claude",
38
38
  SUPPORTED_CLIS,
39
39
  );
40
- expect(result).toEqual(["--timeout", "30s", "--verbose", "--robust", "true", "claude"]);
40
+ expect(result).toEqual(["--cli=claude", "--timeout", "30s", "--verbose", "--robust", "true"]);
41
41
  });
42
42
 
43
- it("CLI name is the last element", () => {
43
+ it("--cli= is the first element", () => {
44
44
  const result = buildRustArgs(argv("--timeout", "5m"), "codex", SUPPORTED_CLIS);
45
- expect(result[result.length - 1]).toBe("codex");
45
+ expect(result[0]).toBe("--cli=codex");
46
46
  });
47
47
  });
48
48
 
49
- // ─── The original bug: --timeout swallowed by trailing_var_arg ─────
49
+ // ─── Regression: flags must not be swallowed ───────────────────────
50
50
 
51
- describe("regression: flags must not be swallowed by CLI name position", () => {
52
- it("--timeout is preserved before CLI name (the original bug)", () => {
51
+ describe("regression: flags are preserved alongside --cli=", () => {
52
+ it("--timeout is preserved", () => {
53
53
  const result = buildRustArgs(argv("--timeout", "1h"), "claude", SUPPORTED_CLIS);
54
- const timeoutIdx = result.indexOf("--timeout");
55
- const cliIdx = result.indexOf("claude");
56
- expect(timeoutIdx).toBeGreaterThanOrEqual(0);
57
- expect(cliIdx).toBeGreaterThan(timeoutIdx);
54
+ expect(result).toContain("--timeout");
55
+ expect(result).toContain("1h");
58
56
  });
59
57
 
60
- it("--verbose is preserved before CLI name", () => {
58
+ it("--verbose is preserved", () => {
61
59
  const result = buildRustArgs(argv("--verbose"), "claude", SUPPORTED_CLIS);
62
- const verboseIdx = result.indexOf("--verbose");
63
- const cliIdx = result.indexOf("claude");
64
- expect(verboseIdx).toBeGreaterThanOrEqual(0);
65
- expect(cliIdx).toBeGreaterThan(verboseIdx);
60
+ expect(result).toContain("--verbose");
66
61
  });
67
62
 
68
- it("-c (continue) flag is preserved before CLI name", () => {
63
+ it("-c (continue) flag is preserved", () => {
69
64
  const result = buildRustArgs(argv("-c"), "claude", SUPPORTED_CLIS);
70
- expect(result.indexOf("-c")).toBeLessThan(result.indexOf("claude"));
71
- });
72
-
73
- it("--robust flag is preserved before CLI name", () => {
74
- const result = buildRustArgs(argv("--robust", "true"), "gemini", SUPPORTED_CLIS);
75
- expect(result.indexOf("--robust")).toBeLessThan(result.indexOf("gemini"));
65
+ expect(result).toContain("-c");
76
66
  });
77
67
 
78
- it("all flags come before CLI name in complex invocation", () => {
68
+ it("all flags are preserved in complex invocation", () => {
79
69
  const result = buildRustArgs(
80
70
  argv("--timeout", "1h", "--verbose", "-c", "--robust", "true"),
81
71
  "claude",
82
72
  SUPPORTED_CLIS,
83
73
  );
84
- const cliIdx = result.indexOf("claude");
85
74
  for (const flag of ["--timeout", "--verbose", "-c", "--robust"]) {
86
- expect(result.indexOf(flag)).toBeLessThan(cliIdx);
75
+ expect(result).toContain(flag);
87
76
  }
77
+ expect(result[0]).toBe("--cli=claude");
88
78
  });
89
79
  });
90
80
 
@@ -110,43 +100,43 @@ describe("buildRustArgs", () => {
110
100
  SUPPORTED_CLIS,
111
101
  );
112
102
  expect(result).not.toContain("--rust");
113
- expect(result).toEqual(["--verbose", "--timeout", "5m", "claude"]);
103
+ expect(result).toEqual(["--cli=claude", "--verbose", "--timeout", "5m"]);
114
104
  });
115
105
  });
116
106
 
117
107
  // ─── CLI name detection in args ────────────────────────────────────
118
108
 
119
109
  describe("does not duplicate CLI name if already in args", () => {
120
- it("skips appending when CLI name is already a positional arg", () => {
110
+ it("skips --cli= when CLI name is already a positional arg", () => {
121
111
  const result = buildRustArgs(argv("--timeout", "30s", "claude"), "claude", SUPPORTED_CLIS);
122
112
  expect(result).toEqual(["--timeout", "30s", "claude"]);
123
- expect(result.filter((a) => a === "claude")).toHaveLength(1);
113
+ expect(result.filter((a) => a.includes("claude"))).toHaveLength(1);
124
114
  });
125
115
 
126
- it("skips appending when --cli= flag is used", () => {
116
+ it("skips --cli= when --cli= flag is already used", () => {
127
117
  const result = buildRustArgs(
128
118
  argv("--cli=gemini", "--timeout", "30s"),
129
119
  "claude",
130
120
  SUPPORTED_CLIS,
131
121
  );
132
122
  expect(result).toEqual(["--cli=gemini", "--timeout", "30s"]);
133
- expect(result).not.toContain("claude");
123
+ expect(result).not.toContain("--cli=claude");
134
124
  });
135
125
 
136
- it("skips appending when --cli flag is used (separate value)", () => {
126
+ it("skips --cli= when --cli flag is used (separate value)", () => {
137
127
  const result = buildRustArgs(
138
128
  argv("--cli", "gemini", "--timeout", "30s"),
139
129
  "claude",
140
130
  SUPPORTED_CLIS,
141
131
  );
142
132
  expect(result).toEqual(["--cli", "gemini", "--timeout", "30s"]);
143
- expect(result).not.toContain("claude");
133
+ expect(result).not.toContain("--cli=claude");
144
134
  });
145
135
 
146
136
  it("detects any supported CLI name in args", () => {
147
137
  for (const cli of ["gemini", "codex", "copilot", "cursor", "grok"]) {
148
138
  const result = buildRustArgs(argv("--timeout", "1m", cli), "claude", SUPPORTED_CLIS);
149
- expect(result).not.toContain("claude");
139
+ expect(result).not.toContain("--cli=claude");
150
140
  expect(result).toContain(cli);
151
141
  }
152
142
  });
@@ -155,22 +145,22 @@ describe("buildRustArgs", () => {
155
145
  // ─── Swarm mode ────────────────────────────────────────────────────
156
146
 
157
147
  describe("swarm mode skips CLI name", () => {
158
- it("does not append CLI name when --swarm is present", () => {
148
+ it("does not add --cli= when --swarm is present", () => {
159
149
  const result = buildRustArgs(argv("--swarm", "my-topic"), "claude", SUPPORTED_CLIS);
160
150
  expect(result).toEqual(["--swarm", "my-topic"]);
161
- expect(result).not.toContain("claude");
151
+ expect(result).not.toContain("--cli=claude");
162
152
  });
163
153
 
164
- it("does not append CLI name when --swarm= is present", () => {
154
+ it("does not add --cli= when --swarm= is present", () => {
165
155
  const result = buildRustArgs(argv("--swarm=my-topic"), "claude", SUPPORTED_CLIS);
166
156
  expect(result).toEqual(["--swarm=my-topic"]);
167
- expect(result).not.toContain("claude");
157
+ expect(result).not.toContain("--cli=claude");
168
158
  });
169
159
 
170
- it("does not append CLI name for bare --swarm", () => {
160
+ it("does not add --cli= for bare --swarm", () => {
171
161
  const result = buildRustArgs(argv("--swarm"), "claude", SUPPORTED_CLIS);
172
162
  expect(result).toEqual(["--swarm"]);
173
- expect(result).not.toContain("claude");
163
+ expect(result).not.toContain("--cli=claude");
174
164
  });
175
165
  });
176
166
 
@@ -193,7 +183,7 @@ describe("buildRustArgs", () => {
193
183
  describe("edge cases", () => {
194
184
  it("handles no user args at all", () => {
195
185
  const result = buildRustArgs(["node", "/path/to/claude-yes"], "claude", SUPPORTED_CLIS);
196
- expect(result).toEqual(["claude"]);
186
+ expect(result).toEqual(["--cli=claude"]);
197
187
  });
198
188
 
199
189
  it("handles -- prompt separator correctly", () => {
@@ -202,38 +192,44 @@ describe("buildRustArgs", () => {
202
192
  "claude",
203
193
  SUPPORTED_CLIS,
204
194
  );
205
- expect(result).toEqual(["--timeout", "1h", "--", "do", "the", "thing", "claude"]);
206
- expect(result.indexOf("--timeout")).toBeLessThan(result.lastIndexOf("claude"));
195
+ expect(result).toEqual(["--cli=claude", "--timeout", "1h", "--", "do", "the", "thing"]);
207
196
  });
208
197
 
209
198
  it("handles -p prompt flag", () => {
210
199
  const result = buildRustArgs(argv("-p", "hello world"), "claude", SUPPORTED_CLIS);
211
- expect(result).toEqual(["-p", "hello world", "claude"]);
200
+ expect(result).toEqual(["--cli=claude", "-p", "hello world"]);
212
201
  });
213
202
 
214
203
  it("preserves args with hyphen values (e.g. negative numbers)", () => {
215
204
  const result = buildRustArgs(argv("--some-flag", "-1"), "claude", SUPPORTED_CLIS);
216
- expect(result).toEqual(["--some-flag", "-1", "claude"]);
205
+ expect(result).toEqual(["--cli=claude", "--some-flag", "-1"]);
217
206
  });
218
207
 
219
208
  it("handles multiple --rust flags (all filtered)", () => {
220
209
  const result = buildRustArgs(argv("--rust", "--rust", "--verbose"), "claude", SUPPORTED_CLIS);
221
- expect(result).toEqual(["--verbose", "claude"]);
210
+ expect(result).toEqual(["--cli=claude", "--verbose"]);
222
211
  });
223
212
 
224
213
  it("does not treat --swarm-topic as --swarm", () => {
225
214
  const result = buildRustArgs(argv("--swarm-topic", "my-topic"), "claude", SUPPORTED_CLIS);
226
- // --swarm-topic is NOT --swarm, so CLI name should still be appended
227
- expect(result).toContain("claude");
215
+ // --swarm-topic is NOT --swarm, so --cli= should still be added
216
+ expect(result[0]).toBe("--cli=claude");
228
217
  });
229
218
 
230
219
  it("does not treat --cli-like strings inside values as CLI names", () => {
231
- // e.g. --prompt "use claude to ..." should not detect "claude" as a CLI arg
232
- // because "use claude to ..." is a value, not a standalone arg
233
220
  const result = buildRustArgs(argv("-p", "use claude to fix"), undefined, SUPPORTED_CLIS);
234
- // "claude" appears inside a value, but since cliFromScript is undefined, nothing appended
221
+ // "claude" appears inside a value, but since cliFromScript is undefined, nothing added
235
222
  expect(result).toEqual(["-p", "use claude to fix"]);
236
223
  });
224
+
225
+ it("bare words (prompt without --) are passed through for Rust to handle", () => {
226
+ const result = buildRustArgs(
227
+ argv("rebuild", "and", "analyze", "problems"),
228
+ "claude",
229
+ SUPPORTED_CLIS,
230
+ );
231
+ expect(result).toEqual(["--cli=claude", "rebuild", "and", "analyze", "problems"]);
232
+ });
237
233
  });
238
234
 
239
235
  // ─── Real-world command scenarios ──────────────────────────────────
@@ -241,7 +237,7 @@ describe("buildRustArgs", () => {
241
237
  describe("real-world scenarios", () => {
242
238
  it("claude-yes --rust --timeout 1h (the original failing case)", () => {
243
239
  const result = buildRustArgs(argv("--rust", "--timeout", "1h"), "claude", SUPPORTED_CLIS);
244
- expect(result).toEqual(["--timeout", "1h", "claude"]);
240
+ expect(result).toEqual(["--cli=claude", "--timeout", "1h"]);
245
241
  });
246
242
 
247
243
  it("claude-yes --rust --timeout 30s --verbose", () => {
@@ -250,12 +246,12 @@ describe("buildRustArgs", () => {
250
246
  "claude",
251
247
  SUPPORTED_CLIS,
252
248
  );
253
- expect(result).toEqual(["--timeout", "30s", "--verbose", "claude"]);
249
+ expect(result).toEqual(["--cli=claude", "--timeout", "30s", "--verbose"]);
254
250
  });
255
251
 
256
252
  it("claude-yes --rust -c (continue session)", () => {
257
253
  const result = buildRustArgs(argv("--rust", "-c"), "claude", SUPPORTED_CLIS);
258
- expect(result).toEqual(["-c", "claude"]);
254
+ expect(result).toEqual(["--cli=claude", "-c"]);
259
255
  });
260
256
 
261
257
  it("codex-yes --rust --timeout 5m -- fix all bugs", () => {
@@ -264,7 +260,7 @@ describe("buildRustArgs", () => {
264
260
  "codex",
265
261
  SUPPORTED_CLIS,
266
262
  );
267
- expect(result).toEqual(["--timeout", "5m", "--", "fix", "all", "bugs", "codex"]);
263
+ expect(result).toEqual(["--cli=codex", "--timeout", "5m", "--", "fix", "all", "bugs"]);
268
264
  });
269
265
 
270
266
  it("agent-yes --rust claude --timeout 1h (explicit CLI in args)", () => {
@@ -283,9 +279,9 @@ describe("buildRustArgs", () => {
283
279
  "claude",
284
280
  SUPPORTED_CLIS,
285
281
  );
286
- // Swarm mode: no CLI name appended
282
+ // Swarm mode: no CLI name added
287
283
  expect(result).toEqual(["--swarm", "my-project", "--timeout", "1h"]);
288
- expect(result).not.toContain("claude");
284
+ expect(result).not.toContain("--cli=claude");
289
285
  });
290
286
 
291
287
  it("gemini-yes --rust --timeout 2m --verbose -p 'hello'", () => {
@@ -294,7 +290,7 @@ describe("buildRustArgs", () => {
294
290
  "gemini",
295
291
  SUPPORTED_CLIS,
296
292
  );
297
- expect(result).toEqual(["--timeout", "2m", "--verbose", "-p", "hello", "gemini"]);
293
+ expect(result).toEqual(["--cli=gemini", "--timeout", "2m", "--verbose", "-p", "hello"]);
298
294
  });
299
295
 
300
296
  it("claude-yes --rust --auto=no --timeout 10m", () => {
@@ -303,7 +299,17 @@ describe("buildRustArgs", () => {
303
299
  "claude",
304
300
  SUPPORTED_CLIS,
305
301
  );
306
- expect(result).toEqual(["--auto=no", "--timeout", "10m", "claude"]);
302
+ expect(result).toEqual(["--cli=claude", "--auto=no", "--timeout", "10m"]);
303
+ });
304
+
305
+ it("cy rebuild and analyze problems (bare prompt words)", () => {
306
+ const result = buildRustArgs(
307
+ argv("rebuild", "and", "analyze", "problems"),
308
+ "claude",
309
+ SUPPORTED_CLIS,
310
+ );
311
+ // CLI passed via --cli=, bare words passed through for Rust to interpret as prompt
312
+ expect(result).toEqual(["--cli=claude", "rebuild", "and", "analyze", "problems"]);
307
313
  });
308
314
  });
309
315
  });
@@ -23,10 +23,10 @@ export function buildRustArgs(
23
23
  rawRustArgs.some((arg) => arg.startsWith("--cli=") || arg === "--cli") ||
24
24
  rawRustArgs.some((arg) => supportedClis.includes(arg));
25
25
 
26
- // Append CLI name at the end so it doesn't trigger trailing_var_arg in clap,
27
- // which would cause all subsequent args (like --timeout) to be treated as positional
26
+ // Pass CLI name via --cli= flag so it doesn't get mixed with trailing positional args
27
+ // (which are treated as prompt text or cli args for the target tool)
28
28
  if (cliFromScript && !hasCliArg && !hasSwarmArg) {
29
- return [...rawRustArgs, cliFromScript];
29
+ return [`--cli=${cliFromScript}`, ...rawRustArgs];
30
30
  }
31
31
 
32
32
  return rawRustArgs;
package/ts/cli.ts CHANGED
@@ -15,55 +15,55 @@ const updateCheckPromise = checkAndAutoUpdate();
15
15
  // Parse CLI arguments
16
16
  const config = parseCliArgs(process.argv);
17
17
 
18
- // Handle --rust: spawn the Rust binary instead
18
+ // Handle --rust: spawn the Rust binary instead, fall back to TypeScript if unavailable
19
19
  if (config.useRust) {
20
- let rustBinary: string;
20
+ let rustBinary: string | undefined;
21
21
 
22
22
  try {
23
- // Get or download the Rust binary for the current platform
24
23
  rustBinary = await getRustBinary({ verbose: config.verbose });
25
24
  } catch (err) {
26
- console.error(err instanceof Error ? err.message : String(err));
27
- process.exit(1);
28
- }
29
-
30
- // Build args for Rust binary
31
- const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
32
-
33
- if (config.verbose) {
34
- console.log(`[rust] Using binary: ${rustBinary}`);
35
- console.log(`[rust] Args: ${rustArgs.join(" ")}`);
25
+ // Rust binary unavailable (not yet released for this version, or network issue) — fall back to TypeScript
26
+ if (config.verbose) {
27
+ console.error(`[rust] ${err instanceof Error ? err.message : String(err)}`);
28
+ console.error("[rust] Falling back to TypeScript implementation.");
29
+ }
36
30
  }
37
31
 
38
- // Spawn the Rust process with stdio inheritance
39
- const child = spawn(rustBinary, rustArgs, {
40
- stdio: "inherit",
41
- env: process.env,
42
- cwd: process.cwd(),
43
- });
32
+ if (rustBinary) {
33
+ const rustArgs = buildRustArgs(process.argv, config.cli, SUPPORTED_CLIS);
44
34
 
45
- child.on("error", (err) => {
46
- if ((err as NodeJS.ErrnoException).code === "ENOENT") {
47
- console.error(`Rust binary '${rustBinary}' not found. Try: npx agent-yes --rust --verbose`);
48
- } else {
49
- console.error(`Failed to spawn Rust binary: ${err.message}`);
35
+ if (config.verbose) {
36
+ console.log(`[rust] Using binary: ${rustBinary}`);
37
+ console.log(`[rust] Args: ${rustArgs.join(" ")}`);
50
38
  }
51
- process.exit(1);
52
- });
53
-
54
- child.on("exit", (code, signal) => {
55
- if (signal) {
56
- process.exit(128 + (signal === "SIGINT" ? 2 : signal === "SIGTERM" ? 15 : 1));
57
- }
58
- process.exit(code ?? 1);
59
- });
60
39
 
61
- // Forward signals to child
62
- process.on("SIGINT", () => child.kill("SIGINT"));
63
- process.on("SIGTERM", () => child.kill("SIGTERM"));
64
-
65
- // Keep the process alive while child is running
66
- await new Promise(() => {}); // Never resolves, exits via child.on("exit")
40
+ const child = spawn(rustBinary, rustArgs, {
41
+ stdio: "inherit",
42
+ env: process.env,
43
+ cwd: process.cwd(),
44
+ });
45
+
46
+ child.on("error", (err) => {
47
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") {
48
+ console.error(`Rust binary '${rustBinary}' not found. Try: npx agent-yes --rust --verbose`);
49
+ } else {
50
+ console.error(`Failed to spawn Rust binary: ${err.message}`);
51
+ }
52
+ process.exit(1);
53
+ });
54
+
55
+ child.on("exit", (code, signal) => {
56
+ if (signal) {
57
+ process.exit(128 + (signal === "SIGINT" ? 2 : signal === "SIGTERM" ? 15 : 1));
58
+ }
59
+ process.exit(code ?? 1);
60
+ });
61
+
62
+ process.on("SIGINT", () => child.kill("SIGINT"));
63
+ process.on("SIGTERM", () => child.kill("SIGTERM"));
64
+
65
+ await new Promise(() => {}); // Never resolves, exits via child.on("exit")
66
+ }
67
67
  }
68
68
 
69
69
  // Handle --version: display version and exit