claude-yes 1.22.0 → 1.23.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/claude-yes.js +24 -12
- package/dist/cli.js +24 -12
- package/dist/cli.js.map +3 -3
- package/dist/codex-yes.js +24 -12
- package/dist/copilot-yes.js +24 -12
- package/dist/cursor-yes.js +24 -12
- package/dist/gemini-yes.js +24 -12
- package/dist/grok-yes.js +24 -12
- package/dist/index.js +24 -12
- package/dist/index.js.map +3 -3
- package/index.ts +32 -41
- package/package.json +3 -2
package/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { fromReadable, fromWritable } from 'from-node-stream';
|
|
2
|
-
import { appendFile, mkdir, writeFile } from 'fs/promises';
|
|
2
|
+
import { appendFile, mkdir, rm, writeFile } from 'fs/promises';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import DIE from 'phpdie';
|
|
5
5
|
import sflow from 'sflow';
|
|
6
6
|
import { TerminalTextRender } from 'terminal-render';
|
|
7
|
+
import tsaComposer from 'tsa-composer';
|
|
7
8
|
import { IdleWaiter } from './idleWaiter';
|
|
8
9
|
import { ReadyManager } from './ReadyManager';
|
|
9
10
|
import { removeControlCharacters } from './removeControlCharacters';
|
|
@@ -26,7 +27,8 @@ export const CLI_CONFIGURES: Record<
|
|
|
26
27
|
},
|
|
27
28
|
claude: {
|
|
28
29
|
install: 'npm install -g @anthropic-ai/claude-code',
|
|
29
|
-
ready: [/^> /], // regex matcher for stdin ready
|
|
30
|
+
// ready: [/^> /], // regex matcher for stdin ready
|
|
31
|
+
ready: [/\? for shortcuts/], // regex matcher for stdin ready
|
|
30
32
|
enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],
|
|
31
33
|
fatal: [
|
|
32
34
|
/No conversation found to continue/,
|
|
@@ -44,8 +46,8 @@ export const CLI_CONFIGURES: Record<
|
|
|
44
46
|
install: 'npm install -g @openai/codex-cli',
|
|
45
47
|
ready: [/⏎ send/],
|
|
46
48
|
enter: [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
/> 1. Yes, allow Codex to work in this folder/,
|
|
50
|
+
/▌ > 1. Approve and run now/,
|
|
49
51
|
],
|
|
50
52
|
fatal: [/Error: The cursor position could not be read within/],
|
|
51
53
|
// add to codex --search by default when not provided by the user
|
|
@@ -70,15 +72,15 @@ export const CLI_CONFIGURES: Record<
|
|
|
70
72
|
},
|
|
71
73
|
};
|
|
72
74
|
/**
|
|
73
|
-
* Main function to run
|
|
75
|
+
* Main function to run agent-cli with automatic yes/no responses
|
|
74
76
|
* @param options Configuration options
|
|
75
|
-
* @param options.continueOnCrash - If true, automatically restart
|
|
76
|
-
* 1. Shows message '
|
|
77
|
-
* 2. Spawns a new '
|
|
77
|
+
* @param options.continueOnCrash - If true, automatically restart agent-cli when it crashes:
|
|
78
|
+
* 1. Shows message 'agent-cli crashed, restarting..'
|
|
79
|
+
* 2. Spawns a new 'agent-cli --continue' process
|
|
78
80
|
* 3. Re-attaches the new process to the shell stdio (pipes new process stdin/stdout)
|
|
79
81
|
* 4. If it crashes with "No conversation found to continue", exits the process
|
|
80
|
-
* @param options.exitOnIdle - Exit when
|
|
81
|
-
* @param options.
|
|
82
|
+
* @param options.exitOnIdle - Exit when agent-cli is idle. Boolean or timeout in milliseconds, recommended 5000 - 60000, default is false
|
|
83
|
+
* @param options.cliArgs - Additional arguments to pass to the agent-cli CLI
|
|
82
84
|
* @param options.removeControlCharactersFromStdout - Remove ANSI control characters from stdout. Defaults to !process.stdout.isTTY
|
|
83
85
|
*
|
|
84
86
|
* @example
|
|
@@ -119,31 +121,16 @@ export default async function claudeYes({
|
|
|
119
121
|
removeControlCharactersFromStdout?: boolean;
|
|
120
122
|
verbose?: boolean;
|
|
121
123
|
} = {}) {
|
|
124
|
+
await rm('agent-yes.log').catch(() => null); // ignore error if file doesn't exist
|
|
125
|
+
const yesLog = tsaComposer()(async function yesLog(msg: string) {
|
|
126
|
+
await appendFile('agent-yes.log', `${msg}\n`).catch(() => null);
|
|
127
|
+
});
|
|
122
128
|
const continueArgs = {
|
|
123
129
|
codex: 'resume --last'.split(' '),
|
|
124
130
|
claude: '--continue'.split(' '),
|
|
125
131
|
gemini: [], // not possible yet
|
|
126
132
|
};
|
|
127
133
|
|
|
128
|
-
// if (verbose) {
|
|
129
|
-
// console.log('calling claudeYes: ', {
|
|
130
|
-
// cli,
|
|
131
|
-
// continueOnCrash,
|
|
132
|
-
// exitOnIdle,
|
|
133
|
-
// cliArgs,
|
|
134
|
-
// cwd,
|
|
135
|
-
// removeControlCharactersFromStdout,
|
|
136
|
-
// logFile,
|
|
137
|
-
// verbose,
|
|
138
|
-
// });
|
|
139
|
-
// }
|
|
140
|
-
// console.log(
|
|
141
|
-
// `⭐ Starting ${cli}, automatically responding to yes/no prompts...`
|
|
142
|
-
// );
|
|
143
|
-
// console.log(
|
|
144
|
-
// '⚠️ Important Security Warning: Only run this on trusted repositories. This tool automatically responds to prompts and can execute commands without user confirmation. Be aware of potential prompt injection attacks where malicious code or instructions could be embedded in files or user inputs to manipulate the automated responses.'
|
|
145
|
-
// );
|
|
146
|
-
|
|
147
134
|
process.stdin.setRawMode?.(true); // must be called any stdout/stdin usage
|
|
148
135
|
let isFatal = false; // when true, do not restart on crash, and exit agent
|
|
149
136
|
const stdinReady = new ReadyManager();
|
|
@@ -246,11 +233,10 @@ export default async function claudeYes({
|
|
|
246
233
|
await exitAgent();
|
|
247
234
|
});
|
|
248
235
|
|
|
249
|
-
console.log(
|
|
250
|
-
|
|
251
|
-
);
|
|
236
|
+
// console.log(
|
|
237
|
+
// `[${cli}-yes] Started ${cli} with args: ${[cliCommand, ...cliArgs].join(" ")}`
|
|
238
|
+
// );
|
|
252
239
|
// Message streaming
|
|
253
|
-
shell.write(`\u001b[${1};${1}R`); // reply cli when getting cursor position
|
|
254
240
|
|
|
255
241
|
sflow(fromReadable<Buffer>(process.stdin))
|
|
256
242
|
.map((buffer) => buffer.toString())
|
|
@@ -272,7 +258,7 @@ export default async function claudeYes({
|
|
|
272
258
|
terminalRender.write(text);
|
|
273
259
|
// todo: .onStatus((msg)=> shell.write(msg))
|
|
274
260
|
if (process.stdin.isTTY) return; // only handle it when stdin is not tty
|
|
275
|
-
if (text.includes('\u001b[6n')) return; // only asked for cursor position
|
|
261
|
+
if (!text.includes('\u001b[6n')) return; // only asked for cursor position
|
|
276
262
|
// todo: use terminalRender API to get cursor position when new version is available
|
|
277
263
|
// xterm replies CSI row; column R if asked cursor position
|
|
278
264
|
// https://en.wikipedia.org/wiki/ANSI_escape_code#:~:text=citation%20needed%5D-,xterm%20replies,-CSI%20row%C2%A0%3B
|
|
@@ -292,10 +278,8 @@ export default async function claudeYes({
|
|
|
292
278
|
e
|
|
293
279
|
.map((e) => removeControlCharacters(e))
|
|
294
280
|
.map((e) => e.replaceAll('\r', '')) // remove carriage return
|
|
295
|
-
|
|
296
|
-
.forEach((e) =>
|
|
297
|
-
appendFile('io.log', 'output|' + JSON.stringify(e) + '\n'),
|
|
298
|
-
) // for debugging
|
|
281
|
+
.lines({ EOL: 'NONE' })
|
|
282
|
+
.forEach((e) => yesLog`output|${e}`) // for debugging
|
|
299
283
|
// Generic auto-response handler driven by CLI_CONFIGURES
|
|
300
284
|
.forEach(async (e, i) => {
|
|
301
285
|
const conf =
|
|
@@ -304,17 +288,21 @@ export default async function claudeYes({
|
|
|
304
288
|
|
|
305
289
|
// ready matcher: if matched, mark stdin ready
|
|
306
290
|
if (conf.ready?.some((rx: RegExp) => e.match(rx))) {
|
|
291
|
+
await yesLog`ready |${e}`;
|
|
307
292
|
if (cli === 'gemini' && i <= 80) return; // gemini initial noise, only after many lines
|
|
308
293
|
stdinReady.ready();
|
|
309
294
|
}
|
|
310
295
|
|
|
311
296
|
// enter matchers: send Enter when any enter regex matches
|
|
312
297
|
if (conf.enter?.some((rx: RegExp) => e.match(rx))) {
|
|
298
|
+
await yesLog`enter |${e}`;
|
|
313
299
|
await sendEnter(300); // send Enter after 300ms idle wait
|
|
300
|
+
return;
|
|
314
301
|
}
|
|
315
302
|
|
|
316
303
|
// fatal matchers: set isFatal flag when matched
|
|
317
304
|
if (conf.fatal?.some((rx: RegExp) => e.match(rx))) {
|
|
305
|
+
await yesLog`fatal |${e}`;
|
|
318
306
|
isFatal = true;
|
|
319
307
|
await exitAgent();
|
|
320
308
|
}
|
|
@@ -328,6 +316,7 @@ export default async function claudeYes({
|
|
|
328
316
|
.then(() => null); // run it immediately without await
|
|
329
317
|
|
|
330
318
|
// wait for cli ready and send prompt if provided
|
|
319
|
+
if (cli === 'codex') shell.write(`\u001b[1;1R`); // send cursor position response when stdin is not tty
|
|
331
320
|
if (prompt) await sendMessage(prompt);
|
|
332
321
|
|
|
333
322
|
const exitCode = await pendingExitCode.promise; // wait for the shell to exit
|
|
@@ -347,10 +336,10 @@ export default async function claudeYes({
|
|
|
347
336
|
async function sendEnter(waitms = 1000) {
|
|
348
337
|
// wait for idle for a bit to let agent cli finish rendering
|
|
349
338
|
const st = Date.now();
|
|
350
|
-
|
|
351
339
|
await idleWaiter.wait(waitms);
|
|
352
340
|
const et = Date.now();
|
|
353
|
-
process.stdout.write(`\ridleWaiter.wait(${waitms}) took ${et - st}ms\r`);
|
|
341
|
+
// process.stdout.write(`\ridleWaiter.wait(${waitms}) took ${et - st}ms\r`);
|
|
342
|
+
await yesLog`sendEn| idleWaiter.wait(${String(waitms)}) took ${String(et - st)}ms`;
|
|
354
343
|
|
|
355
344
|
shell.write('\r');
|
|
356
345
|
}
|
|
@@ -358,6 +347,7 @@ export default async function claudeYes({
|
|
|
358
347
|
async function sendMessage(message: string) {
|
|
359
348
|
await stdinReady.wait();
|
|
360
349
|
// show in-place message: write msg and move cursor back start
|
|
350
|
+
await yesLog`send |${message}`;
|
|
361
351
|
shell.write(message);
|
|
362
352
|
idleWaiter.ping(); // just sent a message, wait for echo
|
|
363
353
|
await sendEnter();
|
|
@@ -385,10 +375,11 @@ export default async function claudeYes({
|
|
|
385
375
|
}
|
|
386
376
|
|
|
387
377
|
function getTerminalDimensions() {
|
|
378
|
+
if (!process.stdout.isTTY) return { cols: 80, rows: 30 }; // default size when not tty
|
|
388
379
|
return {
|
|
389
380
|
// TODO: enforce minimum cols/rows to avoid layout issues
|
|
390
381
|
// cols: Math.max(process.stdout.columns, 80),
|
|
391
|
-
cols: process.stdout.columns,
|
|
382
|
+
cols: Math.min(Math.max(20, process.stdout.columns), 80),
|
|
392
383
|
rows: process.stdout.rows,
|
|
393
384
|
};
|
|
394
385
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-yes",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.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
|
"claude",
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"bun-pty": "^0.3.2",
|
|
64
64
|
"p-map": "^7.0.3",
|
|
65
|
-
"phpdie": "^1.7.0"
|
|
65
|
+
"phpdie": "^1.7.0",
|
|
66
|
+
"tsa-composer": "^3.0.0"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"@biomejs/biome": "^2.2.5",
|