claude-yes 1.18.0 → 1.19.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/README.md +119 -25
- package/ReadyManager.ts +2 -4
- package/dist/claude-yes.js +11 -16
- package/dist/cli.js +11 -16
- package/dist/cli.js.map +3 -3
- package/dist/codex-yes.js +11 -16
- package/dist/copilot-yes.js +11 -16
- package/dist/cursor-yes.js +11 -16
- package/dist/gemini-yes.js +11 -16
- package/dist/index.js +11 -16
- package/dist/index.js.map +4 -4
- package/index.ts +6 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,25 +1,51 @@
|
|
|
1
1
|
# Yes! Claude
|
|
2
2
|
|
|
3
|
-
A wrapper tool that automates interactions with
|
|
3
|
+
A wrapper tool that automates interactions with various AI CLI tools by automatically handling common prompts and responses. Originally designed for Claude CLI, now supports multiple AI coding assistants.
|
|
4
4
|
|
|
5
5
|
⚠️ **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.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- Automatically responds to common prompts like "Yes, proceed" and "Yes"
|
|
11
|
-
-
|
|
12
|
-
- You can still
|
|
9
|
+
- **Multi-CLI Support**: Works with Claude, Gemini, Codex, Copilot, and Cursor CLI tools
|
|
10
|
+
- **Auto-Response**: Automatically responds to common prompts like "Yes, proceed" and "Yes"
|
|
11
|
+
- **Continuous Operation**: Keeps the AI assistant running until your task is done, waiting for your next prompt
|
|
12
|
+
- **Interactive Control**: You can still queue more prompts or cancel executing tasks with `ESC` or `Ctrl+C`
|
|
13
|
+
- **Crash Recovery**: Automatically restarts crashed processes (where supported)
|
|
14
|
+
- **Idle Detection**: Optional auto-exit when the AI becomes idle
|
|
13
15
|
|
|
14
|
-
##
|
|
16
|
+
## Prerequisites
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
Install the AI CLI tool(s) you want to use:
|
|
17
19
|
|
|
20
|
+
### Claude
|
|
18
21
|
```bash
|
|
19
22
|
npm install -g @anthropic-ai/claude-code
|
|
20
23
|
```
|
|
24
|
+
Learn more: https://www.anthropic.com/claude-code
|
|
21
25
|
|
|
22
|
-
|
|
26
|
+
### Gemini
|
|
27
|
+
```bash
|
|
28
|
+
# Install Gemini CLI (if available)
|
|
29
|
+
# Check Google's documentation for installation instructions
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Codex
|
|
33
|
+
```bash
|
|
34
|
+
# Install Codex CLI (if available)
|
|
35
|
+
# Check Microsoft's documentation for installation instructions
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### GitHub Copilot
|
|
39
|
+
```bash
|
|
40
|
+
# Install GitHub Copilot CLI
|
|
41
|
+
# Check GitHub's documentation for installation instructions
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Cursor
|
|
45
|
+
```bash
|
|
46
|
+
# Install Cursor agent CLI
|
|
47
|
+
# Check Cursor's documentation for installation instructions
|
|
48
|
+
```
|
|
23
49
|
|
|
24
50
|
Then install this project:
|
|
25
51
|
|
|
@@ -29,49 +55,117 @@ npm install claude-yes -g
|
|
|
29
55
|
|
|
30
56
|
## Usage
|
|
31
57
|
|
|
32
|
-
###
|
|
58
|
+
### Command Line Interface
|
|
33
59
|
|
|
34
60
|
```bash
|
|
35
|
-
claude-yes [--exit-on-idle=60s] [
|
|
36
|
-
|
|
61
|
+
claude-yes [--cli=<tool>] [--exit-on-idle=60s] [tool-command] [prompts]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### Examples
|
|
37
65
|
|
|
38
|
-
|
|
66
|
+
**Claude (default):**
|
|
67
|
+
```bash
|
|
39
68
|
claude-yes "run all tests and commit current changes"
|
|
40
69
|
bunx claude-yes "Solve TODO.md"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Other AI tools:**
|
|
73
|
+
```bash
|
|
74
|
+
# Use Gemini
|
|
75
|
+
claude-yes --cli=gemini "help me debug this code"
|
|
41
76
|
|
|
42
|
-
#
|
|
77
|
+
# Use Codex
|
|
78
|
+
claude-yes --cli=codex "refactor this function"
|
|
79
|
+
|
|
80
|
+
# Use Copilot
|
|
81
|
+
claude-yes --cli=copilot "generate unit tests"
|
|
82
|
+
|
|
83
|
+
# Use Cursor
|
|
84
|
+
claude-yes --cli=cursor "optimize performance"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Auto-exit when idle (useful for automation):**
|
|
88
|
+
```bash
|
|
43
89
|
claude-yes --exit-on-idle=60s "run all tests and commit current changes"
|
|
90
|
+
```
|
|
44
91
|
|
|
45
|
-
|
|
92
|
+
**Alternative with claude-code-execute:**
|
|
93
|
+
```bash
|
|
46
94
|
claude-code-execute claude-yes "your task here"
|
|
47
95
|
```
|
|
48
96
|
|
|
97
|
+
### Supported CLI Tools
|
|
98
|
+
|
|
99
|
+
| Tool | CLI Name | Description |
|
|
100
|
+
|------|----------|-------------|
|
|
101
|
+
| Claude | `claude` | Anthropic's Claude Code (default) |
|
|
102
|
+
| Gemini | `gemini` | Google's Gemini CLI |
|
|
103
|
+
| Codex | `codex` | Microsoft's Codex CLI |
|
|
104
|
+
| Copilot | `copilot` | GitHub Copilot CLI |
|
|
105
|
+
| Cursor | `cursor` | Cursor agent CLI |
|
|
106
|
+
|
|
49
107
|
The tool will:
|
|
50
108
|
|
|
51
|
-
1.
|
|
52
|
-
2.
|
|
53
|
-
3.
|
|
109
|
+
1. Run the specified AI CLI tool
|
|
110
|
+
2. Automatically respond "Yes" to common yes/no prompts
|
|
111
|
+
3. Handle tool-specific patterns and responses
|
|
112
|
+
4. When using `--exit-on-idle` flag, automatically exit when the tool becomes idle
|
|
54
113
|
|
|
55
114
|
<!-- TODO: add usage As lib: call await claudeYes() and it returns render result -->
|
|
56
115
|
|
|
57
116
|
## Options
|
|
58
117
|
|
|
59
|
-
- `--
|
|
118
|
+
- `--cli=<tool>`: Specify which AI CLI tool to use (claude, gemini, codex, copilot, cursor). Defaults to `claude`.
|
|
119
|
+
- `--exit-on-idle=<seconds>`: Automatically exit when the AI tool becomes idle for the specified duration. Useful for automation scripts.
|
|
60
120
|
|
|
61
|
-
##
|
|
121
|
+
## Library Usage
|
|
62
122
|
|
|
63
|
-
|
|
123
|
+
You can also use this as a library in your Node.js projects:
|
|
64
124
|
|
|
125
|
+
```typescript
|
|
126
|
+
import claudeYes from 'claude-yes';
|
|
127
|
+
|
|
128
|
+
// Use Claude
|
|
129
|
+
await claudeYes({
|
|
130
|
+
prompt: 'help me solve all todos in my codebase',
|
|
131
|
+
cli: 'claude',
|
|
132
|
+
cliArgs: ['--verbose'],
|
|
133
|
+
exitOnIdle: 30000, // exit after 30 seconds of idle
|
|
134
|
+
continueOnCrash: true,
|
|
135
|
+
logFile: 'claude.log',
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Use other tools
|
|
139
|
+
await claudeYes({
|
|
140
|
+
prompt: 'debug this function',
|
|
141
|
+
cli: 'gemini',
|
|
142
|
+
exitOnIdle: 60000,
|
|
143
|
+
});
|
|
65
144
|
```
|
|
66
|
-
❯ 1. Yes
|
|
67
|
-
2. No
|
|
68
|
-
```
|
|
69
145
|
|
|
70
|
-
|
|
146
|
+
## Implementation
|
|
147
|
+
|
|
148
|
+
The tool uses `node-pty` to spawn and manage AI CLI processes, with a sophisticated pattern-matching system that:
|
|
149
|
+
|
|
150
|
+
1. **Detects Ready States**: Recognizes when each CLI tool is ready to accept input
|
|
151
|
+
2. **Auto-Responds**: Automatically sends "Yes" responses to common prompts
|
|
152
|
+
3. **Handles Fatal Errors**: Detects and responds to fatal error conditions
|
|
153
|
+
4. **Manages Process Lifecycle**: Handles crashes, restarts, and graceful exits
|
|
154
|
+
|
|
155
|
+
Each supported CLI has its own configuration defining:
|
|
156
|
+
- **Ready patterns**: Regex patterns that indicate the tool is ready for input
|
|
157
|
+
- **Enter patterns**: Patterns that trigger automatic "Yes" responses
|
|
158
|
+
- **Fatal patterns**: Patterns that indicate fatal errors requiring exit
|
|
159
|
+
- **Binary mapping**: Maps logical names to actual executable names
|
|
160
|
+
- **Argument handling**: Special argument processing (e.g., adding `--search` to Codex)
|
|
71
161
|
|
|
72
162
|
## Dependencies
|
|
73
163
|
|
|
74
|
-
- `node-pty` - For spawning and managing
|
|
164
|
+
- `node-pty` or `bun-pty` - For spawning and managing AI CLI processes
|
|
165
|
+
- `from-node-stream` - Stream processing utilities
|
|
166
|
+
- `sflow` - Functional stream processing
|
|
167
|
+
- `terminal-render` - Terminal rendering and text processing
|
|
168
|
+
- `phpdie` - Error handling utilities
|
|
75
169
|
|
|
76
170
|
## Inspiration
|
|
77
171
|
|
package/ReadyManager.ts
CHANGED
|
@@ -2,10 +2,8 @@ export class ReadyManager {
|
|
|
2
2
|
private isReady = false;
|
|
3
3
|
private readyQueue: (() => void)[] = [];
|
|
4
4
|
wait() {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
this.readyQueue.push(resolve);
|
|
8
|
-
});
|
|
5
|
+
if (this.isReady) return;
|
|
6
|
+
return new Promise<void>((resolve) => this.readyQueue.push(resolve));
|
|
9
7
|
}
|
|
10
8
|
unready() {
|
|
11
9
|
this.isReady = false;
|
package/dist/claude-yes.js
CHANGED
|
@@ -50,11 +50,9 @@ class ReadyManager {
|
|
|
50
50
|
isReady = false;
|
|
51
51
|
readyQueue = [];
|
|
52
52
|
wait() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.readyQueue.push(resolve);
|
|
57
|
-
});
|
|
53
|
+
if (this.isReady)
|
|
54
|
+
return;
|
|
55
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
58
56
|
}
|
|
59
57
|
unready() {
|
|
60
58
|
this.isReady = false;
|
|
@@ -80,7 +78,8 @@ var CLI_CONFIGURES = {
|
|
|
80
78
|
},
|
|
81
79
|
gemini: {
|
|
82
80
|
ready: /Type your message/,
|
|
83
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
81
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
82
|
+
fatal: []
|
|
84
83
|
},
|
|
85
84
|
codex: {
|
|
86
85
|
ready: /⏎ send/,
|
|
@@ -94,12 +93,14 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
},
|
|
95
94
|
copilot: {
|
|
96
95
|
ready: /^ > /,
|
|
97
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
96
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
97
|
+
fatal: []
|
|
98
98
|
},
|
|
99
99
|
cursor: {
|
|
100
100
|
binary: "cursor-agent",
|
|
101
101
|
ready: /\/ commands/,
|
|
102
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
102
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
103
|
+
fatal: []
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
async function claudeYes({
|
|
@@ -198,7 +199,7 @@ async function claudeYes({
|
|
|
198
199
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
199
200
|
shell.write(`\x1B[${row};${col}R`);
|
|
200
201
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
201
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
202
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
202
203
|
if (!conf)
|
|
203
204
|
return;
|
|
204
205
|
try {
|
|
@@ -215,18 +216,12 @@ async function claudeYes({
|
|
|
215
216
|
if (e2.match(rx))
|
|
216
217
|
return await sendEnter();
|
|
217
218
|
}
|
|
218
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
219
|
-
if (e2.match(conf.enter))
|
|
220
|
-
return await sendEnter();
|
|
221
219
|
}
|
|
222
220
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
223
221
|
for (const rx of conf.fatal) {
|
|
224
222
|
if (e2.match(rx))
|
|
225
223
|
return isFatal = true;
|
|
226
224
|
}
|
|
227
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
228
|
-
if (e2.match(conf.fatal))
|
|
229
|
-
return isFatal = true;
|
|
230
225
|
}
|
|
231
226
|
} catch (err) {
|
|
232
227
|
return;
|
|
@@ -333,5 +328,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
333
328
|
});
|
|
334
329
|
process.exit(exitCode ?? 1);
|
|
335
330
|
|
|
336
|
-
//# debugId=
|
|
331
|
+
//# debugId=0E9D5C1D34AAD47764756E2164756E21
|
|
337
332
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js
CHANGED
|
@@ -50,11 +50,9 @@ class ReadyManager {
|
|
|
50
50
|
isReady = false;
|
|
51
51
|
readyQueue = [];
|
|
52
52
|
wait() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.readyQueue.push(resolve);
|
|
57
|
-
});
|
|
53
|
+
if (this.isReady)
|
|
54
|
+
return;
|
|
55
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
58
56
|
}
|
|
59
57
|
unready() {
|
|
60
58
|
this.isReady = false;
|
|
@@ -80,7 +78,8 @@ var CLI_CONFIGURES = {
|
|
|
80
78
|
},
|
|
81
79
|
gemini: {
|
|
82
80
|
ready: /Type your message/,
|
|
83
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
81
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
82
|
+
fatal: []
|
|
84
83
|
},
|
|
85
84
|
codex: {
|
|
86
85
|
ready: /⏎ send/,
|
|
@@ -94,12 +93,14 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
},
|
|
95
94
|
copilot: {
|
|
96
95
|
ready: /^ > /,
|
|
97
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
96
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
97
|
+
fatal: []
|
|
98
98
|
},
|
|
99
99
|
cursor: {
|
|
100
100
|
binary: "cursor-agent",
|
|
101
101
|
ready: /\/ commands/,
|
|
102
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
102
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
103
|
+
fatal: []
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
async function claudeYes({
|
|
@@ -198,7 +199,7 @@ async function claudeYes({
|
|
|
198
199
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
199
200
|
shell.write(`\x1B[${row};${col}R`);
|
|
200
201
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
201
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
202
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
202
203
|
if (!conf)
|
|
203
204
|
return;
|
|
204
205
|
try {
|
|
@@ -215,18 +216,12 @@ async function claudeYes({
|
|
|
215
216
|
if (e2.match(rx))
|
|
216
217
|
return await sendEnter();
|
|
217
218
|
}
|
|
218
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
219
|
-
if (e2.match(conf.enter))
|
|
220
|
-
return await sendEnter();
|
|
221
219
|
}
|
|
222
220
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
223
221
|
for (const rx of conf.fatal) {
|
|
224
222
|
if (e2.match(rx))
|
|
225
223
|
return isFatal = true;
|
|
226
224
|
}
|
|
227
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
228
|
-
if (e2.match(conf.fatal))
|
|
229
|
-
return isFatal = true;
|
|
230
225
|
}
|
|
231
226
|
} catch (err) {
|
|
232
227
|
return;
|
|
@@ -333,5 +328,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
333
328
|
});
|
|
334
329
|
process.exit(exitCode ?? 1);
|
|
335
330
|
|
|
336
|
-
//# debugId=
|
|
331
|
+
//# debugId=0E9D5C1D34AAD47764756E2164756E21
|
|
337
332
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"sources": ["../cli.ts", "index.js"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"#!/usr/bin/env node\nimport enhancedMs from 'enhanced-ms';\nimport yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport claudeYes from '.';\n\n// cli entry point\nconst argv = yargs(hideBin(process.argv))\n .usage('Usage: $0 [options] [claude args] [--] [prompts...]')\n .example(\n '$0 --exit-on-idle=30s --continue-on-crash \"help me solve all todos in my codebase\"',\n 'Run Claude with a 30 seconds idle timeout and continue on crash',\n )\n .option('continue-on-crash', {\n type: 'boolean',\n default: true,\n description:\n 'spawn Claude with --continue if it crashes, only works for claude',\n })\n .option('log-file', {\n type: 'string',\n description: 'Log file to write to',\n })\n .option('cli', {\n type: 'string',\n description:\n 'Claude CLI command, e.g. \"claude,gemini,codex,cursor,copilot\", default is \"claude\"',\n })\n .option('prompt', {\n type: 'string',\n description: 'Prompt to send to Claude',\n alias: 'p',\n })\n .option('verbose', {\n type: 'boolean',\n description: 'Enable verbose logging',\n default: false,\n })\n .option('exit-on-idle', {\n type: 'string',\n description: 'Exit after a period of inactivity, e.g., \"5s\" or \"1m\"',\n })\n .parserConfiguration({\n 'unknown-options-as-args': true,\n 'halt-at-non-option': true,\n })\n .parseSync();\n\n// detect cli name for cli, while package.json have multiple bin link: {\"claude-yes\": \"cli.js\", \"codex-yes\": \"cli.js\", \"gemini-yes\": \"cli.js\"}\nif (!argv.cli) {\n const cliName = process.argv[1]?.split('/').pop()?.split('-')[0];\n argv.cli = cliName || 'claude';\n}\n\n// Support: everything after a literal `--` is a prompt string. Example:\n// claude-yes --exit-on-idle=30s -- \"help me refactor this\"\n// In that example the prompt will be `help me refactor this` and won't be\n// passed as args to the underlying CLI binary.\nconst rawArgs = process.argv.slice(2);\nconst dashIndex = rawArgs.indexOf('--');\nlet promptFromDash: string | undefined = undefined;\nlet cliArgsForSpawn: string[] = [];\nif (dashIndex !== -1) {\n // join everything after `--` into a single prompt string\n const after = rawArgs.slice(dashIndex + 1);\n promptFromDash = after.join(' ');\n // use everything before `--` as the cli args\n cliArgsForSpawn = rawArgs.slice(0, dashIndex).map(String);\n} else {\n // fallback to yargs parsed positional args when `--` is not used\n cliArgsForSpawn = argv._.map((e) => String(e));\n}\n\nconsole.clear();\nconst { exitCode, logs } = await claudeYes({\n cli: argv.cli,\n // prefer explicit --prompt / -p; otherwise use the text after `--` if present\n prompt: argv.prompt || promptFromDash,\n exitOnIdle: argv.exitOnIdle ? enhancedMs(argv.exitOnIdle) : undefined,\n cliArgs: cliArgsForSpawn,\n continueOnCrash: argv.continueOnCrash,\n logFile: argv.logFile,\n verbose: argv.verbose,\n});\n\nprocess.exit(exitCode ?? 1);\n",
|
|
6
|
-
"import { createRequire } from \"node:module\";\nvar __create = Object.create;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __toESM = (mod, isNodeMode, target) => {\n target = mod != null ? __create(__getProtoOf(mod)) : {};\n const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target;\n for (let key of __getOwnPropNames(mod))\n if (!__hasOwnProp.call(to, key))\n __defProp(to, key, {\n get: () => mod[key],\n enumerable: true\n });\n return to;\n};\nvar __require = /* @__PURE__ */ createRequire(import.meta.url);\n\n// index.ts\nimport { fromReadable, fromWritable } from \"from-node-stream\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport path from \"path\";\nimport DIE from \"phpdie\";\nimport sflow from \"sflow\";\nimport { TerminalTextRender } from \"terminal-render\";\n\n// idleWaiter.ts\nclass IdleWaiter {\n lastActivityTime = Date.now();\n checkInterval = 100;\n constructor() {\n this.ping();\n }\n ping() {\n this.lastActivityTime = Date.now();\n return this;\n }\n async wait(ms) {\n while (this.lastActivityTime >= Date.now() - ms)\n await new Promise((resolve) => setTimeout(resolve, this.checkInterval));\n }\n}\n\n// ReadyManager.ts\nclass ReadyManager {\n isReady = false;\n readyQueue = [];\n wait() {\n
|
|
6
|
+
"import { createRequire } from \"node:module\";\nvar __create = Object.create;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __toESM = (mod, isNodeMode, target) => {\n target = mod != null ? __create(__getProtoOf(mod)) : {};\n const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target;\n for (let key of __getOwnPropNames(mod))\n if (!__hasOwnProp.call(to, key))\n __defProp(to, key, {\n get: () => mod[key],\n enumerable: true\n });\n return to;\n};\nvar __require = /* @__PURE__ */ createRequire(import.meta.url);\n\n// index.ts\nimport { fromReadable, fromWritable } from \"from-node-stream\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport path from \"path\";\nimport DIE from \"phpdie\";\nimport sflow from \"sflow\";\nimport { TerminalTextRender } from \"terminal-render\";\n\n// idleWaiter.ts\nclass IdleWaiter {\n lastActivityTime = Date.now();\n checkInterval = 100;\n constructor() {\n this.ping();\n }\n ping() {\n this.lastActivityTime = Date.now();\n return this;\n }\n async wait(ms) {\n while (this.lastActivityTime >= Date.now() - ms)\n await new Promise((resolve) => setTimeout(resolve, this.checkInterval));\n }\n}\n\n// ReadyManager.ts\nclass ReadyManager {\n isReady = false;\n readyQueue = [];\n wait() {\n if (this.isReady)\n return;\n return new Promise((resolve) => this.readyQueue.push(resolve));\n }\n unready() {\n this.isReady = false;\n }\n ready() {\n this.isReady = true;\n if (!this.readyQueue.length)\n return;\n this.readyQueue.splice(0).map((resolve) => resolve());\n }\n}\n\n// removeControlCharacters.ts\nfunction removeControlCharacters(str) {\n return str.replace(/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, \"\");\n}\n\n// index.ts\nvar CLI_CONFIGURES = {\n claude: {\n ready: /^> /,\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}Claude usage limit reached\\./\n ]\n },\n gemini: {\n ready: /Type your message/,\n enter: [/│ ● 1. Yes, allow once/],\n fatal: []\n },\n codex: {\n ready: /⏎ send/,\n enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\n fatal: [/Error: The cursor position could not be read within/],\n ensureArgs: (args) => {\n if (!args.includes(\"--search\"))\n return [\"--search\", ...args];\n return args;\n }\n },\n copilot: {\n ready: /^ > /,\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n fatal: []\n },\n cursor: {\n binary: \"cursor-agent\",\n ready: /\\/ commands/,\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: []\n }\n};\nasync function claudeYes({\n cli = \"claude\",\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false,\n verbose = false\n} = {}) {\n const continueArgs = {\n codex: \"resume --last\".split(\" \"),\n claude: \"--continue\".split(\" \"),\n gemini: []\n };\n process.stdin.setRawMode?.(true);\n let isFatal = false;\n const stdinReady = new ReadyManager;\n const shellOutputStream = new TransformStream;\n const outputWriter = shellOutputStream.writable.getWriter();\n const pty = await import(\"node-pty\").catch(async () => await import(\"bun-pty\")).catch(async () => DIE(\"Please install node-pty or bun-pty, run this: bun install bun-pty\"));\n const getPtyOptions = () => ({\n name: \"xterm-color\",\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? process.env\n });\n const cliConf = CLI_CONFIGURES[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());\n const pendingExitCode = Promise.withResolvers();\n let pendingExitCodeValue = null;\n async function onData(data) {\n await outputWriter.write(data);\n }\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode: exitCode2 }) {\n stdinReady.unready();\n const agentCrashed = exitCode2 !== 0;\n const continueArg = continueArgs[cli];\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(`continueOnCrash is only supported for ${Object.keys(continueArgs).join(\", \")} currently, not ${cli}`);\n }\n if (isFatal) {\n console.log(`${cli} crashed with \"No conversation found to continue\", exiting...`);\n return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);\n }\n console.log(`${cli} crashed, restarting...`);\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve(pendingExitCodeValue = exitCode2);\n });\n process.stdout.on(\"resize\", () => {\n const { cols, rows } = getTerminalDimensions();\n shell.resize(cols, rows);\n });\n const terminalRender = new TerminalTextRender;\n const isStillWorkingQ = () => terminalRender.render().replace(/\\s+/g, \" \").match(/esc to interrupt|to run in background/);\n const idleWaiter = new IdleWaiter;\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\"[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet\");\n return;\n }\n console.log(\"[${cli}-yes] ${cli} is idle, exiting...\");\n await exitAgent();\n });\n sflow(fromReadable(process.stdin)).map((buffer) => buffer.toString()).by({\n writable: new WritableStream({\n write: async (data) => {\n await stdinReady.wait();\n shell.write(data);\n }\n }),\n readable: shellOutputStream.readable\n }).forEach(() => idleWaiter.ping()).forEach((text) => {\n terminalRender.write(text);\n if (process.stdin.isTTY)\n return;\n if (text.includes(\"\\x1B[6n\"))\n return;\n const rendered = terminalRender.render();\n const row = rendered.split(`\n`).length + 1;\n const col = (rendered.split(`\n`).slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\x1B[${row};${col}R`);\n }).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll(\"\\r\", \"\")).lines({ EOL: \"NONE\" }).forEach(async (e2, i) => {\n const conf = CLI_CONFIGURES[cli] || null;\n if (!conf)\n return;\n try {\n if (conf.ready) {\n if (cli === \"gemini\" && conf.ready instanceof RegExp) {\n if (e2.match(conf.ready) && i > 80)\n return stdinReady.ready();\n } else if (e2.match(conf.ready)) {\n return stdinReady.ready();\n }\n }\n if (conf.enter && Array.isArray(conf.enter)) {\n for (const rx of conf.enter) {\n if (e2.match(rx))\n return await sendEnter();\n }\n }\n if (conf.fatal && Array.isArray(conf.fatal)) {\n for (const rx of conf.fatal) {\n if (e2.match(rx))\n return isFatal = true;\n }\n }\n } catch (err) {\n return;\n }\n }).run()).map((e) => removeControlCharactersFromStdout ? removeControlCharacters(e) : e).to(fromWritable(process.stdout)).then(() => null);\n if (prompt)\n (async () => {\n await sendMessage(prompt);\n })();\n const exitCode = await pendingExitCode.promise;\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n if (logFile) {\n verbose && console.log(`[${cli}-yes] Writing rendered logs to ${logFile}`);\n const logFilePath = path.resolve(logFile);\n await mkdir(path.dirname(logFilePath), { recursive: true }).catch(() => null);\n await writeFile(logFilePath, terminalRender.render());\n }\n return { exitCode, logs: terminalRender.render() };\n async function sendEnter(waitms = 1000) {\n const st = Date.now();\n await idleWaiter.wait(waitms);\n const et = Date.now();\n process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n shell.write(\"\\r\");\n }\n async function sendMessage(message) {\n await stdinReady.wait();\n shell.write(message);\n idleWaiter.ping();\n await sendEnter();\n }\n async function exitAgent() {\n continueOnCrash = false;\n await sendMessage(\"/exit\");\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => exited = true),\n new Promise((resolve) => setTimeout(() => {\n if (exited)\n return;\n shell.kill();\n resolve();\n }, 5000))\n ]);\n }\n function getTerminalDimensions() {\n return {\n cols: Math.max(process.stdout.columns, 80),\n rows: process.stdout.rows\n };\n }\n}\nexport {\n removeControlCharacters,\n claudeYes as default,\n CLI_CONFIGURES\n};\n\n//# debugId=095427732AFAFB1F64756E2164756E21\n//# sourceMappingURL=index.js.map\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;AACA;AACA;AACA;;;ACiBA;AACA;AACA;AACA;AACA;AACA;AAGA,MAAM,WAAW;AAAA,EACf,mBAAmB,KAAK,IAAI;AAAA,EAC5B,gBAAgB;AAAA,EAChB,WAAW,GAAG;AAAA,IACZ,KAAK,KAAK;AAAA;AAAA,EAEZ,IAAI,GAAG;AAAA,IACL,KAAK,mBAAmB,KAAK,IAAI;AAAA,IACjC,OAAO;AAAA;AAAA,OAEH,KAAI,CAAC,IAAI;AAAA,IACb,OAAO,KAAK,oBAAoB,KAAK,IAAI,IAAI;AAAA,MAC3C,MAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,aAAa,CAAC;AAAA;AAE5E;AAAA;AAGA,MAAM,aAAa;AAAA,EACjB,UAAU;AAAA,EACV,aAAa,CAAC;AAAA,EACd,IAAI,GAAG;AAAA,IACL,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;AACA;AACA;AACA;;;ACiBA;AACA;AACA;AACA;AACA;AACA;AAGA,MAAM,WAAW;AAAA,EACf,mBAAmB,KAAK,IAAI;AAAA,EAC5B,gBAAgB;AAAA,EAChB,WAAW,GAAG;AAAA,IACZ,KAAK,KAAK;AAAA;AAAA,EAEZ,IAAI,GAAG;AAAA,IACL,KAAK,mBAAmB,KAAK,IAAI;AAAA,IACjC,OAAO;AAAA;AAAA,OAEH,KAAI,CAAC,IAAI;AAAA,IACb,OAAO,KAAK,oBAAoB,KAAK,IAAI,IAAI;AAAA,MAC3C,MAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,aAAa,CAAC;AAAA;AAE5E;AAAA;AAGA,MAAM,aAAa;AAAA,EACjB,UAAU;AAAA,EACV,aAAa,CAAC;AAAA,EACd,IAAI,GAAG;AAAA,IACL,IAAI,KAAK;AAAA,MACP;AAAA,IACF,OAAO,IAAI,QAAQ,CAAC,YAAY,KAAK,WAAW,KAAK,OAAO,CAAC;AAAA;AAAA,EAE/D,OAAO,GAAG;AAAA,IACR,KAAK,UAAU;AAAA;AAAA,EAEjB,KAAK,GAAG;AAAA,IACN,KAAK,UAAU;AAAA,IACf,IAAI,CAAC,KAAK,WAAW;AAAA,MACnB;AAAA,IACF,KAAK,WAAW,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,QAAQ,CAAC;AAAA;AAExD;AAGA,SAAS,uBAAuB,CAAC,KAAK;AAAA,EACpC,OAAO,IAAI,QAAQ,+EAA+E,EAAE;AAAA;AAItG,IAAI,iBAAiB;AAAA,EACnB,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,YAAW,mBAAmB,0BAA0B;AAAA,IAChE,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO,CAAC,wBAAuB;AAAA,IAC/B,OAAO,CAAC;AAAA,EACV;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO,CAAC,iBAAiB,8CAA8C;AAAA,IACvE,OAAO,CAAC,qDAAqD;AAAA,IAC7D,YAAY,CAAC,SAAS;AAAA,MACpB,IAAI,CAAC,KAAK,SAAS,UAAU;AAAA,QAC3B,OAAO,CAAC,YAAY,GAAG,IAAI;AAAA,MAC7B,OAAO;AAAA;AAAA,EAEX;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,OAAO,CAAC,wBAAuB,UAAU;AAAA,IACzC,OAAO,CAAC;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,OAAO,CAAC,kCAAiC,8BAA8B;AAAA,IACvE,OAAO,CAAC;AAAA,EACV;AACF;AACA,eAAe,SAAS;AAAA,EACtB,MAAM;AAAA,EACN,UAAU,CAAC;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oCAAoC;AAAA,EACpC,UAAU;AAAA,IACR,CAAC,GAAG;AAAA,EACN,MAAM,eAAe;AAAA,IACnB,OAAO,gBAAgB,MAAM,GAAG;AAAA,IAChC,QAAQ,aAAa,MAAM,GAAG;AAAA,IAC9B,QAAQ,CAAC;AAAA,EACX;AAAA,EACA,QAAQ,MAAM,aAAa,IAAI;AAAA,EAC/B,IAAI,UAAU;AAAA,EACd,MAAM,aAAa,IAAI;AAAA,EACvB,MAAM,oBAAoB,IAAI;AAAA,EAC9B,MAAM,eAAe,kBAAkB,SAAS,UAAU;AAAA,EAC1D,MAAM,MAAM,MAAa,mBAAY,MAAM,YAAY,MAAa,iBAAU,EAAE,MAAM,YAAY,IAAI,mEAAmE,CAAC;AAAA,EAC1K,MAAM,gBAAgB,OAAO;AAAA,IAC3B,MAAM;AAAA,OACH,sBAAsB;AAAA,IACzB,KAAK,OAAO,QAAQ,IAAI;AAAA,IACxB,KAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EACA,MAAM,UAAU,eAAe,QAAQ,CAAC;AAAA,EACxC,UAAU,QAAQ,aAAa,OAAO,KAAK;AAAA,EAC3C,MAAM,aAAa,SAAS,UAAU;AAAA,EACtC,IAAI,QAAQ,IAAI,MAAM,YAAY,SAAS,cAAc,CAAC;AAAA,EAC1D,MAAM,kBAAkB,QAAQ,cAAc;AAAA,EAC9C,IAAI,uBAAuB;AAAA,EAC3B,eAAe,MAAM,CAAC,MAAM;AAAA,IAC1B,MAAM,aAAa,MAAM,IAAI;AAAA;AAAA,EAE/B,MAAM,OAAO,MAAM;AAAA,EACnB,MAAM,OAAO,SAAS,MAAM,GAAG,UAAU,aAAa;AAAA,IACpD,WAAW,QAAQ;AAAA,IACnB,MAAM,eAAe,cAAc;AAAA,IACnC,MAAM,cAAc,aAAa;AAAA,IACjC,IAAI,gBAAgB,mBAAmB,aAAa;AAAA,MAClD,IAAI,CAAC,aAAa;AAAA,QAChB,OAAO,QAAQ,KAAK,yCAAyC,OAAO,KAAK,YAAY,EAAE,KAAK,IAAI,oBAAoB,KAAK;AAAA,MAC3H;AAAA,MACA,IAAI,SAAS;AAAA,QACX,QAAQ,IAAI,GAAG,kEAAkE;AAAA,QACjF,OAAO,gBAAgB,QAAQ,uBAAuB,SAAS;AAAA,MACjE;AAAA,MACA,QAAQ,IAAI,GAAG,4BAA4B;AAAA,MAC3C,QAAQ,IAAI,MAAM,KAAK,aAAa,cAAc,CAAC;AAAA,MACnD,MAAM,OAAO,MAAM;AAAA,MACnB,MAAM,OAAO,MAAM;AAAA,MACnB;AAAA,IACF;AAAA,IACA,OAAO,gBAAgB,QAAQ,uBAAuB,SAAS;AAAA,GAChE;AAAA,EACD,QAAQ,OAAO,GAAG,UAAU,MAAM;AAAA,IAChC,QAAQ,MAAM,SAAS,sBAAsB;AAAA,IAC7C,MAAM,OAAO,MAAM,IAAI;AAAA,GACxB;AAAA,EACD,MAAM,iBAAiB,IAAI;AAAA,EAC3B,MAAM,kBAAkB,MAAM,eAAe,OAAO,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,uCAAuC;AAAA,EACxH,MAAM,aAAa,IAAI;AAAA,EACvB,IAAI;AAAA,IACF,WAAW,KAAK,UAAU,EAAE,KAAK,YAAY;AAAA,MAC3C,IAAI,gBAAgB,GAAG;AAAA,QACrB,QAAQ,IAAI,uEAAuE;AAAA,QACnF;AAAA,MACF;AAAA,MACA,QAAQ,IAAI,yCAAyC;AAAA,MACrD,MAAM,UAAU;AAAA,KACjB;AAAA,EACH,MAAM,aAAa,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC,EAAE,GAAG;AAAA,IACvE,UAAU,IAAI,eAAe;AAAA,MAC3B,OAAO,OAAO,SAAS;AAAA,QACrB,MAAM,WAAW,KAAK;AAAA,QACtB,MAAM,MAAM,IAAI;AAAA;AAAA,IAEpB,CAAC;AAAA,IACD,UAAU,kBAAkB;AAAA,EAC9B,CAAC,EAAE,QAAQ,MAAM,WAAW,KAAK,CAAC,EAAE,QAAQ,CAAC,SAAS;AAAA,IACpD,eAAe,MAAM,IAAI;AAAA,IACzB,IAAI,QAAQ,MAAM;AAAA,MAChB;AAAA,IACF,IAAI,KAAK,SAAS,SAAS;AAAA,MACzB;AAAA,IACF,MAAM,WAAW,eAAe,OAAO;AAAA,IACvC,MAAM,MAAM,SAAS,MAAM;AAAA,CAC9B,EAAE,SAAS;AAAA,IACR,MAAM,OAAO,SAAS,MAAM;AAAA,CAC/B,EAAE,MAAM,EAAE,EAAE,IAAI,UAAU,KAAK;AAAA,IAC5B,MAAM,MAAM,QAAQ,OAAO,MAAM;AAAA,GAClC,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,wBAAwB,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,GAAG,WAAW,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,EAAE,QAAQ,OAAO,IAAI,MAAM;AAAA,IAC/I,MAAM,OAAO,eAAe,QAAQ;AAAA,IACpC,IAAI,CAAC;AAAA,MACH;AAAA,IACF,IAAI;AAAA,MACF,IAAI,KAAK,OAAO;AAAA,QACd,IAAI,QAAQ,YAAY,KAAK,iBAAiB,QAAQ;AAAA,UACpD,IAAI,GAAG,MAAM,KAAK,KAAK,KAAK,IAAI;AAAA,YAC9B,OAAO,WAAW,MAAM;AAAA,QAC5B,EAAO,SAAI,GAAG,MAAM,KAAK,KAAK,GAAG;AAAA,UAC/B,OAAO,WAAW,MAAM;AAAA,QAC1B;AAAA,MACF;AAAA,MACA,IAAI,KAAK,SAAS,MAAM,QAAQ,KAAK,KAAK,GAAG;AAAA,QAC3C,WAAW,MAAM,KAAK,OAAO;AAAA,UAC3B,IAAI,GAAG,MAAM,EAAE;AAAA,YACb,OAAO,MAAM,UAAU;AAAA,QAC3B;AAAA,MACF;AAAA,MACA,IAAI,KAAK,SAAS,MAAM,QAAQ,KAAK,KAAK,GAAG;AAAA,QAC3C,WAAW,MAAM,KAAK,OAAO;AAAA,UAC3B,IAAI,GAAG,MAAM,EAAE;AAAA,YACb,OAAO,UAAU;AAAA,QACrB;AAAA,MACF;AAAA,MACA,OAAO,KAAK;AAAA,MACZ;AAAA;AAAA,GAEH,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,oCAAoC,wBAAwB,CAAC,IAAI,CAAC,EAAE,GAAG,aAAa,QAAQ,MAAM,CAAC,EAAE,KAAK,MAAM,IAAI;AAAA,EACzI,IAAI;AAAA,KACD,YAAY;AAAA,MACX,MAAM,YAAY,MAAM;AAAA,OACvB;AAAA,EACL,MAAM,WAAW,MAAM,gBAAgB;AAAA,EACvC,QAAQ,IAAI,IAAI,YAAY,wBAAwB,UAAU;AAAA,EAC9D,IAAI,SAAS;AAAA,IACX,WAAW,QAAQ,IAAI,IAAI,qCAAqC,SAAS;AAAA,IACzE,MAAM,cAAc,KAAK,QAAQ,OAAO;AAAA,IACxC,MAAM,MAAM,KAAK,QAAQ,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC,EAAE,MAAM,MAAM,IAAI;AAAA,IAC5E,MAAM,UAAU,aAAa,eAAe,OAAO,CAAC;AAAA,EACtD;AAAA,EACA,OAAO,EAAE,UAAU,MAAM,eAAe,OAAO,EAAE;AAAA,EACjD,eAAe,SAAS,CAAC,SAAS,MAAM;AAAA,IACtC,MAAM,KAAK,KAAK,IAAI;AAAA,IACpB,MAAM,WAAW,KAAK,MAAM;AAAA,IAC5B,MAAM,KAAK,KAAK,IAAI;AAAA,IACpB,QAAQ,OAAO,MAAM,qBAAqB,gBAAgB,KAAK,QAAQ;AAAA,IACvE,MAAM,MAAM,IAAI;AAAA;AAAA,EAElB,eAAe,WAAW,CAAC,SAAS;AAAA,IAClC,MAAM,WAAW,KAAK;AAAA,IACtB,MAAM,MAAM,OAAO;AAAA,IACnB,WAAW,KAAK;AAAA,IAChB,MAAM,UAAU;AAAA;AAAA,EAElB,eAAe,SAAS,GAAG;AAAA,IACzB,kBAAkB;AAAA,IAClB,MAAM,YAAY,OAAO;AAAA,IACzB,IAAI,SAAS;AAAA,IACb,MAAM,QAAQ,KAAK;AAAA,MACjB,gBAAgB,QAAQ,KAAK,MAAM,SAAS,IAAI;AAAA,MAChD,IAAI,QAAQ,CAAC,YAAY,WAAW,MAAM;AAAA,QACxC,IAAI;AAAA,UACF;AAAA,QACF,MAAM,KAAK;AAAA,QACX,QAAQ;AAAA,SACP,IAAI,CAAC;AAAA,IACV,CAAC;AAAA;AAAA,EAEH,SAAS,qBAAqB,GAAG;AAAA,IAC/B,OAAO;AAAA,MACL,MAAM,KAAK,IAAI,QAAQ,OAAO,SAAS,EAAE;AAAA,MACzC,MAAM,QAAQ,OAAO;AAAA,IACvB;AAAA;AAAA;;;AD3QJ,IAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,CAAC,EACrC,MAAM,qDAAqD,EAC3D,QACC,sFACA,iEACF,EACC,OAAO,qBAAqB;AAAA,EAC3B,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aACE;AACJ,CAAC,EACA,OAAO,YAAY;AAAA,EAClB,MAAM;AAAA,EACN,aAAa;AACf,CAAC,EACA,OAAO,OAAO;AAAA,EACb,MAAM;AAAA,EACN,aACE;AACJ,CAAC,EACA,OAAO,UAAU;AAAA,EAChB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,OAAO;AACT,CAAC,EACA,OAAO,WAAW;AAAA,EACjB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,SAAS;AACX,CAAC,EACA,OAAO,gBAAgB;AAAA,EACtB,MAAM;AAAA,EACN,aAAa;AACf,CAAC,EACA,oBAAoB;AAAA,EACnB,2BAA2B;AAAA,EAC3B,sBAAsB;AACxB,CAAC,EACA,UAAU;AAGb,IAAI,CAAC,KAAK,KAAK;AAAA,EACb,MAAM,UAAU,QAAQ,KAAK,IAAI,MAAM,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,EAAE;AAAA,EAC9D,KAAK,MAAM,WAAW;AACxB;AAMA,IAAM,UAAU,QAAQ,KAAK,MAAM,CAAC;AACpC,IAAM,YAAY,QAAQ,QAAQ,IAAI;AACtC,IAAI,iBAAqC;AACzC,IAAI,kBAA4B,CAAC;AACjC,IAAI,cAAc,IAAI;AAAA,EAEpB,MAAM,QAAQ,QAAQ,MAAM,YAAY,CAAC;AAAA,EACzC,iBAAiB,MAAM,KAAK,GAAG;AAAA,EAE/B,kBAAkB,QAAQ,MAAM,GAAG,SAAS,EAAE,IAAI,MAAM;AAC1D,EAAO;AAAA,EAEL,kBAAkB,KAAK,EAAE,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAAA;AAG/C,QAAQ,MAAM;AACd,MAAQ,UAAU,SAAS,MAAM,UAAU;AAAA,EACzC,KAAK,KAAK;AAAA,EAEV,QAAQ,KAAK,UAAU;AAAA,EACvB,YAAY,KAAK,aAAa,WAAW,KAAK,UAAU,IAAI;AAAA,EAC5D,SAAS;AAAA,EACT,iBAAiB,KAAK;AAAA,EACtB,SAAS,KAAK;AAAA,EACd,SAAS,KAAK;AAChB,CAAC;AAED,QAAQ,KAAK,YAAY,CAAC;",
|
|
9
|
+
"debugId": "0E9D5C1D34AAD47764756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/dist/codex-yes.js
CHANGED
|
@@ -50,11 +50,9 @@ class ReadyManager {
|
|
|
50
50
|
isReady = false;
|
|
51
51
|
readyQueue = [];
|
|
52
52
|
wait() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.readyQueue.push(resolve);
|
|
57
|
-
});
|
|
53
|
+
if (this.isReady)
|
|
54
|
+
return;
|
|
55
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
58
56
|
}
|
|
59
57
|
unready() {
|
|
60
58
|
this.isReady = false;
|
|
@@ -80,7 +78,8 @@ var CLI_CONFIGURES = {
|
|
|
80
78
|
},
|
|
81
79
|
gemini: {
|
|
82
80
|
ready: /Type your message/,
|
|
83
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
81
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
82
|
+
fatal: []
|
|
84
83
|
},
|
|
85
84
|
codex: {
|
|
86
85
|
ready: /⏎ send/,
|
|
@@ -94,12 +93,14 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
},
|
|
95
94
|
copilot: {
|
|
96
95
|
ready: /^ > /,
|
|
97
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
96
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
97
|
+
fatal: []
|
|
98
98
|
},
|
|
99
99
|
cursor: {
|
|
100
100
|
binary: "cursor-agent",
|
|
101
101
|
ready: /\/ commands/,
|
|
102
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
102
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
103
|
+
fatal: []
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
async function claudeYes({
|
|
@@ -198,7 +199,7 @@ async function claudeYes({
|
|
|
198
199
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
199
200
|
shell.write(`\x1B[${row};${col}R`);
|
|
200
201
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
201
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
202
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
202
203
|
if (!conf)
|
|
203
204
|
return;
|
|
204
205
|
try {
|
|
@@ -215,18 +216,12 @@ async function claudeYes({
|
|
|
215
216
|
if (e2.match(rx))
|
|
216
217
|
return await sendEnter();
|
|
217
218
|
}
|
|
218
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
219
|
-
if (e2.match(conf.enter))
|
|
220
|
-
return await sendEnter();
|
|
221
219
|
}
|
|
222
220
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
223
221
|
for (const rx of conf.fatal) {
|
|
224
222
|
if (e2.match(rx))
|
|
225
223
|
return isFatal = true;
|
|
226
224
|
}
|
|
227
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
228
|
-
if (e2.match(conf.fatal))
|
|
229
|
-
return isFatal = true;
|
|
230
225
|
}
|
|
231
226
|
} catch (err) {
|
|
232
227
|
return;
|
|
@@ -333,5 +328,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
333
328
|
});
|
|
334
329
|
process.exit(exitCode ?? 1);
|
|
335
330
|
|
|
336
|
-
//# debugId=
|
|
331
|
+
//# debugId=0E9D5C1D34AAD47764756E2164756E21
|
|
337
332
|
//# sourceMappingURL=cli.js.map
|
package/dist/copilot-yes.js
CHANGED
|
@@ -50,11 +50,9 @@ class ReadyManager {
|
|
|
50
50
|
isReady = false;
|
|
51
51
|
readyQueue = [];
|
|
52
52
|
wait() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.readyQueue.push(resolve);
|
|
57
|
-
});
|
|
53
|
+
if (this.isReady)
|
|
54
|
+
return;
|
|
55
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
58
56
|
}
|
|
59
57
|
unready() {
|
|
60
58
|
this.isReady = false;
|
|
@@ -80,7 +78,8 @@ var CLI_CONFIGURES = {
|
|
|
80
78
|
},
|
|
81
79
|
gemini: {
|
|
82
80
|
ready: /Type your message/,
|
|
83
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
81
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
82
|
+
fatal: []
|
|
84
83
|
},
|
|
85
84
|
codex: {
|
|
86
85
|
ready: /⏎ send/,
|
|
@@ -94,12 +93,14 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
},
|
|
95
94
|
copilot: {
|
|
96
95
|
ready: /^ > /,
|
|
97
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
96
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
97
|
+
fatal: []
|
|
98
98
|
},
|
|
99
99
|
cursor: {
|
|
100
100
|
binary: "cursor-agent",
|
|
101
101
|
ready: /\/ commands/,
|
|
102
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
102
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
103
|
+
fatal: []
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
async function claudeYes({
|
|
@@ -198,7 +199,7 @@ async function claudeYes({
|
|
|
198
199
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
199
200
|
shell.write(`\x1B[${row};${col}R`);
|
|
200
201
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
201
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
202
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
202
203
|
if (!conf)
|
|
203
204
|
return;
|
|
204
205
|
try {
|
|
@@ -215,18 +216,12 @@ async function claudeYes({
|
|
|
215
216
|
if (e2.match(rx))
|
|
216
217
|
return await sendEnter();
|
|
217
218
|
}
|
|
218
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
219
|
-
if (e2.match(conf.enter))
|
|
220
|
-
return await sendEnter();
|
|
221
219
|
}
|
|
222
220
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
223
221
|
for (const rx of conf.fatal) {
|
|
224
222
|
if (e2.match(rx))
|
|
225
223
|
return isFatal = true;
|
|
226
224
|
}
|
|
227
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
228
|
-
if (e2.match(conf.fatal))
|
|
229
|
-
return isFatal = true;
|
|
230
225
|
}
|
|
231
226
|
} catch (err) {
|
|
232
227
|
return;
|
|
@@ -333,5 +328,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
333
328
|
});
|
|
334
329
|
process.exit(exitCode ?? 1);
|
|
335
330
|
|
|
336
|
-
//# debugId=
|
|
331
|
+
//# debugId=0E9D5C1D34AAD47764756E2164756E21
|
|
337
332
|
//# sourceMappingURL=cli.js.map
|
package/dist/cursor-yes.js
CHANGED
|
@@ -50,11 +50,9 @@ class ReadyManager {
|
|
|
50
50
|
isReady = false;
|
|
51
51
|
readyQueue = [];
|
|
52
52
|
wait() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.readyQueue.push(resolve);
|
|
57
|
-
});
|
|
53
|
+
if (this.isReady)
|
|
54
|
+
return;
|
|
55
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
58
56
|
}
|
|
59
57
|
unready() {
|
|
60
58
|
this.isReady = false;
|
|
@@ -80,7 +78,8 @@ var CLI_CONFIGURES = {
|
|
|
80
78
|
},
|
|
81
79
|
gemini: {
|
|
82
80
|
ready: /Type your message/,
|
|
83
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
81
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
82
|
+
fatal: []
|
|
84
83
|
},
|
|
85
84
|
codex: {
|
|
86
85
|
ready: /⏎ send/,
|
|
@@ -94,12 +93,14 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
},
|
|
95
94
|
copilot: {
|
|
96
95
|
ready: /^ > /,
|
|
97
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
96
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
97
|
+
fatal: []
|
|
98
98
|
},
|
|
99
99
|
cursor: {
|
|
100
100
|
binary: "cursor-agent",
|
|
101
101
|
ready: /\/ commands/,
|
|
102
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
102
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
103
|
+
fatal: []
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
async function claudeYes({
|
|
@@ -198,7 +199,7 @@ async function claudeYes({
|
|
|
198
199
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
199
200
|
shell.write(`\x1B[${row};${col}R`);
|
|
200
201
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
201
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
202
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
202
203
|
if (!conf)
|
|
203
204
|
return;
|
|
204
205
|
try {
|
|
@@ -215,18 +216,12 @@ async function claudeYes({
|
|
|
215
216
|
if (e2.match(rx))
|
|
216
217
|
return await sendEnter();
|
|
217
218
|
}
|
|
218
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
219
|
-
if (e2.match(conf.enter))
|
|
220
|
-
return await sendEnter();
|
|
221
219
|
}
|
|
222
220
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
223
221
|
for (const rx of conf.fatal) {
|
|
224
222
|
if (e2.match(rx))
|
|
225
223
|
return isFatal = true;
|
|
226
224
|
}
|
|
227
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
228
|
-
if (e2.match(conf.fatal))
|
|
229
|
-
return isFatal = true;
|
|
230
225
|
}
|
|
231
226
|
} catch (err) {
|
|
232
227
|
return;
|
|
@@ -333,5 +328,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
333
328
|
});
|
|
334
329
|
process.exit(exitCode ?? 1);
|
|
335
330
|
|
|
336
|
-
//# debugId=
|
|
331
|
+
//# debugId=0E9D5C1D34AAD47764756E2164756E21
|
|
337
332
|
//# sourceMappingURL=cli.js.map
|
package/dist/gemini-yes.js
CHANGED
|
@@ -50,11 +50,9 @@ class ReadyManager {
|
|
|
50
50
|
isReady = false;
|
|
51
51
|
readyQueue = [];
|
|
52
52
|
wait() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
this.readyQueue.push(resolve);
|
|
57
|
-
});
|
|
53
|
+
if (this.isReady)
|
|
54
|
+
return;
|
|
55
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
58
56
|
}
|
|
59
57
|
unready() {
|
|
60
58
|
this.isReady = false;
|
|
@@ -80,7 +78,8 @@ var CLI_CONFIGURES = {
|
|
|
80
78
|
},
|
|
81
79
|
gemini: {
|
|
82
80
|
ready: /Type your message/,
|
|
83
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
81
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
82
|
+
fatal: []
|
|
84
83
|
},
|
|
85
84
|
codex: {
|
|
86
85
|
ready: /⏎ send/,
|
|
@@ -94,12 +93,14 @@ var CLI_CONFIGURES = {
|
|
|
94
93
|
},
|
|
95
94
|
copilot: {
|
|
96
95
|
ready: /^ > /,
|
|
97
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
96
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
97
|
+
fatal: []
|
|
98
98
|
},
|
|
99
99
|
cursor: {
|
|
100
100
|
binary: "cursor-agent",
|
|
101
101
|
ready: /\/ commands/,
|
|
102
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
102
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
103
|
+
fatal: []
|
|
103
104
|
}
|
|
104
105
|
};
|
|
105
106
|
async function claudeYes({
|
|
@@ -198,7 +199,7 @@ async function claudeYes({
|
|
|
198
199
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
199
200
|
shell.write(`\x1B[${row};${col}R`);
|
|
200
201
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
201
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
202
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
202
203
|
if (!conf)
|
|
203
204
|
return;
|
|
204
205
|
try {
|
|
@@ -215,18 +216,12 @@ async function claudeYes({
|
|
|
215
216
|
if (e2.match(rx))
|
|
216
217
|
return await sendEnter();
|
|
217
218
|
}
|
|
218
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
219
|
-
if (e2.match(conf.enter))
|
|
220
|
-
return await sendEnter();
|
|
221
219
|
}
|
|
222
220
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
223
221
|
for (const rx of conf.fatal) {
|
|
224
222
|
if (e2.match(rx))
|
|
225
223
|
return isFatal = true;
|
|
226
224
|
}
|
|
227
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
228
|
-
if (e2.match(conf.fatal))
|
|
229
|
-
return isFatal = true;
|
|
230
225
|
}
|
|
231
226
|
} catch (err) {
|
|
232
227
|
return;
|
|
@@ -333,5 +328,5 @@ var { exitCode, logs } = await claudeYes({
|
|
|
333
328
|
});
|
|
334
329
|
process.exit(exitCode ?? 1);
|
|
335
330
|
|
|
336
|
-
//# debugId=
|
|
331
|
+
//# debugId=0E9D5C1D34AAD47764756E2164756E21
|
|
337
332
|
//# sourceMappingURL=cli.js.map
|
package/dist/index.js
CHANGED
|
@@ -47,11 +47,9 @@ class ReadyManager {
|
|
|
47
47
|
isReady = false;
|
|
48
48
|
readyQueue = [];
|
|
49
49
|
wait() {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
this.readyQueue.push(resolve);
|
|
54
|
-
});
|
|
50
|
+
if (this.isReady)
|
|
51
|
+
return;
|
|
52
|
+
return new Promise((resolve) => this.readyQueue.push(resolve));
|
|
55
53
|
}
|
|
56
54
|
unready() {
|
|
57
55
|
this.isReady = false;
|
|
@@ -81,7 +79,8 @@ var CLI_CONFIGURES = {
|
|
|
81
79
|
},
|
|
82
80
|
gemini: {
|
|
83
81
|
ready: /Type your message/,
|
|
84
|
-
enter: [/│ ● 1. Yes, allow once/]
|
|
82
|
+
enter: [/│ ● 1. Yes, allow once/],
|
|
83
|
+
fatal: []
|
|
85
84
|
},
|
|
86
85
|
codex: {
|
|
87
86
|
ready: /⏎ send/,
|
|
@@ -95,12 +94,14 @@ var CLI_CONFIGURES = {
|
|
|
95
94
|
},
|
|
96
95
|
copilot: {
|
|
97
96
|
ready: /^ > /,
|
|
98
|
-
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/]
|
|
97
|
+
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
98
|
+
fatal: []
|
|
99
99
|
},
|
|
100
100
|
cursor: {
|
|
101
101
|
binary: "cursor-agent",
|
|
102
102
|
ready: /\/ commands/,
|
|
103
|
-
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/]
|
|
103
|
+
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
104
|
+
fatal: []
|
|
104
105
|
}
|
|
105
106
|
};
|
|
106
107
|
async function claudeYes({
|
|
@@ -199,7 +200,7 @@ async function claudeYes({
|
|
|
199
200
|
`).slice(-1)[0]?.length || 0) + 1;
|
|
200
201
|
shell.write(`\x1B[${row};${col}R`);
|
|
201
202
|
}).forkTo((e) => e.map((e2) => removeControlCharacters(e2)).map((e2) => e2.replaceAll("\r", "")).lines({ EOL: "NONE" }).forEach(async (e2, i) => {
|
|
202
|
-
const conf = CLI_CONFIGURES[cli] ||
|
|
203
|
+
const conf = CLI_CONFIGURES[cli] || null;
|
|
203
204
|
if (!conf)
|
|
204
205
|
return;
|
|
205
206
|
try {
|
|
@@ -216,18 +217,12 @@ async function claudeYes({
|
|
|
216
217
|
if (e2.match(rx))
|
|
217
218
|
return await sendEnter();
|
|
218
219
|
}
|
|
219
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
220
|
-
if (e2.match(conf.enter))
|
|
221
|
-
return await sendEnter();
|
|
222
220
|
}
|
|
223
221
|
if (conf.fatal && Array.isArray(conf.fatal)) {
|
|
224
222
|
for (const rx of conf.fatal) {
|
|
225
223
|
if (e2.match(rx))
|
|
226
224
|
return isFatal = true;
|
|
227
225
|
}
|
|
228
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
229
|
-
if (e2.match(conf.fatal))
|
|
230
|
-
return isFatal = true;
|
|
231
226
|
}
|
|
232
227
|
} catch (err) {
|
|
233
228
|
return;
|
|
@@ -286,5 +281,5 @@ export {
|
|
|
286
281
|
CLI_CONFIGURES
|
|
287
282
|
};
|
|
288
283
|
|
|
289
|
-
//# debugId=
|
|
284
|
+
//# debugId=095427732AFAFB1F64756E2164756E21
|
|
290
285
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../index.ts", "../idleWaiter.ts", "../ReadyManager.ts", "../removeControlCharacters.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { fromReadable, fromWritable } from 'from-node-stream';\nimport { mkdir, writeFile } from 'fs/promises';\nimport path from 'path';\nimport DIE from 'phpdie';\nimport sflow from 'sflow';\nimport { TerminalTextRender } from 'terminal-render';\nimport { IdleWaiter } from './idleWaiter';\nimport { ReadyManager } from './ReadyManager';\nimport { removeControlCharacters } from './removeControlCharacters';\n\nexport const CLI_CONFIGURES = {\n claude: {\n ready: /^> /, // regex matcher for stdin ready,\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}Claude usage limit reached\\./,\n ],\n },\n gemini: {\n // match the agent prompt after initial lines; handled by index logic using line index\n ready: /Type your message/, // used with line index check\n enter: [/│ ● 1. Yes, allow once/],\n },\n codex: {\n ready: /⏎ send/,\n enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\n fatal: [/Error: The cursor position could not be read within/],\n // add to codex --search by default when not provided by the user\n ensureArgs: (args: string[]) => {\n if (!args.includes('--search')) return ['--search', ...args];\n return args;\n },\n },\n copilot: {\n ready: /^ > /,\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n },\n cursor: {\n // map logical \"cursor\" cli name to actual binary name\n binary: 'cursor-agent',\n ready: /\\/ commands/,\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n },\n};\n/**\n * Main function to run Claude with automatic yes/no responses\n * @param options Configuration options\n * @param options.continueOnCrash - If true, automatically restart Claude when it crashes:\n * 1. Shows message 'Claude crashed, restarting..'\n * 2. Spawns a new 'claude --continue' process\n * 3. Re-attaches the new process to the shell stdio (pipes new process stdin/stdout)\n * 4. If it crashes with \"No conversation found to continue\", exits the process\n * @param options.exitOnIdle - Exit when Claude is idle. Boolean or timeout in milliseconds, recommended 5000 - 60000, default is false\n * @param options.claudeArgs - Additional arguments to pass to the Claude CLI\n * @param options.removeControlCharactersFromStdout - Remove ANSI control characters from stdout. Defaults to !process.stdout.isTTY\n *\n * @example\n * ```typescript\n * import claudeYes from 'claude-yes';\n * await claudeYes({\n * prompt: 'help me solve all todos in my codebase',\n *\n * // optional\n * cli: 'claude',\n * cliArgs: ['--verbose'], // additional args to pass to claude\n * exitOnIdle: 30000, // exit after 30 seconds of idle\n * continueOnCrash: true, // restart if claude crashes, default is true\n * logFile: 'claude.log', // save logs to file\n * });\n * ```\n */\nexport default async function claudeYes({\n cli = 'claude',\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false, // = !process.stdout.isTTY,\n verbose = false,\n}: {\n cli?: (string & {}) | keyof typeof CLI_CONFIGURES;\n cliArgs?: string[];\n prompt?: string;\n continueOnCrash?: boolean;\n cwd?: string;\n env?: Record<string, string>;\n exitOnIdle?: number;\n logFile?: string;\n removeControlCharactersFromStdout?: boolean;\n verbose?: boolean;\n} = {}) {\n const continueArgs = {\n codex: 'resume --last'.split(' '),\n claude: '--continue'.split(' '),\n gemini: [], // not possible yet\n };\n\n // if (verbose) {\n // console.log('calling claudeYes: ', {\n // cli,\n // continueOnCrash,\n // exitOnIdle,\n // cliArgs,\n // cwd,\n // removeControlCharactersFromStdout,\n // logFile,\n // verbose,\n // });\n // }\n // console.log(\n // `⭐ Starting ${cli}, automatically responding to yes/no prompts...`\n // );\n // console.log(\n // '⚠️ 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.'\n // );\n\n process.stdin.setRawMode?.(true); // must be called any stdout/stdin usage\n let isFatal = false; // match 'No conversation found to continue'\n const stdinReady = new ReadyManager();\n\n const shellOutputStream = new TransformStream<string, string>();\n const outputWriter = shellOutputStream.writable.getWriter();\n // const pty = await import('node-pty');\n\n // its recommened to use bun-pty in windows\n const pty = await import('node-pty')\n .catch(async () => await import('bun-pty'))\n .catch(async () =>\n DIE('Please install node-pty or bun-pty, run this: bun install bun-pty'),\n );\n\n const getPtyOptions = () => ({\n name: 'xterm-color',\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? (process.env as Record<string, string>),\n });\n\n // Apply CLI specific configurations (moved to CLI_CONFIGURES)\n const cliConf = (CLI_CONFIGURES as Record<string, any>)[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n\n let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());\n const pendingExitCode = Promise.withResolvers<number | null>();\n let pendingExitCodeValue = null;\n\n // TODO handle error if claude is not installed, show msg:\n // npm install -g @anthropic-ai/claude-code\n\n async function onData(data: string) {\n // append data to the buffer, so we can process it later\n await outputWriter.write(data);\n }\n\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode }) {\n stdinReady.unready(); // start buffer stdin\n const agentCrashed = exitCode !== 0;\n const continueArg = (continueArgs as Record<string, string[]>)[cli];\n\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(\n `continueOnCrash is only supported for ${Object.keys(continueArgs).join(', ')} currently, not ${cli}`,\n );\n }\n if (isFatal) {\n console.log(\n `${cli} crashed with \"No conversation found to continue\", exiting...`,\n );\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n }\n console.log(`${cli} crashed, restarting...`);\n\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n });\n\n // when current tty resized, resize the pty\n process.stdout.on('resize', () => {\n const { cols, rows } = getTerminalDimensions(); // minimum 80 columns to avoid layout issues\n shell.resize(cols, rows); // minimum 80 columns to avoid layout issues\n });\n\n const terminalRender = new TerminalTextRender();\n const isStillWorkingQ = () =>\n terminalRender\n .render()\n .replace(/\\s+/g, ' ')\n .match(/esc to interrupt|to run in background/);\n\n const idleWaiter = new IdleWaiter();\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\n '[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet',\n );\n return;\n }\n\n console.log('[${cli}-yes] ${cli} is idle, exiting...');\n await exitAgent();\n });\n\n // Message streaming\n sflow(fromReadable<Buffer>(process.stdin))\n .map((buffer) => buffer.toString())\n // .map((e) => e.replaceAll('\\x1a', '')) // remove ctrl+z from user's input (seems bug)\n // .forEach(e => appendFile('.cache/io.log', \"input |\" + JSON.stringify(e) + '\\n')) // for debugging\n // pipe\n .by({\n writable: new WritableStream<string>({\n write: async (data) => {\n await stdinReady.wait();\n // await idleWaiter.wait(20); // wait for idle for 200ms to avoid messing up claude's input\n shell.write(data);\n },\n }),\n readable: shellOutputStream.readable,\n })\n .forEach(() => idleWaiter.ping())\n .forEach((text) => {\n terminalRender.write(text);\n // todo: .onStatus((msg)=> shell.write(msg))\n if (process.stdin.isTTY) return; // only handle it when stdin is not tty\n if (text.includes('\\u001b[6n')) return; // only asked\n\n // todo: use terminalRender API to get cursor position when new version is available\n // xterm replies CSI row; column R if asked cursor position\n // https://en.wikipedia.org/wiki/ANSI_escape_code#:~:text=citation%20needed%5D-,xterm%20replies,-CSI%20row%C2%A0%3B\n // when agent asking position, respond with row; col\n const rendered = terminalRender.render();\n const row = rendered.split('\\n').length + 1;\n const col = (rendered.split('\\n').slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\u001b[${row};${col}R`);\n })\n\n // auto-response\n .forkTo((e) =>\n e\n .map((e) => removeControlCharacters(e))\n .map((e) => e.replaceAll('\\r', '')) // remove carriage return\n .lines({ EOL: 'NONE' })\n // Generic auto-response handler driven by CLI_CONFIGURES\n .forEach(async (e, i) => {\n const conf = (CLI_CONFIGURES as Record<string, any>)[cli] || {};\n if (!conf) return;\n\n // ready matcher: if matched, mark stdin ready\n try {\n if (conf.ready) {\n // special-case gemini to avoid initial prompt noise: only after many lines\n if (cli === 'gemini' && conf.ready instanceof RegExp) {\n if (e.match(conf.ready) && i > 80) return stdinReady.ready();\n } else if (e.match(conf.ready)) {\n return stdinReady.ready();\n }\n }\n\n // enter matchers: send Enter when any enter regex matches\n if (conf.enter && Array.isArray(conf.enter)) {\n for (const rx of conf.enter) {\n if (e.match(rx)) return await sendEnter();\n }\n } else if (conf.enter && conf.enter instanceof RegExp) {\n if (e.match(conf.enter)) return await sendEnter();\n }\n\n // fatal matchers: set isFatal flag when matched\n if (conf.fatal && Array.isArray(conf.fatal)) {\n for (const rx of conf.fatal) {\n if (e.match(rx)) return (isFatal = true);\n }\n } else if (conf.fatal && conf.fatal instanceof RegExp) {\n if (e.match(conf.fatal)) return (isFatal = true);\n }\n } catch (err) {\n // defensive: if e.match throws (e.g., not a string), ignore\n return;\n }\n })\n // .forEach(e => appendFile('.cache/io.log', \"output|\" + JSON.stringify(e) + '\\n')) // for debugging\n .run(),\n )\n .map((e) =>\n removeControlCharactersFromStdout ? removeControlCharacters(e) : e,\n )\n .to(fromWritable(process.stdout))\n .then(() => null); // run it immediately without await\n\n // wait for cli ready and send prompt if provided\n if (prompt)\n (async () => {\n // console.log(`[${cli}-yes] Ready to send prompt to ${cli}: ${prompt}`);\n // idleWaiter.ping();\n // console.log(\n // 'await idleWaiter.wait(1000); // wait a bit for claude to start'\n // );\n // await idleWaiter.wait(1000); // wait a bit for claude to start\n // console.log('await stdinReady.wait();');\n // await stdinReady.wait();\n // console.log(`[${cli}-yes] Waiting for ${cli} to be ready...`);\n // console.log('await idleWaiter.wait(200);');\n // await idleWaiter.wait(200);\n // console.log(`[${cli}-yes] Sending prompt to ${cli}: ${prompt}`);\n await sendMessage(prompt);\n })();\n\n const exitCode = await pendingExitCode.promise; // wait for the shell to exit\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n\n if (logFile) {\n verbose && console.log(`[${cli}-yes] Writing rendered logs to ${logFile}`);\n const logFilePath = path.resolve(logFile);\n await mkdir(path.dirname(logFilePath), { recursive: true }).catch(\n () => null,\n );\n await writeFile(logFilePath, terminalRender.render());\n }\n\n return { exitCode, logs: terminalRender.render() };\n\n async function sendEnter(waitms = 1000) {\n // wait for idle for a bit to let agent cli finish rendering\n const st = Date.now();\n\n await idleWaiter.wait(waitms);\n const et = Date.now();\n process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n\n shell.write('\\r');\n }\n\n async function sendMessage(message: string) {\n await stdinReady.wait();\n // show in-place message: write msg and move cursor back start\n shell.write(message);\n idleWaiter.ping(); // just sent a message, wait for echo\n await sendEnter();\n }\n\n async function exitAgent() {\n continueOnCrash = false;\n // send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input\n await sendMessage('/exit');\n\n // wait for shell to exit or kill it with a timeout\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => (exited = true)), // resolve when shell exits\n\n // if shell doesn't exit in 5 seconds, kill it\n new Promise<void>((resolve) =>\n setTimeout(() => {\n if (exited) return; // if shell already exited, do nothing\n shell.kill(); // kill the shell process if it doesn't exit in time\n resolve();\n }, 5000),\n ), // 5 seconds timeout\n ]);\n }\n\n function getTerminalDimensions() {\n return {\n cols: Math.max(process.stdout.columns, 80),\n rows: process.stdout.rows,\n };\n }\n}\n\nexport { removeControlCharacters };\n",
|
|
5
|
+
"import { fromReadable, fromWritable } from 'from-node-stream';\nimport { mkdir, writeFile } from 'fs/promises';\nimport path from 'path';\nimport DIE from 'phpdie';\nimport sflow from 'sflow';\nimport { TerminalTextRender } from 'terminal-render';\nimport { IdleWaiter } from './idleWaiter';\nimport { ReadyManager } from './ReadyManager';\nimport { removeControlCharacters } from './removeControlCharacters';\n\nexport const CLI_CONFIGURES = {\n claude: {\n ready: /^> /, // regex matcher for stdin ready,\n enter: [/❯ 1. Yes/, /❯ 1. Dark mode✔/, /Press Enter to continue…/],\n fatal: [\n /No conversation found to continue/,\n /⎿ {2}Claude usage limit reached\\./,\n ],\n },\n gemini: {\n // match the agent prompt after initial lines; handled by index logic using line index\n ready: /Type your message/, // used with line index check\n enter: [/│ ● 1. Yes, allow once/],\n fatal: [],\n },\n codex: {\n ready: /⏎ send/,\n enter: [/ > 1. Approve/, /> 1. Yes, allow Codex to work in this folder/],\n fatal: [/Error: The cursor position could not be read within/],\n // add to codex --search by default when not provided by the user\n ensureArgs: (args: string[]) => {\n if (!args.includes('--search')) return ['--search', ...args];\n return args;\n },\n },\n copilot: {\n ready: /^ > /,\n enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],\n fatal: [],\n },\n cursor: {\n // map logical \"cursor\" cli name to actual binary name\n binary: 'cursor-agent',\n ready: /\\/ commands/,\n enter: [/→ Run \\(once\\) \\(y\\) \\(enter\\)/, /▶ \\[a\\] Trust this workspace/],\n fatal: [],\n },\n};\n/**\n * Main function to run Claude with automatic yes/no responses\n * @param options Configuration options\n * @param options.continueOnCrash - If true, automatically restart Claude when it crashes:\n * 1. Shows message 'Claude crashed, restarting..'\n * 2. Spawns a new 'claude --continue' process\n * 3. Re-attaches the new process to the shell stdio (pipes new process stdin/stdout)\n * 4. If it crashes with \"No conversation found to continue\", exits the process\n * @param options.exitOnIdle - Exit when Claude is idle. Boolean or timeout in milliseconds, recommended 5000 - 60000, default is false\n * @param options.claudeArgs - Additional arguments to pass to the Claude CLI\n * @param options.removeControlCharactersFromStdout - Remove ANSI control characters from stdout. Defaults to !process.stdout.isTTY\n *\n * @example\n * ```typescript\n * import claudeYes from 'claude-yes';\n * await claudeYes({\n * prompt: 'help me solve all todos in my codebase',\n *\n * // optional\n * cli: 'claude',\n * cliArgs: ['--verbose'], // additional args to pass to claude\n * exitOnIdle: 30000, // exit after 30 seconds of idle\n * continueOnCrash: true, // restart if claude crashes, default is true\n * logFile: 'claude.log', // save logs to file\n * });\n * ```\n */\nexport default async function claudeYes({\n cli = 'claude',\n cliArgs = [],\n prompt,\n continueOnCrash,\n cwd,\n env,\n exitOnIdle,\n logFile,\n removeControlCharactersFromStdout = false, // = !process.stdout.isTTY,\n verbose = false,\n}: {\n cli?: (string & {}) | keyof typeof CLI_CONFIGURES;\n cliArgs?: string[];\n prompt?: string;\n continueOnCrash?: boolean;\n cwd?: string;\n env?: Record<string, string>;\n exitOnIdle?: number;\n logFile?: string;\n removeControlCharactersFromStdout?: boolean;\n verbose?: boolean;\n} = {}) {\n const continueArgs = {\n codex: 'resume --last'.split(' '),\n claude: '--continue'.split(' '),\n gemini: [], // not possible yet\n };\n\n // if (verbose) {\n // console.log('calling claudeYes: ', {\n // cli,\n // continueOnCrash,\n // exitOnIdle,\n // cliArgs,\n // cwd,\n // removeControlCharactersFromStdout,\n // logFile,\n // verbose,\n // });\n // }\n // console.log(\n // `⭐ Starting ${cli}, automatically responding to yes/no prompts...`\n // );\n // console.log(\n // '⚠️ 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.'\n // );\n\n process.stdin.setRawMode?.(true); // must be called any stdout/stdin usage\n let isFatal = false; // match 'No conversation found to continue'\n const stdinReady = new ReadyManager();\n\n const shellOutputStream = new TransformStream<string, string>();\n const outputWriter = shellOutputStream.writable.getWriter();\n // const pty = await import('node-pty');\n\n // its recommened to use bun-pty in windows\n const pty = await import('node-pty')\n .catch(async () => await import('bun-pty'))\n .catch(async () =>\n DIE('Please install node-pty or bun-pty, run this: bun install bun-pty'),\n );\n\n const getPtyOptions = () => ({\n name: 'xterm-color',\n ...getTerminalDimensions(),\n cwd: cwd ?? process.cwd(),\n env: env ?? (process.env as Record<string, string>),\n });\n\n // Apply CLI specific configurations (moved to CLI_CONFIGURES)\n const cliConf = (CLI_CONFIGURES as Record<string, any>)[cli] || {};\n cliArgs = cliConf.ensureArgs?.(cliArgs) ?? cliArgs;\n const cliCommand = cliConf?.binary || cli;\n\n let shell = pty.spawn(cliCommand, cliArgs, getPtyOptions());\n const pendingExitCode = Promise.withResolvers<number | null>();\n let pendingExitCodeValue = null;\n\n // TODO handle error if claude is not installed, show msg:\n // npm install -g @anthropic-ai/claude-code\n\n async function onData(data: string) {\n // append data to the buffer, so we can process it later\n await outputWriter.write(data);\n }\n\n shell.onData(onData);\n shell.onExit(function onExit({ exitCode }) {\n stdinReady.unready(); // start buffer stdin\n const agentCrashed = exitCode !== 0;\n const continueArg = (continueArgs as Record<string, string[]>)[cli];\n\n if (agentCrashed && continueOnCrash && continueArg) {\n if (!continueArg) {\n return console.warn(\n `continueOnCrash is only supported for ${Object.keys(continueArgs).join(', ')} currently, not ${cli}`,\n );\n }\n if (isFatal) {\n console.log(\n `${cli} crashed with \"No conversation found to continue\", exiting...`,\n );\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n }\n console.log(`${cli} crashed, restarting...`);\n\n shell = pty.spawn(cli, continueArg, getPtyOptions());\n shell.onData(onData);\n shell.onExit(onExit);\n return;\n }\n return pendingExitCode.resolve((pendingExitCodeValue = exitCode));\n });\n\n // when current tty resized, resize the pty\n process.stdout.on('resize', () => {\n const { cols, rows } = getTerminalDimensions(); // minimum 80 columns to avoid layout issues\n shell.resize(cols, rows); // minimum 80 columns to avoid layout issues\n });\n\n const terminalRender = new TerminalTextRender();\n const isStillWorkingQ = () =>\n terminalRender\n .render()\n .replace(/\\s+/g, ' ')\n .match(/esc to interrupt|to run in background/);\n\n const idleWaiter = new IdleWaiter();\n if (exitOnIdle)\n idleWaiter.wait(exitOnIdle).then(async () => {\n if (isStillWorkingQ()) {\n console.log(\n '[${cli}-yes] ${cli} is idle, but seems still working, not exiting yet',\n );\n return;\n }\n\n console.log('[${cli}-yes] ${cli} is idle, exiting...');\n await exitAgent();\n });\n\n // Message streaming\n sflow(fromReadable<Buffer>(process.stdin))\n .map((buffer) => buffer.toString())\n // .map((e) => e.replaceAll('\\x1a', '')) // remove ctrl+z from user's input (seems bug)\n // .forEach(e => appendFile('.cache/io.log', \"input |\" + JSON.stringify(e) + '\\n')) // for debugging\n // pipe\n .by({\n writable: new WritableStream<string>({\n write: async (data) => {\n await stdinReady.wait();\n // await idleWaiter.wait(20); // wait for idle for 200ms to avoid messing up claude's input\n shell.write(data);\n },\n }),\n readable: shellOutputStream.readable,\n })\n .forEach(() => idleWaiter.ping())\n .forEach((text) => {\n terminalRender.write(text);\n // todo: .onStatus((msg)=> shell.write(msg))\n if (process.stdin.isTTY) return; // only handle it when stdin is not tty\n if (text.includes('\\u001b[6n')) return; // only asked\n\n // todo: use terminalRender API to get cursor position when new version is available\n // xterm replies CSI row; column R if asked cursor position\n // https://en.wikipedia.org/wiki/ANSI_escape_code#:~:text=citation%20needed%5D-,xterm%20replies,-CSI%20row%C2%A0%3B\n // when agent asking position, respond with row; col\n const rendered = terminalRender.render();\n const row = rendered.split('\\n').length + 1;\n const col = (rendered.split('\\n').slice(-1)[0]?.length || 0) + 1;\n shell.write(`\\u001b[${row};${col}R`);\n })\n\n // auto-response\n .forkTo((e) =>\n e\n .map((e) => removeControlCharacters(e))\n .map((e) => e.replaceAll('\\r', '')) // remove carriage return\n .lines({ EOL: 'NONE' })\n // Generic auto-response handler driven by CLI_CONFIGURES\n .forEach(async (e, i) => {\n const conf =\n CLI_CONFIGURES[cli as keyof typeof CLI_CONFIGURES] || null;\n if (!conf) return;\n\n try {\n // ready matcher: if matched, mark stdin ready\n if (conf.ready) {\n // special-case gemini to avoid initial prompt noise: only after many lines\n if (cli === 'gemini' && conf.ready instanceof RegExp) {\n if (e.match(conf.ready) && i > 80) return stdinReady.ready();\n } else if (e.match(conf.ready)) {\n return stdinReady.ready();\n }\n }\n\n // enter matchers: send Enter when any enter regex matches\n if (conf.enter && Array.isArray(conf.enter)) {\n for (const rx of conf.enter) {\n if (e.match(rx)) return await sendEnter();\n }\n }\n\n // fatal matchers: set isFatal flag when matched\n if (conf.fatal && Array.isArray(conf.fatal)) {\n for (const rx of conf.fatal) {\n if (e.match(rx)) return (isFatal = true);\n }\n }\n } catch (err) {\n // defensive: if e.match throws (e.g., not a string), ignore\n return;\n }\n })\n // .forEach(e => appendFile('.cache/io.log', \"output|\" + JSON.stringify(e) + '\\n')) // for debugging\n .run(),\n )\n .map((e) =>\n removeControlCharactersFromStdout ? removeControlCharacters(e) : e,\n )\n .to(fromWritable(process.stdout))\n .then(() => null); // run it immediately without await\n\n // wait for cli ready and send prompt if provided\n if (prompt)\n (async () => {\n // console.log(`[${cli}-yes] Ready to send prompt to ${cli}: ${prompt}`);\n // idleWaiter.ping();\n // console.log(\n // 'await idleWaiter.wait(1000); // wait a bit for claude to start'\n // );\n // await idleWaiter.wait(1000); // wait a bit for claude to start\n // console.log('await stdinReady.wait();');\n // await stdinReady.wait();\n // console.log(`[${cli}-yes] Waiting for ${cli} to be ready...`);\n // console.log('await idleWaiter.wait(200);');\n // await idleWaiter.wait(200);\n // console.log(`[${cli}-yes] Sending prompt to ${cli}: ${prompt}`);\n await sendMessage(prompt);\n })();\n\n const exitCode = await pendingExitCode.promise; // wait for the shell to exit\n console.log(`[${cli}-yes] ${cli} exited with code ${exitCode}`);\n\n if (logFile) {\n verbose && console.log(`[${cli}-yes] Writing rendered logs to ${logFile}`);\n const logFilePath = path.resolve(logFile);\n await mkdir(path.dirname(logFilePath), { recursive: true }).catch(\n () => null,\n );\n await writeFile(logFilePath, terminalRender.render());\n }\n\n return { exitCode, logs: terminalRender.render() };\n\n async function sendEnter(waitms = 1000) {\n // wait for idle for a bit to let agent cli finish rendering\n const st = Date.now();\n\n await idleWaiter.wait(waitms);\n const et = Date.now();\n process.stdout.write(`\\ridleWaiter.wait(${waitms}) took ${et - st}ms\\r`);\n\n shell.write('\\r');\n }\n\n async function sendMessage(message: string) {\n await stdinReady.wait();\n // show in-place message: write msg and move cursor back start\n shell.write(message);\n idleWaiter.ping(); // just sent a message, wait for echo\n await sendEnter();\n }\n\n async function exitAgent() {\n continueOnCrash = false;\n // send exit command to the shell, must sleep a bit to avoid claude treat it as pasted input\n await sendMessage('/exit');\n\n // wait for shell to exit or kill it with a timeout\n let exited = false;\n await Promise.race([\n pendingExitCode.promise.then(() => (exited = true)), // resolve when shell exits\n\n // if shell doesn't exit in 5 seconds, kill it\n new Promise<void>((resolve) =>\n setTimeout(() => {\n if (exited) return; // if shell already exited, do nothing\n shell.kill(); // kill the shell process if it doesn't exit in time\n resolve();\n }, 5000),\n ), // 5 seconds timeout\n ]);\n }\n\n function getTerminalDimensions() {\n return {\n cols: Math.max(process.stdout.columns, 80),\n rows: process.stdout.rows,\n };\n }\n}\n\nexport { removeControlCharacters };\n",
|
|
6
6
|
"/**\n * A utility class to wait for idle periods based on activity pings.\n *\n * @example\n * const idleWaiter = new IdleWaiter();\n *\n * // Somewhere in your code, when activity occurs:\n * idleWaiter.ping();\n *\n * // To wait for an idle period of 5 seconds:\n * await idleWaiter.wait(5000);\n * console.log('System has been idle for 5 seconds');\n */\nexport class IdleWaiter {\n lastActivityTime = Date.now();\n checkInterval = 100; // Default check interval in milliseconds\n\n constructor() {\n this.ping();\n }\n\n ping() {\n this.lastActivityTime = Date.now();\n return this;\n }\n\n async wait(ms: number) {\n while (this.lastActivityTime >= Date.now() - ms)\n await new Promise((resolve) => setTimeout(resolve, this.checkInterval));\n }\n}\n",
|
|
7
|
-
"export class ReadyManager {\n private isReady = false;\n private readyQueue: (() => void)[] = [];\n wait() {\n return new Promise<void>((resolve) =>
|
|
7
|
+
"export class ReadyManager {\n private isReady = false;\n private readyQueue: (() => void)[] = [];\n wait() {\n if (this.isReady) return;\n return new Promise<void>((resolve) => this.readyQueue.push(resolve));\n }\n unready() {\n this.isReady = false;\n }\n ready() {\n this.isReady = true;\n if (!this.readyQueue.length) return; // check len for performance\n this.readyQueue.splice(0).map((resolve) => resolve());\n }\n}\n",
|
|
8
8
|
"export function removeControlCharacters(str: string): string {\n // Matches control characters in the C0 and C1 ranges, including Delete (U+007F)\n return str.replace(\n /[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,\n '',\n );\n}\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;;;ACQO,MAAM,WAAW;AAAA,EACtB,mBAAmB,KAAK,IAAI;AAAA,EAC5B,gBAAgB;AAAA,EAEhB,WAAW,GAAG;AAAA,IACZ,KAAK,KAAK;AAAA;AAAA,EAGZ,IAAI,GAAG;AAAA,IACL,KAAK,mBAAmB,KAAK,IAAI;AAAA,IACjC,OAAO;AAAA;AAAA,OAGH,KAAI,CAAC,IAAY;AAAA,IACrB,OAAO,KAAK,oBAAoB,KAAK,IAAI,IAAI;AAAA,MAC3C,MAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,aAAa,CAAC;AAAA;AAE5E;;;AC9BO,MAAM,aAAa;AAAA,EAChB,UAAU;AAAA,EACV,aAA6B,CAAC;AAAA,EACtC,IAAI,GAAG;AAAA,IACL,
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "095427732AFAFB1F64756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
package/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ export const CLI_CONFIGURES = {
|
|
|
21
21
|
// match the agent prompt after initial lines; handled by index logic using line index
|
|
22
22
|
ready: /Type your message/, // used with line index check
|
|
23
23
|
enter: [/│ ● 1. Yes, allow once/],
|
|
24
|
+
fatal: [],
|
|
24
25
|
},
|
|
25
26
|
codex: {
|
|
26
27
|
ready: /⏎ send/,
|
|
@@ -35,12 +36,14 @@ export const CLI_CONFIGURES = {
|
|
|
35
36
|
copilot: {
|
|
36
37
|
ready: /^ > /,
|
|
37
38
|
enter: [/ │ ❯ 1. Yes, proceed/, /❯ 1. Yes/],
|
|
39
|
+
fatal: [],
|
|
38
40
|
},
|
|
39
41
|
cursor: {
|
|
40
42
|
// map logical "cursor" cli name to actual binary name
|
|
41
43
|
binary: 'cursor-agent',
|
|
42
44
|
ready: /\/ commands/,
|
|
43
45
|
enter: [/→ Run \(once\) \(y\) \(enter\)/, /▶ \[a\] Trust this workspace/],
|
|
46
|
+
fatal: [],
|
|
44
47
|
},
|
|
45
48
|
};
|
|
46
49
|
/**
|
|
@@ -253,11 +256,12 @@ export default async function claudeYes({
|
|
|
253
256
|
.lines({ EOL: 'NONE' })
|
|
254
257
|
// Generic auto-response handler driven by CLI_CONFIGURES
|
|
255
258
|
.forEach(async (e, i) => {
|
|
256
|
-
const conf =
|
|
259
|
+
const conf =
|
|
260
|
+
CLI_CONFIGURES[cli as keyof typeof CLI_CONFIGURES] || null;
|
|
257
261
|
if (!conf) return;
|
|
258
262
|
|
|
259
|
-
// ready matcher: if matched, mark stdin ready
|
|
260
263
|
try {
|
|
264
|
+
// ready matcher: if matched, mark stdin ready
|
|
261
265
|
if (conf.ready) {
|
|
262
266
|
// special-case gemini to avoid initial prompt noise: only after many lines
|
|
263
267
|
if (cli === 'gemini' && conf.ready instanceof RegExp) {
|
|
@@ -272,8 +276,6 @@ export default async function claudeYes({
|
|
|
272
276
|
for (const rx of conf.enter) {
|
|
273
277
|
if (e.match(rx)) return await sendEnter();
|
|
274
278
|
}
|
|
275
|
-
} else if (conf.enter && conf.enter instanceof RegExp) {
|
|
276
|
-
if (e.match(conf.enter)) return await sendEnter();
|
|
277
279
|
}
|
|
278
280
|
|
|
279
281
|
// fatal matchers: set isFatal flag when matched
|
|
@@ -281,8 +283,6 @@ export default async function claudeYes({
|
|
|
281
283
|
for (const rx of conf.fatal) {
|
|
282
284
|
if (e.match(rx)) return (isFatal = true);
|
|
283
285
|
}
|
|
284
|
-
} else if (conf.fatal && conf.fatal instanceof RegExp) {
|
|
285
|
-
if (e.match(conf.fatal)) return (isFatal = true);
|
|
286
286
|
}
|
|
287
287
|
} catch (err) {
|
|
288
288
|
// defensive: if e.match throws (e.g., not a string), ignore
|