agent-yes 1.70.1 → 1.72.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.
@@ -1,4 +1,5 @@
1
1
  import { t as logger } from "./logger-CX77vJDA.js";
2
+ import { i as shouldUseLock, r as releaseLock, t as acquireLock } from "./runningLock-BBI_URhR.js";
2
3
  import { arch, platform } from "process";
3
4
  import { execSync } from "child_process";
4
5
  import { execaCommandSync, parseCommandString } from "execa";
@@ -178,251 +179,6 @@ function removeControlCharacters(str) {
178
179
  return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
179
180
  }
180
181
 
181
- //#endregion
182
- //#region ts/runningLock.ts
183
- const getLockDir = () => path.join(process.env.CLAUDE_YES_HOME || homedir(), ".claude-yes");
184
- const getLockFile = () => path.join(getLockDir(), "running.lock.json");
185
- const MAX_RETRIES = 5;
186
- const RETRY_DELAYS = [
187
- 50,
188
- 100,
189
- 200,
190
- 400,
191
- 800
192
- ];
193
- const POLL_INTERVAL = 2e3;
194
- /**
195
- * Check if a process is running
196
- */
197
- function isProcessRunning(pid) {
198
- try {
199
- process.kill(pid, 0);
200
- return true;
201
- } catch {
202
- return false;
203
- }
204
- }
205
- /**
206
- * Get git repository root for a directory
207
- */
208
- function getGitRoot(cwd) {
209
- try {
210
- return execSync("git rev-parse --show-toplevel", {
211
- cwd,
212
- encoding: "utf8",
213
- stdio: [
214
- "pipe",
215
- "pipe",
216
- "ignore"
217
- ]
218
- }).trim();
219
- } catch {
220
- return null;
221
- }
222
- }
223
- /**
224
- * Check if directory is in a git repository
225
- */
226
- function isGitRepo(cwd) {
227
- try {
228
- return getGitRoot(cwd) !== null;
229
- } catch {
230
- return false;
231
- }
232
- }
233
- /**
234
- * Resolve path to real path (handling symlinks)
235
- */
236
- function resolveRealPath(p) {
237
- try {
238
- return path.resolve(p);
239
- } catch {
240
- return p;
241
- }
242
- }
243
- /**
244
- * Sleep for a given number of milliseconds
245
- */
246
- function sleep$1(ms) {
247
- return new Promise((resolve) => setTimeout(resolve, ms));
248
- }
249
- /**
250
- * Read lock file with retry logic and stale lock cleanup
251
- */
252
- async function readLockFile() {
253
- try {
254
- const lockDir = getLockDir();
255
- const lockFilePath = getLockFile();
256
- await mkdir(lockDir, { recursive: true });
257
- if (!existsSync(lockFilePath)) return { tasks: [] };
258
- const content = await readFile(lockFilePath, "utf8");
259
- const lockFile = JSON.parse(content);
260
- lockFile.tasks = lockFile.tasks.filter((task) => {
261
- if (isProcessRunning(task.pid)) return true;
262
- return false;
263
- });
264
- return lockFile;
265
- } catch {
266
- return { tasks: [] };
267
- }
268
- }
269
- /**
270
- * Write lock file atomically with retry logic
271
- */
272
- async function writeLockFile(lockFile, retryCount = 0) {
273
- try {
274
- const lockDir = getLockDir();
275
- const lockFilePath = getLockFile();
276
- await mkdir(lockDir, { recursive: true });
277
- const tempFile = `${lockFilePath}.tmp.${process.pid}`;
278
- await writeFile(tempFile, JSON.stringify(lockFile, null, 2), "utf8");
279
- await rename(tempFile, lockFilePath);
280
- } catch (error) {
281
- if (retryCount < MAX_RETRIES) {
282
- await sleep$1(RETRY_DELAYS[retryCount] || 800);
283
- return writeLockFile(lockFile, retryCount + 1);
284
- }
285
- throw error;
286
- }
287
- }
288
- /**
289
- * Check if lock exists for the current working directory
290
- */
291
- async function checkLock(cwd, _prompt) {
292
- const resolvedCwd = resolveRealPath(cwd);
293
- const gitRoot = isGitRepo(resolvedCwd) ? getGitRoot(resolvedCwd) : null;
294
- const lockKey = gitRoot || resolvedCwd;
295
- const blockingTasks = (await readLockFile()).tasks.filter((task) => {
296
- if (!isProcessRunning(task.pid)) return false;
297
- if (task.status !== "running") return false;
298
- if (gitRoot && task.gitRoot) return task.gitRoot === gitRoot;
299
- else return task.cwd === lockKey;
300
- });
301
- return {
302
- isLocked: blockingTasks.length > 0,
303
- blockingTasks,
304
- lockKey
305
- };
306
- }
307
- /**
308
- * Add a task to the lock file
309
- */
310
- async function addTask(task) {
311
- const lockFile = await readLockFile();
312
- lockFile.tasks = lockFile.tasks.filter((t) => t.pid !== task.pid);
313
- lockFile.tasks.push(task);
314
- await writeLockFile(lockFile);
315
- }
316
- /**
317
- * Update task status
318
- */
319
- async function updateTaskStatus(pid, status) {
320
- const lockFile = await readLockFile();
321
- const task = lockFile.tasks.find((t) => t.pid === pid);
322
- if (task) {
323
- task.status = status;
324
- await writeLockFile(lockFile);
325
- }
326
- }
327
- /**
328
- * Remove a task from the lock file
329
- */
330
- async function removeTask(pid) {
331
- const lockFile = await readLockFile();
332
- lockFile.tasks = lockFile.tasks.filter((t) => t.pid !== pid);
333
- await writeLockFile(lockFile);
334
- }
335
- /**
336
- * Wait for lock to be released
337
- */
338
- async function waitForUnlock(blockingTasks, currentTask) {
339
- const blockingTask = blockingTasks[0];
340
- if (!blockingTask) return;
341
- console.log(`⏳ Queueing for unlock of: ${blockingTask.task}`);
342
- console.log(` Press 'b' to bypass queue, 'k' to kill previous instance`);
343
- await addTask({
344
- ...currentTask,
345
- status: "queued"
346
- });
347
- const stdin = process.stdin;
348
- const wasRaw = stdin.isRaw;
349
- stdin.setRawMode?.(true);
350
- stdin.resume();
351
- let bypassed = false;
352
- let killed = false;
353
- const keyHandler = (key) => {
354
- const char = key.toString();
355
- if (char === "b" || char === "B") {
356
- console.log("\n⚡ Bypassing queue...");
357
- bypassed = true;
358
- } else if (char === "k" || char === "K") {
359
- console.log("\n🔪 Killing previous instance...");
360
- killed = true;
361
- }
362
- };
363
- stdin.on("data", keyHandler);
364
- let dots = 0;
365
- while (true) {
366
- if (bypassed) {
367
- await updateTaskStatus(currentTask.pid, "running");
368
- console.log("✓ Queue bypassed, starting task...");
369
- break;
370
- }
371
- if (killed && blockingTask) {
372
- try {
373
- process.kill(blockingTask.pid, "SIGTERM");
374
- console.log(`✓ Killed process ${blockingTask.pid}`);
375
- await sleep$1(1e3);
376
- } catch (err) {
377
- console.log(`⚠️ Could not kill process ${blockingTask.pid}: ${err}`);
378
- }
379
- killed = false;
380
- }
381
- await sleep$1(POLL_INTERVAL);
382
- if (!(await checkLock(currentTask.cwd, currentTask.task)).isLocked) {
383
- await updateTaskStatus(currentTask.pid, "running");
384
- console.log(`\n✓ Lock released, starting task...`);
385
- break;
386
- }
387
- dots = (dots + 1) % 4;
388
- process.stdout.write(`\r⏳ Queueing${".".repeat(dots)}${" ".repeat(3 - dots)}`);
389
- }
390
- stdin.off("data", keyHandler);
391
- stdin.setRawMode?.(wasRaw);
392
- if (!wasRaw) stdin.pause();
393
- }
394
- /**
395
- * Acquire lock or wait if locked
396
- */
397
- async function acquireLock(cwd, prompt = "no prompt provided") {
398
- const resolvedCwd = resolveRealPath(cwd);
399
- const task = {
400
- cwd: resolvedCwd,
401
- gitRoot: (isGitRepo(resolvedCwd) ? getGitRoot(resolvedCwd) : null) || void 0,
402
- task: prompt.substring(0, 100),
403
- pid: process.pid,
404
- status: "running",
405
- startedAt: Date.now(),
406
- lockedAt: Date.now()
407
- };
408
- const lockCheck = await checkLock(resolvedCwd, prompt);
409
- if (lockCheck.isLocked) await waitForUnlock(lockCheck.blockingTasks, task);
410
- else await addTask(task);
411
- }
412
- /**
413
- * Release lock for current process
414
- */
415
- async function releaseLock(pid = process.pid) {
416
- await removeTask(pid);
417
- }
418
- /**
419
- * Check if we should use locking for this directory
420
- * Only use locking if we're in a git repository
421
- */
422
- function shouldUseLock(_cwd) {
423
- return true;
424
- }
425
-
426
182
  //#endregion
