agent-yes 1.55.0 → 1.56.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.
@@ -3,7 +3,8 @@ import { arch, platform } from "process";
3
3
  import { execSync } from "child_process";
4
4
  import { closeSync, existsSync, fsyncSync, mkdirSync, openSync } from "fs";
5
5
  import path, { dirname, join } from "path";
6
- import { constants } from "node:os";
6
+ import { readFile } from "node:fs/promises";
7
+ import os, { constants } from "node:os";
7
8
  import path$1 from "node:path";
8
9
  import { homedir } from "os";
9
10
  import { fileURLToPath } from "url";
@@ -21,7 +22,7 @@ import { finished } from "node:stream/promises";
21
22
  import { Duplex, PassThrough, Readable, Transform, Writable, getDefaultHighWaterMark } from "node:stream";
22
23
  import { Buffer as Buffer$1 } from "node:buffer";
23
24
  import { fromWritable } from "from-node-stream";
24
- import { appendFile, mkdir, readFile, readdir, rename, writeFile as writeFile$1 } from "fs/promises";
25
+ import { appendFile, mkdir as mkdir$1, readFile as readFile$1, readdir, rename, writeFile as writeFile$2 } from "fs/promises";
25
26
  import { lock } from "proper-lockfile";
26
27
 
27
28
  //#region node_modules/is-plain-obj/index.js
