claude-yes 1.35.1 → 1.36.1

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/cli.js CHANGED
@@ -20633,12 +20633,94 @@ import { fromReadable } from "from-node-stream";
20633
20633
  import { createReadStream as createReadStream2, mkdirSync } from "fs";
20634
20634
  import { unlink } from "fs/promises";
20635
20635
  import { dirname } from "path";
20636
+ import { createServer } from "net";
20636
20637
  function createFifoStream(cli, customPath) {
20637
- if (process.platform !== "linux") {
20638
+ if (process.platform === "win32") {
20639
+ return createWindowsNamedPipe(cli, customPath);
20640
+ } else if (process.platform === "linux") {
20641
+ return createLinuxFifo(cli, customPath);
20642
+ } else {
20643
+ logger.warn(`[${cli}-yes] IPC not supported on platform: ${process.platform}`);
20644
+ return null;
20645
+ }
20646
+ }
20647
+ function createWindowsNamedPipe(cli, customPath) {
20648
+ try {
20649
+ let pipePath;
20650
+ if (customPath) {
20651
+ pipePath = customPath;
20652
+ } else {
20653
+ const timestamp = new Date().toISOString().replace(/\D/g, "").slice(0, 17);
20654
+ const randomSuffix = Math.random().toString(36).substring(2, 5);
20655
+ pipePath = `\\\\.\\pipe\\agent-yes-${timestamp}${randomSuffix}`;
20656
+ }
20657
+ logger.info(`[${cli}-yes] Creating Windows named pipe at ${pipePath}`);
20658
+ const server = createServer();
20659
+ let connection = null;
20660
+ let isClosing = false;
20661
+ const stream = new ReadableStream({
20662
+ start(controller) {
20663
+ server.on("connection", (socket) => {
20664
+ connection = socket;
20665
+ logger.info(`[${cli}-yes] Client connected to named pipe`);
20666
+ socket.on("data", (chunk) => {
20667
+ const data = chunk.toString();
20668
+ logger.debug(`[${cli}-yes] Received data via named pipe: ${data}`);
20669
+ controller.enqueue(data);
20670
+ });
20671
+ socket.on("end", () => {
20672
+ logger.debug(`[${cli}-yes] Client disconnected from named pipe`);
20673
+ connection = null;
20674
+ });
20675
+ socket.on("error", (error) => {
20676
+ logger.warn(`[${cli}-yes] Named pipe socket error:`, error);
20677
+ if (!isClosing) {
20678
+ controller.error(error);
20679
+ }
20680
+ });
20681
+ });
20682
+ server.on("error", (error) => {
20683
+ logger.warn(`[${cli}-yes] Named pipe server error:`, error);
20684
+ if (!isClosing) {
20685
+ controller.error(error);
20686
+ }
20687
+ });
20688
+ server.listen(pipePath, () => {
20689
+ logger.info(`[${cli}-yes] Named pipe server listening at ${pipePath}`);
20690
+ });
20691
+ },
20692
+ cancel() {
20693
+ isClosing = true;
20694
+ if (connection) {
20695
+ connection.end();
20696
+ }
20697
+ server.close();
20698
+ }
20699
+ });
20700
+ const cleanup = async () => {
20701
+ isClosing = true;
20702
+ if (connection) {
20703
+ connection.end();
20704
+ }
20705
+ server.close();
20706
+ logger.info(`[${cli}-yes] Cleaned up Windows named pipe at ${pipePath}`);
20707
+ };
20708
+ process.on("exit", () => cleanup().catch(() => null));
20709
+ process.on("SIGINT", () => cleanup().catch(() => null));
20710
+ process.on("SIGTERM", () => cleanup().catch(() => null));
20711
+ return {
20712
+ stream,
20713
+ cleanup
20714
+ };
20715
+ } catch (error) {
20716
+ logger.warn(`[${cli}-yes] Failed to create Windows named pipe:`, error);
20638
20717
  return null;
20639
20718
  }
20719
+ }
20720
+ function createLinuxFifo(cli, customPath) {
20640
20721
  let fifoPath = null;
20641
20722
  let fifoStream = null;
20723
+ logger.debug(`[${cli}-yes] Creating Linux FIFO with customPath: ${customPath}`);
20642
20724
  try {
20643
20725
  if (customPath) {
20644
20726
  fifoPath = customPath;
@@ -20647,12 +20729,19 @@ function createFifoStream(cli, customPath) {
20647
20729
  const randomSuffix = Math.random().toString(36).substring(2, 5);
20648
20730
  fifoPath = `/tmp/agent-yes-${timestamp}${randomSuffix}.stdin`;
20649
20731
  }
20650
- mkdirSync(dirname(fifoPath), { recursive: true });
20651
- const mkfifoResult = execaCommandSync(`mkfifo ${fifoPath}`, {
20732
+ try {
20733
+ mkdirSync(dirname(fifoPath), { recursive: true });
20734
+ } catch (dirError) {
20735
+ logger.warn(`[${cli}-yes] Failed to create FIFO directory: ${dirError}`);
20736
+ return null;
20737
+ }
20738
+ const escapedPath = fifoPath.replace(/'/g, `'"'"'`);
20739
+ const mkfifoResult = execaCommandSync(`mkfifo '${escapedPath}'`, {
20652
20740
  reject: false
20653
20741
  });
20654
20742
  if (mkfifoResult.exitCode !== 0) {
20655
20743
  logger.warn(`[${cli}-yes] mkfifo command failed with exit code ${mkfifoResult.exitCode}`);
20744
+ logger.warn(`[${cli}-yes] Command: mkfifo '${escapedPath}'`);
20656
20745
  if (mkfifoResult.stderr) {
20657
20746
  logger.warn(`[${cli}-yes] mkfifo stderr: ${mkfifoResult.stderr}`);
20658
20747
  }
@@ -20732,7 +20821,7 @@ var init_fifo = __esm(() => {
20732
20821
  });
20733
20822
 
20734
20823
  // ts/pidStore.ts
20735
- import { mkdir as mkdir3 } from "fs/promises";
20824
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
20736
20825
  import path9 from "path";
20737
20826
 
20738
20827
  class SqliteAdapter {
@@ -20776,15 +20865,16 @@ class SqliteAdapter {
20776
20865
 
20777
20866
  class PidStore {
20778
20867
  db;
20779
- baseDir;
20868
+ storeDir;
20780
20869
  dbPath;
20781
20870
  constructor(workingDir) {
20782
- this.baseDir = path9.resolve(workingDir, ".agent-yes");
20783
- this.dbPath = path9.join(this.baseDir, "pid.sqlite");
20871
+ this.storeDir = path9.resolve(workingDir, ".agent-yes");
20872
+ this.dbPath = path9.join(this.storeDir, "pid.sqlite");
20784
20873
  }
20785
20874
  async init() {
20786
- await mkdir3(path9.join(this.baseDir, "logs"), { recursive: true });
20787
- await mkdir3(path9.join(this.baseDir, "fifo"), { recursive: true });
20875
+ await mkdir3(path9.join(this.storeDir, "logs"), { recursive: true });
20876
+ await mkdir3(path9.join(this.storeDir, "fifo"), { recursive: true });
20877
+ await this.ensureGitignore();
20788
20878
  this.db = new SqliteAdapter;
20789
20879
  await this.db.init(this.dbPath);
20790
20880
  this.db.run("PRAGMA journal_mode=WAL");
@@ -20856,10 +20946,14 @@ class PidStore {
20856
20946
  logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
20857
20947
  }
20858
20948
  getLogPath(pid) {
20859
- return path9.resolve(this.baseDir, "logs", `${pid}.log`);
20949
+ return path9.resolve(this.storeDir, "logs", `${pid}.log`);
20860
20950
  }
20861
20951
  getFifoPath(pid) {
20862
- return path9.resolve(this.baseDir, "fifo", `${pid}.stdin`);
20952
+ if (process.platform === "win32") {
20953
+ return `\\\\.\\pipe\\agent-yes-${pid}`;
20954
+ } else {
20955
+ return path9.resolve(this.storeDir, "fifo", `${pid}.stdin`);
20956
+ }
20863
20957
  }
20864
20958
  async cleanStaleRecords() {
20865
20959
  const activeRecords = this.db.query("SELECT * FROM pid_records WHERE status != 'exited'");
@@ -20888,6 +20982,28 @@ class PidStore {
20888
20982
  return false;
20889
20983
  }
20890
20984
  }
20985
+ async ensureGitignore() {
20986
+ const gitignorePath = path9.join(this.storeDir, ".gitignore");
20987
+ const gitignoreContent = `# Auto-generated .gitignore for agent-yes
20988
+ # Ignore all log files and runtime data
20989
+ logs/
20990
+ fifo/
20991
+ *.sqlite
20992
+ *.sqlite-*
20993
+ *.log
20994
+ *.raw.log
20995
+ *.lines.log
20996
+ *.debug.log
20997
+ `;
20998
+ try {
20999
+ await writeFile3(gitignorePath, gitignoreContent, { flag: "wx" });
21000
+ logger.debug(`[pidStore] Created .gitignore in ${this.storeDir}`);
21001
+ } catch (error) {
21002
+ if (error.code !== "EEXIST") {
21003
+ logger.warn(`[pidStore] Failed to create .gitignore:`, error);
21004
+ }
21005
+ }
21006
+ }
20891
21007
  static async findActiveFifo(workingDir) {
20892
21008
  const store = new PidStore(workingDir);
20893
21009
  await store.init();
@@ -21026,8 +21142,11 @@ function getDefaultConfig() {
21026
21142
  fatal: []
21027
21143
  },
21028
21144
  amp: {
21029
- help: "",
21030
- install: "npm i -g @sourcegraph/amp",
21145
+ help: "https://ampcode.com/",
21146
+ install: {
21147
+ bash: "curl -fsSL https://ampcode.com/install.sh | bash",
21148
+ npm: "npm i -g @sourcegraph/amp"
21149
+ },
21031
21150
  enter: [
21032
21151
  /^.{0,4} Approve /
21033
21152
  ]
@@ -21221,7 +21340,7 @@ __export(exports_ts, {
21221
21340
  CLIS_CONFIG: () => CLIS_CONFIG2
21222
21341
  });
21223
21342
  import { fromReadable as fromReadable3, fromWritable as fromWritable2 } from "from-node-stream";
21224
- import { mkdir as mkdir7, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
21343
+ import { mkdir as mkdir7, readFile as readFile4, writeFile as writeFile7 } from "fs/promises";
21225
21344
  import path13 from "path";
21226
21345
  async function agentYes2({
21227
21346
  cli,
@@ -21568,15 +21687,15 @@ ${prompt}` : prefix;
21568
21687
  }).by((s) => {
21569
21688
  if (!useFifo)
21570
21689
  return s;
21571
- const fifoResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
21572
- if (!fifoResult)
21690
+ const ipcResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
21691
+ if (!ipcResult)
21573
21692
  return s;
21574
- pendingExitCode.promise.finally(() => fifoResult.cleanup());
21693
+ pendingExitCode.promise.finally(() => ipcResult.cleanup());
21575
21694
  process.stderr.write(`
21576
21695
  Append prompts: ${cli}-yes --append-prompt '...'
21577
21696
 
21578
21697
  `);
21579
- return s.merge(fifoResult.stream);
21698
+ return s.merge(ipcResult.stream);
21580
21699
  }).onStart(async function promptOnStart() {
21581
21700
  logger.debug("Sending prompt message: " + JSON.stringify(prompt));
21582
21701
  if (prompt)
@@ -21598,7 +21717,7 @@ ${prompt}` : prefix;
21598
21717
  return await mkdir7(path13.dirname(rawLogPath), { recursive: true }).then(() => {
21599
21718
  logger.debug(`[${cli}-yes] raw logs streaming to ${rawLogPath}`);
21600
21719
  return f.forEach(async (chars) => {
21601
- await writeFile5(rawLogPath, chars, { flag: "a" }).catch(() => null);
21720
+ await writeFile7(rawLogPath, chars, { flag: "a" }).catch(() => null);
21602
21721
  }).run();
21603
21722
  }).catch(() => f.run());
21604
21723
  }).by(function consoleResponder(e) {
@@ -21670,7 +21789,7 @@ ${prompt}` : prefix;
21670
21789
  })).to(fromWritable2(process.stdout));
21671
21790
  if (logPath) {
21672
21791
  await mkdir7(path13.dirname(logPath), { recursive: true }).catch(() => null);
21673
- await writeFile5(logPath, terminalRender.render()).catch(() => null);
21792
+ await writeFile7(logPath, terminalRender.render()).catch(() => null);
21674
21793
  logger.info(`[${cli}-yes] Full logs saved to ${logPath}`);
21675
21794
  }
21676
21795
  const exitCode = await pendingExitCode.promise;
@@ -21682,7 +21801,7 @@ ${prompt}` : prefix;
21682
21801
  logger.info(`[${cli}-yes] Writing rendered logs to ${logFile}`);
21683
21802
  const logFilePath = path13.resolve(logFile);
21684
21803
  await mkdir7(path13.dirname(logFilePath), { recursive: true }).catch(() => null);
21685
- await writeFile5(logFilePath, terminalRender.render());
21804
+ await writeFile7(logFilePath, terminalRender.render());
21686
21805
  }
21687
21806
  return { exitCode, logs: terminalRender.render() };
21688
21807
  async function sendEnter(waitms = 1000) {
@@ -21701,6 +21820,15 @@ ${prompt}` : prefix;
21701
21820
  resolve5();
21702
21821
  }, 1000))
21703
21822
  ]);
21823
+ await Promise.race([
21824
+ nextStdout.wait(),
21825
+ new Promise((resolve5) => setTimeout(() => {
21826
+ if (!nextStdout.ready) {
21827
+ shell.write("\r");
21828
+ }
21829
+ resolve5();
21830
+ }, 3000))
21831
+ ]);
21704
21832
  }
21705
21833
  async function sendMessage3(message, { waitForReady = true } = {}) {
21706
21834
  if (waitForReady)
@@ -21772,7 +21900,7 @@ init_pidStore();
21772
21900
  await init_pty();
21773
21901
  var import_winston2 = __toESM(require_winston(), 1);
21774
21902
  import { fromReadable as fromReadable2, fromWritable } from "from-node-stream";
21775
- import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
21903
+ import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
21776
21904
  import path11 from "path";
21777
21905
  var config = await init_agent_yes_config().then(() => exports_agent_yes_config).then((mod) => mod.default || mod);
21778
21906
  var CLIS_CONFIG = config.clis;
@@ -22121,15 +22249,15 @@ ${prompt}` : prefix;
22121
22249
  }).by((s) => {
22122
22250
  if (!useFifo)
22123
22251
  return s;
22124
- const fifoResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
22125
- if (!fifoResult)
22252
+ const ipcResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
22253
+ if (!ipcResult)
22126
22254
  return s;
22127
- pendingExitCode.promise.finally(() => fifoResult.cleanup());
22255
+ pendingExitCode.promise.finally(() => ipcResult.cleanup());
22128
22256
  process.stderr.write(`
22129
22257
  Append prompts: ${cli}-yes --append-prompt '...'
22130
22258
 
22131
22259
  `);
22132
- return s.merge(fifoResult.stream);
22260
+ return s.merge(ipcResult.stream);
22133
22261
  }).onStart(async function promptOnStart() {
22134
22262
  logger.debug("Sending prompt message: " + JSON.stringify(prompt));
22135
22263
  if (prompt)
@@ -22151,7 +22279,7 @@ ${prompt}` : prefix;
22151
22279
  return await mkdir5(path11.dirname(rawLogPath), { recursive: true }).then(() => {
22152
22280
  logger.debug(`[${cli}-yes] raw logs streaming to ${rawLogPath}`);
22153
22281
  return f.forEach(async (chars) => {
22154
- await writeFile3(rawLogPath, chars, { flag: "a" }).catch(() => null);
22282
+ await writeFile4(rawLogPath, chars, { flag: "a" }).catch(() => null);
22155
22283
  }).run();
22156
22284
  }).catch(() => f.run());
22157
22285
  }).by(function consoleResponder(e) {
@@ -22223,7 +22351,7 @@ ${prompt}` : prefix;
22223
22351
  })).to(fromWritable(process.stdout));
22224
22352
  if (logPath) {
22225
22353
  await mkdir5(path11.dirname(logPath), { recursive: true }).catch(() => null);
22226
- await writeFile3(logPath, terminalRender.render()).catch(() => null);
22354
+ await writeFile4(logPath, terminalRender.render()).catch(() => null);
22227
22355
  logger.info(`[${cli}-yes] Full logs saved to ${logPath}`);
22228
22356
  }
22229
22357
  const exitCode = await pendingExitCode.promise;
@@ -22235,7 +22363,7 @@ ${prompt}` : prefix;
22235
22363
  logger.info(`[${cli}-yes] Writing rendered logs to ${logFile}`);
22236
22364
  const logFilePath = path11.resolve(logFile);
22237
22365
  await mkdir5(path11.dirname(logFilePath), { recursive: true }).catch(() => null);
22238
- await writeFile3(logFilePath, terminalRender.render());
22366
+ await writeFile4(logFilePath, terminalRender.render());
22239
22367
  }
22240
22368
  return { exitCode, logs: terminalRender.render() };
22241
22369
  async function sendEnter(waitms = 1000) {
@@ -22254,6 +22382,15 @@ ${prompt}` : prefix;
22254
22382
  resolve();
22255
22383
  }, 1000))
22256
22384
  ]);
22385
+ await Promise.race([
22386
+ nextStdout.wait(),
22387
+ new Promise((resolve) => setTimeout(() => {
22388
+ if (!nextStdout.ready) {
22389
+ shell.write("\r");
22390
+ }
22391
+ resolve();
22392
+ }, 3000))
22393
+ ]);
22257
22394
  }
22258
22395
  async function sendMessage3(message, { waitForReady = true } = {}) {
22259
22396
  if (waitForReady)
@@ -24132,13 +24269,13 @@ function stringWidth3(string, options = {}) {
24132
24269
  }
24133
24270
 
24134
24271
  // node_modules/y18n/build/lib/platform-shims/node.js
24135
- import { readFileSync as readFileSync4, statSync as statSync3, writeFile as writeFile4 } from "fs";
24272
+ import { readFileSync as readFileSync4, statSync as statSync3, writeFile as writeFile5 } from "fs";
24136
24273
  import { format as format3 } from "util";
24137
24274
  import { resolve as resolve3 } from "path";
24138
24275
  var node_default = {
24139
24276
  fs: {
24140
24277
  readFileSync: readFileSync4,
24141
- writeFile: writeFile4
24278
+ writeFile: writeFile5
24142
24279
  },
24143
24280
  format: format3,
24144
24281
  resolve: resolve3,
@@ -27848,7 +27985,7 @@ var package_default = {
27848
27985
  // ts/parseCliArgs.ts
27849
27986
  function parseCliArgs(argv) {
27850
27987
  const cliName = argv[1]?.split(/[/\\]/).at(-1)?.replace(/(\.[jt]s)?$/, "").replace(/^(cli|agent)(-yes$)?/, "").replace(/^ay$/, "").replace(/-yes$/, "") || undefined;
27851
- const parsedArgv = yargs_default(hideBin(argv)).usage("Usage: $0 [cli] [agent-yes args] [agent-cli args] [--] [prompts...]").example("$0 claude --idle=30s -- solve all todos in my codebase, commit one by one", "Run Claude with a 30 seconds idle timeout, and the prompt is everything after `--`").option("robust", {
27988
+ const parsedArgv = yargs_default(hideBin(argv)).usage("Usage: $0 [cli] [agent-yes args] [agent-cli args] [--] [prompts...]").example("$0 claude --idle=30s -- solve all todos in my codebase, commit one by one", "Run Claude with a 30 seconds idle timeout, and the prompt is everything after `--`").example("$0 claude --stdpush", "Run Claude with external stdin input enabled via --append-prompt").option("robust", {
27852
27989
  type: "boolean",
27853
27990
  default: true,
27854
27991
  description: "re-spawn Claude with --continue if it crashes, only works for claude yet",
@@ -27896,11 +28033,12 @@ function parseCliArgs(argv) {
27896
28033
  alias: "c"
27897
28034
  }).option("append-prompt", {
27898
28035
  type: "string",
27899
- description: "Send a prompt to the active agent's FIFO stdin in current directory"
27900
- }).option("fifo", {
28036
+ description: "Send a prompt to the active agent's stdin in current directory"
28037
+ }).option("stdpush", {
27901
28038
  type: "boolean",
27902
- description: "Enable FIFO input stream for additional stdin input (Linux only)",
27903
- default: false
28039
+ description: "Enable external input stream to push additional data to stdin",
28040
+ default: false,
28041
+ alias: ["ipc", "fifo"]
27904
28042
  }).positional("cli", {
27905
28043
  describe: "The AI CLI to run, e.g., claude, codex, copilot, cursor, gemini",
27906
28044
  type: "string",
@@ -27973,7 +28111,7 @@ function parseCliArgs(argv) {
27973
28111
  resume: parsedArgv.continue,
27974
28112
  useSkills: parsedArgv.useSkills,
27975
28113
  appendPrompt: parsedArgv.appendPrompt,
27976
- useFifo: parsedArgv.fifo
28114
+ useFifo: parsedArgv.stdpush || parsedArgv.ipc || parsedArgv.fifo
27977
28115
  };
27978
28116
  }
27979
28117
 
@@ -27996,7 +28134,7 @@ var logger2 = import_winston3.default.createLogger({
27996
28134
 
27997
28135
  // ts/pidStore.ts
27998
28136
  init_logger();
27999
- import { mkdir as mkdir6 } from "fs/promises";
28137
+ import { mkdir as mkdir6, writeFile as writeFile6 } from "fs/promises";
28000
28138
  import path12 from "path";
28001
28139
 
28002
28140
  class SqliteAdapter2 {
@@ -28040,15 +28178,16 @@ class SqliteAdapter2 {
28040
28178
 
28041
28179
  class PidStore2 {
28042
28180
  db;
28043
- baseDir;
28181
+ storeDir;
28044
28182
  dbPath;
28045
28183
  constructor(workingDir) {
28046
- this.baseDir = path12.resolve(workingDir, ".agent-yes");
28047
- this.dbPath = path12.join(this.baseDir, "pid.sqlite");
28184
+ this.storeDir = path12.resolve(workingDir, ".agent-yes");
28185
+ this.dbPath = path12.join(this.storeDir, "pid.sqlite");
28048
28186
  }
28049
28187
  async init() {
28050
- await mkdir6(path12.join(this.baseDir, "logs"), { recursive: true });
28051
- await mkdir6(path12.join(this.baseDir, "fifo"), { recursive: true });
28188
+ await mkdir6(path12.join(this.storeDir, "logs"), { recursive: true });
28189
+ await mkdir6(path12.join(this.storeDir, "fifo"), { recursive: true });
28190
+ await this.ensureGitignore();
28052
28191
  this.db = new SqliteAdapter2;
28053
28192
  await this.db.init(this.dbPath);
28054
28193
  this.db.run("PRAGMA journal_mode=WAL");
@@ -28120,10 +28259,14 @@ class PidStore2 {
28120
28259
  logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
28121
28260
  }
28122
28261
  getLogPath(pid) {
28123
- return path12.resolve(this.baseDir, "logs", `${pid}.log`);
28262
+ return path12.resolve(this.storeDir, "logs", `${pid}.log`);
28124
28263
  }
28125
28264
  getFifoPath(pid) {
28126
- return path12.resolve(this.baseDir, "fifo", `${pid}.stdin`);
28265
+ if (process.platform === "win32") {
28266
+ return `\\\\.\\pipe\\agent-yes-${pid}`;
28267
+ } else {
28268
+ return path12.resolve(this.storeDir, "fifo", `${pid}.stdin`);
28269
+ }
28127
28270
  }
28128
28271
  async cleanStaleRecords() {
28129
28272
  const activeRecords = this.db.query("SELECT * FROM pid_records WHERE status != 'exited'");
@@ -28152,6 +28295,28 @@ class PidStore2 {
28152
28295
  return false;
28153
28296
  }
28154
28297
  }
28298
+ async ensureGitignore() {
28299
+ const gitignorePath = path12.join(this.storeDir, ".gitignore");
28300
+ const gitignoreContent = `# Auto-generated .gitignore for agent-yes
28301
+ # Ignore all log files and runtime data
28302
+ logs/
28303
+ fifo/
28304
+ *.sqlite
28305
+ *.sqlite-*
28306
+ *.log
28307
+ *.raw.log
28308
+ *.lines.log
28309
+ *.debug.log
28310
+ `;
28311
+ try {
28312
+ await writeFile6(gitignorePath, gitignoreContent, { flag: "wx" });
28313
+ logger.debug(`[pidStore] Created .gitignore in ${this.storeDir}`);
28314
+ } catch (error) {
28315
+ if (error.code !== "EEXIST") {
28316
+ logger.warn(`[pidStore] Failed to create .gitignore:`, error);
28317
+ }
28318
+ }
28319
+ }
28155
28320
  static async findActiveFifo(workingDir) {
28156
28321
  const store = new PidStore2(workingDir);
28157
28322
  await store.init();
@@ -28164,16 +28329,42 @@ class PidStore2 {
28164
28329
  // ts/cli.ts
28165
28330
  var config3 = parseCliArgs(process.argv);
28166
28331
  if (config3.appendPrompt) {
28167
- const fifoPath = await PidStore2.findActiveFifo(process.cwd());
28168
- if (!fifoPath) {
28169
- console.error("No active agent with FIFO found in current directory.");
28332
+ const ipcPath = await PidStore2.findActiveFifo(process.cwd());
28333
+ if (!ipcPath) {
28334
+ console.error("No active agent with IPC found in current directory.");
28335
+ process.exit(1);
28336
+ }
28337
+ try {
28338
+ if (process.platform === "win32") {
28339
+ const { connect } = await import("net");
28340
+ await new Promise((resolve5, reject) => {
28341
+ const client = connect(ipcPath);
28342
+ client.on("connect", () => {
28343
+ client.write(config3.appendPrompt + "\r");
28344
+ client.end();
28345
+ console.log(`Sent prompt to Windows named pipe: ${ipcPath}`);
28346
+ resolve5();
28347
+ });
28348
+ client.on("error", (error) => {
28349
+ console.error(`Failed to connect to named pipe: ${error}`);
28350
+ reject(error);
28351
+ });
28352
+ setTimeout(() => {
28353
+ client.destroy();
28354
+ reject(new Error("Connection timeout"));
28355
+ }, 5000);
28356
+ });
28357
+ } else {
28358
+ const { writeFileSync: writeFileSync2, openSync, closeSync } = await import("fs");
28359
+ const fd = openSync(ipcPath, "w");
28360
+ writeFileSync2(fd, config3.appendPrompt + "\r");
28361
+ closeSync(fd);
28362
+ console.log(`Sent prompt to FIFO: ${ipcPath}`);
28363
+ }
28364
+ } catch (error) {
28365
+ console.error(`Failed to send prompt: ${error}`);
28170
28366
  process.exit(1);
28171
28367
  }
28172
- const { writeFileSync: writeFileSync2, openSync, closeSync } = await import("fs");
28173
- const fd = openSync(fifoPath, "w");
28174
- writeFileSync2(fd, config3.appendPrompt + "\r");
28175
- closeSync(fd);
28176
- console.log(`Sent prompt to ${fifoPath}`);
28177
28368
  process.exit(0);
28178
28369
  }
28179
28370
  if (!config3.cli) {
@@ -28190,5 +28381,5 @@ var { exitCode } = await cliYes(config3);
28190
28381
  console.log("exiting process");
28191
28382
  process.exit(exitCode ?? 1);
28192
28383
 
28193
- //# debugId=624A56792A6F741964756E2164756E21
28384
+ //# debugId=2520933E2CA2793364756E2164756E21
28194
28385
  //# sourceMappingURL=cli.js.map
package/dist/index.js CHANGED
@@ -20631,12 +20631,94 @@ import { fromReadable } from "from-node-stream";
20631
20631
  import { createReadStream as createReadStream2, mkdirSync } from "fs";
20632
20632
  import { unlink } from "fs/promises";
20633
20633
  import { dirname } from "path";
20634
+ import { createServer } from "net";
20634
20635
  function createFifoStream(cli, customPath) {
20635
- if (process.platform !== "linux") {
20636
+ if (process.platform === "win32") {
20637
+ return createWindowsNamedPipe(cli, customPath);
20638
+ } else if (process.platform === "linux") {
20639
+ return createLinuxFifo(cli, customPath);
20640
+ } else {
20641
+ logger.warn(`[${cli}-yes] IPC not supported on platform: ${process.platform}`);
20636
20642
  return null;
20637
20643
  }
20644
+ }
20645
+ function createWindowsNamedPipe(cli, customPath) {
20646
+ try {
20647
+ let pipePath;
20648
+ if (customPath) {
20649
+ pipePath = customPath;
20650
+ } else {
20651
+ const timestamp = new Date().toISOString().replace(/\D/g, "").slice(0, 17);
20652
+ const randomSuffix = Math.random().toString(36).substring(2, 5);
20653
+ pipePath = `\\\\.\\pipe\\agent-yes-${timestamp}${randomSuffix}`;
20654
+ }
20655
+ logger.info(`[${cli}-yes] Creating Windows named pipe at ${pipePath}`);
20656
+ const server = createServer();
20657
+ let connection = null;
20658
+ let isClosing = false;
20659
+ const stream = new ReadableStream({
20660
+ start(controller) {
20661
+ server.on("connection", (socket) => {
20662
+ connection = socket;
20663
+ logger.info(`[${cli}-yes] Client connected to named pipe`);
20664
+ socket.on("data", (chunk) => {
20665
+ const data = chunk.toString();
20666
+ logger.debug(`[${cli}-yes] Received data via named pipe: ${data}`);
20667
+ controller.enqueue(data);
20668
+ });
20669
+ socket.on("end", () => {
20670
+ logger.debug(`[${cli}-yes] Client disconnected from named pipe`);
20671
+ connection = null;
20672
+ });
20673
+ socket.on("error", (error) => {
20674
+ logger.warn(`[${cli}-yes] Named pipe socket error:`, error);
20675
+ if (!isClosing) {
20676
+ controller.error(error);
20677
+ }
20678
+ });
20679
+ });
20680
+ server.on("error", (error) => {
20681
+ logger.warn(`[${cli}-yes] Named pipe server error:`, error);
20682
+ if (!isClosing) {
20683
+ controller.error(error);
20684
+ }
20685
+ });
20686
+ server.listen(pipePath, () => {
20687
+ logger.info(`[${cli}-yes] Named pipe server listening at ${pipePath}`);
20688
+ });
20689
+ },
20690
+ cancel() {
20691
+ isClosing = true;
20692
+ if (connection) {
20693
+ connection.end();
20694
+ }
20695
+ server.close();
20696
+ }
20697
+ });
20698
+ const cleanup = async () => {
20699
+ isClosing = true;
20700
+ if (connection) {
20701
+ connection.end();
20702
+ }
20703
+ server.close();
20704
+ logger.info(`[${cli}-yes] Cleaned up Windows named pipe at ${pipePath}`);
20705
+ };
20706
+ process.on("exit", () => cleanup().catch(() => null));
20707
+ process.on("SIGINT", () => cleanup().catch(() => null));
20708
+ process.on("SIGTERM", () => cleanup().catch(() => null));
20709
+ return {
20710
+ stream,
20711
+ cleanup
20712
+ };
20713
+ } catch (error) {
20714
+ logger.warn(`[${cli}-yes] Failed to create Windows named pipe:`, error);
20715
+ return null;
20716
+ }
20717
+ }
20718
+ function createLinuxFifo(cli, customPath) {
20638
20719
  let fifoPath = null;
20639
20720
  let fifoStream = null;
20721
+ logger.debug(`[${cli}-yes] Creating Linux FIFO with customPath: ${customPath}`);
20640
20722
  try {
20641
20723
  if (customPath) {
20642
20724
  fifoPath = customPath;
@@ -20645,12 +20727,19 @@ function createFifoStream(cli, customPath) {
20645
20727
  const randomSuffix = Math.random().toString(36).substring(2, 5);
20646
20728
  fifoPath = `/tmp/agent-yes-${timestamp}${randomSuffix}.stdin`;
20647
20729
  }
20648
- mkdirSync(dirname(fifoPath), { recursive: true });
20649
- const mkfifoResult = execaCommandSync(`mkfifo ${fifoPath}`, {
20730
+ try {
20731
+ mkdirSync(dirname(fifoPath), { recursive: true });
20732
+ } catch (dirError) {
20733
+ logger.warn(`[${cli}-yes] Failed to create FIFO directory: ${dirError}`);
20734
+ return null;
20735
+ }
20736
+ const escapedPath = fifoPath.replace(/'/g, `'"'"'`);
20737
+ const mkfifoResult = execaCommandSync(`mkfifo '${escapedPath}'`, {
20650
20738
  reject: false
20651
20739
  });
20652
20740
  if (mkfifoResult.exitCode !== 0) {
20653
20741
  logger.warn(`[${cli}-yes] mkfifo command failed with exit code ${mkfifoResult.exitCode}`);
20742
+ logger.warn(`[${cli}-yes] Command: mkfifo '${escapedPath}'`);
20654
20743
  if (mkfifoResult.stderr) {
20655
20744
  logger.warn(`[${cli}-yes] mkfifo stderr: ${mkfifoResult.stderr}`);
20656
20745
  }
@@ -20730,7 +20819,7 @@ var init_fifo = __esm(() => {
20730
20819
  });
20731
20820
 
20732
20821
  // ts/pidStore.ts
20733
- import { mkdir as mkdir3 } from "fs/promises";
20822
+ import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
20734
20823
  import path9 from "path";
20735
20824
 
20736
20825
  class SqliteAdapter {
@@ -20774,15 +20863,16 @@ class SqliteAdapter {
20774
20863
 
20775
20864
  class PidStore {
20776
20865
  db;
20777
- baseDir;
20866
+ storeDir;
20778
20867
  dbPath;
20779
20868
  constructor(workingDir) {
20780
- this.baseDir = path9.resolve(workingDir, ".agent-yes");
20781
- this.dbPath = path9.join(this.baseDir, "pid.sqlite");
20869
+ this.storeDir = path9.resolve(workingDir, ".agent-yes");
20870
+ this.dbPath = path9.join(this.storeDir, "pid.sqlite");
20782
20871
  }
20783
20872
  async init() {
20784
- await mkdir3(path9.join(this.baseDir, "logs"), { recursive: true });
20785
- await mkdir3(path9.join(this.baseDir, "fifo"), { recursive: true });
20873
+ await mkdir3(path9.join(this.storeDir, "logs"), { recursive: true });
20874
+ await mkdir3(path9.join(this.storeDir, "fifo"), { recursive: true });
20875
+ await this.ensureGitignore();
20786
20876
  this.db = new SqliteAdapter;
20787
20877
  await this.db.init(this.dbPath);
20788
20878
  this.db.run("PRAGMA journal_mode=WAL");
@@ -20854,10 +20944,14 @@ class PidStore {
20854
20944
  logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
20855
20945
  }
20856
20946
  getLogPath(pid) {
20857
- return path9.resolve(this.baseDir, "logs", `${pid}.log`);
20947
+ return path9.resolve(this.storeDir, "logs", `${pid}.log`);
20858
20948
  }
20859
20949
  getFifoPath(pid) {
20860
- return path9.resolve(this.baseDir, "fifo", `${pid}.stdin`);
20950
+ if (process.platform === "win32") {
20951
+ return `\\\\.\\pipe\\agent-yes-${pid}`;
20952
+ } else {
20953
+ return path9.resolve(this.storeDir, "fifo", `${pid}.stdin`);
20954
+ }
20861
20955
  }
20862
20956
  async cleanStaleRecords() {
20863
20957
  const activeRecords = this.db.query("SELECT * FROM pid_records WHERE status != 'exited'");
@@ -20886,6 +20980,28 @@ class PidStore {
20886
20980
  return false;
20887
20981
  }
20888
20982
  }
20983
+ async ensureGitignore() {
20984
+ const gitignorePath = path9.join(this.storeDir, ".gitignore");
20985
+ const gitignoreContent = `# Auto-generated .gitignore for agent-yes
20986
+ # Ignore all log files and runtime data
20987
+ logs/
20988
+ fifo/
20989
+ *.sqlite
20990
+ *.sqlite-*
20991
+ *.log
20992
+ *.raw.log
20993
+ *.lines.log
20994
+ *.debug.log
20995
+ `;
20996
+ try {
20997
+ await writeFile3(gitignorePath, gitignoreContent, { flag: "wx" });
20998
+ logger.debug(`[pidStore] Created .gitignore in ${this.storeDir}`);
20999
+ } catch (error) {
21000
+ if (error.code !== "EEXIST") {
21001
+ logger.warn(`[pidStore] Failed to create .gitignore:`, error);
21002
+ }
21003
+ }
21004
+ }
20889
21005
  static async findActiveFifo(workingDir) {
20890
21006
  const store = new PidStore(workingDir);
20891
21007
  await store.init();
@@ -21024,8 +21140,11 @@ function getDefaultConfig() {
21024
21140
  fatal: []
21025
21141
  },
21026
21142
  amp: {
21027
- help: "",
21028
- install: "npm i -g @sourcegraph/amp",
21143
+ help: "https://ampcode.com/",
21144
+ install: {
21145
+ bash: "curl -fsSL https://ampcode.com/install.sh | bash",
21146
+ npm: "npm i -g @sourcegraph/amp"
21147
+ },
21029
21148
  enter: [
21030
21149
  /^.{0,4} Approve /
21031
21150
  ]
@@ -21195,7 +21314,7 @@ init_pidStore();
21195
21314
  await init_pty();
21196
21315
  var import_winston2 = __toESM(require_winston(), 1);
21197
21316
  import { fromReadable as fromReadable2, fromWritable } from "from-node-stream";
21198
- import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
21317
+ import { mkdir as mkdir5, readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
21199
21318
  import path11 from "path";
21200
21319
  var config = await init_agent_yes_config().then(() => exports_agent_yes_config).then((mod) => mod.default || mod);
21201
21320
  var CLIS_CONFIG = config.clis;
@@ -21544,15 +21663,15 @@ ${prompt}` : prefix;
21544
21663
  }).by((s) => {
21545
21664
  if (!useFifo)
21546
21665
  return s;
21547
- const fifoResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
21548
- if (!fifoResult)
21666
+ const ipcResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
21667
+ if (!ipcResult)
21549
21668
  return s;
21550
- pendingExitCode.promise.finally(() => fifoResult.cleanup());
21669
+ pendingExitCode.promise.finally(() => ipcResult.cleanup());
21551
21670
  process.stderr.write(`
21552
21671
  Append prompts: ${cli}-yes --append-prompt '...'
21553
21672
 
21554
21673
  `);
21555
- return s.merge(fifoResult.stream);
21674
+ return s.merge(ipcResult.stream);
21556
21675
  }).onStart(async function promptOnStart() {
21557
21676
  logger.debug("Sending prompt message: " + JSON.stringify(prompt));
21558
21677
  if (prompt)
@@ -21574,7 +21693,7 @@ ${prompt}` : prefix;
21574
21693
  return await mkdir5(path11.dirname(rawLogPath), { recursive: true }).then(() => {
21575
21694
  logger.debug(`[${cli}-yes] raw logs streaming to ${rawLogPath}`);
21576
21695
  return f.forEach(async (chars) => {
21577
- await writeFile3(rawLogPath, chars, { flag: "a" }).catch(() => null);
21696
+ await writeFile4(rawLogPath, chars, { flag: "a" }).catch(() => null);
21578
21697
  }).run();
21579
21698
  }).catch(() => f.run());
21580
21699
  }).by(function consoleResponder(e) {
@@ -21646,7 +21765,7 @@ ${prompt}` : prefix;
21646
21765
  })).to(fromWritable(process.stdout));
21647
21766
  if (logPath) {
21648
21767
  await mkdir5(path11.dirname(logPath), { recursive: true }).catch(() => null);
21649
- await writeFile3(logPath, terminalRender.render()).catch(() => null);
21768
+ await writeFile4(logPath, terminalRender.render()).catch(() => null);
21650
21769
  logger.info(`[${cli}-yes] Full logs saved to ${logPath}`);
21651
21770
  }
21652
21771
  const exitCode = await pendingExitCode.promise;
@@ -21658,7 +21777,7 @@ ${prompt}` : prefix;
21658
21777
  logger.info(`[${cli}-yes] Writing rendered logs to ${logFile}`);
21659
21778
  const logFilePath = path11.resolve(logFile);
21660
21779
  await mkdir5(path11.dirname(logFilePath), { recursive: true }).catch(() => null);
21661
- await writeFile3(logFilePath, terminalRender.render());
21780
+ await writeFile4(logFilePath, terminalRender.render());
21662
21781
  }
21663
21782
  return { exitCode, logs: terminalRender.render() };
21664
21783
  async function sendEnter(waitms = 1000) {
@@ -21677,6 +21796,15 @@ ${prompt}` : prefix;
21677
21796
  resolve();
21678
21797
  }, 1000))
21679
21798
  ]);
21799
+ await Promise.race([
21800
+ nextStdout.wait(),
21801
+ new Promise((resolve) => setTimeout(() => {
21802
+ if (!nextStdout.ready) {
21803
+ shell.write("\r");
21804
+ }
21805
+ resolve();
21806
+ }, 3000))
21807
+ ]);
21680
21808
  }
21681
21809
  async function sendMessage3(message, { waitForReady = true } = {}) {
21682
21810
  if (waitForReady)
@@ -21725,5 +21853,5 @@ export {
21725
21853
  CLIS_CONFIG
21726
21854
  };
21727
21855
 
21728
- //# debugId=41F67CAFCE0253CB64756E2164756E21
21856
+ //# debugId=581E1D2585250E0F64756E2164756E21
21729
21857
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-yes",
3
- "version": "1.35.1",
3
+ "version": "1.36.1",
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",
package/ts/cli.ts CHANGED
@@ -10,18 +10,48 @@ import { PidStore } from "./pidStore.ts";
10
10
  // Parse CLI arguments
11
11
  const config = parseCliArgs(process.argv);
12
12
 
13
- // Handle --append-prompt: write to active FIFO and exit
13
+ // Handle --append-prompt: write to active IPC (FIFO/Named Pipe) and exit
14
14
  if (config.appendPrompt) {
15
- const fifoPath = await PidStore.findActiveFifo(process.cwd());
16
- if (!fifoPath) {
17
- console.error("No active agent with FIFO found in current directory.");
15
+ const ipcPath = await PidStore.findActiveFifo(process.cwd());
16
+ if (!ipcPath) {
17
+ console.error("No active agent with IPC found in current directory.");
18
+ process.exit(1);
19
+ }
20
+
21
+ try {
22
+ if (process.platform === "win32") {
23
+ // Windows named pipe
24
+ const { connect } = await import("net");
25
+ await new Promise<void>((resolve, reject) => {
26
+ const client = connect(ipcPath);
27
+ client.on('connect', () => {
28
+ client.write(config.appendPrompt + "\r");
29
+ client.end();
30
+ console.log(`Sent prompt to Windows named pipe: ${ipcPath}`);
31
+ resolve();
32
+ });
33
+ client.on('error', (error) => {
34
+ console.error(`Failed to connect to named pipe: ${error}`);
35
+ reject(error);
36
+ });
37
+ // Timeout after 5 seconds
38
+ setTimeout(() => {
39
+ client.destroy();
40
+ reject(new Error('Connection timeout'));
41
+ }, 5000);
42
+ });
43
+ } else {
44
+ // Linux FIFO (original implementation)
45
+ const { writeFileSync, openSync, closeSync } = await import("fs");
46
+ const fd = openSync(ipcPath, "w");
47
+ writeFileSync(fd, config.appendPrompt + "\r");
48
+ closeSync(fd);
49
+ console.log(`Sent prompt to FIFO: ${ipcPath}`);
50
+ }
51
+ } catch (error) {
52
+ console.error(`Failed to send prompt: ${error}`);
18
53
  process.exit(1);
19
54
  }
20
- const { writeFileSync, openSync, closeSync } = await import("fs");
21
- const fd = openSync(fifoPath, "w");
22
- writeFileSync(fd, config.appendPrompt + "\r");
23
- closeSync(fd);
24
- console.log(`Sent prompt to ${fifoPath}`);
25
55
  process.exit(0);
26
56
  }
27
57
 
package/ts/index.ts CHANGED
@@ -580,14 +580,14 @@ export default async function agentYes({
580
580
  });
581
581
  })
582
582
 
583
- // read from FIFO if available, e.g. /tmp/agent-yes-*.stdin, which can be used to send additional input from other processes
583
+ // read from IPC stream if available (FIFO on Linux, Named Pipes on Windows)
584
584
  .by((s) => {
585
585
  if (!useFifo) return s;
586
- const fifoResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
587
- if (!fifoResult) return s;
588
- pendingExitCode.promise.finally(() => fifoResult.cleanup());
586
+ const ipcResult = createFifoStream(cli, pidStore.getFifoPath(shell.pid));
587
+ if (!ipcResult) return s;
588
+ pendingExitCode.promise.finally(() => ipcResult.cleanup());
589
589
  process.stderr.write(`\n Append prompts: ${cli}-yes --append-prompt '...'\n\n`);
590
- return s.merge(fifoResult.stream);
590
+ return s.merge(ipcResult.stream);
591
591
  })
592
592
 
593
593
  // .map((e) => e.replaceAll('\x1a', '')) // remove ctrl+z from user's input, to prevent bug (but this seems bug)
@@ -808,6 +808,19 @@ export default async function agentYes({
808
808
  }, 1000),
809
809
  ),
810
810
  ]);
811
+
812
+ // retry the second time if not received any output in 3 second after sending Enter
813
+ await Promise.race([
814
+ nextStdout.wait(),
815
+ new Promise<void>((resolve) =>
816
+ setTimeout(() => {
817
+ if (!nextStdout.ready) {
818
+ shell.write("\r");
819
+ }
820
+ resolve();
821
+ }, 3000),
822
+ ),
823
+ ]);
811
824
  }
812
825
 
813
826
  async function sendMessage(message: string, { waitForReady = true } = {}) {
@@ -27,6 +27,10 @@ export function parseCliArgs(argv: string[]) {
27
27
  "$0 claude --idle=30s -- solve all todos in my codebase, commit one by one",
28
28
  "Run Claude with a 30 seconds idle timeout, and the prompt is everything after `--`",
29
29
  )
30
+ .example(
31
+ "$0 claude --stdpush",
32
+ "Run Claude with external stdin input enabled via --append-prompt",
33
+ )
30
34
  // TODO: add a --docker option, will tell cli.ts to start docker process with tty and handles all stdio forwarding
31
35
 
32
36
  .option("robust", {
@@ -91,12 +95,13 @@ export function parseCliArgs(argv: string[]) {
91
95
  })
92
96
  .option("append-prompt", {
93
97
  type: "string",
94
- description: "Send a prompt to the active agent's FIFO stdin in current directory",
98
+ description: "Send a prompt to the active agent's stdin in current directory",
95
99
  })
96
- .option("fifo", {
100
+ .option("stdpush", {
97
101
  type: "boolean",
98
- description: "Enable FIFO input stream for additional stdin input (Linux only)",
102
+ description: "Enable external input stream to push additional data to stdin",
99
103
  default: false,
104
+ alias: ["ipc", "fifo"], // backward compatibility
100
105
  })
101
106
  .positional("cli", {
102
107
  describe: "The AI CLI to run, e.g., claude, codex, copilot, cursor, gemini",
@@ -191,6 +196,6 @@ export function parseCliArgs(argv: string[]) {
191
196
  resume: parsedArgv.continue, // Note: intentional use resume here to avoid preserved keyword (continue)
192
197
  useSkills: parsedArgv.useSkills,
193
198
  appendPrompt: parsedArgv.appendPrompt,
194
- useFifo: parsedArgv.fifo,
199
+ useFifo: parsedArgv.stdpush || parsedArgv.ipc || parsedArgv.fifo, // Support --stdpush, --ipc, and --fifo (backward compatibility)
195
200
  };
196
201
  }
package/ts/pidStore.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { mkdir } from "fs/promises";
1
+ import { mkdir, writeFile } from "fs/promises";
2
2
  import path from "path";
3
3
  import { logger } from "./logger.ts";
4
4
 
@@ -67,17 +67,20 @@ class SqliteAdapter {
67
67
 
68
68
  export class PidStore {
69
69
  protected db!: SqliteAdapter;
70
- private baseDir: string;
70
+ private storeDir: string;
71
71
  private dbPath: string;
72
72
 
73
73
  constructor(workingDir: string) {
74
- this.baseDir = path.resolve(workingDir, ".agent-yes");
75
- this.dbPath = path.join(this.baseDir, "pid.sqlite");
74
+ this.storeDir = path.resolve(workingDir, ".agent-yes");
75
+ this.dbPath = path.join(this.storeDir, "pid.sqlite");
76
76
  }
77
77
 
78
78
  async init(): Promise<void> {
79
- await mkdir(path.join(this.baseDir, "logs"), { recursive: true });
80
- await mkdir(path.join(this.baseDir, "fifo"), { recursive: true });
79
+ await mkdir(path.join(this.storeDir, "logs"), { recursive: true });
80
+ await mkdir(path.join(this.storeDir, "fifo"), { recursive: true });
81
+
82
+ // Auto-generate .gitignore for .agent-yes directory
83
+ await this.ensureGitignore();
81
84
 
82
85
  this.db = new SqliteAdapter();
83
86
  await this.db.init(this.dbPath);
@@ -182,11 +185,17 @@ export class PidStore {
182
185
  }
183
186
 
184
187
  getLogPath(pid: number): string {
185
- return path.resolve(this.baseDir, "logs", `${pid}.log`);
188
+ return path.resolve(this.storeDir, "logs", `${pid}.log`);
186
189
  }
187
190
 
188
191
  getFifoPath(pid: number): string {
189
- return path.resolve(this.baseDir, "fifo", `${pid}.stdin`);
192
+ if (process.platform === "win32") {
193
+ // Windows named pipe format
194
+ return `\\\\.\\pipe\\agent-yes-${pid}`;
195
+ } else {
196
+ // Linux FIFO file path
197
+ return path.resolve(this.storeDir, "fifo", `${pid}.stdin`);
198
+ }
190
199
  }
191
200
 
192
201
  async cleanStaleRecords(): Promise<void> {
@@ -226,6 +235,31 @@ export class PidStore {
226
235
  }
227
236
  }
228
237
 
238
+ private async ensureGitignore(): Promise<void> {
239
+ const gitignorePath = path.join(this.storeDir, ".gitignore");
240
+ const gitignoreContent = `# Auto-generated .gitignore for agent-yes
241
+ # Ignore all log files and runtime data
242
+ logs/
243
+ fifo/
244
+ *.sqlite
245
+ *.sqlite-*
246
+ *.log
247
+ *.raw.log
248
+ *.lines.log
249
+ *.debug.log
250
+ `;
251
+
252
+ try {
253
+ await writeFile(gitignorePath, gitignoreContent, { flag: 'wx' }); // wx = create only if doesn't exist
254
+ logger.debug(`[pidStore] Created .gitignore in ${this.storeDir}`);
255
+ } catch (error: any) {
256
+ if (error.code !== 'EEXIST') {
257
+ logger.warn(`[pidStore] Failed to create .gitignore:`, error);
258
+ }
259
+ // If file exists, that's fine - don't overwrite existing gitignore
260
+ }
261
+ }
262
+
229
263
  static async findActiveFifo(workingDir: string): Promise<string | null> {
230
264
  const store = new PidStore(workingDir);
231
265
  await store.init();