agent-yes 1.72.4 → 1.73.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.
@@ -8,9 +8,9 @@ import { appendFile, mkdir, readFile, readdir, rename, unlink, writeFile } from
8
8
  import path, { dirname, join } from "path";
9
9
  import DIE from "phpdie";
10
10
  import sflow from "sflow";
11
- import { TerminalRenderStream } from "terminal-render";
12
- import { homedir } from "os";
11
+ import xterm from "@xterm/headless";
13
12
  import winston from "winston";
13
+ import { homedir } from "os";
14
14
  import { closeSync, constants, createReadStream, existsSync, fsyncSync, mkdirSync, openSync } from "fs";
15
15
  import { createServer } from "net";
16
16
  import { lock } from "proper-lockfile";
@@ -37,6 +37,109 @@ var __exportAll = (all, no_symbols) => {
37
37
  return target;
38
38
  };
39
39
 
40
+ //#endregion
41
+ //#region ts/xterm-proxy.ts
42
+ const { Terminal } = xterm;
43
+ /**
44
+ * XtermProxy wraps @xterm/headless to act as a full xterm terminal emulator
45
+ * between a PTY process and downstream consumers.
46
+ *
47
+ * It automatically responds to ALL terminal queries (DSR, DA, OSC, etc.)
48
+ * by piping xterm's onData responses back to the PTY — so the spawned
49
+ * process never blocks waiting for a terminal reply, even in non-TTY
50
+ * environments or when the real terminal is backgrounded.
51
+ */
52
+ var XtermProxy = class {
53
+ term;
54
+ writeToPty;
55
+ readableController = null;
56
+ /** Downstream readable — passthrough of PTY output for sflow pipeline */
57
+ readable;
58
+ constructor(opts) {
59
+ const cols = opts.cols ?? 80;
60
+ const rows = opts.rows ?? 24;
61
+ this.writeToPty = opts.writeToPty;
62
+ this.term = new Terminal({
63
+ cols,
64
+ rows,
65
+ allowProposedApi: true,
66
+ scrollback: 1e4
67
+ });
68
+ this.term.onData((data) => {
69
+ logger.debug("xterm-proxy|onData response", data);
70
+ this.writeToPty(data);
71
+ });
72
+ this.readable = new ReadableStream({ start: (controller) => {
73
+ this.readableController = controller;
74
+ } });
75
+ }
76
+ /**
77
+ * Feed PTY output into the xterm emulator.
78
+ * - xterm processes escape sequences and updates internal state
79
+ * - Terminal queries (ESC[6n, ESC[c, etc.) trigger onData → writeToPty
80
+ * - Raw data is pushed to readable for downstream consumption
81
+ */
82
+ write(data) {
83
+ this.term.write(data, () => {
84
+ try {
85
+ this.readableController?.enqueue(data);
86
+ } catch {}
87
+ });
88
+ }
89
+ /** Get cursor position from xterm's buffer state */
90
+ getCursorPosition() {
91
+ const buf = this.term.buffer.active;
92
+ return {
93
+ row: buf.cursorY,
94
+ col: buf.cursorX
95
+ };
96
+ }
97
+ /**
98
+ * Get the last N lines of rendered terminal content (plain text, no ANSI).
99
+ * Equivalent to terminal-render's tail(n).
100
+ */
101
+ tail(n) {
102
+ const buf = this.term.buffer.active;
103
+ const totalLines = buf.length;
104
+ const startLine = Math.max(0, totalLines - n);
105
+ const lines = [];
106
+ for (let i = startLine; i < totalLines; i++) {
107
+ const line = buf.getLine(i);
108
+ lines.push(line ? line.translateToString(true) : "");
109
+ }
110
+ while (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
111
+ return lines.join("\n");
112
+ }
113
+ /**
114
+ * Render the full terminal buffer as plain text.
115
+ * Equivalent to terminal-render's render().
116
+ */
117
+ render() {
118
+ const buf = this.term.buffer.active;
119
+ const lines = [];
120
+ for (let i = 0; i < buf.length; i++) {
121
+ const line = buf.getLine(i);
122
+ lines.push(line ? line.translateToString(true) : "");
123
+ }
124
+ while (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
125
+ return lines.join("\n");
126
+ }
127
+ /** Resize the virtual terminal */
128
+ resize(cols, rows) {
129
+ this.term.resize(cols, rows);
130
+ }
131
+ /** Clean up resources */
132
+ dispose() {
133
+ if (this.readableController) {
134
+ try {
135
+ this.readableController.close();
136
+ } catch {}
137
+ this.readableController = null;
138
+ }
139
+ this.term.dispose();
140
+ }
141
+ };
142
+
40
143
  //#endregion
41
144
  //#region ts/resume/codexSessionManager.ts
42
145
  const getSessionsFile = () => process.env.CLI_YES_TEST_HOME ? path.join(process.env.CLI_YES_TEST_HOME, ".config", "agent-yes", "codex-sessions.json") : path.join(homedir(), ".config", "agent-yes", "codex-sessions.json");
@@ -1299,9 +1402,11 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1299
1402
  if (verbose) logger.debug(`[stdin] isTTY: ${process.stdin.isTTY}, setRawMode available: ${!!process.stdin.setRawMode}`);
1300
1403
  process.stdin.setRawMode?.(true);
1301
1404
  if (verbose) logger.debug(`[stdin] Raw mode set, isRaw: ${process.stdin.isRaw}`);
1302
- const terminalStream = new TerminalRenderStream({ mode: "raw" });
1303
- const terminalRender = terminalStream.getRenderer();
1304
- const outputWriter = terminalStream.writable.getWriter();
1405
+ let shellWrite = () => {};
1406
+ const xtermProxy = new XtermProxy({
1407
+ ...getTerminalDimensions(),
1408
+ writeToPty: (data) => shellWrite(data)
1409
+ });
1305
1410
  logger.debug(`Using ${ptyPackage} for pseudo terminal management.`);
1306
1411
  if (!!process.env.CLAUDE_PPID) logger.info(`[${cli}-yes] Running as sub-agent (CLAUDE_PPID=${process.env.CLAUDE_PPID})`);
1307
1412
  const cliConf = CLIS_CONFIG[cli] || {};
@@ -1393,9 +1498,10 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1393
1498
  install,
1394
1499
  ptyOptions
1395
1500
  });
