chrome-cdp-cli 2.1.0 ā 2.1.2
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 +380 -955
- package/dist/cli/EnhancedCLIInterface.js +48 -38
- package/dist/cli/OutputFormatter.js +77 -75
- package/dist/cli/OutputManager.js +20 -20
- package/dist/client/index.js +0 -1
- package/dist/handlers/EvaluateScriptHandler.js +74 -270
- package/package.json +1 -1
- package/dist/client/ProxyClient.js +0 -278
- package/dist/handlers/RestartProxyHandler.js +0 -97
- package/dist/proxy/ProxyManager.js +0 -270
- package/dist/proxy/index.js +0 -60
- package/dist/proxy/server/CDPEventMonitor.js +0 -263
- package/dist/proxy/server/CDPProxyServer.js +0 -441
- package/dist/proxy/server/CommandExecutionService.js +0 -297
- package/dist/proxy/server/ConnectionPool.js +0 -437
- package/dist/proxy/server/FileSystemSecurity.js +0 -358
- package/dist/proxy/server/HealthMonitor.js +0 -242
- package/dist/proxy/server/MessageStore.js +0 -291
- package/dist/proxy/server/PerformanceMonitor.js +0 -277
- package/dist/proxy/server/ProxyAPIServer.js +0 -1125
- package/dist/proxy/server/SecurityManager.js +0 -337
- package/dist/proxy/server/WSProxy.js +0 -468
- package/dist/proxy/types/ProxyTypes.js +0 -2
|
@@ -10,7 +10,7 @@ class OutputManager {
|
|
|
10
10
|
this.currentOperation = {
|
|
11
11
|
name: operationName,
|
|
12
12
|
startTime: Date.now(),
|
|
13
|
-
command
|
|
13
|
+
command,
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
endOperation(result) {
|
|
@@ -23,17 +23,17 @@ class OutputManager {
|
|
|
23
23
|
metadata = {
|
|
24
24
|
command: this.currentOperation.command.name,
|
|
25
25
|
args: this.currentOperation.command.args,
|
|
26
|
-
config: this.currentOperation.command.config
|
|
26
|
+
config: this.currentOperation.command.config,
|
|
27
27
|
};
|
|
28
28
|
operationConfig = this.currentOperation.command.config;
|
|
29
29
|
this.currentOperation = undefined;
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
32
|
operationConfig = {
|
|
33
|
-
outputFormat:
|
|
33
|
+
outputFormat: "text",
|
|
34
34
|
quiet: false,
|
|
35
35
|
verbose: false,
|
|
36
|
-
debug: false
|
|
36
|
+
debug: false,
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
const enhancedResult = (0, OutputFormatter_1.enhanceCommandResult)(result, timing, metadata);
|
|
@@ -51,7 +51,7 @@ class OutputManager {
|
|
|
51
51
|
const result = {
|
|
52
52
|
success: false,
|
|
53
53
|
error,
|
|
54
|
-
exitCode
|
|
54
|
+
exitCode,
|
|
55
55
|
};
|
|
56
56
|
const options = (0, OutputFormatter_1.createOutputOptions)(config, false, false);
|
|
57
57
|
return this.formatter.formatOutput(result, options);
|
|
@@ -59,7 +59,7 @@ class OutputManager {
|
|
|
59
59
|
formatSuccess(config, data) {
|
|
60
60
|
const result = {
|
|
61
61
|
success: true,
|
|
62
|
-
data
|
|
62
|
+
data,
|
|
63
63
|
};
|
|
64
64
|
const options = (0, OutputFormatter_1.createOutputOptions)(config, false, false);
|
|
65
65
|
return this.formatter.formatOutput(result, options);
|
|
@@ -69,14 +69,16 @@ class OutputManager {
|
|
|
69
69
|
name,
|
|
70
70
|
description,
|
|
71
71
|
template,
|
|
72
|
-
variables
|
|
72
|
+
variables,
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
getAvailableTemplates() {
|
|
76
76
|
return this.formatter.getAvailableTemplates();
|
|
77
77
|
}
|
|
78
78
|
shouldSuppressOutput(config, result) {
|
|
79
|
-
return config.quiet &&
|
|
79
|
+
return (config.quiet &&
|
|
80
|
+
result.success &&
|
|
81
|
+
(result.data === undefined || result.data === null));
|
|
80
82
|
}
|
|
81
83
|
getTimingInfo(startTime, endTime, operationName) {
|
|
82
84
|
const duration = endTime - startTime;
|
|
@@ -84,14 +86,12 @@ class OutputManager {
|
|
|
84
86
|
}
|
|
85
87
|
formatDataSourceInfo(dataSource, hasHistoricalData) {
|
|
86
88
|
if (!dataSource)
|
|
87
|
-
return
|
|
88
|
-
const sourceIcon =
|
|
89
|
-
const sourceText =
|
|
90
|
-
? 'Data from proxy server'
|
|
91
|
-
: 'Data from direct connection';
|
|
89
|
+
return "";
|
|
90
|
+
const sourceIcon = "ā ļø";
|
|
91
|
+
const sourceText = "Data from direct connection";
|
|
92
92
|
const historyText = hasHistoricalData
|
|
93
|
-
?
|
|
94
|
-
:
|
|
93
|
+
? "(includes historical data)"
|
|
94
|
+
: "(new data only)";
|
|
95
95
|
return `${sourceIcon} ${sourceText} ${historyText}`;
|
|
96
96
|
}
|
|
97
97
|
createProgressIndicator(message) {
|
|
@@ -99,8 +99,8 @@ class OutputManager {
|
|
|
99
99
|
}
|
|
100
100
|
formatValidationErrors(errors) {
|
|
101
101
|
if (errors.length === 0)
|
|
102
|
-
return
|
|
103
|
-
let output =
|
|
102
|
+
return "";
|
|
103
|
+
let output = "ā Validation Errors:\n\n";
|
|
104
104
|
errors.forEach((error, index) => {
|
|
105
105
|
output += `${index + 1}. ${error.field}: ${error.message}\n`;
|
|
106
106
|
if (error.suggestion) {
|
|
@@ -112,7 +112,7 @@ class OutputManager {
|
|
|
112
112
|
formatHelpInfo(title, content, examples) {
|
|
113
113
|
let output = `š ${title}\n\n${content}\n`;
|
|
114
114
|
if (examples && examples.length > 0) {
|
|
115
|
-
output +=
|
|
115
|
+
output += "\nš” Examples:\n";
|
|
116
116
|
examples.forEach((example, index) => {
|
|
117
117
|
output += `${index + 1}. ${example}\n`;
|
|
118
118
|
});
|
|
@@ -127,7 +127,7 @@ class ProgressIndicator {
|
|
|
127
127
|
this.startTime = Date.now();
|
|
128
128
|
}
|
|
129
129
|
start() {
|
|
130
|
-
const frames = [
|
|
130
|
+
const frames = ["ā ", "ā ", "ā ¹", "ā ø", "ā ¼", "ā “", "ā ¦", "ā §", "ā ", "ā "];
|
|
131
131
|
let frameIndex = 0;
|
|
132
132
|
this.interval = setInterval(() => {
|
|
133
133
|
const elapsed = Date.now() - this.startTime;
|
|
@@ -141,7 +141,7 @@ class ProgressIndicator {
|
|
|
141
141
|
clearInterval(this.interval);
|
|
142
142
|
this.interval = undefined;
|
|
143
143
|
}
|
|
144
|
-
process.stdout.write(
|
|
144
|
+
process.stdout.write("\r\x1b[K");
|
|
145
145
|
}
|
|
146
146
|
updateMessage(message) {
|
|
147
147
|
this.message = message;
|
package/dist/client/index.js
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.EvaluateScriptHandler = void 0;
|
|
7
|
-
const ProxyClient_1 = require("../client/ProxyClient");
|
|
8
4
|
const logger_1 = require("../utils/logger");
|
|
9
5
|
const fs_1 = require("fs");
|
|
10
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
11
6
|
class EvaluateScriptHandler {
|
|
12
|
-
constructor(
|
|
13
|
-
this.name =
|
|
14
|
-
this.proxyClient = new ProxyClient_1.ProxyClient();
|
|
15
|
-
this.useProxy = useProxy;
|
|
7
|
+
constructor(debug = false) {
|
|
8
|
+
this.name = "eval";
|
|
16
9
|
this.logger = new logger_1.Logger();
|
|
17
10
|
if (debug) {
|
|
18
11
|
this.logger.setLevel(3);
|
|
@@ -22,55 +15,24 @@ class EvaluateScriptHandler {
|
|
|
22
15
|
}
|
|
23
16
|
}
|
|
24
17
|
setDebug(debug) {
|
|
25
|
-
|
|
26
|
-
this.logger.setLevel(3);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
this.logger.setLevel(2);
|
|
30
|
-
}
|
|
18
|
+
this.logger.setLevel(debug ? 3 : 2);
|
|
31
19
|
}
|
|
32
20
|
async execute(client, args) {
|
|
33
|
-
this.logger.debug(
|
|
21
|
+
this.logger.debug("EvaluateScriptHandler.execute called with args:", args);
|
|
34
22
|
const scriptArgs = args;
|
|
35
23
|
if (!scriptArgs.expression && !scriptArgs.file) {
|
|
36
24
|
return {
|
|
37
25
|
success: false,
|
|
38
|
-
error: 'Either "expression" or "file" argument is required'
|
|
26
|
+
error: 'Either "expression" or "file" argument is required',
|
|
39
27
|
};
|
|
40
28
|
}
|
|
41
29
|
if (scriptArgs.expression && scriptArgs.file) {
|
|
42
30
|
return {
|
|
43
31
|
success: false,
|
|
44
|
-
error: 'Cannot specify both "expression" and "file" arguments'
|
|
32
|
+
error: 'Cannot specify both "expression" and "file" arguments',
|
|
45
33
|
};
|
|
46
34
|
}
|
|
47
|
-
this.logger.debug('Arguments validated, useProxy:', this.useProxy);
|
|
48
35
|
try {
|
|
49
|
-
if (this.useProxy) {
|
|
50
|
-
this.logger.debug('Checking proxy availability...');
|
|
51
|
-
const proxyAvailable = await this.proxyClient.isProxyAvailable();
|
|
52
|
-
this.logger.debug('Proxy available:', proxyAvailable);
|
|
53
|
-
if (proxyAvailable) {
|
|
54
|
-
console.log('[INFO] Using proxy connection for script evaluation');
|
|
55
|
-
this.logger.debug('About to call executeWithProxy...');
|
|
56
|
-
const result = await this.executeWithProxy(scriptArgs);
|
|
57
|
-
this.logger.debug('executeWithProxy returned:', result);
|
|
58
|
-
return result;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
console.warn('[WARN] Proxy not available, falling back to direct CDP connection');
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
console.warn('[WARN] Proxy execution failed, falling back to direct CDP:', error instanceof Error ? error.message : error);
|
|
67
|
-
}
|
|
68
|
-
this.logger.debug('Falling back to direct CDP');
|
|
69
|
-
return await this.executeWithDirectCDP(client, scriptArgs);
|
|
70
|
-
}
|
|
71
|
-
async executeWithProxy(scriptArgs) {
|
|
72
|
-
try {
|
|
73
|
-
this.logger.debug('Starting executeWithProxy');
|
|
74
36
|
let expression;
|
|
75
37
|
if (scriptArgs.file) {
|
|
76
38
|
expression = await this.readScriptFile(scriptArgs.file);
|
|
@@ -78,128 +40,18 @@ class EvaluateScriptHandler {
|
|
|
78
40
|
else {
|
|
79
41
|
expression = scriptArgs.expression;
|
|
80
42
|
}
|
|
81
|
-
this.
|
|
82
|
-
this.logger.debug('Creating new proxy connection...');
|
|
83
|
-
const connectionId = await this.proxyClient.connect('localhost', 9222);
|
|
84
|
-
this.logger.debug(`Created new proxy connection: ${connectionId}`);
|
|
85
|
-
try {
|
|
86
|
-
const result = await this.executeScriptThroughHTTP(connectionId, expression, scriptArgs);
|
|
87
|
-
return {
|
|
88
|
-
success: true,
|
|
89
|
-
data: result
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
finally {
|
|
93
|
-
await this.proxyClient.disconnect();
|
|
94
|
-
}
|
|
43
|
+
return await this.executeWithTimeout(client, expression, scriptArgs);
|
|
95
44
|
}
|
|
96
45
|
catch (error) {
|
|
97
|
-
this.logger.debug('Error in executeWithProxy:', error);
|
|
98
46
|
return {
|
|
99
47
|
success: false,
|
|
100
|
-
error: error instanceof Error ? error.message : String(error)
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
async executeScriptThroughHTTP(connectionId, expression, args) {
|
|
105
|
-
const timeout = args.timeout || 30000;
|
|
106
|
-
const awaitPromise = args.awaitPromise ?? true;
|
|
107
|
-
const returnByValue = args.returnByValue ?? true;
|
|
108
|
-
console.log(`[DEBUG] Starting HTTP script execution, timeout: ${timeout}ms`);
|
|
109
|
-
console.log(`[DEBUG] Expression: ${expression.substring(0, 100)}${expression.length > 100 ? '...' : ''}`);
|
|
110
|
-
try {
|
|
111
|
-
const proxyUrl = this.proxyClient.getConfig().proxyUrl;
|
|
112
|
-
const commandId = Date.now() + Math.floor(Math.random() * 10000);
|
|
113
|
-
const command = {
|
|
114
|
-
id: commandId,
|
|
115
|
-
method: 'Runtime.evaluate',
|
|
116
|
-
params: {
|
|
117
|
-
expression: expression,
|
|
118
|
-
awaitPromise: awaitPromise,
|
|
119
|
-
returnByValue: returnByValue,
|
|
120
|
-
userGesture: true,
|
|
121
|
-
generatePreview: false
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
console.log(`[DEBUG] Sending HTTP command to ${proxyUrl}/api/execute/${connectionId}`);
|
|
125
|
-
const controller = new AbortController();
|
|
126
|
-
const timeoutHandle = setTimeout(() => controller.abort(), timeout);
|
|
127
|
-
try {
|
|
128
|
-
const response = await (0, node_fetch_1.default)(`${proxyUrl}/api/execute/${connectionId}`, {
|
|
129
|
-
method: 'POST',
|
|
130
|
-
headers: {
|
|
131
|
-
'Content-Type': 'application/json',
|
|
132
|
-
'x-client-id': `eval_handler_${Date.now()}`
|
|
133
|
-
},
|
|
134
|
-
body: JSON.stringify({
|
|
135
|
-
command,
|
|
136
|
-
timeout
|
|
137
|
-
}),
|
|
138
|
-
signal: controller.signal
|
|
139
|
-
});
|
|
140
|
-
clearTimeout(timeoutHandle);
|
|
141
|
-
if (!response.ok) {
|
|
142
|
-
const errorData = await response.json().catch(() => ({}));
|
|
143
|
-
throw new Error(`HTTP ${response.status}: ${errorData.error || response.statusText}`);
|
|
144
|
-
}
|
|
145
|
-
const result = await response.json();
|
|
146
|
-
console.log(`[DEBUG] HTTP command response:`, result);
|
|
147
|
-
if (!result.success) {
|
|
148
|
-
throw new Error(`Command execution failed: ${result.error || 'Unknown error'}`);
|
|
149
|
-
}
|
|
150
|
-
const commandResult = result.data.result;
|
|
151
|
-
if (result.data.error) {
|
|
152
|
-
throw new Error(`CDP Error: ${result.data.error.message}`);
|
|
153
|
-
}
|
|
154
|
-
if (commandResult.exceptionDetails) {
|
|
155
|
-
console.log(`[DEBUG] Exception details:`, commandResult.exceptionDetails);
|
|
156
|
-
const error = new Error(commandResult.result?.description || 'Script execution failed');
|
|
157
|
-
error.exceptionDetails = commandResult.exceptionDetails;
|
|
158
|
-
throw error;
|
|
159
|
-
}
|
|
160
|
-
let value = commandResult.result?.value;
|
|
161
|
-
if (commandResult.result?.type === 'undefined') {
|
|
162
|
-
value = '';
|
|
163
|
-
}
|
|
164
|
-
else if (commandResult.result?.unserializableValue) {
|
|
165
|
-
value = commandResult.result.unserializableValue;
|
|
166
|
-
}
|
|
167
|
-
console.log(`[DEBUG] Successful HTTP result:`, value);
|
|
168
|
-
return value;
|
|
169
|
-
}
|
|
170
|
-
catch (error) {
|
|
171
|
-
clearTimeout(timeoutHandle);
|
|
172
|
-
throw error;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
catch (error) {
|
|
176
|
-
console.log(`[DEBUG] Error in HTTP script execution:`, error);
|
|
177
|
-
throw error;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
async executeWithDirectCDP(client, scriptArgs) {
|
|
181
|
-
try {
|
|
182
|
-
let expression;
|
|
183
|
-
if (scriptArgs.file) {
|
|
184
|
-
expression = await this.readScriptFile(scriptArgs.file);
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
expression = scriptArgs.expression;
|
|
188
|
-
}
|
|
189
|
-
const result = await this.executeWithTimeout(client, expression, scriptArgs);
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
return {
|
|
194
|
-
success: false,
|
|
195
|
-
error: error instanceof Error ? error.message : String(error)
|
|
48
|
+
error: error instanceof Error ? error.message : String(error),
|
|
196
49
|
};
|
|
197
50
|
}
|
|
198
51
|
}
|
|
199
52
|
async readScriptFile(filePath) {
|
|
200
53
|
try {
|
|
201
|
-
|
|
202
|
-
return content;
|
|
54
|
+
return await fs_1.promises.readFile(filePath, "utf-8");
|
|
203
55
|
}
|
|
204
56
|
catch (error) {
|
|
205
57
|
throw new Error(`Failed to read script file "${filePath}": ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -210,171 +62,133 @@ class EvaluateScriptHandler {
|
|
|
210
62
|
const awaitPromise = args.awaitPromise ?? true;
|
|
211
63
|
const returnByValue = args.returnByValue ?? true;
|
|
212
64
|
const timeoutPromise = new Promise((_, reject) => {
|
|
213
|
-
setTimeout(() => {
|
|
214
|
-
reject(new Error(`Script execution timeout after ${timeout}ms`));
|
|
215
|
-
}, timeout);
|
|
65
|
+
setTimeout(() => reject(new Error(`Script execution timeout after ${timeout}ms`)), timeout);
|
|
216
66
|
});
|
|
217
67
|
const executionPromise = this.executeScript(client, expression, awaitPromise, returnByValue);
|
|
218
68
|
try {
|
|
219
|
-
|
|
220
|
-
return result;
|
|
69
|
+
return await Promise.race([executionPromise, timeoutPromise]);
|
|
221
70
|
}
|
|
222
71
|
catch (error) {
|
|
223
72
|
return {
|
|
224
73
|
success: false,
|
|
225
|
-
error: error instanceof Error ? error.message : String(error)
|
|
74
|
+
error: error instanceof Error ? error.message : String(error),
|
|
226
75
|
};
|
|
227
76
|
}
|
|
228
77
|
}
|
|
229
78
|
async executeScript(client, expression, awaitPromise, returnByValue) {
|
|
230
|
-
const consoleHandler = (params) =>
|
|
231
|
-
|
|
232
|
-
};
|
|
233
|
-
client.on('Runtime.consoleAPICalled', consoleHandler);
|
|
79
|
+
const consoleHandler = (params) => this.handleConsoleOutput(params);
|
|
80
|
+
client.on("Runtime.consoleAPICalled", consoleHandler);
|
|
234
81
|
try {
|
|
235
|
-
const response = (await client.send(
|
|
82
|
+
const response = (await client.send("Runtime.evaluate", {
|
|
236
83
|
expression,
|
|
237
84
|
awaitPromise,
|
|
238
85
|
returnByValue,
|
|
239
86
|
userGesture: true,
|
|
240
|
-
generatePreview: false
|
|
87
|
+
generatePreview: false,
|
|
241
88
|
}));
|
|
242
89
|
if (!response) {
|
|
243
|
-
return {
|
|
244
|
-
success: false,
|
|
245
|
-
error: 'CDP returned empty response'
|
|
246
|
-
};
|
|
90
|
+
return { success: false, error: "CDP returned empty response" };
|
|
247
91
|
}
|
|
248
92
|
if (response.exceptionDetails) {
|
|
249
93
|
return this.formatException(response.exceptionDetails);
|
|
250
94
|
}
|
|
251
95
|
if (!response.result) {
|
|
252
|
-
return {
|
|
253
|
-
success: false,
|
|
254
|
-
error: 'CDP response missing result field'
|
|
255
|
-
};
|
|
96
|
+
return { success: false, error: "CDP response missing result field" };
|
|
256
97
|
}
|
|
257
|
-
return {
|
|
258
|
-
success: true,
|
|
259
|
-
data: this.formatResult(response.result)
|
|
260
|
-
};
|
|
98
|
+
return { success: true, data: this.formatResult(response.result) };
|
|
261
99
|
}
|
|
262
100
|
catch (error) {
|
|
263
101
|
return {
|
|
264
102
|
success: false,
|
|
265
|
-
error: `CDP command failed: ${error instanceof Error ? error.message : String(error)}
|
|
103
|
+
error: `CDP command failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
266
104
|
};
|
|
267
105
|
}
|
|
268
106
|
finally {
|
|
269
|
-
client.off(
|
|
107
|
+
client.off("Runtime.consoleAPICalled", consoleHandler);
|
|
270
108
|
}
|
|
271
109
|
}
|
|
272
110
|
handleConsoleOutput(params) {
|
|
273
111
|
try {
|
|
274
|
-
const
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
112
|
+
const p = params;
|
|
113
|
+
const text = (p.args || [])
|
|
114
|
+
.map((a) => a.value !== undefined
|
|
115
|
+
? typeof a.value === "string"
|
|
116
|
+
? a.value
|
|
117
|
+
: JSON.stringify(a.value)
|
|
118
|
+
: a.description || "")
|
|
119
|
+
.join(" ");
|
|
120
|
+
const type = this.mapConsoleType(p.type);
|
|
121
|
+
if (type === "warn" || type === "error") {
|
|
122
|
+
process.stderr.write(text + "\n");
|
|
279
123
|
}
|
|
280
124
|
else {
|
|
281
|
-
process.
|
|
125
|
+
process.stdout.write(text + "\n");
|
|
282
126
|
}
|
|
283
127
|
}
|
|
284
|
-
catch
|
|
285
|
-
this.logger.debug('Error handling console output:', error);
|
|
128
|
+
catch {
|
|
286
129
|
}
|
|
287
130
|
}
|
|
288
|
-
formatConsoleArgs(args) {
|
|
289
|
-
return args.map(arg => {
|
|
290
|
-
if (arg.value !== undefined) {
|
|
291
|
-
if (typeof arg.value === 'string') {
|
|
292
|
-
return arg.value;
|
|
293
|
-
}
|
|
294
|
-
return JSON.stringify(arg.value);
|
|
295
|
-
}
|
|
296
|
-
return arg.description || '';
|
|
297
|
-
}).join(' ');
|
|
298
|
-
}
|
|
299
131
|
mapConsoleType(cdpType) {
|
|
300
132
|
switch (cdpType) {
|
|
301
|
-
case
|
|
302
|
-
return
|
|
303
|
-
case
|
|
304
|
-
return
|
|
305
|
-
case
|
|
306
|
-
return
|
|
307
|
-
case
|
|
308
|
-
return
|
|
309
|
-
case 'debug':
|
|
310
|
-
return 'debug';
|
|
133
|
+
case "warning":
|
|
134
|
+
return "warn";
|
|
135
|
+
case "error":
|
|
136
|
+
return "error";
|
|
137
|
+
case "info":
|
|
138
|
+
return "info";
|
|
139
|
+
case "debug":
|
|
140
|
+
return "debug";
|
|
311
141
|
default:
|
|
312
|
-
return
|
|
142
|
+
return "log";
|
|
313
143
|
}
|
|
314
144
|
}
|
|
315
145
|
formatException(exceptionDetails) {
|
|
316
146
|
if (!exceptionDetails) {
|
|
317
|
-
return {
|
|
318
|
-
success: false,
|
|
319
|
-
error: 'Unknown JavaScript error'
|
|
320
|
-
};
|
|
147
|
+
return { success: false, error: "Unknown JavaScript error" };
|
|
321
148
|
}
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
let stackTrace = '';
|
|
149
|
+
const errorMessage = exceptionDetails.exception?.description || exceptionDetails.text;
|
|
150
|
+
let stackTrace = "";
|
|
325
151
|
if (exceptionDetails.stackTrace?.callFrames) {
|
|
326
|
-
stackTrace =
|
|
327
|
-
|
|
328
|
-
.
|
|
329
|
-
|
|
152
|
+
stackTrace =
|
|
153
|
+
"\nStack trace:\n" +
|
|
154
|
+
exceptionDetails.stackTrace.callFrames
|
|
155
|
+
.map((f) => ` at ${f.functionName || "<anonymous>"} (${f.url}:${f.lineNumber}:${f.columnNumber})`)
|
|
156
|
+
.join("\n");
|
|
330
157
|
}
|
|
331
158
|
return {
|
|
332
159
|
success: false,
|
|
333
|
-
error: `JavaScript error at line ${exceptionDetails.lineNumber}, column ${exceptionDetails.columnNumber}: ${errorMessage}${stackTrace}
|
|
160
|
+
error: `JavaScript error at line ${exceptionDetails.lineNumber}, column ${exceptionDetails.columnNumber}: ${errorMessage}${stackTrace}`,
|
|
334
161
|
};
|
|
335
162
|
}
|
|
336
163
|
formatResult(result) {
|
|
337
|
-
if (!result)
|
|
338
|
-
return
|
|
339
|
-
|
|
340
|
-
if (result.type === 'undefined') {
|
|
341
|
-
return '';
|
|
342
|
-
}
|
|
343
|
-
if (result.value !== undefined) {
|
|
164
|
+
if (!result || result.type === "undefined")
|
|
165
|
+
return "";
|
|
166
|
+
if (result.value !== undefined)
|
|
344
167
|
return result.value;
|
|
345
|
-
|
|
346
|
-
if (result.objectId) {
|
|
168
|
+
if (result.objectId)
|
|
347
169
|
return {
|
|
348
170
|
type: result.type,
|
|
349
171
|
description: result.description,
|
|
350
|
-
objectId: result.objectId
|
|
172
|
+
objectId: result.objectId,
|
|
351
173
|
};
|
|
352
|
-
}
|
|
353
174
|
return result.description || result.type;
|
|
354
175
|
}
|
|
355
176
|
validateArgs(args) {
|
|
356
|
-
if (typeof args !==
|
|
177
|
+
if (typeof args !== "object" || args === null)
|
|
357
178
|
return false;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (!scriptArgs.expression && !scriptArgs.file) {
|
|
179
|
+
const a = args;
|
|
180
|
+
if (!a.expression && !a.file)
|
|
361
181
|
return false;
|
|
362
|
-
|
|
363
|
-
if (scriptArgs.expression && scriptArgs.file) {
|
|
182
|
+
if (a.expression && a.file)
|
|
364
183
|
return false;
|
|
365
|
-
|
|
366
|
-
if (scriptArgs.expression && typeof scriptArgs.expression !== 'string') {
|
|
184
|
+
if (a.expression && typeof a.expression !== "string")
|
|
367
185
|
return false;
|
|
368
|
-
|
|
369
|
-
if (scriptArgs.file && typeof scriptArgs.file !== 'string') {
|
|
186
|
+
if (a.file && typeof a.file !== "string")
|
|
370
187
|
return false;
|
|
371
|
-
|
|
372
|
-
if (scriptArgs.awaitPromise !== undefined && typeof scriptArgs.awaitPromise !== 'boolean') {
|
|
188
|
+
if (a.awaitPromise !== undefined && typeof a.awaitPromise !== "boolean")
|
|
373
189
|
return false;
|
|
374
|
-
|
|
375
|
-
if (scriptArgs.timeout !== undefined && typeof scriptArgs.timeout !== 'number') {
|
|
190
|
+
if (a.timeout !== undefined && typeof a.timeout !== "number")
|
|
376
191
|
return false;
|
|
377
|
-
}
|
|
378
192
|
return true;
|
|
379
193
|
}
|
|
380
194
|
getHelp() {
|
|
@@ -382,13 +196,13 @@ class EvaluateScriptHandler {
|
|
|
382
196
|
eval - Execute JavaScript code in the browser context
|
|
383
197
|
|
|
384
198
|
Usage:
|
|
385
|
-
eval "
|
|
386
|
-
eval --file script.js
|
|
387
|
-
eval "fetch('/api')"
|
|
388
|
-
eval "
|
|
199
|
+
cdp eval "document.title"
|
|
200
|
+
cdp eval --file script.js
|
|
201
|
+
cdp eval "await fetch('/api').then(r => r.json())"
|
|
202
|
+
cdp eval "heavyComputation()" --timeout 60000
|
|
389
203
|
|
|
390
204
|
Arguments:
|
|
391
|
-
<expression> JavaScript code to execute
|
|
205
|
+
<expression> JavaScript code to execute
|
|
392
206
|
--expression <code> JavaScript code to execute (explicit flag)
|
|
393
207
|
--file <path> Path to JavaScript file to execute
|
|
394
208
|
--await-promise Wait for Promise resolution (default: true)
|
|
@@ -396,20 +210,10 @@ Arguments:
|
|
|
396
210
|
--return-by-value Return result by value (default: true)
|
|
397
211
|
|
|
398
212
|
Examples:
|
|
399
|
-
|
|
400
|
-
eval "
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
eval --expression "2 + 2"
|
|
404
|
-
|
|
405
|
-
# Execute async code
|
|
406
|
-
eval "await fetch('/api').then(r => r.json())"
|
|
407
|
-
|
|
408
|
-
# Execute from file
|
|
409
|
-
eval --file ./scripts/init.js
|
|
410
|
-
|
|
411
|
-
# Set custom timeout
|
|
412
|
-
eval "heavyComputation()" --timeout 120000
|
|
213
|
+
cdp eval "2 + 2"
|
|
214
|
+
cdp eval "Array.from(document.links).map(l => l.href)"
|
|
215
|
+
cdp eval --file ./scripts/init.js
|
|
216
|
+
cdp eval "await new Promise(r => setTimeout(r, 5000))" --timeout 10000
|
|
413
217
|
`;
|
|
414
218
|
}
|
|
415
219
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrome-cdp-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
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",
|