agent-yes 1.62.2 → 1.64.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/README.md +1 -1
- package/dist/{SUPPORTED_CLIS-CxaWfAAA.js → SUPPORTED_CLIS-DXou-_yV.js} +181 -22
- package/dist/cli.js +6 -5
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/ts/index.ts +21 -24
- package/ts/parseCliArgs.ts +2 -2
- package/ts/rustBinary.ts +6 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent-Yes! for Claude/Codex/Gemini/Cursor/Copilot/Qwen/Auggie
|
|
2
2
|
|
|
3
|
-
A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses. Originally designed for Claude CLI, now supports multiple AI coding assistants.
|
|
3
|
+
A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses. Originally designed for Claude CLI, now supports multiple AI coding assistants. Rewritten in Rust for improved performance and reliability.
|
|
4
4
|
|
|
5
5
|
⚠️ **Important Security Warning**: Only run this on trusted repositories. This tool automatically responds to prompts and can execute commands without user confirmation. Be aware of potential prompt injection attacks where malicious code or instructions could be embedded in files or user inputs to manipulate the automated responses.
|
|
6
6
|
|
|
@@ -2,15 +2,16 @@ import { t as logger } from "./logger-CX77vJDA.js";
|
|
|
2
2
|
import { arch, platform } from "process";
|
|
3
3
|
import { execSync } from "child_process";
|
|
4
4
|
import { execaCommandSync, parseCommandString } from "execa";
|
|
5
|
-
import { fromWritable } from "from-node-stream";
|
|
6
|
-
import { appendFile, mkdir, readFile, readdir, rename, writeFile } from "fs/promises";
|
|
5
|
+
import { fromReadable, fromWritable } from "from-node-stream";
|
|
6
|
+
import { appendFile, mkdir, readFile, readdir, rename, unlink, writeFile } from "fs/promises";
|
|
7
7
|
import path, { dirname, join } from "path";
|
|
8
8
|
import DIE from "phpdie";
|
|
9
9
|
import sflow from "sflow";
|
|
10
10
|
import { TerminalRenderStream } from "terminal-render";
|
|
11
11
|
import { homedir } from "os";
|
|
12
12
|
import winston from "winston";
|
|
13
|
-
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync } from "fs";
|
|
13
|
+
import { closeSync, constants, createReadStream, existsSync, fsyncSync, mkdirSync, openSync } from "fs";
|
|
14
|
+
import { createServer } from "net";
|
|
14
15
|
import { lock } from "proper-lockfile";
|
|
15
16
|
import { execSync as execSync$1 } from "node:child_process";
|
|
16
17
|
import { fileURLToPath } from "url";
|
|
@@ -422,6 +423,163 @@ function shouldUseLock(_cwd) {
|
|
|
422
423
|
return true;
|
|
423
424
|
}
|
|
424
425
|
|
|
426
|
+
//#endregion
|
|
427
|
+
//#region ts/beta/fifo.ts
|
|
428
|
+
/**
|
|
429
|
+
* Creates an IPC stream (FIFO on Linux, Named Pipes on Windows) for additional stdin input
|
|
430
|
+
* @param cli - The CLI name for logging purposes
|
|
431
|
+
* @param customPath - Optional custom path for the IPC file; if provided, uses this instead of generating a path
|
|
432
|
+
* @returns An object with stream and cleanup function, or null if failed
|
|
433
|
+
*/
|
|
434
|
+
async function createFifoStream(cli, customPath) {
|
|
435
|
+
if (process.platform === "win32") return await createWindowsNamedPipe(cli, customPath);
|
|
436
|
+
else if (process.platform === "linux") return await createLinuxFifo(cli, customPath);
|
|
437
|
+
else {
|
|
438
|
+
logger.warn(`[${cli}-yes] IPC not supported on platform: ${process.platform}`);
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Creates a Windows named pipe for IPC
|
|
444
|
+
*/
|
|
445
|
+
async function createWindowsNamedPipe(cli, customPath) {
|
|
446
|
+
try {
|
|
447
|
+
let pipePath;
|
|
448
|
+
if (customPath) pipePath = customPath;
|
|
449
|
+
else pipePath = `\\\\.\\pipe\\agent-yes-${(/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 17)}${Math.random().toString(36).substring(2, 5)}`;
|
|
450
|
+
logger.info(`[${cli}-yes] Creating Windows named pipe at ${pipePath}`);
|
|
451
|
+
const server = createServer();
|
|
452
|
+
let connection = null;
|
|
453
|
+
let isClosing = false;
|
|
454
|
+
const stream = new ReadableStream({
|
|
455
|
+
start(controller) {
|
|
456
|
+
server.on("connection", (socket) => {
|
|
457
|
+
connection = socket;
|
|
458
|
+
logger.info(`[${cli}-yes] Client connected to named pipe`);
|
|
459
|
+
socket.on("data", (chunk) => {
|
|
460
|
+
const data = chunk.toString();
|
|
461
|
+
logger.debug(`[${cli}-yes] Received data via named pipe: ${data}`);
|
|
462
|
+
controller.enqueue(data);
|
|
463
|
+
});
|
|
464
|
+
socket.on("end", () => {
|
|
465
|
+
logger.debug(`[${cli}-yes] Client disconnected from named pipe`);
|
|
466
|
+
connection = null;
|
|
467
|
+
});
|
|
468
|
+
socket.on("error", (error) => {
|
|
469
|
+
logger.warn(`[${cli}-yes] Named pipe socket error:`, error);
|
|
470
|
+
if (!isClosing) controller.error(error);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
server.on("error", (error) => {
|
|
474
|
+
logger.warn(`[${cli}-yes] Named pipe server error:`, error);
|
|
475
|
+
if (!isClosing) controller.error(error);
|
|
476
|
+
});
|
|
477
|
+
server.listen(pipePath, () => {
|
|
478
|
+
logger.info(`[${cli}-yes] Named pipe server listening at ${pipePath}`);
|
|
479
|
+
});
|
|
480
|
+
},
|
|
481
|
+
cancel() {
|
|
482
|
+
isClosing = true;
|
|
483
|
+
if (connection) connection.end();
|
|
484
|
+
server.close();
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
const cleanup = async () => {
|
|
488
|
+
isClosing = true;
|
|
489
|
+
if (connection) connection.end();
|
|
490
|
+
server.close();
|
|
491
|
+
logger.info(`[${cli}-yes] Cleaned up Windows named pipe at ${pipePath}`);
|
|
492
|
+
};
|
|
493
|
+
process.on("exit", () => cleanup().catch(() => null));
|
|
494
|
+
process.on("SIGINT", () => cleanup().catch(() => null));
|
|
495
|
+
process.on("SIGTERM", () => cleanup().catch(() => null));
|
|
496
|
+
return {
|
|
497
|
+
stream,
|
|
498
|
+
[Symbol.asyncDispose]: cleanup
|
|
499
|
+
};
|
|
500
|
+
} catch (error) {
|
|
501
|
+
logger.warn(`[${cli}-yes] Failed to create Windows named pipe:`, error);
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Creates a Linux FIFO for IPC (original implementation)
|
|
507
|
+
*/
|
|
508
|
+
async function createLinuxFifo(cli, customPath) {
|
|
509
|
+
let fifoPath = null;
|
|
510
|
+
let fifoStream = null;
|
|
511
|
+
logger.debug(`[${cli}-yes] Creating Linux FIFO with customPath: ${customPath}`);
|
|
512
|
+
try {
|
|
513
|
+
if (customPath) fifoPath = customPath;
|
|
514
|
+
else fifoPath = `/tmp/agent-yes-${(/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 17)}${Math.random().toString(36).substring(2, 5)}.stdin`;
|
|
515
|
+
try {
|
|
516
|
+
mkdirSync(dirname(fifoPath), { recursive: true });
|
|
517
|
+
} catch (dirError) {
|
|
518
|
+
logger.warn(`[${cli}-yes] Failed to create FIFO directory: ${dirError}`);
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
const escapedPath = fifoPath.replace(/'/g, "'\"'\"'");
|
|
522
|
+
const mkfifoResult = execaCommandSync(`mkfifo '${escapedPath}'`, { reject: false });
|
|
523
|
+
if (mkfifoResult.exitCode !== 0) {
|
|
524
|
+
logger.warn(`[${cli}-yes] mkfifo command failed with exit code ${mkfifoResult.exitCode}`);
|
|
525
|
+
logger.warn(`[${cli}-yes] Command: mkfifo '${escapedPath}'`);
|
|
526
|
+
if (mkfifoResult.stderr) logger.warn(`[${cli}-yes] mkfifo stderr: ${mkfifoResult.stderr}`);
|
|
527
|
+
if (mkfifoResult.stdout) logger.warn(`[${cli}-yes] mkfifo stdout: ${mkfifoResult.stdout}`);
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
logger.info(`[${cli}-yes] Created FIFO at ${fifoPath}`);
|
|
531
|
+
try {
|
|
532
|
+
fifoStream = createReadStream("", {
|
|
533
|
+
fd: openSync(fifoPath, constants.O_RDONLY | constants.O_NONBLOCK),
|
|
534
|
+
autoClose: true
|
|
535
|
+
});
|
|
536
|
+
const dummyWriteFd = openSync(fifoPath, constants.O_WRONLY | constants.O_NONBLOCK);
|
|
537
|
+
logger.info(`[${cli}-yes] FIFO opened for reading`);
|
|
538
|
+
const cleanupFifo = async () => {
|
|
539
|
+
try {
|
|
540
|
+
closeSync(dummyWriteFd);
|
|
541
|
+
} catch {}
|
|
542
|
+
if (fifoStream) try {
|
|
543
|
+
fifoStream.close();
|
|
544
|
+
logger.debug(`[${cli}-yes] Closed FIFO stream`);
|
|
545
|
+
} catch (error) {
|
|
546
|
+
logger.debug(`[${cli}-yes] Error closing FIFO stream:`, { error });
|
|
547
|
+
}
|
|
548
|
+
if (fifoPath) try {
|
|
549
|
+
await unlink(fifoPath).catch(() => null);
|
|
550
|
+
logger.info(`[${cli}-yes] Cleaned up FIFO at ${fifoPath}`);
|
|
551
|
+
} catch {}
|
|
552
|
+
};
|
|
553
|
+
process.on("exit", () => {
|
|
554
|
+
if (fifoPath) unlink(fifoPath).catch(() => null);
|
|
555
|
+
});
|
|
556
|
+
process.on("SIGINT", async () => {
|
|
557
|
+
await cleanupFifo();
|
|
558
|
+
});
|
|
559
|
+
process.on("SIGTERM", async () => {
|
|
560
|
+
await cleanupFifo();
|
|
561
|
+
});
|
|
562
|
+
return {
|
|
563
|
+
stream: sflow(fromReadable(fifoStream)).map((buffer) => buffer.toString()),
|
|
564
|
+
[Symbol.asyncDispose]: cleanupFifo
|
|
565
|
+
};
|
|
566
|
+
} catch (error) {
|
|
567
|
+
logger.warn(`[${cli}-yes] Failed to open FIFO at ${fifoPath}:`, { error });
|
|
568
|
+
if (error instanceof Error) {
|
|
569
|
+
logger.warn(`[${cli}-yes] Error details: ${error.message}`);
|
|
570
|
+
if (error.stack) logger.debug(`[${cli}-yes] Stack trace: ${error.stack}`);
|
|
571
|
+
}
|
|
572
|
+
if (fifoPath) unlink(fifoPath).catch(() => null);
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
} catch (error) {
|
|
576
|
+
logger.warn(`[${cli}-yes] Failed to create FIFO:`, { error });
|
|
577
|
+
if (error instanceof Error) logger.warn(`[${cli}-yes] Error details: ${error.message}`);
|
|
578
|
+
if (fifoPath) unlink(fifoPath).catch(() => null);
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
425
583
|
//#endregion
|
|
426
584
|
//#region ts/JsonlStore.ts
|
|
427
585
|
/**
|
|
@@ -792,19 +950,13 @@ var ReadyManager = class {
|
|
|
792
950
|
async function sendEnter(context, waitms = 1e3) {
|
|
793
951
|
const st = Date.now();
|
|
794
952
|
await context.idleWaiter.wait(waitms);
|
|
795
|
-
|
|
796
|
-
logger.debug(`sendingEnter| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`);
|
|
953
|
+
logger.debug(`sendEnter| idleWait took ${String(Date.now() - st)}ms`);
|
|
797
954
|
context.nextStdout.unready();
|
|
798
955
|
context.shell.write("\r");
|
|
799
|
-
|
|
800
|
-
await Promise.race([context.nextStdout.wait(), new Promise((resolve) => setTimeout(() => {
|
|
801
|
-
if (!context.nextStdout.isReady) context.shell.write("\r");
|
|
802
|
-
resolve();
|
|
803
|
-
}, 1e3))]);
|
|
804
|
-
await Promise.race([context.nextStdout.wait(), new Promise((resolve) => setTimeout(() => {
|
|
956
|
+
for (const ms of [1e3, 3e3]) await Promise.race([context.nextStdout.wait(), new Promise((resolve) => setTimeout(() => {
|
|
805
957
|
if (!context.nextStdout.isReady) context.shell.write("\r");
|
|
806
958
|
resolve();
|
|
807
|
-
},
|
|
959
|
+
}, ms))]);
|
|
808
960
|
}
|
|
809
961
|
/**
|
|
810
962
|
* Send a message to the shell
|
|
@@ -907,7 +1059,7 @@ function tryCatch(catchFn, fn) {
|
|
|
907
1059
|
//#endregion
|
|
908
1060
|
//#region package.json
|
|
909
1061
|
var name = "agent-yes";
|
|
910
|
-
var version = "1.
|
|
1062
|
+
var version = "1.64.0";
|
|
911
1063
|
|
|
912
1064
|
//#endregion
|
|
913
1065
|
//#region ts/pty-fix.ts
|
|
@@ -1363,7 +1515,7 @@ const CLIS_CONFIG = config.clis;
|
|
|
1363
1515
|
* });
|
|
1364
1516
|
* ```
|
|
1365
1517
|
*/
|
|
1366
|
-
async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, exitOnIdle, logFile, removeControlCharactersFromStdout = false, verbose = false, queue = false, install = false, resume = false, useSkills = false, useStdinAppend
|
|
1518
|
+
async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, exitOnIdle, logFile, removeControlCharactersFromStdout = false, verbose = false, queue = false, install = false, resume = false, useSkills = false, useStdinAppend = false, autoYes = true }) {
|
|
1367
1519
|
if (!cli) throw new Error(`cli is required`);
|
|
1368
1520
|
const conf = CLIS_CONFIG[cli] || DIE(`Unsupported cli tool: ${cli}, current process.argv: ${process.argv.join(" ")}`);
|
|
1369
1521
|
const workingDir = cwd ?? process.cwd();
|
|
@@ -1484,6 +1636,12 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1484
1636
|
install,
|
|
1485
1637
|
ptyOptions
|
|
1486
1638
|
});
|
|
1639
|
+
function onData(data) {
|
|
1640
|
+
const currentPid = shell.pid;
|
|
1641
|
+
outputWriter.write(data);
|
|
1642
|
+
globalAgentRegistry.appendStdout(currentPid, data);
|
|
1643
|
+
}
|
|
1644
|
+
shell.onData(onData);
|
|
1487
1645
|
try {
|
|
1488
1646
|
await pidStore.registerProcess({
|
|
1489
1647
|
pid: shell.pid,
|
|
@@ -1531,12 +1689,6 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1531
1689
|
if (!ctx.stdinFirstReady.isReady) ctx.stdinFirstReady.ready();
|
|
1532
1690
|
});
|
|
1533
1691
|
const pendingExitCode = Promise.withResolvers();
|
|
1534
|
-
function onData(data) {
|
|
1535
|
-
const currentPid = shell.pid;
|
|
1536
|
-
outputWriter.write(data);
|
|
1537
|
-
globalAgentRegistry.appendStdout(currentPid, data);
|
|
1538
|
-
}
|
|
1539
|
-
shell.onData(onData);
|
|
1540
1692
|
shell.onExit(async function onExit({ exitCode }) {
|
|
1541
1693
|
const exitedPid = shell.pid;
|
|
1542
1694
|
globalAgentRegistry.unregister(exitedPid);
|
|
@@ -1842,7 +1994,14 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
|
|
|
1842
1994
|
}
|
|
1843
1995
|
return out;
|
|
1844
1996
|
};
|
|
1845
|
-
})()).
|
|
1997
|
+
})()).by(async (s) => {
|
|
1998
|
+
if (!useStdinAppend) return s;
|
|
1999
|
+
const ipcResult = await createFifoStream(cli, pidStore.getFifoPath(shell.pid));
|
|
2000
|
+
if (!ipcResult) return s;
|
|
2001
|
+
pendingExitCode.promise.finally(async () => await ipcResult[Symbol.asyncDispose]());
|
|
2002
|
+
process.stderr.write(`\n Append prompts: ${cli}-yes --append-prompt '...'\n\n`);
|
|
2003
|
+
return s.merge(ipcResult.stream);
|
|
2004
|
+
}).confluenceByConcat().onStart(async function promptOnStart() {
|
|
1846
2005
|
logger.debug("Sending prompt message: " + JSON.stringify(prompt));
|
|
1847
2006
|
if (prompt) await sendMessage(ctx.messageContext, prompt);
|
|
1848
2007
|
}).by({
|
|
@@ -1953,4 +2112,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
|
|
|
1953
2112
|
|
|
1954
2113
|
//#endregion
|
|
1955
2114
|
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 };
|
|
1956
|
-
//# sourceMappingURL=SUPPORTED_CLIS-
|
|
2115
|
+
//# sourceMappingURL=SUPPORTED_CLIS-DXou-_yV.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-DXou-_yV.js";
|
|
3
3
|
import { t as logger } from "./logger-CX77vJDA.js";
|
|
4
4
|
import { argv } from "process";
|
|
5
5
|
import { spawn } from "child_process";
|
|
@@ -85,8 +85,8 @@ function parseCliArgs(argv) {
|
|
|
85
85
|
default: "yes"
|
|
86
86
|
}).option("rust", {
|
|
87
87
|
type: "boolean",
|
|
88
|
-
description: "Use the Rust implementation
|
|
89
|
-
default:
|
|
88
|
+
description: "Use the Rust implementation (enabled by default, use --no-rust for TypeScript)",
|
|
89
|
+
default: true
|
|
90
90
|
}).option("swarm", {
|
|
91
91
|
type: "string",
|
|
92
92
|
description: `Enable swarm mode for multi-agent P2P networking (requires --rust).
|
|
@@ -271,10 +271,11 @@ function getBinDir() {
|
|
|
271
271
|
*/
|
|
272
272
|
function findRustBinary(verbose = false) {
|
|
273
273
|
const binaryName = getBinaryName();
|
|
274
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
274
275
|
const searchPaths = [
|
|
276
|
+
path.resolve(import.meta.dirname ?? import.meta.dir, `../rs/target/release/agent-yes${ext}`),
|
|
277
|
+
path.resolve(import.meta.dirname ?? import.meta.dir, `../rs/target/debug/agent-yes${ext}`),
|
|
275
278
|
path.join(getBinDir(), binaryName),
|
|
276
|
-
path.resolve(import.meta.dirname ?? import.meta.dir, "../rs/target/release/agent-yes"),
|
|
277
|
-
path.resolve(import.meta.dirname ?? import.meta.dir, "../rs/target/debug/agent-yes"),
|
|
278
279
|
path.join(getBinDir(), binaryName)
|
|
279
280
|
];
|
|
280
281
|
if (verbose) {
|
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-DXou-_yV.js";
|
|
2
2
|
import "./logger-CX77vJDA.js";
|
|
3
3
|
|
|
4
4
|
export { AgentContext, CLIS_CONFIG, config, agentYes as default, removeControlCharacters };
|
package/package.json
CHANGED
package/ts/index.ts
CHANGED
|
@@ -14,7 +14,6 @@ import pty, { ptyPackage } from "./pty.ts";
|
|
|
14
14
|
import { removeControlCharacters } from "./removeControlCharacters.ts";
|
|
15
15
|
import { acquireLock, releaseLock, shouldUseLock } from "./runningLock.ts";
|
|
16
16
|
import { logger } from "./logger.ts";
|
|
17
|
-
// oxlint-disable-next-line no-unused-vars -- kept for FIFO re-enable (see TODO at index.ts:833)
|
|
18
17
|
import { createFifoStream } from "./beta/fifo.ts";
|
|
19
18
|
import { PidStore } from "./pidStore.ts";
|
|
20
19
|
import { SUPPORTED_CLIS } from "./SUPPORTED_CLIS.ts";
|
|
@@ -118,7 +117,7 @@ export default async function agentYes({
|
|
|
118
117
|
install = false,
|
|
119
118
|
resume = false,
|
|
120
119
|
useSkills = false,
|
|
121
|
-
useStdinAppend
|
|
120
|
+
useStdinAppend = false,
|
|
122
121
|
autoYes = true,
|
|
123
122
|
}: {
|
|
124
123
|
cli: SUPPORTED_CLIS;
|
|
@@ -328,6 +327,15 @@ export default async function agentYes({
|
|
|
328
327
|
ptyOptions,
|
|
329
328
|
});
|
|
330
329
|
|
|
330
|
+
// Attach data handler IMMEDIATELY after spawn to avoid losing early PTY output.
|
|
331
|
+
// node-pty emits 'data' events eagerly — if no listener is attached, events are lost.
|
|
332
|
+
function onData(data: string) {
|
|
333
|
+
const currentPid = shell.pid;
|
|
334
|
+
outputWriter.write(data);
|
|
335
|
+
globalAgentRegistry.appendStdout(currentPid, data);
|
|
336
|
+
}
|
|
337
|
+
shell.onData(onData);
|
|
338
|
+
|
|
331
339
|
// Register process in pidStore (non-blocking - failures should not prevent agent from running)
|
|
332
340
|
try {
|
|
333
341
|
await pidStore.registerProcess({ pid: shell.pid, cli, args: cliArgs, prompt, cwd: workingDir });
|
|
@@ -387,16 +395,6 @@ export default async function agentYes({
|
|
|
387
395
|
|
|
388
396
|
const pendingExitCode = Promise.withResolvers<number | null>();
|
|
389
397
|
|
|
390
|
-
function onData(data: string) {
|
|
391
|
-
const currentPid = shell.pid; // Capture PID before any potential shell reassignment
|
|
392
|
-
// Write eagerly — TerminalRenderStream never exerts backpressure,
|
|
393
|
-
// so the PTY is always drained and the child process never blocks.
|
|
394
|
-
outputWriter.write(data);
|
|
395
|
-
// append to agent registry for MCP server
|
|
396
|
-
globalAgentRegistry.appendStdout(currentPid, data);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
shell.onData(onData);
|
|
400
398
|
shell.onExit(async function onExit({ exitCode }) {
|
|
401
399
|
const exitedPid = shell.pid; // Capture PID immediately before any shell reassignment
|
|
402
400
|
// Unregister from agent registry
|
|
@@ -833,18 +831,17 @@ export default async function agentYes({
|
|
|
833
831
|
})(),
|
|
834
832
|
)
|
|
835
833
|
|
|
836
|
-
//
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
//
|
|
847
|
-
// .confluenceByConcat() // necessary when .by() above is async
|
|
834
|
+
// Read from IPC stream if available (FIFO on Linux, Named Pipes on Windows)
|
|
835
|
+
.by(async (s) => {
|
|
836
|
+
if (!useStdinAppend) return s;
|
|
837
|
+
const fifoPath = pidStore.getFifoPath(shell.pid);
|
|
838
|
+
const ipcResult = await createFifoStream(cli, fifoPath);
|
|
839
|
+
if (!ipcResult) return s;
|
|
840
|
+
pendingExitCode.promise.finally(async () => await ipcResult[Symbol.asyncDispose]());
|
|
841
|
+
process.stderr.write(`\n Append prompts: ${cli}-yes --append-prompt '...'\n\n`);
|
|
842
|
+
return s.merge(ipcResult.stream);
|
|
843
|
+
})
|
|
844
|
+
.confluenceByConcat() // necessary because .by() above is async
|
|
848
845
|
|
|
849
846
|
// .map((e) => e.replaceAll('\x1a', '')) // remove ctrl+z from user's input, to prevent bug (but this seems bug)
|
|
850
847
|
// .forEach(e => appendFile('.cache/io.log', "input |" + JSON.stringify(e) + '\n')) // for debugging
|
package/ts/parseCliArgs.ts
CHANGED
|
@@ -121,8 +121,8 @@ export function parseCliArgs(argv: string[]) {
|
|
|
121
121
|
})
|
|
122
122
|
.option("rust", {
|
|
123
123
|
type: "boolean",
|
|
124
|
-
description: "Use the Rust implementation
|
|
125
|
-
default:
|
|
124
|
+
description: "Use the Rust implementation (enabled by default, use --no-rust for TypeScript)",
|
|
125
|
+
default: true,
|
|
126
126
|
})
|
|
127
127
|
.option("swarm", {
|
|
128
128
|
type: "string",
|
package/ts/rustBinary.ts
CHANGED
|
@@ -61,13 +61,14 @@ export function getBinDir(): string {
|
|
|
61
61
|
export function findRustBinary(verbose = false): string | undefined {
|
|
62
62
|
const binaryName = getBinaryName();
|
|
63
63
|
|
|
64
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
64
65
|
const searchPaths = [
|
|
65
|
-
// 1. Check in
|
|
66
|
-
path.
|
|
66
|
+
// 1. Check relative to this script (in the repo during development)
|
|
67
|
+
path.resolve(import.meta.dirname ?? import.meta.dir, `../rs/target/release/agent-yes${ext}`),
|
|
68
|
+
path.resolve(import.meta.dirname ?? import.meta.dir, `../rs/target/debug/agent-yes${ext}`),
|
|
67
69
|
|
|
68
|
-
// 2. Check
|
|
69
|
-
path.
|
|
70
|
-
path.resolve(import.meta.dirname ?? import.meta.dir, "../rs/target/debug/agent-yes"),
|
|
70
|
+
// 2. Check in npm package bin directory
|
|
71
|
+
path.join(getBinDir(), binaryName),
|
|
71
72
|
|
|
72
73
|
// 3. Check in user's cache directory
|
|
73
74
|
path.join(getBinDir(), binaryName),
|