1501
+ shellWrite = (data) => shell.write(data);
1396
1502
  function onData(data) {
1397
1503
  const currentPid = shell.pid;
1398
- outputWriter.write(data);
1504
+ xtermProxy.write(data);
1399
1505
  globalAgentRegistry.appendStdout(currentPid, data);
1400
1506
  }
1401
1507
  shell.onData(onData);
@@ -1479,6 +1585,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1479
1585
  env: ptyEnv
1480
1586
  };
1481
1587
  shell = pty.spawn(bin, args, restartPtyOptions);
1588
+ shellWrite = (data) => shell.write(data);
1482
1589
  try {
1483
1590
  await pidStore.registerProcess({
1484
1591
  pid: shell.pid,
@@ -1561,6 +1668,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1561
1668
  env: ptyEnv
1562
1669
  };
1563
1670
  shell = pty.spawn(cli, restoreArgs, restorePtyOptions);
1671
+ shellWrite = (data) => shell.write(data);
1564
1672
  try {
1565
1673
  await pidStore.registerProcess({
1566
1674
  pid: shell.pid,
@@ -1609,15 +1717,16 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1609
1717
  process.stdout.on("resize", () => {
1610
1718
  const { cols, rows } = getTerminalDimensions();
1611
1719
  shell.resize(cols, rows);
1720
+ xtermProxy.resize(cols, rows);
1612
1721
  });
1613
1722
  const isStillWorkingQ = () => {
1614
- const rendered = terminalRender.tail(24).replace(/\s+/g, " ");
1723
+ const rendered = xtermProxy.tail(24).replace(/\s+/g, " ");
1615
1724
  return conf.working?.some((rgx) => rgx.test(rendered));
1616
1725
  };
1617
1726
  let lastHeartbeatRendered = "";
1618
1727
  const heartbeatInterval = setInterval(async () => {
1619
1728
  try {
1620
- const rendered = removeControlCharacters(terminalRender.tail(12));
1729
+ const rendered = removeControlCharacters(xtermProxy.tail(12));
1621
1730
  if (rendered === lastHeartbeatRendered) return;
1622
1731
  lastHeartbeatRendered = rendered;
1623
1732
  const lines = rendered.split("\n").filter((line) => line.trim());
@@ -1792,7 +1901,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1792
1901
  await ctx.stdinReady.wait();
1793
1902
  shell.write(data);
1794
1903
  } }),
1795
- readable: terminalStream.readable
1904
+ readable: xtermProxy.readable
1796
1905
  }).forEach(() => {
1797
1906
  ctx.idleWaiter.ping();
1798
1907
  pidStore.updateStatus(shell.pid, "active").catch(() => null);
@@ -1808,19 +1917,10 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1808
1917
  }).catch(() => f.run());
1809
1918
  }).by(function consoleResponder(e) {
1810
1919
  let lastRendered = "";
1811
- return e.forEach((chunk) => {
1812
- if (chunk.includes("\x1B[c") || chunk.includes("\x1B[0c")) {
1813
- shell.write("\x1B[?1;2c");
1814
- if (verbose) logger.debug("device|respond DA: VT100 with Advanced Video Option");
1815
- return;
1816
- }
1817
- if (process.stdin.isTTY) return;
1818
- if (!chunk.includes("\x1B[6n")) return;
1819
- const { col, row } = terminalRender.getCursorPosition();
1820
- shell.write(`\u001b[${row};${col}R`);
1821
- logger.debug(`cursor|respond position: row=${String(row)}, col=${String(col)}`);
1822
- }).forEach(async (line, lineIndex) => {
1823
- if (terminalRender.tail(24) === lastRendered) return;
1920
+ return e.forEach(async (line, lineIndex) => {
1921
+ const rendered = xtermProxy.tail(24);
1922
+ if (rendered === lastRendered) return;
1923
+ lastRendered = rendered;
1824
1924
  logger.debug(`stdout|${line}`);
1825
1925
  if (conf.ready?.some((rx) => line.match(rx))) {
1826
1926
  logger.debug(`ready |${line}`);
@@ -1854,15 +1954,16 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
1854
1954
  }
1855
1955
  });
1856
1956
  }).by((s) => removeControlCharactersFromStdout ? s.map((e) => removeControlCharacters(e)) : s).by(createTerminatorStream(pendingExitCode.promise)).to(fromWritable(process.stdout));
1857
- await saveLogFile(ctx.logPaths.logPath, terminalRender.render());
1957
+ await saveLogFile(ctx.logPaths.logPath, xtermProxy.render());
1858
1958
  const exitCode = await pendingExitCode.promise;
1859
1959
  logger.info(`[${cli}-yes] ${cli} exited with code ${exitCode}`);
1860
1960
  await pidStore.close();
1861
- await outputWriter.close();
1862
- await saveDeprecatedLogFile(logFile, terminalRender.render(), verbose);
1961
+ const finalRender = xtermProxy.render();
1962
+ xtermProxy.dispose();
1963
+ await saveDeprecatedLogFile(logFile, finalRender, verbose);
1863
1964
  return {
1864
1965
  exitCode,
1865
- logs: terminalRender.render()
1966
+ logs: finalRender
1866
1967
  };
1867
1968
  async function exitAgent() {
1868
1969
  ctx.robust = false;
@@ -1895,4 +1996,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
1895
1996
 
1896
1997
  //#endregion
1897
1998
  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 };
1898
- //# sourceMappingURL=SUPPORTED_CLIS-Bqw9gxey.js.map
1999
+ //# sourceMappingURL=SUPPORTED_CLIS-DgHs-Q6i.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-Bqw9gxey.js";
2
+ import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-DgHs-Q6i.js";
3
3
  import { t as logger } from "./logger-CX77vJDA.js";
4
4
  import { argv } from "process";
5
5
  import { execFileSync, spawn } from "child_process";
@@ -10,7 +10,7 @@ import { execaCommand } from "execa";
10
10
  import { chmod, copyFile, mkdir, readFile, writeFile } from "fs/promises";
11
11
  import path from "path";
12
12
  import { homedir } from "os";
13
- import { existsSync, mkdirSync, unlinkSync } from "fs";
13
+ import { existsSync, lstatSync, mkdirSync, readlinkSync, unlinkSync } from "fs";
14
14
 
15
15
  //#region ts/parseCliArgs.ts
16
16
  /**
@@ -156,26 +156,53 @@ function parseCliArgs(argv) {
156
156
  if (key === "continue") yargsConsumed.add("-c");
157
157
  }
158
158
  });
159
+ const positionalPromptWords = [];
159
160
  const cliArgsForSpawn = (() => {
160
- if (parsedArgv._[0] && !cliName) return rawArgs.slice((cliArgIndex ?? 0) + 1, dashIndex ?? void 0);
161
- else if (cliName) {
161
+ if (parsedArgv._[0] && !cliName) {
162
+ const allAfterCli = rawArgs.slice((cliArgIndex ?? 0) + 1, dashIndex ?? void 0);
163
+ const result = [];
164
+ for (let i = 0; i < allAfterCli.length; i++) {
165
+ const arg = allAfterCli[i];
166
+ if (arg.startsWith("-")) {
167
+ result.push(arg);
168
+ if (!arg.includes("=") && i + 1 < allAfterCli.length) {
169
+ const nextArg = allAfterCli[i + 1];
170
+ if (nextArg && !nextArg.startsWith("-")) {
171
+ result.push(nextArg);
172
+ i++;
173
+ }
174
+ }
175
+ } else positionalPromptWords.push(arg);
176
+ }
177
+ return result;
178
+ } else if (cliName) {
162
179
  const result = [];
163
180
  const argsToCheck = rawArgs.slice(0, dashIndex ?? void 0);
164
181
  for (let i = 0; i < argsToCheck.length; i++) {
165
182
  const arg = argsToCheck[i];
166
183
  if (!arg) continue;
167
184
  const [flag] = arg.split("=");
168
- if (flag && yargsConsumed.has(flag)) {
185
+ if (flag && yargsConsumed.has(flag) || flag?.startsWith("--no-") && yargsConsumed.has(`--${flag.slice(5)}`)) {
169
186
  if (!arg.includes("=") && i + 1 < argsToCheck.length) {
170
187
  const nextArg = argsToCheck[i + 1];
171
188
  if (nextArg && !nextArg.startsWith("-")) i++;
172
189
  }
173
- } else result.push(arg);
190
+ } else if (arg.startsWith("-")) {
191
+ result.push(arg);
192
+ if (!arg.includes("=") && i + 1 < argsToCheck.length) {
193
+ const nextArg = argsToCheck[i + 1];
194
+ if (nextArg && !nextArg.startsWith("-")) {
195
+ result.push(nextArg);
196
+ i++;
197
+ }
198
+ }
199
+ } else positionalPromptWords.push(arg);
174
200
  }
175
201
  return result;
176
202
  }
177
203
  return [];
178
204
  })();
205
+ const positionalPrompt = positionalPromptWords.join(" ") || void 0;
179
206
  const dashPrompt = dashIndex === void 0 ? void 0 : rawArgs.slice(dashIndex + 1).join(" ");
180
207
  if (parsedArgv.exitOnIdle !== void 0) console.warn("\x1B[33m⚠ Warning: --exit-on-idle and -e are deprecated. Please use --timeout instead.\x1B[0m");
181
208
  return {
@@ -183,7 +210,11 @@ function parseCliArgs(argv) {
183
210
  env: process.env,
184
211
  cli: cliName || parsedArgv.cli || (dashIndex !== 0 ? parsedArgv._[0]?.toString()?.replace?.(/-yes$/, "") : void 0),
185
212
  cliArgs: [...cliArgsForSpawn, ...parsedArgv.yes ? ["--dangerously-skip-permissions"] : []],
186
- prompt: [parsedArgv.prompt, dashPrompt].filter(Boolean).join(" ") || void 0,
213
+ prompt: [
214
+ parsedArgv.prompt,
215
+ positionalPrompt,
216
+ dashPrompt
217
+ ].filter(Boolean).join(" ") || void 0,
187
218
  install: parsedArgv.install,
188
219
  exitOnIdle: Number((parsedArgv.timeout || parsedArgv.idle || parsedArgv.exitOnIdle)?.replace(/.*/, (e) => String(ms(e))) || 0),
189
220
  queue: parsedArgv.queue,
@@ -242,7 +273,12 @@ function detectPackageManager() {
242
273
  */
243
274
  async function checkAndAutoUpdate() {
244
275
  if (process.env.AGENT_YES_NO_UPDATE) return;
245
- if (process.env.AGENT_YES_UPDATED === version) return;
276
+ if (process.env.AGENT_YES_UPDATED) return;
277
+ if (import.meta.url.startsWith("file://") && !import.meta.url.includes("node_modules")) {
278
+ const scriptDir = path.dirname(new URL(import.meta.url).pathname);
279
+ const repoRoot = path.resolve(scriptDir, "..");
280
+ if (existsSync(path.join(repoRoot, ".git"))) return;
281
+ }
246
282
  try {
247
283
  let latestVersion;
248
284
  const cache = await readUpdateCache();
@@ -321,10 +357,47 @@ function compareVersions(v1, v2) {
321
357
  return 0;
322
358
  }
323
359
  /**
360
+ * Detect how agent-yes was installed.
361
+ * Returns a short label: "git", "bun link", "bun", "npm", "npx", or "unknown"
362
+ */
363
+ function detectInstallMethod() {
364
+ try {
365
+ const scriptDir = path.dirname(new URL(import.meta.url).pathname);
366
+ if (!scriptDir.includes("node_modules")) {
367
+ const repoRoot = path.resolve(scriptDir, "..");
368
+ if (existsSync(path.join(repoRoot, ".git"))) return "git";
369
+ return "source";
370
+ }
371
+ const nodeModulesEntry = scriptDir.replace(/\/dist$/, "");
372
+ try {
373
+ if (lstatSync(nodeModulesEntry).isSymbolicLink()) {
374
+ const target = readlinkSync(nodeModulesEntry);
375
+ const resolvedTarget = path.resolve(path.dirname(nodeModulesEntry), target);
376
+ if (existsSync(path.join(resolvedTarget, ".git"))) return "bun link (git)";
377
+ return "bun link";
378
+ }
379
+ } catch {}
380
+ if (scriptDir.includes(".bun/")) return "bun";
381
+ if (scriptDir.includes(".npm/")) return "npx";
382
+ if (process.env.npm_execpath?.includes("bun")) return "bun";
383
+ if (process.env.npm_config_user_agent?.startsWith("bun")) return "bun";
384
+ if (process.env.npm_config_user_agent?.startsWith("npm")) return "npm";
385
+ return "npm";
386
+ } catch {
387
+ return "unknown";
388
+ }
389
+ }
390
+ /**
391
+ * Format version string with install method
392
+ */
393
+ function versionString() {
394
+ return `agent-yes v${version} (${detectInstallMethod()})`;
395
+ }
396
+ /**
324
397
  * Display version information with async latest version check
325
398
  */
326
399
  async function displayVersion() {
327
- console.log(version);
400
+ console.log(versionString());
328
401
  const latestVersion = await fetchLatestVersion();
329
402
  if (latestVersion) {
330
403
  const comparison = compareVersions(version, latestVersion);
@@ -466,6 +539,53 @@ async function downloadBinary(verbose = false) {
466
539
  return binaryPath;
467
540
  }
468
541
  /**
542
+ * Get the version of a Rust binary by running it with --version
543
+ */
544
+ function getRustBinaryVersion(binaryPath) {
545
+ try {
546
+ const match = execFileSync(binaryPath, ["--version"], {
547
+ timeout: 5e3,
548
+ encoding: "utf8",
549
+ stdio: [
550
+ "ignore",
551
+ "pipe",
552
+ "ignore"
553
+ ]
554
+ }).match(/(\d+\.\d+\.\d+)/);
555
+ return match ? match[1] : null;
556
+ } catch {
557
+ return null;
558
+ }
559
+ }
560
+ /**
561
+ * Check if a binary path is inside a git repo (dev build), and rebuild if outdated.
562
+ * Returns the same path if up-to-date or rebuilt, undefined if rebuild failed.
563
+ */
564
+ function autoRebuildIfOutdated(binaryPath, verbose) {
565
+ if (!binaryPath.includes("/target/release") && !binaryPath.includes("/target/debug")) return true;
566
+ const binaryVersion = getRustBinaryVersion(binaryPath);
567
+ if (verbose) console.log(`[rust] Binary version: ${binaryVersion}, package version: ${version}`);
568
+ if (binaryVersion === version) return true;
569
+ const rsDir = binaryPath.replace(/\/target\/(release|debug)\/agent-yes.*$/, "");
570
+ if (!existsSync(path.join(rsDir, "Cargo.toml"))) {
571
+ if (verbose) console.log(`[rust] Cannot find Cargo.toml at ${rsDir}, skipping rebuild`);
572
+ return true;
573
+ }
574
+ process.stderr.write(`\x1b[33m[rust] Binary outdated (${binaryVersion ?? "unknown"} → ${version}), rebuilding…\x1b[0m\n`);
575
+ try {
576
+ execFileSync("cargo", ["build", ...binaryPath.includes("/target/release") ? ["--release"] : []], {
577
+ cwd: rsDir,
578
+ stdio: "inherit",
579
+ timeout: 3e5
580
+ });
581
+ process.stderr.write(`\x1b[32m[rust] Rebuild complete\x1b[0m\n`);
582
+ return true;
583
+ } catch {
584
+ process.stderr.write(`\x1b[31m[rust] Auto-rebuild failed, using outdated binary\x1b[0m\n`);
585
+ return true;
586
+ }
587
+ }
588
+ /**
469
589
  * Get or download the Rust binary
470
590
  */
471
591
  async function getRustBinary(options = {}) {
@@ -474,6 +594,7 @@ async function getRustBinary(options = {}) {
474
594
  const existing = findRustBinary(verbose);
475
595
  if (existing) {
476
596
  if (verbose) console.log(`[rust] Using existing binary: ${existing}`);
597
+ autoRebuildIfOutdated(existing, verbose);
477
598
  return existing;
478
599
  }
479
600
  }
@@ -507,6 +628,7 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
507
628
  //#endregion
508
629
  //#region ts/cli.ts
509
630
  await checkAndAutoUpdate();
631
+ logger.info(versionString());
510
632
  const config = parseCliArgs(process.argv);
511
633
  if (config.tray) {
512
634
  const { startTray } = await import("./tray-CPpdxTV-.js");
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-Bqw9gxey.js";
1
+ import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-DgHs-Q6i.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.72.4",
3
+ "version": "1.73.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",
@@ -81,10 +81,12 @@
81
81
  "release": "standard-version && npm publish",
82
82
  "release:beta": "standard-version && npm publish --tag beta",
83
83
  "test": "vitest run",
84
- "test:coverage": "vitest run --coverage"
84
+ "test:coverage": "vitest run --coverage",
85
+ "test:ui": "vitest run --config tests/ui-test/vitest.config.ts"
85
86
  },
86
87
  "dependencies": {
87
88
  "@snomiao/bun-pty": "^0.3.4",
89
+ "@xterm/headless": "^6.0.0",
88
90
  "bun-pty": "^0.4.8",
89
91
  "execa": "^9.6.1",
90
92
  "from-node-stream": "^0.2.0",
@@ -92,12 +94,12 @@
92
94
  "phpdie": "^1.7.0",
93
95
  "proper-lockfile": "^4.1.2",
94
96
  "sflow": "^1.27.0",
95
- "terminal-render": "^1.5.1",
96
97
  "winston": "^3.19.0",
97
98
  "yaml": "^2.8.2",
98
99
  "yargs": "^18.0.0"
99
100
  },
100
101
  "devDependencies": {
102
+ "@google/generative-ai": "^0.24.1",
101
103
  "@semantic-release/exec": "^7.1.0",
102
104
  "@semantic-release/git": "^10.0.1",
103
105
  "@types/bun": "^1.3.6",
@@ -105,6 +107,7 @@
105
107
  "@types/ms": "^2.1.0",
106
108
  "@types/node": "^25.0.10",
107
109
  "@types/proper-lockfile": "^4.1.4",
110
+ "@types/ws": "^8.18.1",
108
111
  "@types/yargs": "^17.0.35",
109
112
  "@typescript/native-preview": "^7.0.0-dev.20260124.1",
110
113
  "@vitest/coverage-v8": "4.1.0",
@@ -114,11 +117,13 @@
114
117
  "oxfmt": "^0.26.0",
115
118
  "oxlint": "^1.41.0",
116
119
  "patch-package": "^8.0.1",
120
+ "playwright": "^1.58.2",
117
121
  "rambda": "^11.0.1",
118
122
  "semantic-release": "^25.0.2",
119
123
  "standard-version": "^9.5.0",
120
124
  "tsdown": "^0.20.3",
121
125
  "vitest": "4.1.0",
126
+ "ws": "^8.20.0",
122
127
  "zod": "^3.23.0"
123
128
  },
124
129
  "peerDependencies": {
package/ts/cli.ts CHANGED
@@ -5,7 +5,7 @@ import { parseCliArgs } from "./parseCliArgs.ts";
5
5
  import { SUPPORTED_CLIS } from "./SUPPORTED_CLIS.ts";
6
6
  import { logger } from "./logger.ts";
7
7
  import { PidStore } from "./pidStore.ts";
8
- import { checkAndAutoUpdate, displayVersion } from "./versionChecker.ts";
8
+ import { checkAndAutoUpdate, displayVersion, versionString } from "./versionChecker.ts";
9
9
  import { getRustBinary } from "./rustBinary.ts";
10
10
  import { buildRustArgs } from "./buildRustArgs.ts";
11
11
 
@@ -13,6 +13,8 @@ import { buildRustArgs } from "./buildRustArgs.ts";
13
13
  // Fast path: cached result (no network), so this adds near-zero latency most of the time.
14
14
  await checkAndAutoUpdate();
15
15
 
16
+ logger.info(versionString());
17
+
16
18
  // Parse CLI arguments
17
19
  const config = parseCliArgs(process.argv);
18
20