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.
- package/dist/{SUPPORTED_CLIS-Bqw9gxey.js → SUPPORTED_CLIS-DgHs-Q6i.js} +128 -27
- package/dist/cli.js +131 -9
- package/dist/index.js +1 -1
- package/package.json +8 -3
- package/ts/cli.ts +3 -1
- package/ts/index.ts +86 -99
- package/ts/parseCliArgs.spec.ts +88 -0
- package/ts/parseCliArgs.ts +45 -6
- package/ts/rustBinary.ts +68 -0
- package/ts/versionChecker.spec.ts +48 -0
- package/ts/versionChecker.ts +66 -9
- package/ts/xterm-proxy.ts +130 -0
|
@@ -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
|
|
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
|
-
|
|
1303
|
-
const
|
|
1304
|
-
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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:
|
|
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((
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
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,
|
|
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
|
-
|
|
1862
|
-
|
|
1961
|
+
const finalRender = xtermProxy.render();
|
|
1962
|
+
xtermProxy.dispose();
|
|
1963
|
+
await saveDeprecatedLogFile(logFile, finalRender, verbose);
|
|
1863
1964
|
return {
|
|
1864
1965
|
exitCode,
|
|
1865
|
-
logs:
|
|
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-
|
|
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-
|
|
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)
|
|
161
|
-
|
|
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
|
|
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: [
|
|
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
|
|
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(
|
|
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-
|
|
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.
|
|
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
|
|