@godscene/web 1.7.11
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 +7 -0
- package/bin/midscene-playground +3 -0
- package/bin/midscene-web +2 -0
- package/dist/es/bin.mjs +14 -0
- package/dist/es/bridge-mode/agent-cli-side.mjs +135 -0
- package/dist/es/bridge-mode/browser.mjs +2 -0
- package/dist/es/bridge-mode/common.mjs +41 -0
- package/dist/es/bridge-mode/index.mjs +4 -0
- package/dist/es/bridge-mode/io-client.mjs +99 -0
- package/dist/es/bridge-mode/io-server.mjs +218 -0
- package/dist/es/bridge-mode/page-browser-side.mjs +119 -0
- package/dist/es/cdp-proxy-constants.mjs +7 -0
- package/dist/es/cdp-proxy-manager.mjs +217 -0
- package/dist/es/cdp-proxy.mjs +151 -0
- package/dist/es/cdp-target-store.mjs +26 -0
- package/dist/es/chrome-extension/agent.mjs +8 -0
- package/dist/es/chrome-extension/cdpInput.mjs +172 -0
- package/dist/es/chrome-extension/cdpInput.mjs.LICENSE.txt +5 -0
- package/dist/es/chrome-extension/dynamic-scripts.mjs +36 -0
- package/dist/es/chrome-extension/index.mjs +5 -0
- package/dist/es/chrome-extension/page.mjs +733 -0
- package/dist/es/cli-options.mjs +97 -0
- package/dist/es/cli.mjs +26 -0
- package/dist/es/common/cache-helper.mjs +26 -0
- package/dist/es/common/viewport.mjs +36 -0
- package/dist/es/index.mjs +8 -0
- package/dist/es/mcp-server.mjs +33 -0
- package/dist/es/mcp-tools-cdp.mjs +164 -0
- package/dist/es/mcp-tools-puppeteer.mjs +246 -0
- package/dist/es/mcp-tools.mjs +81 -0
- package/dist/es/platform.mjs +37 -0
- package/dist/es/playwright/ai-fixture.mjs +364 -0
- package/dist/es/playwright/index.mjs +36 -0
- package/dist/es/playwright/page.mjs +42 -0
- package/dist/es/playwright/reporter/index.mjs +178 -0
- package/dist/es/puppeteer/agent-launcher.mjs +172 -0
- package/dist/es/puppeteer/base-page.mjs +830 -0
- package/dist/es/puppeteer/index.mjs +35 -0
- package/dist/es/puppeteer/page.mjs +7 -0
- package/dist/es/static/index.mjs +3 -0
- package/dist/es/static/static-agent.mjs +10 -0
- package/dist/es/static/static-page.mjs +123 -0
- package/dist/es/utils.mjs +6 -0
- package/dist/es/web-element.mjs +57 -0
- package/dist/es/web-page.mjs +272 -0
- package/dist/lib/bin.js +20 -0
- package/dist/lib/bridge-mode/agent-cli-side.js +172 -0
- package/dist/lib/bridge-mode/browser.js +36 -0
- package/dist/lib/bridge-mode/common.js +105 -0
- package/dist/lib/bridge-mode/index.js +44 -0
- package/dist/lib/bridge-mode/io-client.js +133 -0
- package/dist/lib/bridge-mode/io-server.js +255 -0
- package/dist/lib/bridge-mode/page-browser-side.js +163 -0
- package/dist/lib/cdp-proxy-constants.js +50 -0
- package/dist/lib/cdp-proxy-manager.js +273 -0
- package/dist/lib/cdp-proxy.js +179 -0
- package/dist/lib/cdp-target-store.js +66 -0
- package/dist/lib/chrome-extension/agent.js +42 -0
- package/dist/lib/chrome-extension/cdpInput.js +206 -0
- package/dist/lib/chrome-extension/cdpInput.js.LICENSE.txt +5 -0
- package/dist/lib/chrome-extension/dynamic-scripts.js +86 -0
- package/dist/lib/chrome-extension/index.js +58 -0
- package/dist/lib/chrome-extension/page.js +767 -0
- package/dist/lib/cli-options.js +131 -0
- package/dist/lib/cli.js +54 -0
- package/dist/lib/common/cache-helper.js +66 -0
- package/dist/lib/common/viewport.js +88 -0
- package/dist/lib/index.js +66 -0
- package/dist/lib/mcp-server.js +73 -0
- package/dist/lib/mcp-tools-cdp.js +208 -0
- package/dist/lib/mcp-tools-puppeteer.js +296 -0
- package/dist/lib/mcp-tools.js +115 -0
- package/dist/lib/platform.js +71 -0
- package/dist/lib/playwright/ai-fixture.js +401 -0
- package/dist/lib/playwright/index.js +89 -0
- package/dist/lib/playwright/page.js +76 -0
- package/dist/lib/playwright/reporter/index.js +212 -0
- package/dist/lib/puppeteer/agent-launcher.js +240 -0
- package/dist/lib/puppeteer/base-page.js +876 -0
- package/dist/lib/puppeteer/index.js +85 -0
- package/dist/lib/puppeteer/page.js +41 -0
- package/dist/lib/static/index.js +50 -0
- package/dist/lib/static/static-agent.js +44 -0
- package/dist/lib/static/static-page.js +157 -0
- package/dist/lib/utils.js +38 -0
- package/dist/lib/web-element.js +94 -0
- package/dist/lib/web-page.js +322 -0
- package/dist/types/bin.d.ts +1 -0
- package/dist/types/bridge-mode/agent-cli-side.d.ts +49 -0
- package/dist/types/bridge-mode/browser.d.ts +2 -0
- package/dist/types/bridge-mode/common.d.ts +74 -0
- package/dist/types/bridge-mode/index.d.ts +4 -0
- package/dist/types/bridge-mode/io-client.d.ts +10 -0
- package/dist/types/bridge-mode/io-server.d.ts +27 -0
- package/dist/types/bridge-mode/page-browser-side.d.ts +21 -0
- package/dist/types/cdp-proxy-constants.d.ts +4 -0
- package/dist/types/cdp-proxy-manager.d.ts +53 -0
- package/dist/types/cdp-proxy.d.ts +37 -0
- package/dist/types/cdp-target-store.d.ts +26 -0
- package/dist/types/chrome-extension/agent.d.ts +4 -0
- package/dist/types/chrome-extension/cdpInput.d.ts +52 -0
- package/dist/types/chrome-extension/dynamic-scripts.d.ts +3 -0
- package/dist/types/chrome-extension/index.d.ts +5 -0
- package/dist/types/chrome-extension/page.d.ts +120 -0
- package/dist/types/cli-options.d.ts +8 -0
- package/dist/types/cli.d.ts +1 -0
- package/dist/types/common/cache-helper.d.ts +20 -0
- package/dist/types/common/viewport.d.ts +17 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/mcp-server.d.ts +26 -0
- package/dist/types/mcp-tools-cdp.d.ts +23 -0
- package/dist/types/mcp-tools-puppeteer.d.ts +23 -0
- package/dist/types/mcp-tools.d.ts +14 -0
- package/dist/types/platform.d.ts +10 -0
- package/dist/types/playwright/ai-fixture.d.ts +133 -0
- package/dist/types/playwright/index.d.ts +13 -0
- package/dist/types/playwright/page.d.ts +11 -0
- package/dist/types/playwright/reporter/index.d.ts +28 -0
- package/dist/types/puppeteer/agent-launcher.d.ts +59 -0
- package/dist/types/puppeteer/base-page.d.ts +123 -0
- package/dist/types/puppeteer/index.d.ts +11 -0
- package/dist/types/puppeteer/page.d.ts +6 -0
- package/dist/types/static/index.d.ts +2 -0
- package/dist/types/static/static-agent.d.ts +5 -0
- package/dist/types/static/static-page.d.ts +46 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/types/web-element.d.ts +48 -0
- package/dist/types/web-page.d.ts +69 -0
- package/package.json +173 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module)=>{
|
|
5
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
14
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: definition[key]
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
})();
|
|
20
|
+
(()=>{
|
|
21
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
22
|
+
})();
|
|
23
|
+
(()=>{
|
|
24
|
+
__webpack_require__.r = (exports1)=>{
|
|
25
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
26
|
+
value: 'Module'
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
29
|
+
value: true
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
})();
|
|
33
|
+
var __webpack_exports__ = {};
|
|
34
|
+
__webpack_require__.r(__webpack_exports__);
|
|
35
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
36
|
+
killProxy: ()=>killProxy,
|
|
37
|
+
getProxyEndpoint: ()=>getProxyEndpoint,
|
|
38
|
+
readProxyUpstream: ()=>readProxyUpstream,
|
|
39
|
+
isProxyAlive: ()=>isProxyAlive,
|
|
40
|
+
readProxyEndpoint: ()=>readProxyEndpoint
|
|
41
|
+
});
|
|
42
|
+
const external_node_child_process_namespaceObject = require("node:child_process");
|
|
43
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
44
|
+
const external_node_http_namespaceObject = require("node:http");
|
|
45
|
+
var external_node_http_default = /*#__PURE__*/ __webpack_require__.n(external_node_http_namespaceObject);
|
|
46
|
+
const external_node_path_namespaceObject = require("node:path");
|
|
47
|
+
const logger_namespaceObject = require("@godscene/shared/logger");
|
|
48
|
+
const external_cdp_proxy_constants_js_namespaceObject = require("./cdp-proxy-constants.js");
|
|
49
|
+
const external_cdp_target_store_js_namespaceObject = require("./cdp-target-store.js");
|
|
50
|
+
const debug = (0, logger_namespaceObject.getDebug)('mcp:cdp:proxy');
|
|
51
|
+
const PROXY_TERM_GRACE_MS = 2000;
|
|
52
|
+
const PROXY_TERM_POLL_MS = 50;
|
|
53
|
+
const PROXY_STDERR_BUFFER_LIMIT = 8192;
|
|
54
|
+
const PROXY_STARTUP_TIMEOUT_MS = 10000;
|
|
55
|
+
function isPageLevelEndpoint(endpoint) {
|
|
56
|
+
return /\/devtools\/page\//.test(endpoint);
|
|
57
|
+
}
|
|
58
|
+
function resolveBrowserEndpoint(pageEndpoint) {
|
|
59
|
+
return new Promise((resolve, reject)=>{
|
|
60
|
+
let host;
|
|
61
|
+
try {
|
|
62
|
+
const url = new URL(pageEndpoint);
|
|
63
|
+
host = url.host;
|
|
64
|
+
} catch {
|
|
65
|
+
reject(new Error(`Invalid CDP endpoint URL: ${pageEndpoint}`));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const req = external_node_http_default().get(`http://${host}/json/version`, {
|
|
69
|
+
timeout: 5000
|
|
70
|
+
}, (res)=>{
|
|
71
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
72
|
+
reject(new Error(`/json/version returned HTTP ${res.statusCode}`));
|
|
73
|
+
res.resume();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
let data = '';
|
|
77
|
+
res.on('data', (chunk)=>{
|
|
78
|
+
data += chunk.toString();
|
|
79
|
+
});
|
|
80
|
+
res.on('end', ()=>{
|
|
81
|
+
try {
|
|
82
|
+
const info = JSON.parse(data);
|
|
83
|
+
if (info.webSocketDebuggerUrl) resolve(info.webSocketDebuggerUrl);
|
|
84
|
+
else reject(new Error('webSocketDebuggerUrl not found in /json/version response'));
|
|
85
|
+
} catch {
|
|
86
|
+
reject(new Error(`Failed to parse /json/version response: ${data}`));
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
req.on('error', (err)=>reject(new Error(`Failed to fetch /json/version: ${err.message}`)));
|
|
91
|
+
req.on('timeout', ()=>{
|
|
92
|
+
req.destroy();
|
|
93
|
+
reject(new Error('Timeout fetching /json/version'));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function isProxyAlive() {
|
|
98
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) return false;
|
|
99
|
+
try {
|
|
100
|
+
const pid = Number((0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE, 'utf-8').trim());
|
|
101
|
+
process.kill(pid, 0);
|
|
102
|
+
return true;
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function readProxyEndpoint() {
|
|
108
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE)) return null;
|
|
109
|
+
try {
|
|
110
|
+
return (0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE, 'utf-8').trim();
|
|
111
|
+
} catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function readProxyUpstream() {
|
|
116
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE)) return null;
|
|
117
|
+
try {
|
|
118
|
+
return (0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE, 'utf-8').trim();
|
|
119
|
+
} catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function sweepProxyMetadataFiles() {
|
|
124
|
+
try {
|
|
125
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE);
|
|
126
|
+
} catch {}
|
|
127
|
+
try {
|
|
128
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE);
|
|
129
|
+
} catch {}
|
|
130
|
+
try {
|
|
131
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE);
|
|
132
|
+
} catch {}
|
|
133
|
+
}
|
|
134
|
+
async function killProxy() {
|
|
135
|
+
(0, external_cdp_target_store_js_namespaceObject.cleanupTargetIdFile)();
|
|
136
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) return;
|
|
137
|
+
let pid;
|
|
138
|
+
try {
|
|
139
|
+
pid = Number((0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE, 'utf-8').trim());
|
|
140
|
+
if (!Number.isFinite(pid)) return void sweepProxyMetadataFiles();
|
|
141
|
+
} catch (err) {
|
|
142
|
+
debug('killProxy: cannot read pid file: %s', err);
|
|
143
|
+
sweepProxyMetadataFiles();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
process.kill(pid, 'SIGTERM');
|
|
148
|
+
debug('Sent SIGTERM to proxy pid %d', pid);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
debug('killProxy: SIGTERM failed (pid %d): %s', pid, err);
|
|
151
|
+
sweepProxyMetadataFiles();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const deadline = Date.now() + PROXY_TERM_GRACE_MS;
|
|
155
|
+
while(Date.now() < deadline && (0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE))await new Promise((r)=>setTimeout(r, PROXY_TERM_POLL_MS));
|
|
156
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) {
|
|
157
|
+
debug('proxy pid %d did not clean up within %dms, forcing SIGKILL', pid, PROXY_TERM_GRACE_MS);
|
|
158
|
+
try {
|
|
159
|
+
process.kill(pid, 'SIGKILL');
|
|
160
|
+
} catch {}
|
|
161
|
+
sweepProxyMetadataFiles();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function spawnProxy(chromeEndpoint) {
|
|
165
|
+
return new Promise((resolve, reject)=>{
|
|
166
|
+
const proxyScript = (0, external_node_path_namespaceObject.join)(__dirname, 'cdp-proxy.js');
|
|
167
|
+
const proc = (0, external_node_child_process_namespaceObject.spawn)(process.execPath, [
|
|
168
|
+
proxyScript,
|
|
169
|
+
chromeEndpoint
|
|
170
|
+
], {
|
|
171
|
+
detached: true,
|
|
172
|
+
stdio: [
|
|
173
|
+
'ignore',
|
|
174
|
+
'pipe',
|
|
175
|
+
'pipe'
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
proc.unref();
|
|
179
|
+
let output = '';
|
|
180
|
+
let stderrBuf = '';
|
|
181
|
+
let settled = false;
|
|
182
|
+
const appendStderr = (chunk)=>{
|
|
183
|
+
stderrBuf += chunk.toString();
|
|
184
|
+
if (stderrBuf.length > PROXY_STDERR_BUFFER_LIMIT) stderrBuf = stderrBuf.slice(-PROXY_STDERR_BUFFER_LIMIT);
|
|
185
|
+
};
|
|
186
|
+
proc.stderr.on('data', appendStderr);
|
|
187
|
+
const formatStderr = ()=>{
|
|
188
|
+
const trimmed = stderrBuf.trim();
|
|
189
|
+
return trimmed ? ` (stderr: ${trimmed})` : '';
|
|
190
|
+
};
|
|
191
|
+
const timer = setTimeout(()=>{
|
|
192
|
+
if (!settled) {
|
|
193
|
+
settled = true;
|
|
194
|
+
reject(new Error(`Proxy startup timeout (${PROXY_STARTUP_TIMEOUT_MS / 1000}s)${formatStderr()}`));
|
|
195
|
+
}
|
|
196
|
+
}, PROXY_STARTUP_TIMEOUT_MS);
|
|
197
|
+
const onData = (chunk)=>{
|
|
198
|
+
output += chunk.toString();
|
|
199
|
+
const lines = output.split('\n');
|
|
200
|
+
for (const line of lines)if (line.trim()) try {
|
|
201
|
+
const parsed = JSON.parse(line);
|
|
202
|
+
if (parsed.endpoint && !settled) {
|
|
203
|
+
settled = true;
|
|
204
|
+
clearTimeout(timer);
|
|
205
|
+
proc.stdout.removeListener('data', onData);
|
|
206
|
+
proc.stderr.removeListener('data', appendStderr);
|
|
207
|
+
proc.stdout.destroy();
|
|
208
|
+
proc.stderr.destroy();
|
|
209
|
+
resolve(parsed.endpoint);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
} catch {}
|
|
213
|
+
};
|
|
214
|
+
proc.stdout.on('data', onData);
|
|
215
|
+
proc.on('error', (err)=>{
|
|
216
|
+
if (!settled) {
|
|
217
|
+
settled = true;
|
|
218
|
+
clearTimeout(timer);
|
|
219
|
+
reject(new Error(`Failed to spawn proxy: ${err.message}`));
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
proc.on('exit', (code, signal)=>{
|
|
223
|
+
if (!settled) {
|
|
224
|
+
settled = true;
|
|
225
|
+
clearTimeout(timer);
|
|
226
|
+
const how = signal ? `signal ${signal}` : `code ${code}`;
|
|
227
|
+
reject(new Error(`Proxy exited with ${how} before ready${formatStderr()}`));
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async function getProxyEndpoint(chromeEndpoint) {
|
|
233
|
+
let browserEndpoint = chromeEndpoint;
|
|
234
|
+
if (isPageLevelEndpoint(chromeEndpoint)) {
|
|
235
|
+
debug('Page-level CDP endpoint detected, resolving via /json/version: %s', chromeEndpoint);
|
|
236
|
+
try {
|
|
237
|
+
browserEndpoint = await resolveBrowserEndpoint(chromeEndpoint);
|
|
238
|
+
debug('Resolved browser endpoint: %s', browserEndpoint);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
throw new Error(`Cannot use page-level CDP endpoint directly. Puppeteer requires a browser-level endpoint (e.g., ws://host:port/devtools/browser/<id>). Auto-resolution via /json/version failed: ${err.message}. Please provide a browser-level CDP endpoint instead.`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (isProxyAlive()) {
|
|
244
|
+
const endpoint = readProxyEndpoint();
|
|
245
|
+
const savedUpstream = readProxyUpstream();
|
|
246
|
+
if (endpoint) if (!savedUpstream || savedUpstream === browserEndpoint) return endpoint;
|
|
247
|
+
else {
|
|
248
|
+
debug('Proxy connected to different upstream (%s), killing', savedUpstream);
|
|
249
|
+
await killProxy();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
return await spawnProxy(browserEndpoint);
|
|
254
|
+
} catch (err) {
|
|
255
|
+
console.warn(`[cdp] proxy failed, falling back to direct connection: ${err}`);
|
|
256
|
+
return browserEndpoint;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
exports.getProxyEndpoint = __webpack_exports__.getProxyEndpoint;
|
|
260
|
+
exports.isProxyAlive = __webpack_exports__.isProxyAlive;
|
|
261
|
+
exports.killProxy = __webpack_exports__.killProxy;
|
|
262
|
+
exports.readProxyEndpoint = __webpack_exports__.readProxyEndpoint;
|
|
263
|
+
exports.readProxyUpstream = __webpack_exports__.readProxyUpstream;
|
|
264
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
265
|
+
"getProxyEndpoint",
|
|
266
|
+
"isProxyAlive",
|
|
267
|
+
"killProxy",
|
|
268
|
+
"readProxyEndpoint",
|
|
269
|
+
"readProxyUpstream"
|
|
270
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
271
|
+
Object.defineProperty(exports, '__esModule', {
|
|
272
|
+
value: true
|
|
273
|
+
});
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.n = (module)=>{
|
|
5
|
+
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
6
|
+
__webpack_require__.d(getter, {
|
|
7
|
+
a: getter
|
|
8
|
+
});
|
|
9
|
+
return getter;
|
|
10
|
+
};
|
|
11
|
+
})();
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
14
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: definition[key]
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
})();
|
|
20
|
+
(()=>{
|
|
21
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
22
|
+
})();
|
|
23
|
+
var __webpack_exports__ = {};
|
|
24
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
25
|
+
const external_node_http_namespaceObject = require("node:http");
|
|
26
|
+
const external_ws_namespaceObject = require("ws");
|
|
27
|
+
var external_ws_default = /*#__PURE__*/ __webpack_require__.n(external_ws_namespaceObject);
|
|
28
|
+
const external_cdp_proxy_constants_js_namespaceObject = require("./cdp-proxy-constants.js");
|
|
29
|
+
const IDLE_TIMEOUT_MS = 300000;
|
|
30
|
+
const chromeEndpoint = process.argv[2];
|
|
31
|
+
if (!chromeEndpoint) {
|
|
32
|
+
process.stderr.write('Usage: node cdp-proxy.js <chrome-ws-endpoint>\n');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
function cleanupIfOwned() {
|
|
36
|
+
try {
|
|
37
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) return;
|
|
38
|
+
const pid = Number((0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE, 'utf-8').trim());
|
|
39
|
+
if (pid !== process.pid) return;
|
|
40
|
+
} catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE);
|
|
45
|
+
} catch {}
|
|
46
|
+
try {
|
|
47
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE);
|
|
48
|
+
} catch {}
|
|
49
|
+
try {
|
|
50
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE);
|
|
51
|
+
} catch {}
|
|
52
|
+
}
|
|
53
|
+
const STDERR_FLUSH_FALLBACK_MS = 500;
|
|
54
|
+
function exitWithStderr(message, code = 0) {
|
|
55
|
+
let exited = false;
|
|
56
|
+
const doExit = ()=>{
|
|
57
|
+
if (exited) return;
|
|
58
|
+
exited = true;
|
|
59
|
+
process.exit(code);
|
|
60
|
+
};
|
|
61
|
+
const fallback = setTimeout(doExit, STDERR_FLUSH_FALLBACK_MS);
|
|
62
|
+
fallback.unref?.();
|
|
63
|
+
try {
|
|
64
|
+
process.stderr.write(message, ()=>doExit());
|
|
65
|
+
} catch {
|
|
66
|
+
doExit();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function shutdown(reason) {
|
|
70
|
+
cleanupIfOwned();
|
|
71
|
+
exitWithStderr(`[cdp-proxy] shutting down: ${reason}\n`, 0);
|
|
72
|
+
}
|
|
73
|
+
process.on('SIGTERM', ()=>shutdown('SIGTERM'));
|
|
74
|
+
process.on('SIGINT', ()=>shutdown('SIGINT'));
|
|
75
|
+
process.on('uncaughtException', (e)=>shutdown(`uncaught: ${e.message}`));
|
|
76
|
+
let idleTimer = null;
|
|
77
|
+
function resetIdleTimer() {
|
|
78
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
79
|
+
idleTimer = setTimeout(()=>shutdown('idle timeout (5min)'), IDLE_TIMEOUT_MS);
|
|
80
|
+
}
|
|
81
|
+
resetIdleTimer();
|
|
82
|
+
const clients = new Set();
|
|
83
|
+
let reconnecting = false;
|
|
84
|
+
let needsUpstreamReconnect = false;
|
|
85
|
+
const pendingUpstreamMessages = [];
|
|
86
|
+
function createUpstream(endpoint) {
|
|
87
|
+
const ws = new (external_ws_default())(endpoint);
|
|
88
|
+
ws.on('error', (err)=>{
|
|
89
|
+
reconnecting = false;
|
|
90
|
+
shutdown(`upstream error: ${err.message}`);
|
|
91
|
+
});
|
|
92
|
+
ws.on('close', (code, reasonBuf)=>{
|
|
93
|
+
if (reconnecting) return;
|
|
94
|
+
const reason = reasonBuf?.toString?.() || '';
|
|
95
|
+
const detail = reason ? ` (code=${code}, reason=${reason})` : ` (code=${code})`;
|
|
96
|
+
shutdown(`upstream closed${detail}`);
|
|
97
|
+
});
|
|
98
|
+
ws.on('message', (data, isBinary)=>{
|
|
99
|
+
resetIdleTimer();
|
|
100
|
+
for (const client of clients)if (client.readyState === external_ws_default().OPEN) client.send(data, {
|
|
101
|
+
binary: isBinary
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
ws.on('open', ()=>{
|
|
105
|
+
reconnecting = false;
|
|
106
|
+
for (const msg of pendingUpstreamMessages)ws.send(msg.data, {
|
|
107
|
+
binary: msg.isBinary
|
|
108
|
+
});
|
|
109
|
+
pendingUpstreamMessages.length = 0;
|
|
110
|
+
});
|
|
111
|
+
return ws;
|
|
112
|
+
}
|
|
113
|
+
let upstream = createUpstream(chromeEndpoint);
|
|
114
|
+
function reconnectUpstream() {
|
|
115
|
+
reconnecting = true;
|
|
116
|
+
upstream.removeAllListeners();
|
|
117
|
+
upstream.close();
|
|
118
|
+
upstream = createUpstream(chromeEndpoint);
|
|
119
|
+
resetIdleTimer();
|
|
120
|
+
}
|
|
121
|
+
const httpServer = (0, external_node_http_namespaceObject.createServer)((_req, res)=>{
|
|
122
|
+
res.writeHead(404);
|
|
123
|
+
res.end();
|
|
124
|
+
});
|
|
125
|
+
const wss = new external_ws_namespaceObject.WebSocketServer({
|
|
126
|
+
server: httpServer
|
|
127
|
+
});
|
|
128
|
+
wss.on('connection', (clientWs)=>{
|
|
129
|
+
if (needsUpstreamReconnect && upstream.readyState === external_ws_default().OPEN) {
|
|
130
|
+
reconnectUpstream();
|
|
131
|
+
needsUpstreamReconnect = false;
|
|
132
|
+
}
|
|
133
|
+
clients.add(clientWs);
|
|
134
|
+
resetIdleTimer();
|
|
135
|
+
clientWs.on('message', (data, isBinary)=>{
|
|
136
|
+
resetIdleTimer();
|
|
137
|
+
if (upstream.readyState === external_ws_default().OPEN) upstream.send(data, {
|
|
138
|
+
binary: isBinary
|
|
139
|
+
});
|
|
140
|
+
else pendingUpstreamMessages.push({
|
|
141
|
+
data,
|
|
142
|
+
isBinary
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
const removeClient = ()=>{
|
|
146
|
+
clients.delete(clientWs);
|
|
147
|
+
if (0 === clients.size) {
|
|
148
|
+
pendingUpstreamMessages.length = 0;
|
|
149
|
+
needsUpstreamReconnect = true;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
clientWs.on('close', removeClient);
|
|
153
|
+
clientWs.on('error', removeClient);
|
|
154
|
+
});
|
|
155
|
+
upstream.once('open', ()=>{
|
|
156
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE)) try {
|
|
157
|
+
const existingPid = Number((0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE, 'utf-8').trim());
|
|
158
|
+
if (existingPid !== process.pid) try {
|
|
159
|
+
process.kill(existingPid, 0);
|
|
160
|
+
exitWithStderr(`[cdp-proxy] duplicate proxy detected (existing pid=${existingPid})\n`, 0);
|
|
161
|
+
return;
|
|
162
|
+
} catch {}
|
|
163
|
+
} catch {}
|
|
164
|
+
httpServer.listen(0, '127.0.0.1', ()=>{
|
|
165
|
+
const addr = httpServer.address();
|
|
166
|
+
if (!addr || 'string' == typeof addr) return void shutdown('failed to get server address');
|
|
167
|
+
const proxyEndpoint = `ws://127.0.0.1:${addr.port}/devtools/browser`;
|
|
168
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_ENDPOINT_FILE, proxyEndpoint);
|
|
169
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_PID_FILE, String(process.pid));
|
|
170
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(external_cdp_proxy_constants_js_namespaceObject.PROXY_UPSTREAM_FILE, chromeEndpoint);
|
|
171
|
+
process.stdout.write(`${JSON.stringify({
|
|
172
|
+
endpoint: proxyEndpoint
|
|
173
|
+
})}\n`);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
177
|
+
Object.defineProperty(exports, '__esModule', {
|
|
178
|
+
value: true
|
|
179
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
saveTargetId: ()=>saveTargetId,
|
|
28
|
+
cleanupTargetIdFile: ()=>cleanupTargetIdFile,
|
|
29
|
+
readSavedTargetId: ()=>readSavedTargetId
|
|
30
|
+
});
|
|
31
|
+
const external_node_fs_namespaceObject = require("node:fs");
|
|
32
|
+
const logger_namespaceObject = require("@godscene/shared/logger");
|
|
33
|
+
const external_cdp_proxy_constants_js_namespaceObject = require("./cdp-proxy-constants.js");
|
|
34
|
+
const debug = (0, logger_namespaceObject.getDebug)('mcp:cdp:target-store');
|
|
35
|
+
function readSavedTargetId() {
|
|
36
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.TARGET_ID_FILE)) return null;
|
|
37
|
+
try {
|
|
38
|
+
return (0, external_node_fs_namespaceObject.readFileSync)(external_cdp_proxy_constants_js_namespaceObject.TARGET_ID_FILE, 'utf-8').trim() || null;
|
|
39
|
+
} catch {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function saveTargetId(targetId) {
|
|
44
|
+
try {
|
|
45
|
+
(0, external_node_fs_namespaceObject.writeFileSync)(external_cdp_proxy_constants_js_namespaceObject.TARGET_ID_FILE, targetId, 'utf-8');
|
|
46
|
+
debug('Saved targetId: %s', targetId);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
debug('Failed to save targetId: %s', err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function cleanupTargetIdFile() {
|
|
52
|
+
try {
|
|
53
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_cdp_proxy_constants_js_namespaceObject.TARGET_ID_FILE)) (0, external_node_fs_namespaceObject.unlinkSync)(external_cdp_proxy_constants_js_namespaceObject.TARGET_ID_FILE);
|
|
54
|
+
} catch {}
|
|
55
|
+
}
|
|
56
|
+
exports.cleanupTargetIdFile = __webpack_exports__.cleanupTargetIdFile;
|
|
57
|
+
exports.readSavedTargetId = __webpack_exports__.readSavedTargetId;
|
|
58
|
+
exports.saveTargetId = __webpack_exports__.saveTargetId;
|
|
59
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
60
|
+
"cleanupTargetIdFile",
|
|
61
|
+
"readSavedTargetId",
|
|
62
|
+
"saveTargetId"
|
|
63
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
64
|
+
Object.defineProperty(exports, '__esModule', {
|
|
65
|
+
value: true
|
|
66
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, definition)=>{
|
|
5
|
+
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: definition[key]
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
})();
|
|
11
|
+
(()=>{
|
|
12
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
13
|
+
})();
|
|
14
|
+
(()=>{
|
|
15
|
+
__webpack_require__.r = (exports1)=>{
|
|
16
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
17
|
+
value: 'Module'
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
20
|
+
value: true
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
var __webpack_exports__ = {};
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
ChromeExtensionProxyPageAgent: ()=>ChromeExtensionProxyPageAgent
|
|
28
|
+
});
|
|
29
|
+
const agent_namespaceObject = require("@godscene/core/agent");
|
|
30
|
+
const base_page_js_namespaceObject = require("../puppeteer/base-page.js");
|
|
31
|
+
class ChromeExtensionProxyPageAgent extends agent_namespaceObject.Agent {
|
|
32
|
+
isRetryableContextError(error) {
|
|
33
|
+
return error instanceof Error && base_page_js_namespaceObject.BROWSER_NAVIGATION_ERROR_PATTERN.test(error.message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.ChromeExtensionProxyPageAgent = __webpack_exports__.ChromeExtensionProxyPageAgent;
|
|
37
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
38
|
+
"ChromeExtensionProxyPageAgent"
|
|
39
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
40
|
+
Object.defineProperty(exports, '__esModule', {
|
|
41
|
+
value: true
|
|
42
|
+
});
|