@@ -8937,7 +8938,7 @@ const getCodexSessionsDir = () => process.env.CLI_YES_TEST_HOME ? path.join(proc
8937
8938
  */
8938
8939
  async function loadSessionMap() {
8939
8940
  try {
8940
- const content = await readFile(getSessionsFile(), "utf-8");
8941
+ const content = await readFile$1(getSessionsFile(), "utf-8");
8941
8942
  return JSON.parse(content);
8942
8943
  } catch {
8943
8944
  return {};
@@ -8949,8 +8950,8 @@ async function loadSessionMap() {
8949
8950
  async function saveSessionMap(sessionMap) {
8950
8951
  try {
8951
8952
  const sessionsFile = getSessionsFile();
8952
- await mkdir(path.dirname(sessionsFile), { recursive: true });
8953
- await writeFile$1(sessionsFile, JSON.stringify(sessionMap, null, 2));
8953
+ await mkdir$1(path.dirname(sessionsFile), { recursive: true });
8954
+ await writeFile$2(sessionsFile, JSON.stringify(sessionMap, null, 2));
8954
8955
  } catch (error) {
8955
8956
  console.warn("Failed to save codex session map:", error);
8956
8957
  }
@@ -8971,7 +8972,7 @@ async function storeSessionForCwd(cwd, sessionId) {
8971
8972
  */
8972
8973
  async function parseCodexSessionFile(filePath) {
8973
8974
  try {
8974
- const lines = (await readFile(filePath, "utf-8")).trim().split("\n");
8975
+ const lines = (await readFile$1(filePath, "utf-8")).trim().split("\n");
8975
8976
  for (const line of lines) {
8976
8977
  if (!line.trim()) continue;
8977
8978
  const data = JSON.parse(line);
@@ -9145,9 +9146,9 @@ async function readLockFile() {
9145
9146
  try {
9146
9147
  const lockDir = getLockDir();
9147
9148
  const lockFilePath = getLockFile();
9148
- await mkdir(lockDir, { recursive: true });
9149
+ await mkdir$1(lockDir, { recursive: true });
9149
9150
  if (!existsSync(lockFilePath)) return { tasks: [] };
9150
- const content = await readFile(lockFilePath, "utf8");
9151
+ const content = await readFile$1(lockFilePath, "utf8");
9151
9152
  const lockFile = JSON.parse(content);
9152
9153
  lockFile.tasks = lockFile.tasks.filter((task) => {
9153
9154
  if (isProcessRunning(task.pid)) return true;
@@ -9165,9 +9166,9 @@ async function writeLockFile(lockFile, retryCount = 0) {
9165
9166
  try {
9166
9167
  const lockDir = getLockDir();
9167
9168
  const lockFilePath = getLockFile();
9168
- await mkdir(lockDir, { recursive: true });
9169
+ await mkdir$1(lockDir, { recursive: true });
9169
9170
  const tempFile = `${lockFilePath}.tmp.${process.pid}`;
9170
- await writeFile$1(tempFile, JSON.stringify(lockFile, null, 2), "utf8");
9171
+ await writeFile$2(tempFile, JSON.stringify(lockFile, null, 2), "utf8");
9171
9172
  await rename(tempFile, lockFilePath);
9172
9173
  } catch (error) {
9173
9174
  if (retryCount < MAX_RETRIES) {
@@ -9342,7 +9343,7 @@ var JsonlStore = class {
9342
9343
  * Handles crash recovery: partial last line skipped, temp file recovery.
9343
9344
  */
9344
9345
  async load() {
9345
- await mkdir(path.dirname(this.filePath), { recursive: true });
9346
+ await mkdir$1(path.dirname(this.filePath), { recursive: true });
9346
9347
  if (!existsSync(this.filePath) && existsSync(this.tempPath)) {
9347
9348
  logger.debug("[JsonlStore] Recovering from temp file");
9348
9349
  await rename(this.tempPath, this.filePath);
@@ -9350,7 +9351,7 @@ var JsonlStore = class {
9350
9351
  this.docs = /* @__PURE__ */ new Map();
9351
9352
  let raw = "";
9352
9353
  try {
9353
- raw = await readFile(this.filePath, "utf-8");
9354
+ raw = await readFile$1(this.filePath, "utf-8");
9354
9355
  } catch (err) {
9355
9356
  if (err.code === "ENOENT") return this.docs;
9356
9357
  throw err;
@@ -9462,7 +9463,7 @@ var JsonlStore = class {
9462
9463
  });
9463
9464
  }).join("\n");
9464
9465
  const content = lines ? lines + "\n" : "";
9465
- await writeFile$1(this.tempPath, content);
9466
+ await writeFile$2(this.tempPath, content);
9466
9467
  const fd = openSync(this.tempPath, "r");
9467
9468
  fsyncSync(fd);
9468
9469
  closeSync(fd);
@@ -9603,8 +9604,8 @@ pid-db/
9603
9604
 
9604
9605
  `;
9605
9606
  try {
9606
- await mkdir(this.storeDir, { recursive: true });
9607
- await writeFile$1(gitignorePath, gitignoreContent, { flag: "wx" });
9607
+ await mkdir$1(this.storeDir, { recursive: true });
9608
+ await writeFile$2(gitignorePath, gitignoreContent, { flag: "wx" });
9608
9609
  logger.debug(`[pidStore] Created .gitignore in ${this.storeDir}`);
9609
9610
  } catch (error) {
9610
9611
  if (error.code !== "EEXIST") logger.warn(`[pidStore] Failed to create .gitignore:`, error);
@@ -9727,7 +9728,7 @@ var import_winston = /* @__PURE__ */ __toESM(require_winston(), 1);
9727
9728
  */
9728
9729
  async function initializeLogPaths(pidStore, pid) {
9729
9730
  const logDir = pidStore.getLogDir();
9730
- await mkdir(logDir, { recursive: true });
9731
+ await mkdir$1(logDir, { recursive: true });
9731
9732
  return {
9732
9733
  logPath: logDir,
9733
9734
  rawLogPath: path.resolve(path.dirname(logDir), `${pid}.raw.log`),
@@ -9752,8 +9753,8 @@ function setupDebugLogging(debuggingLogsPath) {
9752
9753
  */
9753
9754
  async function saveLogFile(logPath, content) {
9754
9755
  if (!logPath) return;
9755
- await mkdir(path.dirname(logPath), { recursive: true }).catch(() => null);
9756
- await writeFile$1(logPath, content).catch(() => null);
9756
+ await mkdir$1(path.dirname(logPath), { recursive: true }).catch(() => null);
9757
+ await writeFile$2(logPath, content).catch(() => null);
9757
9758
  logger.info(`Full logs saved to ${logPath}`);
9758
9759
  }
9759
9760
  /**
@@ -9766,8 +9767,8 @@ async function saveDeprecatedLogFile(logFile, content, verbose) {
9766
9767
  if (!logFile) return;
9767
9768
  if (verbose) logger.info(`Writing rendered logs to ${logFile}`);
9768
9769
  const logFilePath = path.resolve(logFile);
9769
- await mkdir(path.dirname(logFilePath), { recursive: true }).catch(() => null);
9770
- await writeFile$1(logFilePath, content);
9770
+ await mkdir$1(path.dirname(logFilePath), { recursive: true }).catch(() => null);
9771
+ await writeFile$2(logFilePath, content);
9771
9772
  }
9772
9773
 
9773
9774
  //#endregion
@@ -10151,6 +10152,70 @@ var AgentRegistry = class {
10151
10152
  };
10152
10153
  const globalAgentRegistry = new AgentRegistry();
10153
10154
 
10155
+ //#endregion
10156
+ //#region ts/installEnv.ts
10157
+ const installDir = path$1.join(import.meta.dir, "..");
10158
+ function parseEnvContent(content) {
10159
+ const result = {};
10160
+ for (const line of content.split("\n")) {
10161
+ const trimmed = line.trim();
10162
+ if (!trimmed || trimmed.startsWith("#")) continue;
10163
+ const eqIndex = trimmed.indexOf("=");
10164
+ if (eqIndex < 0) continue;
10165
+ const key = trimmed.slice(0, eqIndex).trim();
10166
+ let value = trimmed.slice(eqIndex + 1).trim();
10167
+ if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
10168
+ result[key] = value;
10169
+ }
10170
+ return result;
10171
+ }
10172
+ let _installEnv = null;
10173
+ /**
10174
+ * Load .env from the agent-yes install directory (not the working dir).
10175
+ * Install dir is ${import.meta.dir}/.. relative to this file.
10176
+ * Cached after first load.
10177
+ */
10178
+ async function loadInstallEnv() {
10179
+ if (_installEnv) return _installEnv;
10180
+ const envPath = path$1.join(installDir, ".env");
10181
+ try {
10182
+ _installEnv = parseEnvContent(await readFile(envPath, "utf-8"));
10183
+ } catch {
10184
+ _installEnv = {};
10185
+ }
10186
+ return _installEnv;
10187
+ }
10188
+ /**
10189
+ * Get a value from the install .env, falling back to process.env.
10190
+ */
10191
+ async function getInstallEnv(key) {
10192
+ return (await loadInstallEnv())[key] ?? process.env[key];
10193
+ }
10194
+
10195
+ //#endregion
10196
+ //#region ts/webhookNotifier.ts
10197
+ /**
10198
+ * Notify the AGENT_YES_MESSAGE_WEBHOOK URL with a status message.
10199
+ *
10200
+ * AGENT_YES_MESSAGE_WEBHOOK should be set in the agent-yes install dir .env, e.g.:
10201
+ * AGENT_YES_MESSAGE_WEBHOOK=https://example.com/hook?q=%s
10202
+ *
10203
+ * The %s placeholder is replaced with the URL-encoded message:
10204
+ * [STATUS] hostname:cwd details
10205
+ */
10206
+ async function notifyWebhook(status, details, cwd = process.cwd()) {
10207
+ const webhookTemplate = await getInstallEnv("AGENT_YES_MESSAGE_WEBHOOK");
10208
+ if (!webhookTemplate) return;
10209
+ const message = `[${status}] ${os.hostname()}:${cwd}${details ? " " + details : ""}`;
10210
+ const url = webhookTemplate.replace("%s", encodeURIComponent(message));
10211
+ try {
10212
+ const res = await fetch(url);
10213
+ logger.debug(`[webhook] ${status} notified (${res.status}): ${url}`);
10214
+ } catch (error) {
10215
+ logger.warn(`[webhook] Failed to notify ${status}: ${error}`);
10216
+ }
10217
+ }
10218
+
10154
10219
  //#endregion
10155
10220
  //#region ts/index.ts
10156
10221
  const config = await import("./agent-yes.config-mJP0MKqV.js").then((mod) => mod.default || mod);
@@ -10231,7 +10296,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10231
10296
  let currentDir = workingDir;
10232
10297
  const searchLimit = gitRoot || path.parse(currentDir).root;
10233
10298
  while (true) {
10234
- const md = await readFile(path.resolve(currentDir, "SKILL.md"), "utf8").catch(() => null);
10299
+ const md = await readFile$1(path.resolve(currentDir, "SKILL.md"), "utf8").catch(() => null);
10235
10300
  if (md) {
10236
10301
  const headerMatch = md.match(/^[\s\S]*?(?=\n##\s)/);
10237
10302
  const headerRaw = (headerMatch ? headerMatch[0] : md).trim();
@@ -10314,6 +10379,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10314
10379
  } catch (error) {
10315
10380
  logger.warn(`[pidStore] Failed to register process ${shell.pid}:`, error);
10316
10381
  }
10382
+ notifyWebhook("RUNNING", prompt ?? "", workingDir).catch(() => null);
10317
10383
  const logPaths = await initializeLogPaths(pidStore, shell.pid);
10318
10384
  setupDebugLogging(logPaths.debuggingLogsPath);
10319
10385
  const ctx = new AgentContext({
@@ -10427,6 +10493,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10427
10493
  } catch (error) {
10428
10494
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
10429
10495
  }
10496
+ notifyWebhook("EXIT", `fatal exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
10430
10497
  return pendingExitCode.resolve(exitCode);
10431
10498
  }
10432
10499
  try {
@@ -10495,6 +10562,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10495
10562
  } catch (error) {
10496
10563
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
10497
10564
  }
10565
+ notifyWebhook("EXIT", `${exitReason} exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
10498
10566
  return pendingExitCode.resolve(exitCode);
10499
10567
  });
10500
10568
  process.stdout.on("resize", () => {
@@ -10563,6 +10631,7 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10563
10631
  return;
10564
10632
  }
10565
10633
  logger.info(`[${cli}-yes] ${cli} is idle, exiting...`);
10634
+ notifyWebhook("IDLE", "", workingDir).catch(() => null);
10566
10635
  await exitAgent();
10567
10636
  });
10568
10637
  const stdinStream = new ReadableStream({
@@ -10674,10 +10743,10 @@ async function agentYes({ cli, cliArgs = [], prompt, robust = true, cwd, env, ex
10674
10743
  }).forkTo(async function rawLogger(f) {
10675
10744
  const rawLogPath = ctx.logPaths.rawLogPath;
10676
10745
  if (!rawLogPath) return f.run();
10677
- return await mkdir(path.dirname(rawLogPath), { recursive: true }).then(() => {
10746
+ return await mkdir$1(path.dirname(rawLogPath), { recursive: true }).then(() => {
10678
10747
  logger.debug(`[${cli}-yes] raw logs streaming to ${rawLogPath}`);
10679
10748
  return f.forEach(async (chars) => {
10680
- await writeFile$1(rawLogPath, chars, { flag: "a" }).catch(() => null);
10749
+ await writeFile$2(rawLogPath, chars, { flag: "a" }).catch(() => null);
10681
10750
  }).run();
10682
10751
  }).catch(() => f.run());
10683
10752
  }).by(function consoleResponder(e) {
@@ -10770,4 +10839,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
10770
10839
 
10771
10840
  //#endregion
10772
10841
  export { AgentContext as a, config as i, CLIS_CONFIG as n, PidStore as o, agentYes as r, removeControlCharacters as s, SUPPORTED_CLIS as t };
10773
- //# sourceMappingURL=SUPPORTED_CLIS-Db5tikbx.js.map
10842
+ //# sourceMappingURL=SUPPORTED_CLIS-BqLSl2Mv.js.map
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  import { c as __toESM, i as __commonJSMin, r as require_ms, t as logger } from "./logger-DH1Rx9HI.js";
3
3
  import "./agent-yes.config-Dr2p5kBW.js";
4
- import { o as PidStore, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-Db5tikbx.js";
4
+ import { o as PidStore, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-BqLSl2Mv.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { argv } from "process";
7
7
  import { spawn } from "child_process";
@@ -4505,7 +4505,7 @@ const Yargs = YargsFactory(esm_default);
4505
4505
  //#endregion
4506
4506
  //#region package.json
4507
4507
  var name = "agent-yes";
4508
- var version = "1.55.0";
4508
+ var version = "1.56.0";
4509
4509
 
4510
4510
  //#endregion
4511
4511
  //#region ts/parseCliArgs.ts
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./logger-DH1Rx9HI.js";
2
- import { a as AgentContext, i as config, n as CLIS_CONFIG, r as agentYes, s as removeControlCharacters } from "./SUPPORTED_CLIS-Db5tikbx.js";
2
+ import { a as AgentContext, i as config, n as CLIS_CONFIG, r as agentYes, s as removeControlCharacters } from "./SUPPORTED_CLIS-BqLSl2Mv.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.55.0",
3
+ "version": "1.56.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",
package/ts/index.ts CHANGED
@@ -30,6 +30,7 @@ import { createAutoResponseHandler } from "./core/responders.ts";
30
30
  import { createTerminatorStream } from "./core/streamHelpers.ts";
31
31
  import { globalAgentRegistry } from "./agentRegistry.ts";
32
32
  import { ReadyManager } from "./ReadyManager.ts";
33
+ import { notifyWebhook } from "./webhookNotifier.ts";
33
34
 
34
35
  export { removeControlCharacters };
35
36
  export { AgentContext };
@@ -330,6 +331,7 @@ export default async function agentYes({
330
331
  } catch (error) {
331
332
  logger.warn(`[pidStore] Failed to register process ${shell.pid}:`, error);
332
333
  }
334
+ notifyWebhook("RUNNING", prompt ?? "", workingDir).catch(() => null);
333
335
 
334
336
  // Initialize log paths (independent of registration)
335
337
  const logPaths = await initializeLogPaths(pidStore, shell.pid);
@@ -483,6 +485,7 @@ export default async function agentYes({
483
485
  } catch (error) {
484
486
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
485
487
  }
488
+ notifyWebhook("EXIT", `fatal exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
486
489
  return pendingExitCode.resolve(exitCode);
487
490
  }
488
491
 
@@ -558,6 +561,7 @@ export default async function agentYes({
558
561
  } catch (error) {
559
562
  logger.warn(`[pidStore] Failed to update status for PID ${exitedPid}:`, error);
560
563
  }
564
+ notifyWebhook("EXIT", `${exitReason} exitCode=${exitCode ?? "?"}`, workingDir).catch(() => null);
561
565
  return pendingExitCode.resolve(exitCode);
562
566
  });
563
567
 
@@ -660,6 +664,7 @@ export default async function agentYes({
660
664
  }
661
665
 
662
666
  logger.info(`[${cli}-yes] ${cli} is idle, exiting...`);
667
+ notifyWebhook("IDLE", "", workingDir).catch(() => null);
663
668
  await exitAgent();
664
669
  });
665
670
 
@@ -0,0 +1,53 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ // Install dir is one level up from this file (ts/ -> package root)
5
+ const installDir = path.join(import.meta.dir, "..");
6
+
7
+ function parseEnvContent(content: string): Record<string, string> {
8
+ const result: Record<string, string> = {};
9
+ for (const line of content.split("\n")) {
10
+ const trimmed = line.trim();
11
+ if (!trimmed || trimmed.startsWith("#")) continue;
12
+ const eqIndex = trimmed.indexOf("=");
13
+ if (eqIndex < 0) continue;
14
+ const key = trimmed.slice(0, eqIndex).trim();
15
+ let value = trimmed.slice(eqIndex + 1).trim();
16
+ // Strip surrounding quotes
17
+ if (
18
+ (value.startsWith('"') && value.endsWith('"')) ||
19
+ (value.startsWith("'") && value.endsWith("'"))
20
+ ) {
21
+ value = value.slice(1, -1);
22
+ }
23
+ result[key] = value;
24
+ }
25
+ return result;
26
+ }
27
+
28
+ let _installEnv: Record<string, string> | null = null;
29
+
30
+ /**
31
+ * Load .env from the agent-yes install directory (not the working dir).
32
+ * Install dir is ${import.meta.dir}/.. relative to this file.
33
+ * Cached after first load.
34
+ */
35
+ export async function loadInstallEnv(): Promise<Record<string, string>> {
36
+ if (_installEnv) return _installEnv;
37
+ const envPath = path.join(installDir, ".env");
38
+ try {
39
+ const content = await readFile(envPath, "utf-8");
40
+ _installEnv = parseEnvContent(content);
41
+ } catch {
42
+ _installEnv = {};
43
+ }
44
+ return _installEnv;
45
+ }
46
+
47
+ /**
48
+ * Get a value from the install .env, falling back to process.env.
49
+ */
50
+ export async function getInstallEnv(key: string): Promise<string | undefined> {
51
+ const env = await loadInstallEnv();
52
+ return env[key] ?? process.env[key];
53
+ }
@@ -0,0 +1,34 @@
1
+ import os from "node:os";
2
+ import { getInstallEnv } from "./installEnv.ts";
3
+ import { logger } from "./logger.ts";
4
+
5
+ export type WebhookStatus = "RUNNING" | "IDLE" | "EXIT";
6
+
7
+ /**
8
+ * Notify the AGENT_YES_MESSAGE_WEBHOOK URL with a status message.
9
+ *
10
+ * AGENT_YES_MESSAGE_WEBHOOK should be set in the agent-yes install dir .env, e.g.:
11
+ * AGENT_YES_MESSAGE_WEBHOOK=https://example.com/hook?q=%s
12
+ *
13
+ * The %s placeholder is replaced with the URL-encoded message:
14
+ * [STATUS] hostname:cwd details
15
+ */
16
+ export async function notifyWebhook(
17
+ status: WebhookStatus,
18
+ details: string,
19
+ cwd = process.cwd(),
20
+ ): Promise<void> {
21
+ const webhookTemplate = await getInstallEnv("AGENT_YES_MESSAGE_WEBHOOK");
22
+ if (!webhookTemplate) return;
23
+
24
+ const hostname = os.hostname();
25
+ const message = `[${status}] ${hostname}:${cwd}${details ? " " + details : ""}`;
26
+ const url = webhookTemplate.replace("%s", encodeURIComponent(message));
27
+
28
+ try {
29
+ const res = await fetch(url);
30
+ logger.debug(`[webhook] ${status} notified (${res.status}): ${url}`);
31
+ } catch (error) {
32
+ logger.warn(`[webhook] Failed to notify ${status}: ${error}`);
33
+ }
34
+ }