427
183
  //#region ts/beta/fifo.ts
428
184
  /**
@@ -1059,7 +815,7 @@ function tryCatch(catchFn, fn) {
1059
815
  //#endregion
1060
816
  //#region package.json
1061
817
  var name = "agent-yes";
1062
- var version = "1.70.1";
818
+ var version = "1.72.0";
1063
819
 
1064
820
  //#endregion
1065
821
  //#region ts/pty-fix.ts
@@ -1486,7 +1242,7 @@ async function notifyWebhook(status, details, cwd = process.cwd()) {
1486
1242
 
1487
1243
  //#endregion
1488
1244
  //#region ts/index.ts
1489
- const config = await import("./agent-yes.config-DcxG25Gv.js").then((mod) => mod.default || mod);
1245
+ const config = await import("./agent-yes.config-CtQprJrA.js").then((mod) => mod.default || mod);
1490
1246
  const CLIS_CONFIG = config.clis;
1491
1247
  /**
1492
1248
  * Main function to run agent-cli with automatic yes/no responses
@@ -2139,4 +1895,4 @@ const SUPPORTED_CLIS = Object.keys(CLIS_CONFIG);
2139
1895
 
2140
1896
  //#endregion
2141
1897
  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 };
2142
- //# sourceMappingURL=SUPPORTED_CLIS-Bq5hoKRN.js.map
1898
+ //# sourceMappingURL=SUPPORTED_CLIS-jR_I2op4.js.map
@@ -332,4 +332,4 @@ function getDefaultConfig() {
332
332
 
333
333
  //#endregion
334
334
  export { agent_yes_config_default as default };
335
- //# sourceMappingURL=agent-yes.config-DcxG25Gv.js.map
335
+ //# sourceMappingURL=agent-yes.config-CtQprJrA.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-Bq5hoKRN.js";
2
+ import { c as PidStore, o as name, s as version, t as SUPPORTED_CLIS } from "./SUPPORTED_CLIS-jR_I2op4.js";
3
3
  import { t as logger } from "./logger-CX77vJDA.js";
4
4
  import { argv } from "process";
5
5
  import { spawn } from "child_process";
@@ -91,6 +91,10 @@ function parseCliArgs(argv) {
91
91
  description: "Pass --dangerously-skip-permissions to the CLI (claude shortcut)",
92
92
  default: false,
93
93
  alias: "y"
94
+ }).option("tray", {
95
+ type: "boolean",
96
+ description: "Show a system tray icon with running agent count (macOS/Windows only)",
97
+ default: false
94
98
  }).option("rust", {
95
99
  type: "boolean",
96
100
  description: "Use the Rust implementation (enabled by default, use --no-rust for TypeScript)",
@@ -193,6 +197,7 @@ function parseCliArgs(argv) {
193
197
  showVersion: parsedArgv.version,
194
198
  autoYes: parsedArgv.auto !== "no",
195
199
  idleAction: parsedArgv.idleAction,
200
+ tray: parsedArgv.tray,
196
201
  useRust: parsedArgv.rust,
197
202
  swarm: parsedArgv.swarm ?? (parsedArgv.experimentalSwarm ? parsedArgv.swarmTopic : void 0),
198
203
  experimentalSwarm: parsedArgv.experimentalSwarm,
@@ -475,6 +480,11 @@ function buildRustArgs(argv, cliFromScript, supportedClis) {
475
480
  //#region ts/cli.ts
476
481
  const updateCheckPromise = checkAndAutoUpdate();
477
482
  const config = parseCliArgs(process.argv);
483
+ if (config.tray) {
484
+ const { startTray } = await import("./tray-Dyiihcrq.js");
485
+ await startTray();
486
+ await new Promise(() => {});
487
+ }
478
488
  if (config.useRust) {
479
489
  let rustBinary;
480
490
  try {
@@ -562,6 +572,10 @@ if (config.verbose) {
562
572
  console.log(config);
563
573
  console.log(argv);
564
574
  }
575
+ {
576
+ const { ensureTray } = await import("./tray-Dyiihcrq.js");
577
+ ensureTray();
578
+ }
565
579
  const { default: cliYes } = await import("./index.js");
566
580
  const { exitCode } = await cliYes({
567
581
  ...config,
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-Bq5hoKRN.js";
1
+ import { a as AgentContext, i as config, l as removeControlCharacters, n as CLIS_CONFIG, r as agentYes } from "./SUPPORTED_CLIS-jR_I2op4.js";
2
2
  import "./logger-CX77vJDA.js";
3
3
 
4
4
  export { AgentContext, CLIS_CONFIG, config, agentYes as default, removeControlCharacters };
@@ -0,0 +1,263 @@
1
+ import { execSync } from "child_process";
2
+ import { mkdir, readFile, rename, writeFile } from "fs/promises";
3
+ import path from "path";
4
+ import { homedir } from "os";
5
+ import { existsSync } from "fs";
6
+
7
+ //#region ts/runningLock.ts
8
+ const getLockDir = () => path.join(process.env.CLAUDE_YES_HOME || homedir(), ".claude-yes");
9
+ const getLockFile = () => path.join(getLockDir(), "running.lock.json");
10
+ const MAX_RETRIES = 5;
11
+ const RETRY_DELAYS = [
12
+ 50,
13
+ 100,
14
+ 200,
15
+ 400,
16
+ 800
17
+ ];
18
+ const POLL_INTERVAL = 2e3;
19
+ /**
20
+ * Check if a process is running
21
+ */
22
+ function isProcessRunning(pid) {
23
+ try {
24
+ process.kill(pid, 0);
25
+ return true;
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Get git repository root for a directory
32
+ */
33
+ function getGitRoot(cwd) {
34
+ try {
35
+ return execSync("git rev-parse --show-toplevel", {
36
+ cwd,
37
+ encoding: "utf8",
38
+ stdio: [
39
+ "pipe",
40
+ "pipe",
41
+ "ignore"
42
+ ]
43
+ }).trim();
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ /**
49
+ * Check if directory is in a git repository
50
+ */
51
+ function isGitRepo(cwd) {
52
+ try {
53
+ return getGitRoot(cwd) !== null;
54
+ } catch {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ * Resolve path to real path (handling symlinks)
60
+ */
61
+ function resolveRealPath(p) {
62
+ try {
63
+ return path.resolve(p);
64
+ } catch {
65
+ return p;
66
+ }
67
+ }
68
+ /**
69
+ * Sleep for a given number of milliseconds
70
+ */
71
+ function sleep(ms) {
72
+ return new Promise((resolve) => setTimeout(resolve, ms));
73
+ }
74
+ /**
75
+ * Read lock file with retry logic and stale lock cleanup
76
+ */
77
+ async function readLockFile() {
78
+ try {
79
+ const lockDir = getLockDir();
80
+ const lockFilePath = getLockFile();
81
+ await mkdir(lockDir, { recursive: true });
82
+ if (!existsSync(lockFilePath)) return { tasks: [] };
83
+ const content = await readFile(lockFilePath, "utf8");
84
+ const lockFile = JSON.parse(content);
85
+ lockFile.tasks = lockFile.tasks.filter((task) => {
86
+ if (isProcessRunning(task.pid)) return true;
87
+ return false;
88
+ });
89
+ return lockFile;
90
+ } catch {
91
+ return { tasks: [] };
92
+ }
93
+ }
94
+ /**
95
+ * Write lock file atomically with retry logic
96
+ */
97
+ async function writeLockFile(lockFile, retryCount = 0) {
98
+ try {
99
+ const lockDir = getLockDir();
100
+ const lockFilePath = getLockFile();
101
+ await mkdir(lockDir, { recursive: true });
102
+ const tempFile = `${lockFilePath}.tmp.${process.pid}`;
103
+ await writeFile(tempFile, JSON.stringify(lockFile, null, 2), "utf8");
104
+ await rename(tempFile, lockFilePath);
105
+ } catch (error) {
106
+ if (retryCount < MAX_RETRIES) {
107
+ await sleep(RETRY_DELAYS[retryCount] || 800);
108
+ return writeLockFile(lockFile, retryCount + 1);
109
+ }
110
+ throw error;
111
+ }
112
+ }
113
+ /**
114
+ * Check if lock exists for the current working directory
115
+ */
116
+ async function checkLock(cwd, _prompt) {
117
+ const resolvedCwd = resolveRealPath(cwd);
118
+ const gitRoot = isGitRepo(resolvedCwd) ? getGitRoot(resolvedCwd) : null;
119
+ const lockKey = gitRoot || resolvedCwd;
120
+ const blockingTasks = (await readLockFile()).tasks.filter((task) => {
121
+ if (!isProcessRunning(task.pid)) return false;
122
+ if (task.status !== "running") return false;
123
+ if (gitRoot && task.gitRoot) return task.gitRoot === gitRoot;
124
+ else return task.cwd === lockKey;
125
+ });
126
+ return {
127
+ isLocked: blockingTasks.length > 0,
128
+ blockingTasks,
129
+ lockKey
130
+ };
131
+ }
132
+ /**
133
+ * Add a task to the lock file
134
+ */
135
+ async function addTask(task) {
136
+ const lockFile = await readLockFile();
137
+ lockFile.tasks = lockFile.tasks.filter((t) => t.pid !== task.pid);
138
+ lockFile.tasks.push(task);
139
+ await writeLockFile(lockFile);
140
+ }
141
+ /**
142
+ * Update task status
143
+ */
144
+ async function updateTaskStatus(pid, status) {
145
+ const lockFile = await readLockFile();
146
+ const task = lockFile.tasks.find((t) => t.pid === pid);
147
+ if (task) {
148
+ task.status = status;
149
+ await writeLockFile(lockFile);
150
+ }
151
+ }
152
+ /**
153
+ * Remove a task from the lock file
154
+ */
155
+ async function removeTask(pid) {
156
+ const lockFile = await readLockFile();
157
+ lockFile.tasks = lockFile.tasks.filter((t) => t.pid !== pid);
158
+ await writeLockFile(lockFile);
159
+ }
160
+ /**
161
+ * Wait for lock to be released
162
+ */
163
+ async function waitForUnlock(blockingTasks, currentTask) {
164
+ const blockingTask = blockingTasks[0];
165
+ if (!blockingTask) return;
166
+ console.log(`⏳ Queueing for unlock of: ${blockingTask.task}`);
167
+ console.log(` Press 'b' to bypass queue, 'k' to kill previous instance`);
168
+ await addTask({
169
+ ...currentTask,
170
+ status: "queued"
171
+ });
172
+ const stdin = process.stdin;
173
+ const wasRaw = stdin.isRaw;
174
+ stdin.setRawMode?.(true);
175
+ stdin.resume();
176
+ let bypassed = false;
177
+ let killed = false;
178
+ const keyHandler = (key) => {
179
+ const char = key.toString();
180
+ if (char === "b" || char === "B") {
181
+ console.log("\n⚡ Bypassing queue...");
182
+ bypassed = true;
183
+ } else if (char === "k" || char === "K") {
184
+ console.log("\n🔪 Killing previous instance...");
185
+ killed = true;
186
+ }
187
+ };
188
+ stdin.on("data", keyHandler);
189
+ let dots = 0;
190
+ while (true) {
191
+ if (bypassed) {
192
+ await updateTaskStatus(currentTask.pid, "running");
193
+ console.log("✓ Queue bypassed, starting task...");
194
+ break;
195
+ }
196
+ if (killed && blockingTask) {
197
+ try {
198
+ process.kill(blockingTask.pid, "SIGTERM");
199
+ console.log(`✓ Killed process ${blockingTask.pid}`);
200
+ await sleep(1e3);
201
+ } catch (err) {
202
+ console.log(`⚠️ Could not kill process ${blockingTask.pid}: ${err}`);
203
+ }
204
+ killed = false;
205
+ }
206
+ await sleep(POLL_INTERVAL);
207
+ if (!(await checkLock(currentTask.cwd, currentTask.task)).isLocked) {
208
+ await updateTaskStatus(currentTask.pid, "running");
209
+ console.log(`\n✓ Lock released, starting task...`);
210
+ break;
211
+ }
212
+ dots = (dots + 1) % 4;
213
+ process.stdout.write(`\r⏳ Queueing${".".repeat(dots)}${" ".repeat(3 - dots)}`);
214
+ }
215
+ stdin.off("data", keyHandler);
216
+ stdin.setRawMode?.(wasRaw);
217
+ if (!wasRaw) stdin.pause();
218
+ }
219
+ /**
220
+ * Get the count of currently running agents
221
+ */
222
+ async function getRunningAgentCount() {
223
+ const running = (await readLockFile()).tasks.filter((t) => t.status === "running");
224
+ return {
225
+ count: running.length,
226
+ tasks: running
227
+ };
228
+ }
229
+ /**
230
+ * Acquire lock or wait if locked
231
+ */
232
+ async function acquireLock(cwd, prompt = "no prompt provided") {
233
+ const resolvedCwd = resolveRealPath(cwd);
234
+ const task = {
235
+ cwd: resolvedCwd,
236
+ gitRoot: (isGitRepo(resolvedCwd) ? getGitRoot(resolvedCwd) : null) || void 0,
237
+ task: prompt.substring(0, 100),
238
+ pid: process.pid,
239
+ status: "running",
240
+ startedAt: Date.now(),
241
+ lockedAt: Date.now()
242
+ };
243
+ const lockCheck = await checkLock(resolvedCwd, prompt);
244
+ if (lockCheck.isLocked) await waitForUnlock(lockCheck.blockingTasks, task);
245
+ else await addTask(task);
246
+ }
247
+ /**
248
+ * Release lock for current process
249
+ */
250
+ async function releaseLock(pid = process.pid) {
251
+ await removeTask(pid);
252
+ }
253
+ /**
254
+ * Check if we should use locking for this directory
255
+ * Only use locking if we're in a git repository
256
+ */
257
+ function shouldUseLock(_cwd) {
258
+ return true;
259
+ }
260
+
261
+ //#endregion
262
+ export { shouldUseLock as i, getRunningAgentCount as n, releaseLock as r, acquireLock as t };
263
+ //# sourceMappingURL=runningLock-BBI_URhR.js.map