claude-yes 1.33.0 → 1.35.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/index.js CHANGED
@@ -20730,24 +20730,81 @@ var init_fifo = __esm(() => {
20730
20730
  });
20731
20731
 
20732
20732
  // ts/pidStore.ts
20733
- import Datastore from "@seald-io/nedb";
20734
20733
  import { mkdir as mkdir3 } from "fs/promises";
20735
20734
  import path9 from "path";
20736
20735
 
20736
+ class SqliteAdapter {
20737
+ db;
20738
+ async init(dbPath) {
20739
+ if (typeof globalThis.Bun !== "undefined") {
20740
+ try {
20741
+ const { Database } = await import("bun:sqlite");
20742
+ this.db = new Database(dbPath);
20743
+ } catch (error) {
20744
+ logger.warn("[pidStore] bun:sqlite not available, falling back to better-sqlite3");
20745
+ const Database = (await import("better-sqlite3")).default;
20746
+ this.db = new Database(dbPath);
20747
+ }
20748
+ } else {
20749
+ const Database = (await import("better-sqlite3")).default;
20750
+ this.db = new Database(dbPath);
20751
+ }
20752
+ }
20753
+ query(sql, params = []) {
20754
+ if (typeof this.db.prepare === "function") {
20755
+ return this.db.prepare(sql).all(params);
20756
+ } else {
20757
+ return this.db.query(sql).all(params);
20758
+ }
20759
+ }
20760
+ run(sql, params = []) {
20761
+ if (typeof this.db.prepare === "function") {
20762
+ return this.db.prepare(sql).run(params);
20763
+ } else {
20764
+ this.db.run(sql, params);
20765
+ return {};
20766
+ }
20767
+ }
20768
+ close() {
20769
+ if (this.db.close) {
20770
+ this.db.close();
20771
+ }
20772
+ }
20773
+ }
20774
+
20737
20775
  class PidStore {
20738
20776
  db;
20739
20777
  baseDir;
20778
+ dbPath;
20740
20779
  constructor(workingDir) {
20741
20780
  this.baseDir = path9.resolve(workingDir, ".agent-yes");
20781
+ this.dbPath = path9.join(this.baseDir, "pid.sqlite");
20742
20782
  }
20743
20783
  async init() {
20744
20784
  await mkdir3(path9.join(this.baseDir, "logs"), { recursive: true });
20745
20785
  await mkdir3(path9.join(this.baseDir, "fifo"), { recursive: true });
20746
- this.db = new Datastore({
20747
- filename: path9.join(this.baseDir, "pid.jsonl"),
20748
- autoload: true
20749
- });
20750
- await this.db.loadDatabaseAsync();
20786
+ this.db = new SqliteAdapter;
20787
+ await this.db.init(this.dbPath);
20788
+ this.db.run("PRAGMA journal_mode=WAL");
20789
+ this.db.run("PRAGMA synchronous=NORMAL");
20790
+ this.db.run("PRAGMA cache_size=1000");
20791
+ this.db.run("PRAGMA temp_store=memory");
20792
+ this.db.run(`
20793
+ CREATE TABLE IF NOT EXISTS pid_records (
20794
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
20795
+ pid INTEGER NOT NULL UNIQUE,
20796
+ cli TEXT NOT NULL,
20797
+ args TEXT NOT NULL,
20798
+ prompt TEXT,
20799
+ logFile TEXT NOT NULL,
20800
+ fifoFile TEXT NOT NULL,
20801
+ status TEXT NOT NULL DEFAULT 'active',
20802
+ exitReason TEXT NOT NULL DEFAULT '',
20803
+ exitCode INTEGER,
20804
+ startedAt INTEGER NOT NULL,
20805
+ updatedAt INTEGER NOT NULL
20806
+ )
20807
+ `);
20751
20808
  await this.cleanStaleRecords();
20752
20809
  }
20753
20810
  async registerProcess({
@@ -20757,29 +20814,43 @@ class PidStore {
20757
20814
  prompt
20758
20815
  }) {
20759
20816
  const now = Date.now();
20760
- const record = {
20761
- pid,
20762
- cli,
20763
- args,
20764
- prompt,
20765
- logFile: this.getLogPath(pid),
20766
- fifoFile: this.getFifoPath(pid),
20767
- status: "active",
20768
- exitReason: "",
20769
- startedAt: now,
20770
- updatedAt: now
20771
- };
20772
- await this.db.insertAsync(record);
20817
+ const argsJson = JSON.stringify(args);
20818
+ const logFile = this.getLogPath(pid);
20819
+ const fifoFile = this.getFifoPath(pid);
20820
+ try {
20821
+ this.db.run(`
20822
+ INSERT INTO pid_records (pid, cli, args, prompt, logFile, fifoFile, status, exitReason, startedAt, updatedAt)
20823
+ VALUES (?, ?, ?, ?, ?, ?, 'active', '', ?, ?)
20824
+ `, [pid, cli, argsJson, prompt, logFile, fifoFile, now, now]);
20825
+ } catch (error) {
20826
+ if (error.code === "SQLITE_CONSTRAINT_UNIQUE") {
20827
+ this.db.run(`
20828
+ UPDATE pid_records
20829
+ SET cli = ?, args = ?, prompt = ?, logFile = ?, fifoFile = ?, status = 'active', exitReason = '', startedAt = ?, updatedAt = ?
20830
+ WHERE pid = ?
20831
+ `, [cli, argsJson, prompt, logFile, fifoFile, now, now, pid]);
20832
+ } else {
20833
+ throw error;
20834
+ }
20835
+ }
20836
+ const result = this.db.query("SELECT * FROM pid_records WHERE pid = ?", [pid])[0];
20837
+ if (!result) {
20838
+ const allRecords = this.db.query("SELECT * FROM pid_records");
20839
+ logger.error(`[pidStore] Failed to find record for PID ${pid}. All records:`, allRecords);
20840
+ throw new Error(`Failed to register process ${pid}`);
20841
+ }
20773
20842
  logger.debug(`[pidStore] Registered process ${pid}`);
20774
- return record;
20843
+ return result;
20775
20844
  }
20776
20845
  async updateStatus(pid, status, extra) {
20777
- const update2 = {
20778
- status,
20779
- updatedAt: Date.now(),
20780
- ...extra
20781
- };
20782
- await this.db.updateAsync({ pid }, { $set: update2 }, {});
20846
+ const updatedAt = Date.now();
20847
+ const exitReason = extra?.exitReason || "";
20848
+ const exitCode = extra?.exitCode;
20849
+ if (exitCode !== undefined) {
20850
+ this.db.run("UPDATE pid_records SET status = ?, exitReason = ?, exitCode = ?, updatedAt = ? WHERE pid = ?", [status, exitReason, exitCode, updatedAt, pid]);
20851
+ } else {
20852
+ this.db.run("UPDATE pid_records SET status = ?, exitReason = ?, updatedAt = ? WHERE pid = ?", [status, exitReason, updatedAt, pid]);
20853
+ }
20783
20854
  logger.debug(`[pidStore] Updated process ${pid} status=${status}`);
20784
20855
  }
20785
20856
  getLogPath(pid) {
@@ -20789,25 +20860,23 @@ class PidStore {
20789
20860
  return path9.resolve(this.baseDir, "fifo", `${pid}.stdin`);
20790
20861
  }
20791
20862
  async cleanStaleRecords() {
20792
- const activeRecords = await this.db.findAsync({
20793
- status: { $ne: "exited" }
20794
- });
20863
+ const activeRecords = this.db.query("SELECT * FROM pid_records WHERE status != 'exited'");
20795
20864
  for (const record of activeRecords) {
20796
20865
  if (!this.isProcessAlive(record.pid)) {
20797
- await this.db.updateAsync({ pid: record.pid }, {
20798
- $set: {
20799
- status: "exited",
20800
- exitReason: "stale-cleanup",
20801
- updatedAt: Date.now()
20802
- }
20803
- }, {});
20866
+ this.db.run("UPDATE pid_records SET status = 'exited', exitReason = 'stale-cleanup', updatedAt = ? WHERE pid = ?", [Date.now(), record.pid]);
20804
20867
  logger.debug(`[pidStore] Cleaned stale record for PID ${record.pid}`);
20805
20868
  }
20806
20869
  }
20807
20870
  }
20808
20871
  async close() {
20809
- await this.db.compactDatafileAsync();
20810
- logger.debug("[pidStore] Database compacted and closed");
20872
+ try {
20873
+ this.db.run("PRAGMA optimize");
20874
+ this.db.run("VACUUM");
20875
+ } catch (error) {
20876
+ logger.warn("[pidStore] Failed to optimize database:", error);
20877
+ }
20878
+ this.db.close();
20879
+ logger.debug("[pidStore] Database optimized and closed");
20811
20880
  }
20812
20881
  isProcessAlive(pid) {
20813
20882
  try {
@@ -20820,10 +20889,9 @@ class PidStore {
20820
20889
  static async findActiveFifo(workingDir) {
20821
20890
  const store = new PidStore(workingDir);
20822
20891
  await store.init();
20823
- const records = await store.db.findAsync({ status: { $ne: "exited" } });
20892
+ const records = store.db.query("SELECT * FROM pid_records WHERE status != 'exited' ORDER BY startedAt DESC LIMIT 1");
20824
20893
  await store.close();
20825
- const sorted = records.sort((a2, b) => b.startedAt - a2.startedAt);
20826
- return sorted[0]?.fifoFile ?? null;
20894
+ return records[0]?.fifoFile ?? null;
20827
20895
  }
20828
20896
  }
20829
20897
  var init_pidStore = __esm(() => {
@@ -20879,8 +20947,12 @@ function getDefaultConfig() {
20879
20947
  },
20880
20948
  claude: {
20881
20949
  promptArg: "last-arg",
20882
- install: "npm install -g @anthropic-ai/claude-code@latest",
20883
- ready: [/\? for shortcuts/],
20950
+ install: {
20951
+ powershell: "irm https://claude.ai/install.ps1 | iex",
20952
+ bash: "curl -fsSL https://claude.ai/install.sh | bash",
20953
+ npm: "npm i -g @anthropic-ai/claude-code@latest"
20954
+ },
20955
+ ready: [/^\? for shortcuts/, /^> /],
20884
20956
  typingRespond: {
20885
20957
  "1\n": [/│ Do you want to use this API key\?/]
20886
20958
  },
@@ -21295,6 +21367,26 @@ ${prompt}` : prefix;
21295
21367
  logger.warn(`Unknown promptArg format: ${cliConf.promptArg}`);
21296
21368
  }
21297
21369
  }
21370
+ const getInstallCommand = (installConfig) => {
21371
+ if (typeof installConfig === "string") {
21372
+ return installConfig;
21373
+ }
21374
+ const isWindows = process.platform === "win32";
21375
+ const platform3 = isWindows ? "windows" : "unix";
21376
+ if (installConfig[platform3]) {
21377
+ return installConfig[platform3];
21378
+ }
21379
+ if (isWindows && installConfig.powershell) {
21380
+ return installConfig.powershell;
21381
+ }
21382
+ if (!isWindows && installConfig.bash) {
21383
+ return installConfig.bash;
21384
+ }
21385
+ if (installConfig.npm) {
21386
+ return installConfig.npm;
21387
+ }
21388
+ return null;
21389
+ };
21298
21390
  const spawn2 = () => {
21299
21391
  const cliCommand = cliConf?.binary || cli;
21300
21392
  let [bin, ...args] = [...parseCommandString(cliCommand), ...cliArgs];
@@ -21309,14 +21401,19 @@ ${prompt}` : prefix;
21309
21401
  logger.error(`Fatal: Failed to start ${cli}.`);
21310
21402
  const isNotFound = isCommandNotFoundError(error);
21311
21403
  if (cliConf?.install && isNotFound) {
21312
- logger.info(`Please install the cli by run ${cliConf.install}`);
21404
+ const installCmd = getInstallCommand(cliConf.install);
21405
+ if (!installCmd) {
21406
+ logger.error(`No suitable install command found for ${cli} on this platform`);
21407
+ throw error;
21408
+ }
21409
+ logger.info(`Please install the cli by run ${installCmd}`);
21313
21410
  if (install) {
21314
21411
  logger.info(`Attempting to install ${cli}...`);
21315
- execaCommandSync(cliConf.install, { stdio: "inherit" });
21412
+ execaCommandSync(installCmd, { stdio: "inherit" });
21316
21413
  logger.info(`${cli} installed successfully. Please rerun the command.`);
21317
21414
  return spawn2();
21318
21415
  } else {
21319
- logger.error(`If you did not installed it yet, Please install it first: ${cliConf.install}`);
21416
+ logger.error(`If you did not installed it yet, Please install it first: ${installCmd}`);
21320
21417
  throw error;
21321
21418
  }
21322
21419
  }
@@ -21351,7 +21448,10 @@ ${prompt}` : prefix;
21351
21448
  stdinReady.unready();
21352
21449
  const agentCrashed = exitCode2 !== 0;
21353
21450
  if (shouldRestartWithoutContinue) {
21354
- await pidStore.updateStatus(shell.pid, "exited", { exitReason: "restarted", exitCode: exitCode2 ?? undefined });
21451
+ await pidStore.updateStatus(shell.pid, "exited", {
21452
+ exitReason: "restarted",
21453
+ exitCode: exitCode2 ?? undefined
21454
+ });
21355
21455
  shouldRestartWithoutContinue = false;
21356
21456
  isFatal = false;
21357
21457
  const cliCommand = cliConf?.binary || cli;
@@ -21372,10 +21472,16 @@ ${prompt}` : prefix;
21372
21472
  return;
21373
21473
  }
21374
21474
  if (isFatal) {
21375
- await pidStore.updateStatus(shell.pid, "exited", { exitReason: "fatal", exitCode: exitCode2 ?? undefined });
21475
+ await pidStore.updateStatus(shell.pid, "exited", {
21476
+ exitReason: "fatal",
21477
+ exitCode: exitCode2 ?? undefined
21478
+ });
21376
21479
  return pendingExitCode.resolve(exitCode2);
21377
21480
  }
21378
- await pidStore.updateStatus(shell.pid, "exited", { exitReason: "restarted", exitCode: exitCode2 ?? undefined });
21481
+ await pidStore.updateStatus(shell.pid, "exited", {
21482
+ exitReason: "restarted",
21483
+ exitCode: exitCode2 ?? undefined
21484
+ });
21379
21485
  logger.info(`${cli} crashed, restarting...`);
21380
21486
  let restoreArgs = conf.restoreArgs;
21381
21487
  if (cli === "codex") {
@@ -21394,7 +21500,10 @@ ${prompt}` : prefix;
21394
21500
  return;
21395
21501
  }
21396
21502
  const exitReason = agentCrashed ? "crash" : "normal";
21397
- await pidStore.updateStatus(shell.pid, "exited", { exitReason, exitCode: exitCode2 ?? undefined });
21503
+ await pidStore.updateStatus(shell.pid, "exited", {
21504
+ exitReason,
21505
+ exitCode: exitCode2 ?? undefined
21506
+ });
21398
21507
  return pendingExitCode.resolve(exitCode2);
21399
21508
  });
21400
21509
  process.stdout.on("resize", () => {
@@ -21613,5 +21722,5 @@ export {
21613
21722
  CLIS_CONFIG
21614
21723
  };
21615
21724
 
21616
- //# debugId=E6394A1D786EEA6E64756E2164756E21
21725
+ //# debugId=9A92FE5B1254037264756E2164756E21
21617
21726
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-yes",
3
- "version": "1.33.0",
3
+ "version": "1.35.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",
@@ -29,10 +29,10 @@
29
29
  "url": "git+https://github.com/snomiao/agent-yes.git"
30
30
  },
31
31
  "bin": {
32
- "ay": "./dist/agent-yes.js",
33
32
  "agent-yes": "./dist/agent-yes.js",
34
33
  "amp-yes": "./dist/amp-yes.js",
35
34
  "auggie-yes": "./dist/auggie-yes.js",
35
+ "ay": "./dist/agent-yes.js",
36
36
  "claude-yes": "./dist/claude-yes.js",
37
37
  "codex-yes": "./dist/codex-yes.js",
38
38
  "copilot-yes": "./dist/copilot-yes.js",
@@ -45,10 +45,10 @@
45
45
  "doc": "docs"
46
46
  },
47
47
  "files": [
48
- "dist/**/*.js",
49
- "!dist/**/*.map",
50
48
  "scripts",
51
- "ts/*.ts"
49
+ "ts/*.ts",
50
+ "!dist/**/*.map",
51
+ "dist/**/*.js"
52
52
  ],
53
53
  "type": "module",
54
54
  "module": "ts/index.ts",
@@ -62,7 +62,7 @@
62
62
  "registry": "https://registry.npmjs.org/"
63
63
  },
64
64
  "scripts": {
65
- "build": "bun build ./ts/cli.ts ./ts/index.ts --outdir=dist --target=node --sourcemap --external=@seald-io/nedb --external=@snomiao/bun-pty --external=bun-pty --external=node-pty --external=from-node-stream --external=bun",
65
+ "build": "bun build ./ts/cli.ts ./ts/index.ts --outdir=dist --target=node --sourcemap --external=better-sqlite3 --external=@snomiao/bun-pty --external=bun-pty --external=node-pty --external=from-node-stream --external=bun",
66
66
  "postbuild": "bun ./ts/postbuild.ts",
67
67
  "demo": "bun run build && bun link && claude-yes -- demo",
68
68
  "dev": "bun ts/index.ts",
@@ -74,8 +74,8 @@
74
74
  "test": "bun test --coverage"
75
75
  },
76
76
  "dependencies": {
77
- "@seald-io/nedb": "^4.0.4",
78
77
  "@snomiao/bun-pty": "^0.3.4",
78
+ "better-sqlite3": "^12.1.0",
79
79
  "bun-pty": "^0.4.8",
80
80
  "from-node-stream": "^0.1.2"
81
81
  },
@@ -85,6 +85,7 @@
85
85
  "@semantic-release/exec": "^7.1.0",
86
86
  "@semantic-release/git": "^10.0.1",
87
87
  "@semantic-release/release-notes-generator": "^14.1.0",
88
+ "@types/better-sqlite3": "^7.6.12",
88
89
  "@types/bun": "^1.3.6",
89
90
  "@types/jest": "^30.0.0",
90
91
  "@types/ms": "^2.1.0",
package/ts/index.ts CHANGED
@@ -21,13 +21,14 @@ import { createFifoStream } from "./beta/fifo.ts";
21
21
  import { PidStore } from "./pidStore.ts";
22
22
  import { SUPPORTED_CLIS } from "./SUPPORTED_CLIS.ts";
23
23
  import winston from "winston";
24
- import { mapObject, pipe } from "rambda";
25
24
 
26
25
  export { removeControlCharacters };
27
26
 
28
27
  export type AgentCliConfig = {
29
28
  // cli
30
- install?: string; // hint user for install command if not installed
29
+ install?:
30
+ | string
31
+ | { powershell?: string; bash?: string; npm?: string; unix?: string; windows?: string }; // hint user for install command if not installed
31
32
  version?: string; // hint user for version command to check if installed
32
33
  binary?: string; // actual binary name if different from cli, e.g. cursor -> cursor-agent
33
34
  defaultArgs?: string[]; // function to ensure certain args are present
@@ -328,6 +329,41 @@ export default async function agentYes({
328
329
  }
329
330
  // Determine the actual cli command to run
330
331
 
332
+ // Helper function to get install command based on platform/availability
333
+ const getInstallCommand = (
334
+ installConfig:
335
+ | string
336
+ | { powershell?: string; bash?: string; npm?: string; unix?: string; windows?: string },
337
+ ): string | null => {
338
+ if (typeof installConfig === "string") {
339
+ return installConfig;
340
+ }
341
+
342
+ const isWindows = process.platform === "win32";
343
+ const platform = isWindows ? "windows" : "unix";
344
+
345
+ // Try platform-specific commands first
346
+ if (installConfig[platform]) {
347
+ return installConfig[platform];
348
+ }
349
+
350
+ // Try shell-specific commands
351
+ if (isWindows && installConfig.powershell) {
352
+ return installConfig.powershell;
353
+ }
354
+
355
+ if (!isWindows && installConfig.bash) {
356
+ return installConfig.bash;
357
+ }
358
+
359
+ // Fallback to npm if available
360
+ if (installConfig.npm) {
361
+ return installConfig.npm;
362
+ }
363
+
364
+ return null;
365
+ };
366
+
331
367
  const spawn = () => {
332
368
  const cliCommand = cliConf?.binary || cli;
333
369
  let [bin, ...args] = [...parseCommandString(cliCommand), ...cliArgs];
@@ -348,17 +384,21 @@ export default async function agentYes({
348
384
 
349
385
  const isNotFound = isCommandNotFoundError(error);
350
386
  if (cliConf?.install && isNotFound) {
351
- logger.info(`Please install the cli by run ${cliConf.install}`);
387
+ const installCmd = getInstallCommand(cliConf.install);
388
+ if (!installCmd) {
389
+ logger.error(`No suitable install command found for ${cli} on this platform`);
390
+ throw error;
391
+ }
392
+
393
+ logger.info(`Please install the cli by run ${installCmd}`);
352
394
 
353
395
  if (install) {
354
396
  logger.info(`Attempting to install ${cli}...`);
355
- execaCommandSync(cliConf.install, { stdio: "inherit" });
397
+ execaCommandSync(installCmd, { stdio: "inherit" });
356
398
  logger.info(`${cli} installed successfully. Please rerun the command.`);
357
399
  return spawn();
358
400
  } else {
359
- logger.error(
360
- `If you did not installed it yet, Please install it first: ${cliConf.install}`,
361
- );
401
+ logger.error(`If you did not installed it yet, Please install it first: ${installCmd}`);
362
402
  throw error;
363
403
  }
364
404
  }
@@ -415,7 +455,10 @@ export default async function agentYes({
415
455
  // Handle restart without continue args (e.g., "No conversation found to continue")
416
456
  // logger.debug(``, { shouldRestartWithoutContinue, robust })
417
457
  if (shouldRestartWithoutContinue) {
418
- await pidStore.updateStatus(shell.pid, "exited", { exitReason: "restarted", exitCode: exitCode ?? undefined });
458
+ await pidStore.updateStatus(shell.pid, "exited", {
459
+ exitReason: "restarted",
460
+ exitCode: exitCode ?? undefined,
461
+ });
419
462
  shouldRestartWithoutContinue = false; // reset flag
420
463
  isFatal = false; // reset fatal flag to allow restart
421
464
 
@@ -445,11 +488,17 @@ export default async function agentYes({
445
488
  return;
446
489
  }
447
490
  if (isFatal) {
448
- await pidStore.updateStatus(shell.pid, "exited", { exitReason: "fatal", exitCode: exitCode ?? undefined });
491
+ await pidStore.updateStatus(shell.pid, "exited", {
492
+ exitReason: "fatal",
493
+ exitCode: exitCode ?? undefined,
494
+ });
449
495
  return pendingExitCode.resolve(exitCode);
450
496
  }
451
497
 
452
- await pidStore.updateStatus(shell.pid, "exited", { exitReason: "restarted", exitCode: exitCode ?? undefined });
498
+ await pidStore.updateStatus(shell.pid, "exited", {
499
+ exitReason: "restarted",
500
+ exitCode: exitCode ?? undefined,
501
+ });
453
502
  logger.info(`${cli} crashed, restarting...`);
454
503
 
455
504
  // For codex, try to use stored session ID for this directory
@@ -472,7 +521,10 @@ export default async function agentYes({
472
521
  return;
473
522
  }
474
523
  const exitReason = agentCrashed ? "crash" : "normal";
475
- await pidStore.updateStatus(shell.pid, "exited", { exitReason, exitCode: exitCode ?? undefined });
524
+ await pidStore.updateStatus(shell.pid, "exited", {
525
+ exitReason,
526
+ exitCode: exitCode ?? undefined,
527
+ });
476
528
  return pendingExitCode.resolve(exitCode);
477
529
  });
478
530
 
package/ts/logger.ts CHANGED
@@ -19,4 +19,3 @@ export const logger = winston.createLogger({
19
19
  ],
20
20
  silent: false,
21
21
  });
22
-