@weavetab/mcp 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +49 -49
- package/ARCHITECTURE.md +590 -590
- package/LICENSE +216 -216
- package/README.md +269 -269
- package/SECURITY.md +207 -207
- package/TROUBLESHOOTING.md +373 -365
- package/dist/anticaptcha/detector.js +395 -395
- package/dist/anticaptcha/solver.js +130 -130
- package/dist/cdp/bridge.js +73 -73
- package/dist/cdp/connector.js +46 -22
- package/dist/cdp/extension.js +34 -34
- package/dist/cdp/helpers.js +174 -174
- package/dist/cdp/pruner.js +195 -195
- package/dist/cdp/ref_cache.js +66 -66
- package/dist/cdp/security.js +10 -10
- package/dist/cdp/verify.js +57 -57
- package/dist/cdp/walker.js +563 -525
- package/dist/cli/plugin.js +26 -3
- package/dist/config/loader.d.ts +0 -3
- package/dist/config/loader.js +0 -9
- package/dist/index.js +0 -4
- package/dist/intelligence/intent.js +81 -81
- package/dist/intelligence/sessionMemory.js +2 -2
- package/dist/overlay/ghost.js +22 -22
- package/dist/overlay/injector.js +89 -89
- package/dist/plugin/extension_bridge.js +54 -54
- package/dist/plugin/interface.d.ts +7 -0
- package/dist/plugin/loader.js +3 -4
- package/dist/plugin/schema.d.ts +11 -0
- package/dist/plugin/schema.js +59 -0
- package/dist/security/guard.js +18 -18
- package/dist/sensors/actionability.js +167 -167
- package/dist/sensors/guard.js +29 -29
- package/dist/sensors/network.js +15 -17
- package/dist/server.d.ts +1 -1
- package/dist/server.js +173 -144
- package/dist/state/delta.js +6 -7
- package/dist/tools/automation.js +85 -85
- package/dist/tools/canvas.js +48 -25
- package/dist/tools/checkpoint.js +94 -35
- package/dist/tools/click.js +52 -41
- package/dist/tools/clipboard.js +80 -74
- package/dist/tools/design_extract.js +441 -441
- package/dist/tools/dialog.js +13 -13
- package/dist/tools/emulation.d.ts +2 -0
- package/dist/tools/emulation.js +7 -0
- package/dist/tools/fill.js +344 -347
- package/dist/tools/find.js +78 -52
- package/dist/tools/highlight.js +67 -67
- package/dist/tools/inspect.js +54 -25
- package/dist/tools/key.js +42 -35
- package/dist/tools/navigate.d.ts +1 -1
- package/dist/tools/navigate.js +35 -35
- package/dist/tools/office/parse.js +62 -18
- package/dist/tools/pdf.d.ts +9 -0
- package/dist/tools/pdf.js +7 -4
- package/dist/tools/performance.d.ts +11 -4
- package/dist/tools/performance.js +94 -42
- package/dist/tools/performance_test.d.ts +2 -2
- package/dist/tools/performance_test.js +69 -69
- package/dist/tools/pointer.js +116 -116
- package/dist/tools/read.js +99 -67
- package/dist/tools/recording.js +9 -0
- package/dist/tools/scrape.js +146 -146
- package/dist/tools/screenshot.d.ts +2 -0
- package/dist/tools/screenshot.js +46 -4
- package/dist/tools/scroll.d.ts +3 -1
- package/dist/tools/scroll.js +13 -15
- package/dist/tools/select.d.ts +3 -0
- package/dist/tools/select.js +131 -124
- package/dist/tools/snapshot.js +8 -6
- package/dist/tools/storage.d.ts +5 -1
- package/dist/tools/storage.js +16 -0
- package/dist/tools/tabs.d.ts +7 -5
- package/dist/tools/tabs.js +79 -26
- package/dist/tools/thought.js +8 -8
- package/dist/tools/type.js +274 -274
- package/dist/tools/type_secret.js +23 -23
- package/dist/tools/upload.js +3 -3
- package/dist/tools/video_compiler.js +9 -0
- package/dist/tools/wait.js +35 -35
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/DOCUMENTATION.md +583 -585
- package/docs/PLUGINS.md +139 -121
- package/docs/TOOLS.md +3 -4
- package/docs/architecture/blind-injection.md +83 -83
- package/docs/architecture/overview.md +49 -49
- package/docs/architecture/security.md +36 -36
- package/docs/architecture/transport.md +37 -37
- package/docs/cli/cli-commands.md +50 -50
- package/docs/cli/cli-flags.md +28 -28
- package/docs/cli/cli-scripting.md +35 -35
- package/docs/configuration/config-locations.md +23 -23
- package/docs/configuration/configuration.md +39 -27
- package/docs/configuration/env-variables.md +19 -19
- package/docs/configuration/folders.md +62 -55
- package/docs/desktop-automation/electron-apps.md +225 -214
- package/docs/get-started/installation.md +1 -1
- package/docs/get-started/introduction.md +60 -60
- package/docs/get-started/quickstart.md +2 -2
- package/docs/get-started/setup-wizard.md +27 -27
- package/docs/intelligence/site-profiles.md +151 -151
- package/docs/tools/tools.md +582 -631
- package/docs/troubleshooting/trouble-browser.md +27 -27
- package/docs/troubleshooting/trouble-loop.md +31 -31
- package/ext-dist/background.js +415 -415
- package/ext-dist/content.js +2527 -2527
- package/ext-dist/dashboard.html +583 -583
- package/ext-dist/hud/hud.js +3 -3
- package/ext-dist/hud/index.html +20 -20
- package/ext-dist/manifest.json +73 -73
- package/ext-dist/styles.css +223 -223
- package/mcp.json +796 -805
- package/package.json +118 -118
- package/server.json +23 -23
- package/dist/cdp/walker.test.d.ts +0 -2
- package/dist/cdp/walker.test.js +0 -172
- package/dist/intelligence/sessionMemory.test.d.ts +0 -2
- package/dist/intelligence/sessionMemory.test.js +0 -62
- package/dist/intelligence/trail.test.d.ts +0 -2
- package/dist/intelligence/trail.test.js +0 -110
- package/dist/state/cache.test.d.ts +0 -2
- package/dist/state/cache.test.js +0 -76
- package/dist/state/delta.test.d.ts +0 -2
- package/dist/state/delta.test.js +0 -279
- package/dist/state/groups.d.ts +0 -15
- package/dist/state/groups.js +0 -80
- package/dist/tools/accessibility.d.ts +0 -14
- package/dist/tools/accessibility.js +0 -32
- package/dist/tools/ask.d.ts +0 -14
- package/dist/tools/ask.js +0 -49
- package/dist/tools/click_and_wait.d.ts +0 -33
- package/dist/tools/click_and_wait.js +0 -149
- package/dist/tools/drag.d.ts +0 -15
- package/dist/tools/drag.js +0 -29
- package/dist/tools/geo.d.ts +0 -19
- package/dist/tools/geo.js +0 -29
- package/dist/tools/github/analyze.d.ts +0 -4
- package/dist/tools/github/analyze.js +0 -113
- package/dist/tools/github/cache.d.ts +0 -21
- package/dist/tools/github/cache.js +0 -28
- package/dist/tools/github/index.d.ts +0 -19
- package/dist/tools/github/index.js +0 -40
- package/dist/tools/github/issues.d.ts +0 -9
- package/dist/tools/github/issues.js +0 -88
- package/dist/tools/github/pr.d.ts +0 -5
- package/dist/tools/github/pr.js +0 -88
- package/dist/tools/github/rateLimiter.d.ts +0 -4
- package/dist/tools/github/rateLimiter.js +0 -46
- package/dist/tools/github/read.d.ts +0 -34
- package/dist/tools/github/read.js +0 -74
- package/dist/tools/github/repoContext.d.ts +0 -20
- package/dist/tools/github/repoContext.js +0 -129
- package/dist/tools/hover.d.ts +0 -19
- package/dist/tools/hover.js +0 -57
- package/dist/tools/integration.test.d.ts +0 -2
- package/dist/tools/integration.test.js +0 -96
- package/dist/tools/macro_compiler.d.ts +0 -7
- package/dist/tools/macro_compiler.js +0 -82
- package/dist/tools/mouse.d.ts +0 -21
- package/dist/tools/mouse.js +0 -62
- package/dist/tools/response.d.ts +0 -129
- package/dist/tools/response.js +0 -5
- package/dist/tools/wait_for.d.ts +0 -23
- package/dist/tools/wait_for.js +0 -30
- package/dist/tools/windows.d.ts +0 -22
- package/dist/tools/windows.js +0 -57
|
@@ -41,52 +41,52 @@ async function solveSliderDrag(session, detection, t0) {
|
|
|
41
41
|
try {
|
|
42
42
|
// Locate slider thumb and track
|
|
43
43
|
const sliderInfo = await session.Runtime.evaluate({
|
|
44
|
-
expression: `(function() {
|
|
45
|
-
// Priority selectors for slider thumb
|
|
46
|
-
var thumbSels = [
|
|
47
|
-
'.geetest_slider_button', '.geetest_drag_thumb', '.geetest-slider-btn',
|
|
48
|
-
'.slide-verify-slider', '[class*="slider-btn"]', '[class*="slider-thumb"]',
|
|
49
|
-
'[class*="drag-btn"]', '[class*="slide-btn"]', '[class*="slider_button"]',
|
|
50
|
-
'.nc-lang-cnt [class*="btn"]', '.btn_slide', '.handler',
|
|
51
|
-
'[class*="verify"][class*="btn"]',
|
|
52
|
-
];
|
|
53
|
-
var trackSels = [
|
|
54
|
-
'.geetest_slider_bar', '.geetest_track', '.slide-verify-bar',
|
|
55
|
-
'[class*="slider-bar"]', '[class*="track"]', '[class*="slider-wrap"]',
|
|
56
|
-
'.nc-tpl [class*="bg"]', '[class*="verify"][class*="bar"]',
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
var thumb = null, track = null;
|
|
60
|
-
|
|
61
|
-
// Also try the provided selector
|
|
62
|
-
${detection.selector ? `thumb = document.querySelector(${JSON.stringify(detection.selector)});` : ''}
|
|
63
|
-
|
|
64
|
-
if (!thumb) {
|
|
65
|
-
for (var i = 0; i < thumbSels.length; i++) {
|
|
66
|
-
var el = document.querySelector(thumbSels[i]);
|
|
67
|
-
if (el && el.getBoundingClientRect().width > 0) {
|
|
68
|
-
thumb = el;
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
for (var j = 0; j < trackSels.length; j++) {
|
|
74
|
-
var el2 = document.querySelector(trackSels[j]);
|
|
75
|
-
if (el2 && el2.getBoundingClientRect().width > 20) {
|
|
76
|
-
track = el2;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (!thumb) return null;
|
|
82
|
-
var tr = thumb.getBoundingClientRect();
|
|
83
|
-
var trackWidth = track ? track.getBoundingClientRect().width : window.innerWidth * 0.6;
|
|
84
|
-
return {
|
|
85
|
-
thumbX: Math.round(tr.left + tr.width / 2),
|
|
86
|
-
thumbY: Math.round(tr.top + tr.height / 2),
|
|
87
|
-
thumbWidth: Math.round(tr.width),
|
|
88
|
-
trackWidth: Math.round(trackWidth),
|
|
89
|
-
};
|
|
44
|
+
expression: `(function() {
|
|
45
|
+
// Priority selectors for slider thumb
|
|
46
|
+
var thumbSels = [
|
|
47
|
+
'.geetest_slider_button', '.geetest_drag_thumb', '.geetest-slider-btn',
|
|
48
|
+
'.slide-verify-slider', '[class*="slider-btn"]', '[class*="slider-thumb"]',
|
|
49
|
+
'[class*="drag-btn"]', '[class*="slide-btn"]', '[class*="slider_button"]',
|
|
50
|
+
'.nc-lang-cnt [class*="btn"]', '.btn_slide', '.handler',
|
|
51
|
+
'[class*="verify"][class*="btn"]',
|
|
52
|
+
];
|
|
53
|
+
var trackSels = [
|
|
54
|
+
'.geetest_slider_bar', '.geetest_track', '.slide-verify-bar',
|
|
55
|
+
'[class*="slider-bar"]', '[class*="track"]', '[class*="slider-wrap"]',
|
|
56
|
+
'.nc-tpl [class*="bg"]', '[class*="verify"][class*="bar"]',
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
var thumb = null, track = null;
|
|
60
|
+
|
|
61
|
+
// Also try the provided selector
|
|
62
|
+
${detection.selector ? `thumb = document.querySelector(${JSON.stringify(detection.selector)});` : ''}
|
|
63
|
+
|
|
64
|
+
if (!thumb) {
|
|
65
|
+
for (var i = 0; i < thumbSels.length; i++) {
|
|
66
|
+
var el = document.querySelector(thumbSels[i]);
|
|
67
|
+
if (el && el.getBoundingClientRect().width > 0) {
|
|
68
|
+
thumb = el;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (var j = 0; j < trackSels.length; j++) {
|
|
74
|
+
var el2 = document.querySelector(trackSels[j]);
|
|
75
|
+
if (el2 && el2.getBoundingClientRect().width > 20) {
|
|
76
|
+
track = el2;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!thumb) return null;
|
|
82
|
+
var tr = thumb.getBoundingClientRect();
|
|
83
|
+
var trackWidth = track ? track.getBoundingClientRect().width : window.innerWidth * 0.6;
|
|
84
|
+
return {
|
|
85
|
+
thumbX: Math.round(tr.left + tr.width / 2),
|
|
86
|
+
thumbY: Math.round(tr.top + tr.height / 2),
|
|
87
|
+
thumbWidth: Math.round(tr.width),
|
|
88
|
+
trackWidth: Math.round(trackWidth),
|
|
89
|
+
};
|
|
90
90
|
})()`,
|
|
91
91
|
returnByValue: true,
|
|
92
92
|
});
|
|
@@ -203,31 +203,31 @@ async function solvePressAndHold(session, detection, t0) {
|
|
|
203
203
|
const holdMs = detection.holdDurationMs || 2500;
|
|
204
204
|
// Locate the hold button
|
|
205
205
|
const btnInfo = await session.Runtime.evaluate({
|
|
206
|
-
expression: `(function() {
|
|
207
|
-
var sels = [
|
|
208
|
-
${detection.selector ? JSON.stringify(detection.selector) + ',' : ''}
|
|
209
|
-
'#px-captcha', '._pxCaptcha',
|
|
210
|
-
'[class*="press-hold"]', '[class*="hold-btn"]', '[class*="presshold"]',
|
|
211
|
-
'button[class*="verify"]',
|
|
212
|
-
];
|
|
213
|
-
for (var i = 0; i < sels.length; i++) {
|
|
214
|
-
var el = document.querySelector(sels[i]);
|
|
215
|
-
if (el) {
|
|
216
|
-
var r = el.getBoundingClientRect();
|
|
217
|
-
if (r.width > 0 && r.height > 0) {
|
|
218
|
-
return { x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) };
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
// Last resort: find any visible button with "hold" in text
|
|
223
|
-
var btns = document.querySelectorAll('button, [role="button"]');
|
|
224
|
-
for (var j = 0; j < btns.length; j++) {
|
|
225
|
-
if (/hold|press/i.test(btns[j].textContent || '')) {
|
|
226
|
-
var br = btns[j].getBoundingClientRect();
|
|
227
|
-
if (br.width > 0) return { x: Math.round(br.left+br.width/2), y: Math.round(br.top+br.height/2) };
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return null;
|
|
206
|
+
expression: `(function() {
|
|
207
|
+
var sels = [
|
|
208
|
+
${detection.selector ? JSON.stringify(detection.selector) + ',' : ''}
|
|
209
|
+
'#px-captcha', '._pxCaptcha',
|
|
210
|
+
'[class*="press-hold"]', '[class*="hold-btn"]', '[class*="presshold"]',
|
|
211
|
+
'button[class*="verify"]',
|
|
212
|
+
];
|
|
213
|
+
for (var i = 0; i < sels.length; i++) {
|
|
214
|
+
var el = document.querySelector(sels[i]);
|
|
215
|
+
if (el) {
|
|
216
|
+
var r = el.getBoundingClientRect();
|
|
217
|
+
if (r.width > 0 && r.height > 0) {
|
|
218
|
+
return { x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Last resort: find any visible button with "hold" in text
|
|
223
|
+
var btns = document.querySelectorAll('button, [role="button"]');
|
|
224
|
+
for (var j = 0; j < btns.length; j++) {
|
|
225
|
+
if (/hold|press/i.test(btns[j].textContent || '')) {
|
|
226
|
+
var br = btns[j].getBoundingClientRect();
|
|
227
|
+
if (br.width > 0) return { x: Math.round(br.left+br.width/2), y: Math.round(br.top+br.height/2) };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
231
|
})()`,
|
|
232
232
|
returnByValue: true,
|
|
233
233
|
});
|
|
@@ -293,16 +293,16 @@ async function solveCheckbox(session, detection, t0) {
|
|
|
293
293
|
try {
|
|
294
294
|
// Find the iframe and click the checkbox inside it via coordinates
|
|
295
295
|
const frameInfo = await session.Runtime.evaluate({
|
|
296
|
-
expression: `(function() {
|
|
297
|
-
var frames = document.querySelectorAll('iframe[src*="recaptcha"], iframe[src*="hcaptcha"]');
|
|
298
|
-
for (var i = 0; i < frames.length; i++) {
|
|
299
|
-
var r = frames[i].getBoundingClientRect();
|
|
300
|
-
if (r.width > 0 && r.height > 0) {
|
|
301
|
-
// Checkbox is typically at 20px from left, center vertically
|
|
302
|
-
return { x: Math.round(r.left + 20), y: Math.round(r.top + r.height/2) };
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
return null;
|
|
296
|
+
expression: `(function() {
|
|
297
|
+
var frames = document.querySelectorAll('iframe[src*="recaptcha"], iframe[src*="hcaptcha"]');
|
|
298
|
+
for (var i = 0; i < frames.length; i++) {
|
|
299
|
+
var r = frames[i].getBoundingClientRect();
|
|
300
|
+
if (r.width > 0 && r.height > 0) {
|
|
301
|
+
// Checkbox is typically at 20px from left, center vertically
|
|
302
|
+
return { x: Math.round(r.left + 20), y: Math.round(r.top + r.height/2) };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
306
|
})()`,
|
|
307
307
|
returnByValue: true,
|
|
308
308
|
});
|
|
@@ -351,17 +351,17 @@ async function solveInvisible(session, detection, t0) {
|
|
|
351
351
|
// Invisible CAPTCHAs score based on user interaction signals.
|
|
352
352
|
// Simulate natural page interaction to boost the score.
|
|
353
353
|
await session.Runtime.evaluate({
|
|
354
|
-
expression: `(function() {
|
|
355
|
-
// Scroll slightly to simulate reading
|
|
356
|
-
window.scrollBy({ top: 120, behavior: 'smooth' });
|
|
357
|
-
// Move mouse (won't dispatch but registers user-intent in page context)
|
|
358
|
-
document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: 400, clientY: 300 }));
|
|
359
|
-
// Trigger focus/blur cycle on any form input
|
|
360
|
-
var inputs = document.querySelectorAll('input:not([type="hidden"]), textarea');
|
|
361
|
-
if (inputs.length > 0) {
|
|
362
|
-
inputs[0].focus();
|
|
363
|
-
setTimeout(function() { inputs[0].blur(); }, 200);
|
|
364
|
-
}
|
|
354
|
+
expression: `(function() {
|
|
355
|
+
// Scroll slightly to simulate reading
|
|
356
|
+
window.scrollBy({ top: 120, behavior: 'smooth' });
|
|
357
|
+
// Move mouse (won't dispatch but registers user-intent in page context)
|
|
358
|
+
document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: 400, clientY: 300 }));
|
|
359
|
+
// Trigger focus/blur cycle on any form input
|
|
360
|
+
var inputs = document.querySelectorAll('input:not([type="hidden"]), textarea');
|
|
361
|
+
if (inputs.length > 0) {
|
|
362
|
+
inputs[0].focus();
|
|
363
|
+
setTimeout(function() { inputs[0].blur(); }, 200);
|
|
364
|
+
}
|
|
365
365
|
})()`,
|
|
366
366
|
returnByValue: false,
|
|
367
367
|
});
|
|
@@ -369,14 +369,14 @@ async function solveInvisible(session, detection, t0) {
|
|
|
369
369
|
// Try to programmatically trigger grecaptcha execute (v3)
|
|
370
370
|
if (detection.type === "recaptcha_v3") {
|
|
371
371
|
await session.Runtime.evaluate({
|
|
372
|
-
expression: `(function() {
|
|
373
|
-
try {
|
|
374
|
-
if (window.grecaptcha && window.grecaptcha.execute) {
|
|
375
|
-
window.grecaptcha.ready(function() {
|
|
376
|
-
window.grecaptcha.execute().catch(function(){});
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
} catch(e) {}
|
|
372
|
+
expression: `(function() {
|
|
373
|
+
try {
|
|
374
|
+
if (window.grecaptcha && window.grecaptcha.execute) {
|
|
375
|
+
window.grecaptcha.ready(function() {
|
|
376
|
+
window.grecaptcha.execute().catch(function(){});
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
} catch(e) {}
|
|
380
380
|
})()`,
|
|
381
381
|
returnByValue: false,
|
|
382
382
|
});
|
|
@@ -400,31 +400,31 @@ async function solveInvisible(session, detection, t0) {
|
|
|
400
400
|
async function solveMathCaptcha(session, detection, t0) {
|
|
401
401
|
try {
|
|
402
402
|
const result = await session.Runtime.evaluate({
|
|
403
|
-
expression: `(function(sel) {
|
|
404
|
-
var container = document.querySelector(sel) || document.body;
|
|
405
|
-
var text = container.textContent || '';
|
|
406
|
-
// Match expressions like "3 + 7 =", "12 - 4 =", "6 × 3", "8 ÷ 2"
|
|
407
|
-
var m = text.match(/(\\d+)\\s*([+\\-*×x÷/])\\s*(\\d+)/);
|
|
408
|
-
if (!m) return null;
|
|
409
|
-
var a = parseInt(m[1]), op = m[2], b = parseInt(m[3]);
|
|
410
|
-
var ans;
|
|
411
|
-
if (op === '+') ans = a + b;
|
|
412
|
-
else if (op === '-') ans = a - b;
|
|
413
|
-
else if (op === '*' || op === '×' || op === 'x') ans = a * b;
|
|
414
|
-
else if (op === '/' || op === '÷') ans = Math.floor(a / b);
|
|
415
|
-
else return null;
|
|
416
|
-
// Fill the answer input
|
|
417
|
-
var inp = container.querySelector('input[type="text"], input[type="number"]');
|
|
418
|
-
if (!inp) inp = document.querySelector('input[name*="captcha"], input[id*="captcha"]');
|
|
419
|
-
if (inp) {
|
|
420
|
-
inp.focus();
|
|
421
|
-
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
|
|
422
|
-
if (nativeInputValueSetter) nativeInputValueSetter.call(inp, String(ans));
|
|
423
|
-
inp.dispatchEvent(new Event('input', { bubbles: true }));
|
|
424
|
-
inp.dispatchEvent(new Event('change', { bubbles: true }));
|
|
425
|
-
return { solved: true, answer: ans };
|
|
426
|
-
}
|
|
427
|
-
return { solved: false, answer: ans };
|
|
403
|
+
expression: `(function(sel) {
|
|
404
|
+
var container = document.querySelector(sel) || document.body;
|
|
405
|
+
var text = container.textContent || '';
|
|
406
|
+
// Match expressions like "3 + 7 =", "12 - 4 =", "6 × 3", "8 ÷ 2"
|
|
407
|
+
var m = text.match(/(\\d+)\\s*([+\\-*×x÷/])\\s*(\\d+)/);
|
|
408
|
+
if (!m) return null;
|
|
409
|
+
var a = parseInt(m[1]), op = m[2], b = parseInt(m[3]);
|
|
410
|
+
var ans;
|
|
411
|
+
if (op === '+') ans = a + b;
|
|
412
|
+
else if (op === '-') ans = a - b;
|
|
413
|
+
else if (op === '*' || op === '×' || op === 'x') ans = a * b;
|
|
414
|
+
else if (op === '/' || op === '÷') ans = Math.floor(a / b);
|
|
415
|
+
else return null;
|
|
416
|
+
// Fill the answer input
|
|
417
|
+
var inp = container.querySelector('input[type="text"], input[type="number"]');
|
|
418
|
+
if (!inp) inp = document.querySelector('input[name*="captcha"], input[id*="captcha"]');
|
|
419
|
+
if (inp) {
|
|
420
|
+
inp.focus();
|
|
421
|
+
var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
|
|
422
|
+
if (nativeInputValueSetter) nativeInputValueSetter.call(inp, String(ans));
|
|
423
|
+
inp.dispatchEvent(new Event('input', { bubbles: true }));
|
|
424
|
+
inp.dispatchEvent(new Event('change', { bubbles: true }));
|
|
425
|
+
return { solved: true, answer: ans };
|
|
426
|
+
}
|
|
427
|
+
return { solved: false, answer: ans };
|
|
428
428
|
})(${JSON.stringify(detection.selector || 'body')})`,
|
|
429
429
|
returnByValue: true,
|
|
430
430
|
});
|
|
@@ -493,11 +493,11 @@ async function checkCaptchaGone(session, detection) {
|
|
|
493
493
|
if (!detection.selector)
|
|
494
494
|
return null;
|
|
495
495
|
const check = await session.Runtime.evaluate({
|
|
496
|
-
expression: `(function(sel) {
|
|
497
|
-
var el = document.querySelector(sel);
|
|
498
|
-
if (!el) return false; // gone = solved
|
|
499
|
-
var r = el.getBoundingClientRect();
|
|
500
|
-
return r.width > 0 && r.height > 0 && r.top < window.innerHeight;
|
|
496
|
+
expression: `(function(sel) {
|
|
497
|
+
var el = document.querySelector(sel);
|
|
498
|
+
if (!el) return false; // gone = solved
|
|
499
|
+
var r = el.getBoundingClientRect();
|
|
500
|
+
return r.width > 0 && r.height > 0 && r.top < window.innerHeight;
|
|
501
501
|
})(${JSON.stringify(detection.selector)})`,
|
|
502
502
|
returnByValue: true,
|
|
503
503
|
});
|
package/dist/cdp/bridge.js
CHANGED
|
@@ -312,79 +312,79 @@ function recordLaunchSuccess(profileDir) {
|
|
|
312
312
|
launchFailureCount.delete(`${profileDir}_time`);
|
|
313
313
|
}
|
|
314
314
|
// ─── Stealth script: injected before any page JS runs ─────────────────────────
|
|
315
|
-
const STEALTH_SCRIPT = `
|
|
316
|
-
(function() {
|
|
317
|
-
'use strict';
|
|
318
|
-
|
|
319
|
-
// 1. Spoof navigator.webdriver
|
|
320
|
-
Object.defineProperty(navigator, 'webdriver', {
|
|
321
|
-
get: () => undefined,
|
|
322
|
-
configurable: true,
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
// 2. Remove chrome automation props
|
|
326
|
-
if (window.navigator.plugins.length === 0) {
|
|
327
|
-
Object.defineProperty(navigator, 'plugins', {
|
|
328
|
-
get: () => [1, 2, 3, 4, 5],
|
|
329
|
-
configurable: true,
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// 3. Spoof navigator.languages (defaults to en-US if unset)
|
|
334
|
-
if (!navigator.languages || navigator.languages.length === 0) {
|
|
335
|
-
Object.defineProperty(navigator, 'languages', {
|
|
336
|
-
get: () => ['en-US', 'en'],
|
|
337
|
-
configurable: true,
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// 4. Spoof Chrome runtime
|
|
342
|
-
window.chrome = window.chrome || {};
|
|
343
|
-
window.chrome.runtime = window.chrome.runtime || {};
|
|
344
|
-
|
|
345
|
-
// 5. Randomize hardwareConcurrency (4–8 cores)
|
|
346
|
-
Object.defineProperty(navigator, 'hardwareConcurrency', {
|
|
347
|
-
get: () => 4 + Math.floor(Math.random() * 4),
|
|
348
|
-
configurable: true,
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// 6. Randomize deviceMemory (4, 8, or 12 GB, weighted toward 8)
|
|
352
|
-
Object.defineProperty(navigator, 'deviceMemory', {
|
|
353
|
-
get: () => [4, 8, 8, 8, 12][Math.floor(Math.random() * 5)],
|
|
354
|
-
configurable: true,
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// 7. WebGL vendor/renderer spoofing — only spoof the two info params,
|
|
358
|
-
// pass everything else through untouched. Wrapped in try/catch so a
|
|
359
|
-
// missing WebGL context never breaks the page.
|
|
360
|
-
try {
|
|
361
|
-
var _origGetParam = WebGLRenderingContext.prototype.getParameter;
|
|
362
|
-
WebGLRenderingContext.prototype.getParameter = function(p) {
|
|
363
|
-
if (p === 37445) return 'Google Inc. (Intel)';
|
|
364
|
-
if (p === 37446) {
|
|
365
|
-
return navigator.platform.indexOf('Mac') === 0
|
|
366
|
-
? 'ANGLE (Intel, Intel(R) Iris(TM) Plus Graphics 640, OpenGL 4.1)'
|
|
367
|
-
: 'ANGLE (Intel, Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0, D3D11)';
|
|
368
|
-
}
|
|
369
|
-
return _origGetParam.apply(this, arguments);
|
|
370
|
-
};
|
|
371
|
-
if (typeof WebGL2RenderingContext !== 'undefined') {
|
|
372
|
-
var _origGetParam2 = WebGL2RenderingContext.prototype.getParameter;
|
|
373
|
-
WebGL2RenderingContext.prototype.getParameter = function(p) {
|
|
374
|
-
if (p === 37445) return 'Google Inc. (Intel)';
|
|
375
|
-
if (p === 37446) {
|
|
376
|
-
return navigator.platform.indexOf('Mac') === 0
|
|
377
|
-
? 'ANGLE (Intel, Intel(R) Iris(TM) Plus Graphics 640, OpenGL 4.1)'
|
|
378
|
-
: 'ANGLE (Intel, Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0, D3D11)';
|
|
379
|
-
}
|
|
380
|
-
return _origGetParam2.apply(this, arguments);
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
} catch(e) {}
|
|
384
|
-
|
|
385
|
-
// NOTE: Function.prototype.toString proxy removed — it was wrapping
|
|
386
|
-
// every toString call globally and could break page rendering.
|
|
387
|
-
})();
|
|
315
|
+
const STEALTH_SCRIPT = `
|
|
316
|
+
(function() {
|
|
317
|
+
'use strict';
|
|
318
|
+
|
|
319
|
+
// 1. Spoof navigator.webdriver
|
|
320
|
+
Object.defineProperty(navigator, 'webdriver', {
|
|
321
|
+
get: () => undefined,
|
|
322
|
+
configurable: true,
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// 2. Remove chrome automation props
|
|
326
|
+
if (window.navigator.plugins.length === 0) {
|
|
327
|
+
Object.defineProperty(navigator, 'plugins', {
|
|
328
|
+
get: () => [1, 2, 3, 4, 5],
|
|
329
|
+
configurable: true,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// 3. Spoof navigator.languages (defaults to en-US if unset)
|
|
334
|
+
if (!navigator.languages || navigator.languages.length === 0) {
|
|
335
|
+
Object.defineProperty(navigator, 'languages', {
|
|
336
|
+
get: () => ['en-US', 'en'],
|
|
337
|
+
configurable: true,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// 4. Spoof Chrome runtime
|
|
342
|
+
window.chrome = window.chrome || {};
|
|
343
|
+
window.chrome.runtime = window.chrome.runtime || {};
|
|
344
|
+
|
|
345
|
+
// 5. Randomize hardwareConcurrency (4–8 cores)
|
|
346
|
+
Object.defineProperty(navigator, 'hardwareConcurrency', {
|
|
347
|
+
get: () => 4 + Math.floor(Math.random() * 4),
|
|
348
|
+
configurable: true,
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// 6. Randomize deviceMemory (4, 8, or 12 GB, weighted toward 8)
|
|
352
|
+
Object.defineProperty(navigator, 'deviceMemory', {
|
|
353
|
+
get: () => [4, 8, 8, 8, 12][Math.floor(Math.random() * 5)],
|
|
354
|
+
configurable: true,
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
// 7. WebGL vendor/renderer spoofing — only spoof the two info params,
|
|
358
|
+
// pass everything else through untouched. Wrapped in try/catch so a
|
|
359
|
+
// missing WebGL context never breaks the page.
|
|
360
|
+
try {
|
|
361
|
+
var _origGetParam = WebGLRenderingContext.prototype.getParameter;
|
|
362
|
+
WebGLRenderingContext.prototype.getParameter = function(p) {
|
|
363
|
+
if (p === 37445) return 'Google Inc. (Intel)';
|
|
364
|
+
if (p === 37446) {
|
|
365
|
+
return navigator.platform.indexOf('Mac') === 0
|
|
366
|
+
? 'ANGLE (Intel, Intel(R) Iris(TM) Plus Graphics 640, OpenGL 4.1)'
|
|
367
|
+
: 'ANGLE (Intel, Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0, D3D11)';
|
|
368
|
+
}
|
|
369
|
+
return _origGetParam.apply(this, arguments);
|
|
370
|
+
};
|
|
371
|
+
if (typeof WebGL2RenderingContext !== 'undefined') {
|
|
372
|
+
var _origGetParam2 = WebGL2RenderingContext.prototype.getParameter;
|
|
373
|
+
WebGL2RenderingContext.prototype.getParameter = function(p) {
|
|
374
|
+
if (p === 37445) return 'Google Inc. (Intel)';
|
|
375
|
+
if (p === 37446) {
|
|
376
|
+
return navigator.platform.indexOf('Mac') === 0
|
|
377
|
+
? 'ANGLE (Intel, Intel(R) Iris(TM) Plus Graphics 640, OpenGL 4.1)'
|
|
378
|
+
: 'ANGLE (Intel, Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0, D3D11)';
|
|
379
|
+
}
|
|
380
|
+
return _origGetParam2.apply(this, arguments);
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
} catch(e) {}
|
|
384
|
+
|
|
385
|
+
// NOTE: Function.prototype.toString proxy removed — it was wrapping
|
|
386
|
+
// every toString call globally and could break page rendering.
|
|
387
|
+
})();
|
|
388
388
|
`;
|
|
389
389
|
// ─── Mandatory security flags (always applied, never overridable) ──────────────
|
|
390
390
|
const MANDATORY_FLAGS = Object.freeze([
|
package/dist/cdp/connector.js
CHANGED
|
@@ -169,12 +169,12 @@ async function initSession(session, targetId, port, config, isElectron) {
|
|
|
169
169
|
try {
|
|
170
170
|
// Check for multiple indicators that extension is loaded
|
|
171
171
|
const { result: extCheck } = await session.Runtime.evaluate({
|
|
172
|
-
expression: `!!(
|
|
173
|
-
document.querySelector('weavetab-host') ||
|
|
174
|
-
document.getElementById('__Weavetab_cursor_host') ||
|
|
175
|
-
document.getElementById('wt-ui-styles') ||
|
|
176
|
-
document.querySelector('[data-wt-internal]') ||
|
|
177
|
-
window.__wt_chat_queue
|
|
172
|
+
expression: `!!(
|
|
173
|
+
document.querySelector('weavetab-host') ||
|
|
174
|
+
document.getElementById('__Weavetab_cursor_host') ||
|
|
175
|
+
document.getElementById('wt-ui-styles') ||
|
|
176
|
+
document.querySelector('[data-wt-internal]') ||
|
|
177
|
+
window.__wt_chat_queue
|
|
178
178
|
)`,
|
|
179
179
|
returnByValue: true,
|
|
180
180
|
});
|
|
@@ -288,14 +288,29 @@ export async function getOrConnect(config, targetApp) {
|
|
|
288
288
|
for (let retry = 0; retry < 10; retry++) {
|
|
289
289
|
try {
|
|
290
290
|
targets = await withCDPTimeout(CDP.List({ host: "127.0.0.1", port }), 2000, "CDP.List Electron retry");
|
|
291
|
-
if
|
|
291
|
+
// Break early if we found a non-splash main window target
|
|
292
|
+
const hasMain = targets.some(t => {
|
|
293
|
+
const u = (t.url || "").toLowerCase();
|
|
294
|
+
const tit = (t.title || "").toLowerCase();
|
|
295
|
+
return !u.includes("splash") && !tit.includes("updater") && !u.startsWith("devtools://");
|
|
296
|
+
});
|
|
297
|
+
if (hasMain || (retry > 4 && targets.length > 0))
|
|
292
298
|
break;
|
|
293
299
|
}
|
|
294
300
|
catch { /* wait */ }
|
|
295
301
|
await new Promise(r => setTimeout(r, 500));
|
|
296
302
|
}
|
|
297
303
|
}
|
|
298
|
-
|
|
304
|
+
// Filter out splash screens, updater windows, and devtools targets
|
|
305
|
+
const isCandidate = (t) => {
|
|
306
|
+
const u = (t.url || "").toLowerCase();
|
|
307
|
+
const tit = (t.title || "").toLowerCase();
|
|
308
|
+
return !u.includes("splash") && !tit.includes("updater") && !u.startsWith("devtools://");
|
|
309
|
+
};
|
|
310
|
+
let pageTarget = targets.find(t => (t.type === "page" || t.type === "webview" || t.type === "app") && isCandidate(t))
|
|
311
|
+
?? targets.find(isCandidate)
|
|
312
|
+
?? targets.find(t => t.type === "page" || t.type === "webview" || t.type === "app")
|
|
313
|
+
?? targets[0];
|
|
299
314
|
if (!pageTarget) {
|
|
300
315
|
throw new Error(`[Weavetab] ✗ No window or webview target found in Electron app "${targetApp}".`);
|
|
301
316
|
}
|
|
@@ -622,7 +637,19 @@ export async function getTabList(agentId, targetApp) {
|
|
|
622
637
|
const aid = agentId || getConfigAgentId(config);
|
|
623
638
|
const bctxId = sessionRegistry.getBrowserContextIdForAgent(aid);
|
|
624
639
|
return targetInfos
|
|
625
|
-
.filter(t =>
|
|
640
|
+
.filter(t => {
|
|
641
|
+
const matchType = (t.type === "page" || t.type === "webview" || t.type === "app" || t.type === "other" || t.type === "iframe");
|
|
642
|
+
const matchCtx = (!bctxId || t.browserContextId === bctxId);
|
|
643
|
+
if (!matchType || !matchCtx)
|
|
644
|
+
return false;
|
|
645
|
+
if (targetApp) {
|
|
646
|
+
const u = (t.url || "").toLowerCase();
|
|
647
|
+
const tit = (t.title || "").toLowerCase();
|
|
648
|
+
if (u.includes("splash") || tit.includes("updater") || u.startsWith("devtools://"))
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
return true;
|
|
652
|
+
})
|
|
626
653
|
.map(t => ({
|
|
627
654
|
id: t.targetId,
|
|
628
655
|
title: t.title || t.url || t.type,
|
|
@@ -679,21 +706,18 @@ export async function connectToTab(targetId, port, agentId, browserContextId, ap
|
|
|
679
706
|
}
|
|
680
707
|
catch { }
|
|
681
708
|
if (!t) {
|
|
682
|
-
|
|
683
|
-
const metaSession = await withCDPTimeout(CDP({ host: "127.0.0.1", port: p }), 3000, "connectToTab meta CDP");
|
|
684
|
-
const { targetInfos } = await withCDPTimeout(metaSession.Target.getTargets(), 3000, "connectToTab meta getTargets");
|
|
685
|
-
await metaSession.close();
|
|
686
|
-
const ti = targetInfos.find(item => item.targetId === targetId);
|
|
687
|
-
if (ti) {
|
|
688
|
-
t = { id: ti.targetId, targetId: ti.targetId, url: ti.url, title: ti.title, type: ti.type };
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
catch { }
|
|
709
|
+
throw new Error(`Tab not found: "${targetId}". Check browser_tabs({ action: "list" }) for active IDs.`);
|
|
692
710
|
}
|
|
693
|
-
|
|
694
|
-
|
|
711
|
+
let session;
|
|
712
|
+
try {
|
|
713
|
+
session = await withCDPTimeout(CDP({ host: "127.0.0.1", port: p, target: targetId }), 5000, "connectToTab CDP");
|
|
714
|
+
}
|
|
715
|
+
catch (err) {
|
|
716
|
+
if (err?.message?.includes("webSocketDebuggerUrl") || err?.message?.includes("Cannot read propert")) {
|
|
717
|
+
throw new Error(`Tab not found or closed: "${targetId}".`);
|
|
718
|
+
}
|
|
719
|
+
throw err;
|
|
695
720
|
}
|
|
696
|
-
const session = await withCDPTimeout(CDP({ host: "127.0.0.1", port: p, target: targetId }), 5000, "connectToTab CDP");
|
|
697
721
|
session.on("close", () => {
|
|
698
722
|
logDebug(`[Weavetab CDP] connectToTab session closed (${appName || "browser"}) — unregistering.`);
|
|
699
723
|
// Cancel this tab's analytics interval so it doesn't outlive the session
|