chrome-cdp-cli 1.7.5 → 1.7.6
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
CHANGED
|
@@ -1,41 +1,16 @@
|
|
|
1
1
|
# Chrome DevTools CLI
|
|
2
2
|
|
|
3
|
+
A command-line tool for browser automation via Chrome DevTools Protocol (CDP). Designed for developers who need reliable, scriptable browser control with both dedicated commands and flexible JavaScript execution.
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
## 🤔 Why This Tool Exists
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
**The honest story:** I started using `chrome-devtools-mcp` like everyone else. It worked great... until it didn't. One day it just stopped working - Cursor showed 26 tools available, everything looked normal, but every single tool call threw errors. Classic black box problem: you can't debug what you can't see inside.
|
|
7
8
|
|
|
8
|
-
**
|
|
9
|
+
**The MCP reality check:** Model Context Protocol sounded promising, but let's be real - it's not exactly taking the world by storm. Meanwhile, Anthropic introduced the SKILL concept, which actually makes sense for how LLMs work. And what pairs perfectly with Skills? Good old-fashioned command-line tools. They're debuggable, efficient, and you can actually see what's happening when things go wrong.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
**The pragmatic solution:** Instead of wrestling with mysterious MCP failures, why not build a CLI that just works? One that you can debug, extend, and actually understand. Plus, when your AI assistant needs to automate a browser, it can just write the command and execute it - no black boxes, no mysterious failures, just straightforward automation.
|
|
11
12
|
|
|
12
|
-
**The
|
|
13
|
-
|
|
14
|
-
1. **🧠 LLMs Excel at JavaScript**: Large Language Models are exceptionally good at writing JavaScript code. They can generate complex automation scripts, handle async operations, and adapt to different scenarios - all in JavaScript.
|
|
15
|
-
|
|
16
|
-
2. **⚡ Rapid Script Validation**: LLMs can write a script, test it immediately with `eval`, see the results, and refine it in seconds. This iterative loop is where LLMs shine.
|
|
17
|
-
|
|
18
|
-
3. **🔄 Maximum Flexibility**: Instead of waiting for specific commands to be implemented, LLMs can accomplish any browser task through JavaScript execution. Need to click an element? `document.querySelector('#btn').click()`. Need to wait for content? `await new Promise(...)`. Need complex data extraction? Just write the JavaScript.
|
|
19
|
-
|
|
20
|
-
4. **🎯 Perfect for AI Workflows**: When you ask Claude or Cursor to automate a browser task, they can write the JavaScript directly - no need to learn complex CLI syntax or wait for feature implementations.
|
|
21
|
-
|
|
22
|
-
### IDE Integration for LLM Workflows
|
|
23
|
-
|
|
24
|
-
**Built-in support for AI development environments:**
|
|
25
|
-
|
|
26
|
-
- **🖥️ Cursor Commands**: Install with `install-cursor-command` - brings browser automation directly into Cursor's command palette
|
|
27
|
-
- **🤖 Claude Skills**: Install with `install-claude-skill` - enables Claude to use browser automation in conversations
|
|
28
|
-
- **⚡ Seamless Integration**: AI assistants can generate automation scripts and execute them instantly through these integrations
|
|
29
|
-
|
|
30
|
-
**Why this matters:** When LLMs are integrated into your IDE, they can write browser automation scripts as part of your development workflow. The eval-first approach means they can accomplish any task without waiting for specific command implementations.
|
|
31
|
-
|
|
32
|
-
### The LLM Advantage
|
|
33
|
-
|
|
34
|
-
- **🧠 Natural Language → JavaScript**: Ask an LLM "click the submit button" → it generates `document.querySelector('#submit').click()`
|
|
35
|
-
- **⚡ Instant Testing**: Write, execute, see results, refine - all in seconds
|
|
36
|
-
- **🔄 Iterative Refinement**: LLMs can adjust scripts based on results immediately
|
|
37
|
-
- **📚 Context-Aware**: AI understands your project and can write automation scripts that fit your specific needs
|
|
38
|
-
- **🎯 No Learning Curve**: LLMs already know JavaScript - no need to learn CLI-specific syntax
|
|
13
|
+
**The result:** A tool that's both powerful enough for complex automation and simple enough that you (and your AI assistant) can actually use it without pulling your hair out.
|
|
39
14
|
|
|
40
15
|
## Implementation Status
|
|
41
16
|
|
|
@@ -51,39 +26,39 @@ A command-line tool designed specifically for Large Language Models (LLMs) and A
|
|
|
51
26
|
- 🛠️ **IDE Integration**: Install Cursor commands and Claude skills with directory validation and --force option
|
|
52
27
|
- 📦 **Build System**: Complete TypeScript build pipeline with testing framework
|
|
53
28
|
|
|
54
|
-
### 🚧
|
|
29
|
+
### 🚧 Available via JavaScript Execution
|
|
55
30
|
|
|
56
|
-
|
|
31
|
+
For maximum flexibility, many advanced features are available through the `eval` command. This approach is particularly powerful for AI assistants and complex automation scenarios:
|
|
57
32
|
|
|
58
33
|
- 📄 **Page Navigation**: `eval "window.location.href = 'https://example.com'"`
|
|
59
34
|
- 🚀 **Performance Data**: `eval "performance.now()"` or `eval "performance.getEntriesByType('navigation')"`
|
|
60
35
|
- 📱 **User Agent**: `eval "navigator.userAgent"`
|
|
61
36
|
- 🌐 **Network Requests**: `eval "fetch('/api').then(r => r.json())"`
|
|
62
37
|
|
|
63
|
-
**Why
|
|
38
|
+
**Why JavaScript execution is powerful:**
|
|
64
39
|
|
|
65
|
-
1. **
|
|
66
|
-
2. **Rapid
|
|
67
|
-
3. **
|
|
68
|
-
4. **
|
|
69
|
-
5. **Maximum flexibility**:
|
|
40
|
+
1. **Universal capability**: Any browser API, any complexity level, any scenario
|
|
41
|
+
2. **Rapid prototyping**: Write → Execute → See Results → Refine
|
|
42
|
+
3. **AI-friendly**: Perfect for AI assistants that excel at JavaScript
|
|
43
|
+
4. **No waiting**: Accomplish tasks immediately without waiting for feature implementations
|
|
44
|
+
5. **Maximum flexibility**: Handle edge cases and custom scenarios easily
|
|
70
45
|
|
|
71
|
-
**This
|
|
46
|
+
**This provides both dedicated commands for common tasks and unlimited flexibility through JavaScript execution.**
|
|
72
47
|
|
|
73
|
-
### 🎯 IDE Integration - Built for
|
|
48
|
+
### 🎯 IDE Integration - Built for Modern Development
|
|
74
49
|
|
|
75
50
|
**Why we support Cursor Commands & Claude Skills:**
|
|
76
51
|
|
|
77
|
-
This tool
|
|
52
|
+
This tool integrates seamlessly with modern AI-powered development environments. The IDE integrations (`install-cursor-command` and `install-claude-skill`) bring browser automation directly into your workflow:
|
|
78
53
|
|
|
79
|
-
- **🔄 Seamless
|
|
80
|
-
- **🧠
|
|
81
|
-
- **⚡ Instant
|
|
82
|
-
- **📚 Context-Aware
|
|
83
|
-
- **🎯 Natural Language → Automation**: Ask "click the submit button" → AI generates
|
|
54
|
+
- **🔄 Seamless Workflow**: AI assistants can write and execute browser automation scripts directly in your IDE
|
|
55
|
+
- **🧠 Natural Integration**: JavaScript execution means AI can accomplish any browser task
|
|
56
|
+
- **⚡ Instant Execution**: Write scripts → execute via commands → see results → refine in real-time
|
|
57
|
+
- **📚 Context-Aware**: AI understands your project context and generates relevant automation
|
|
58
|
+
- **🎯 Natural Language → Automation**: Ask "click the submit button" → AI generates and executes the solution
|
|
84
59
|
- **🤖 Perfect for AI Assistants**: Claude and Cursor can use browser automation as part of their toolset
|
|
85
60
|
|
|
86
|
-
**The integration exists because
|
|
61
|
+
**The integration exists because modern development is AI-assisted - these tools work together to enable efficient browser automation.**
|
|
87
62
|
|
|
88
63
|
### ⏳ Not Yet Implemented
|
|
89
64
|
|
|
@@ -437,7 +412,7 @@ chrome-cdp-cli install_cursor_command --force
|
|
|
437
412
|
chrome-cdp-cli install_claude_skill --force
|
|
438
413
|
```
|
|
439
414
|
|
|
440
|
-
### 🚧 Available via
|
|
415
|
+
### 🚧 Available via JavaScript Execution
|
|
441
416
|
|
|
442
417
|
#### Page Management
|
|
443
418
|
```bash
|
|
@@ -464,7 +439,7 @@ chrome-cdp-cli click "#button"
|
|
|
464
439
|
chrome-cdp-cli hover ".menu-item"
|
|
465
440
|
chrome-cdp-cli fill "#email" "user@example.com"
|
|
466
441
|
|
|
467
|
-
# Via
|
|
442
|
+
# Via JavaScript execution (flexible for complex scenarios)
|
|
468
443
|
chrome-cdp-cli eval "document.querySelector('#button').click()"
|
|
469
444
|
chrome-cdp-cli eval "document.querySelector('.menu-item').dispatchEvent(new MouseEvent('mouseover'))"
|
|
470
445
|
chrome-cdp-cli eval "document.querySelector('#email').value = 'user@example.com'"
|
|
@@ -492,7 +467,7 @@ chrome-cdp-cli fill_form --fields '[
|
|
|
492
467
|
chrome-cdp-cli fill "#name" "John Doe"
|
|
493
468
|
chrome-cdp-cli fill "#email" "john@example.com"
|
|
494
469
|
|
|
495
|
-
# Via
|
|
470
|
+
# Via JavaScript execution (for complex form operations)
|
|
496
471
|
chrome-cdp-cli eval "
|
|
497
472
|
document.querySelector('#name').value = 'John Doe';
|
|
498
473
|
document.querySelector('#email').value = 'john@example.com';
|
|
@@ -505,7 +480,7 @@ chrome-cdp-cli eval "document.querySelector('#myform').submit()"
|
|
|
505
480
|
# Select dropdown option (native)
|
|
506
481
|
chrome-cdp-cli fill "#dropdown" "option1"
|
|
507
482
|
|
|
508
|
-
# Select dropdown option (via
|
|
483
|
+
# Select dropdown option (via JavaScript execution)
|
|
509
484
|
chrome-cdp-cli eval "document.querySelector('#dropdown').value = 'option1'"
|
|
510
485
|
|
|
511
486
|
# Check checkbox
|
|
@@ -690,25 +665,25 @@ new Promise(resolve => {
|
|
|
690
665
|
- Quiet and verbose modes
|
|
691
666
|
- Custom output templates
|
|
692
667
|
|
|
693
|
-
### Why
|
|
668
|
+
### Why JavaScript Execution? (Built for Modern Development)
|
|
694
669
|
|
|
695
|
-
**This is not a workaround - it's
|
|
670
|
+
**This is not a workaround - it's a core design philosophy optimized for modern development workflows:**
|
|
696
671
|
|
|
697
|
-
1. **🧠
|
|
672
|
+
1. **🧠 Universal Language**: JavaScript is the language of the web. Developers and AI assistants alike excel at writing JavaScript for browser automation.
|
|
698
673
|
|
|
699
|
-
2. **⚡ Rapid
|
|
674
|
+
2. **⚡ Rapid Prototyping**: The perfect workflow: Write JavaScript → Execute → See Results → Refine. This iterative loop is ideal for both human developers and AI assistants.
|
|
700
675
|
|
|
701
676
|
3. **🔄 Maximum Flexibility**: Any browser task, any complexity, any scenario - all through JavaScript. No waiting for specific command implementations.
|
|
702
677
|
|
|
703
|
-
4. **🤖 AI-Native Workflow**: When you ask Claude or Cursor to automate something, they write JavaScript - exactly what `eval` executes.
|
|
678
|
+
4. **🤖 AI-Native Workflow**: When you ask Claude or Cursor to automate something, they naturally write JavaScript - exactly what the `eval` command executes.
|
|
704
679
|
|
|
705
680
|
5. **📚 Natural Language → Automation**: "Click the submit button" → AI generates `document.querySelector('#submit').click()` → Executes instantly.
|
|
706
681
|
|
|
707
682
|
6. **🎯 Context-Aware**: AI understands your project and can write automation scripts that fit your specific needs.
|
|
708
683
|
|
|
709
|
-
7. **⚡ Instant Iteration**:
|
|
684
|
+
7. **⚡ Instant Iteration**: Both developers and AI can adjust scripts based on results immediately - no need to wait for feature releases.
|
|
710
685
|
|
|
711
|
-
**This tool
|
|
686
|
+
**This tool bridges the gap between dedicated commands for common tasks and unlimited flexibility through JavaScript execution, making it perfect for both traditional development and AI-assisted workflows.**
|
|
712
687
|
|
|
713
688
|
## Form Filling & Element Interaction
|
|
714
689
|
|
|
@@ -35,28 +35,45 @@ class CLIApplication {
|
|
|
35
35
|
this.cli.registerHandler(new handlers_1.WaitForHandler());
|
|
36
36
|
this.cli.registerHandler(new handlers_1.HandleDialogHandler());
|
|
37
37
|
}
|
|
38
|
+
configureDebugMode(debug) {
|
|
39
|
+
const registry = this.cli.getRegistry();
|
|
40
|
+
const handlerNames = registry.getCommandNames();
|
|
41
|
+
for (const handlerName of handlerNames) {
|
|
42
|
+
const handler = registry.get(handlerName);
|
|
43
|
+
if (handler && typeof handler.setDebug === 'function') {
|
|
44
|
+
handler.setDebug(debug);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
38
48
|
async run(argv) {
|
|
39
49
|
try {
|
|
40
|
-
console.log('[DEBUG] CLIApplication.run called with argv:', argv);
|
|
41
50
|
const command = this.cli.parseArgs(argv);
|
|
42
|
-
|
|
51
|
+
if (command.config.debug) {
|
|
52
|
+
this.logger.setLevel(3);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.logger.setLevel(2);
|
|
56
|
+
}
|
|
57
|
+
this.configureDebugMode(command.config.debug);
|
|
58
|
+
this.logger.debug('CLIApplication.run called with argv:', argv);
|
|
59
|
+
this.logger.debug('Parsed command:', command);
|
|
43
60
|
if (command.config.verbose) {
|
|
44
61
|
this.proxyManager.setLogging(true);
|
|
45
62
|
}
|
|
46
|
-
|
|
63
|
+
this.logger.debug('Ensuring proxy is ready...');
|
|
47
64
|
await this.ensureProxyReady();
|
|
48
65
|
if (this.needsConnection(command.name)) {
|
|
49
|
-
|
|
66
|
+
this.logger.debug('Command needs connection, ensuring connection...');
|
|
50
67
|
await this.ensureConnection(command);
|
|
51
68
|
}
|
|
52
|
-
|
|
69
|
+
this.logger.debug('Executing command via CLI interface...');
|
|
53
70
|
const result = await this.cli.execute(command);
|
|
54
|
-
|
|
71
|
+
this.logger.debug('Command execution result:', result);
|
|
55
72
|
this.outputResult(result, command);
|
|
56
73
|
return result.exitCode || (result.success ? CommandRouter_1.ExitCode.SUCCESS : CommandRouter_1.ExitCode.GENERAL_ERROR);
|
|
57
74
|
}
|
|
58
75
|
catch (error) {
|
|
59
|
-
|
|
76
|
+
this.logger.debug('Error in CLIApplication.run:', error);
|
|
60
77
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
61
78
|
console.error(`Error: ${errorMessage}`);
|
|
62
79
|
return CommandRouter_1.ExitCode.GENERAL_ERROR;
|
package/dist/cli/CLIInterface.js
CHANGED
|
@@ -61,6 +61,7 @@ class CLIInterface {
|
|
|
61
61
|
.option('-v, --verbose', 'Enable verbose logging', CLIInterface_1.DEFAULT_CLI_CONFIG.verbose)
|
|
62
62
|
.option('-q, --quiet', 'Enable quiet mode', CLIInterface_1.DEFAULT_CLI_CONFIG.quiet)
|
|
63
63
|
.option('-t, --timeout <timeout>', 'Command timeout in milliseconds', (value) => parseInt(value, 10), CLIInterface_1.DEFAULT_CLI_CONFIG.timeout)
|
|
64
|
+
.option('-d, --debug', 'Enable debug logging', CLIInterface_1.DEFAULT_CLI_CONFIG.debug)
|
|
64
65
|
.option('-c, --config <config>', 'Configuration file path');
|
|
65
66
|
}
|
|
66
67
|
parseArgs(argv) {
|
|
@@ -77,7 +78,12 @@ class CLIInterface {
|
|
|
77
78
|
const arg = args[i];
|
|
78
79
|
if (arg.startsWith('--')) {
|
|
79
80
|
const optionName = arg.substring(2);
|
|
80
|
-
|
|
81
|
+
const booleanFlags = ['verbose', 'quiet', 'debug'];
|
|
82
|
+
if (booleanFlags.includes(optionName)) {
|
|
83
|
+
options[optionName] = true;
|
|
84
|
+
i++;
|
|
85
|
+
}
|
|
86
|
+
else if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
81
87
|
options[optionName] = args[i + 1];
|
|
82
88
|
i += 2;
|
|
83
89
|
}
|
|
@@ -88,7 +94,12 @@ class CLIInterface {
|
|
|
88
94
|
}
|
|
89
95
|
else if (arg.startsWith('-') && arg.length > 1) {
|
|
90
96
|
const shortOption = arg.substring(1);
|
|
91
|
-
|
|
97
|
+
const booleanShortFlags = ['v', 'q', 'd'];
|
|
98
|
+
if (booleanShortFlags.includes(shortOption)) {
|
|
99
|
+
options[shortOption] = true;
|
|
100
|
+
i++;
|
|
101
|
+
}
|
|
102
|
+
else if (i + 1 < args.length && !args[i + 1].startsWith('-')) {
|
|
92
103
|
options[shortOption] = args[i + 1];
|
|
93
104
|
i += 2;
|
|
94
105
|
}
|
|
@@ -114,6 +125,8 @@ class CLIInterface {
|
|
|
114
125
|
options.quiet = true;
|
|
115
126
|
if (options.t)
|
|
116
127
|
options.timeout = parseInt(options.t, 10);
|
|
128
|
+
if (options.d)
|
|
129
|
+
options.debug = true;
|
|
117
130
|
if (options.c)
|
|
118
131
|
options.config = options.c;
|
|
119
132
|
if (options.port && typeof options.port === 'string') {
|
|
@@ -163,7 +176,8 @@ class CLIInterface {
|
|
|
163
176
|
outputFormat: cliOptions.format || fileConfig.outputFormat || CLIInterface_1.DEFAULT_CLI_CONFIG.outputFormat,
|
|
164
177
|
verbose: cliOptions.verbose || fileConfig.verbose || CLIInterface_1.DEFAULT_CLI_CONFIG.verbose,
|
|
165
178
|
quiet: cliOptions.quiet || fileConfig.quiet || CLIInterface_1.DEFAULT_CLI_CONFIG.quiet,
|
|
166
|
-
timeout: cliOptions.timeout || fileConfig.timeout || CLIInterface_1.DEFAULT_CLI_CONFIG.timeout
|
|
179
|
+
timeout: cliOptions.timeout || fileConfig.timeout || CLIInterface_1.DEFAULT_CLI_CONFIG.timeout,
|
|
180
|
+
debug: cliOptions.debug || fileConfig.debug || CLIInterface_1.DEFAULT_CLI_CONFIG.debug
|
|
167
181
|
};
|
|
168
182
|
}
|
|
169
183
|
loadConfigFile(configPath) {
|
|
@@ -199,6 +213,9 @@ class CLIInterface {
|
|
|
199
213
|
if (config.timeout !== undefined && (typeof config.timeout !== 'number' || config.timeout < 1)) {
|
|
200
214
|
throw new Error('Configuration "timeout" must be a positive number');
|
|
201
215
|
}
|
|
216
|
+
if (config.debug !== undefined && typeof config.debug !== 'boolean') {
|
|
217
|
+
throw new Error('Configuration "debug" must be a boolean');
|
|
218
|
+
}
|
|
202
219
|
}
|
|
203
220
|
extractCommandArgs(command, args, options) {
|
|
204
221
|
const commandArgs = {};
|
|
@@ -169,18 +169,24 @@ class CommandRouter {
|
|
|
169
169
|
}
|
|
170
170
|
async executeWithTimeout(handler, command) {
|
|
171
171
|
const timeout = command.config.timeout;
|
|
172
|
-
|
|
172
|
+
if (command.config.debug) {
|
|
173
|
+
this.logger.setLevel(3);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
this.logger.setLevel(2);
|
|
177
|
+
}
|
|
178
|
+
this.logger.debug(`CommandRouter.executeWithTimeout called for command: ${command.name}, timeout: ${timeout}ms`);
|
|
173
179
|
const timeoutPromise = new Promise((_, reject) => {
|
|
174
180
|
setTimeout(() => {
|
|
175
|
-
|
|
181
|
+
this.logger.debug(`Command timeout reached for: ${command.name} after ${timeout}ms`);
|
|
176
182
|
reject(new Error(`Command timeout after ${timeout}ms`));
|
|
177
183
|
}, timeout);
|
|
178
184
|
});
|
|
179
|
-
|
|
185
|
+
this.logger.debug(`Starting handler execution for: ${command.name}`);
|
|
180
186
|
const executionPromise = handler.execute(this.client, command.args);
|
|
181
187
|
try {
|
|
182
188
|
const result = await Promise.race([executionPromise, timeoutPromise]);
|
|
183
|
-
|
|
189
|
+
this.logger.debug(`Command completed successfully for: ${command.name}`);
|
|
184
190
|
if (!result || typeof result !== 'object') {
|
|
185
191
|
return {
|
|
186
192
|
success: false,
|
|
@@ -194,7 +200,7 @@ class CommandRouter {
|
|
|
194
200
|
return result;
|
|
195
201
|
}
|
|
196
202
|
catch (error) {
|
|
197
|
-
|
|
203
|
+
this.logger.debug(`Command execution error for: ${command.name}:`, error);
|
|
198
204
|
if (error instanceof Error && error.message.includes('timeout')) {
|
|
199
205
|
return {
|
|
200
206
|
success: false,
|
|
@@ -218,6 +224,7 @@ Global Options:
|
|
|
218
224
|
-v, --verbose Enable verbose logging
|
|
219
225
|
-q, --quiet Enable quiet mode
|
|
220
226
|
-t, --timeout <ms> Command timeout in milliseconds (default: 30000)
|
|
227
|
+
-d, --debug Enable debug logging
|
|
221
228
|
-c, --config <path> Configuration file path
|
|
222
229
|
-V, --version Show version number
|
|
223
230
|
|
|
@@ -5,16 +5,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.EvaluateScriptHandler = void 0;
|
|
7
7
|
const ProxyClient_1 = require("../client/ProxyClient");
|
|
8
|
+
const logger_1 = require("../utils/logger");
|
|
8
9
|
const fs_1 = require("fs");
|
|
9
10
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
10
11
|
class EvaluateScriptHandler {
|
|
11
|
-
constructor(useProxy = false) {
|
|
12
|
+
constructor(useProxy = false, debug = false) {
|
|
12
13
|
this.name = 'eval';
|
|
13
14
|
this.proxyClient = new ProxyClient_1.ProxyClient();
|
|
14
15
|
this.useProxy = useProxy;
|
|
16
|
+
this.logger = new logger_1.Logger();
|
|
17
|
+
if (debug) {
|
|
18
|
+
this.logger.setLevel(3);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.logger.setLevel(2);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
setDebug(debug) {
|
|
25
|
+
if (debug) {
|
|
26
|
+
this.logger.setLevel(3);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.logger.setLevel(2);
|
|
30
|
+
}
|
|
15
31
|
}
|
|
16
32
|
async execute(client, args) {
|
|
17
|
-
|
|
33
|
+
this.logger.debug('EvaluateScriptHandler.execute called with args:', args);
|
|
18
34
|
const scriptArgs = args;
|
|
19
35
|
if (!scriptArgs.expression && !scriptArgs.file) {
|
|
20
36
|
return {
|
|
@@ -28,17 +44,17 @@ class EvaluateScriptHandler {
|
|
|
28
44
|
error: 'Cannot specify both "expression" and "file" arguments'
|
|
29
45
|
};
|
|
30
46
|
}
|
|
31
|
-
|
|
47
|
+
this.logger.debug('Arguments validated, useProxy:', this.useProxy);
|
|
32
48
|
try {
|
|
33
49
|
if (this.useProxy) {
|
|
34
|
-
|
|
50
|
+
this.logger.debug('Checking proxy availability...');
|
|
35
51
|
const proxyAvailable = await this.proxyClient.isProxyAvailable();
|
|
36
|
-
|
|
52
|
+
this.logger.debug('Proxy available:', proxyAvailable);
|
|
37
53
|
if (proxyAvailable) {
|
|
38
54
|
console.log('[INFO] Using proxy connection for script evaluation');
|
|
39
|
-
|
|
55
|
+
this.logger.debug('About to call executeWithProxy...');
|
|
40
56
|
const result = await this.executeWithProxy(scriptArgs);
|
|
41
|
-
|
|
57
|
+
this.logger.debug('executeWithProxy returned:', result);
|
|
42
58
|
return result;
|
|
43
59
|
}
|
|
44
60
|
else {
|
|
@@ -49,12 +65,12 @@ class EvaluateScriptHandler {
|
|
|
49
65
|
catch (error) {
|
|
50
66
|
console.warn('[WARN] Proxy execution failed, falling back to direct CDP:', error instanceof Error ? error.message : error);
|
|
51
67
|
}
|
|
52
|
-
|
|
68
|
+
this.logger.debug('Falling back to direct CDP');
|
|
53
69
|
return await this.executeWithDirectCDP(client, scriptArgs);
|
|
54
70
|
}
|
|
55
71
|
async executeWithProxy(scriptArgs) {
|
|
56
72
|
try {
|
|
57
|
-
|
|
73
|
+
this.logger.debug('Starting executeWithProxy');
|
|
58
74
|
let expression;
|
|
59
75
|
if (scriptArgs.file) {
|
|
60
76
|
expression = await this.readScriptFile(scriptArgs.file);
|
|
@@ -62,10 +78,10 @@ class EvaluateScriptHandler {
|
|
|
62
78
|
else {
|
|
63
79
|
expression = scriptArgs.expression;
|
|
64
80
|
}
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
this.logger.debug('Expression to execute:', expression.substring(0, 100));
|
|
82
|
+
this.logger.debug('Creating new proxy connection...');
|
|
67
83
|
const connectionId = await this.proxyClient.connect('localhost', 9222);
|
|
68
|
-
|
|
84
|
+
this.logger.debug(`Created new proxy connection: ${connectionId}`);
|
|
69
85
|
try {
|
|
70
86
|
const result = await this.executeScriptThroughHTTP(connectionId, expression, scriptArgs);
|
|
71
87
|
return {
|
|
@@ -78,7 +94,7 @@ class EvaluateScriptHandler {
|
|
|
78
94
|
}
|
|
79
95
|
}
|
|
80
96
|
catch (error) {
|
|
81
|
-
|
|
97
|
+
this.logger.debug('Error in executeWithProxy:', error);
|
|
82
98
|
return {
|
|
83
99
|
success: false,
|
|
84
100
|
error: error instanceof Error ? error.message : String(error)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-cdp-cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.6",
|
|
4
4
|
"description": "Browser automation CLI via Chrome DevTools Protocol. Designed for developers and AI assistants - combines dedicated commands for common tasks with flexible JavaScript execution for complex scenarios. Features: element interaction, screenshots, DOM snapshots, console/network monitoring. Built-in IDE integration for Cursor and Claude.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|