@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
package/dist/tools/find.js
CHANGED
|
@@ -3,58 +3,84 @@ export async function browserFind(session, options, _config) {
|
|
|
3
3
|
if (!query)
|
|
4
4
|
throw new Error("browser_find requires a query string");
|
|
5
5
|
const { result } = await session.Runtime.evaluate({
|
|
6
|
-
expression: `(function(q, returnAll, maxMatches) {
|
|
7
|
-
function norm(s) { return (s || '').toLowerCase().replace(/[.\\u2026\\s]+/g, ' ').trim(); }
|
|
8
|
-
var qLow = norm(q);
|
|
9
|
-
var walker = document.createTreeWalker(document.body, NodeFilter.
|
|
10
|
-
var matchedNodes = [];
|
|
11
|
-
var seenElements = new Set();
|
|
12
|
-
|
|
13
|
-
while (walker.nextNode()) {
|
|
14
|
-
var node = walker.currentNode;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
6
|
+
expression: `(function(q, returnAll, maxMatches) {
|
|
7
|
+
function norm(s) { return (s || '').toLowerCase().replace(/[.\\u2026\\s]+/g, ' ').trim(); }
|
|
8
|
+
var qLow = norm(q);
|
|
9
|
+
var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, null, false);
|
|
10
|
+
var matchedNodes = [];
|
|
11
|
+
var seenElements = new Set();
|
|
12
|
+
|
|
13
|
+
while (walker.nextNode()) {
|
|
14
|
+
var node = walker.currentNode;
|
|
15
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
16
|
+
var t = norm(node.nodeValue);
|
|
17
|
+
if (t && t.includes(qLow)) {
|
|
18
|
+
var p = node.parentElement;
|
|
19
|
+
if (p && !seenElements.has(p)) {
|
|
20
|
+
seenElements.add(p);
|
|
21
|
+
matchedNodes.push(p);
|
|
22
|
+
if (!returnAll && matchedNodes.length >= 1) break;
|
|
23
|
+
if (matchedNodes.length >= maxMatches) break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
27
|
+
var el = node;
|
|
28
|
+
if (seenElements.has(el)) continue;
|
|
29
|
+
var aria = norm(el.getAttribute('aria-label') || el.getAttribute('title') || el.getAttribute('placeholder') || el.getAttribute('data-placeholder') || '');
|
|
30
|
+
if (aria && aria.includes(qLow)) {
|
|
31
|
+
seenElements.add(el);
|
|
32
|
+
matchedNodes.push(el);
|
|
33
|
+
if (!returnAll && matchedNodes.length >= 1) break;
|
|
34
|
+
if (matchedNodes.length >= maxMatches) break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (matchedNodes.length === 0) return null;
|
|
40
|
+
|
|
41
|
+
var out = matchedNodes.map(function(match, i) {
|
|
42
|
+
var r = match.getBoundingClientRect();
|
|
43
|
+
var wtId = match.getAttribute('data-wt-id');
|
|
44
|
+
var sel = '';
|
|
45
|
+
if (wtId) {
|
|
46
|
+
sel = '[data-wt-id="' + wtId + '"]';
|
|
47
|
+
} else if (match.id) {
|
|
48
|
+
sel = '#' + CSS.escape(match.id);
|
|
49
|
+
} else {
|
|
50
|
+
// Construct clean selector path without dirtying the DOM
|
|
51
|
+
var path = [];
|
|
52
|
+
var curr = match;
|
|
53
|
+
while (curr && curr.nodeType === Node.ELEMENT_NODE && curr !== document.body && curr !== document.documentElement) {
|
|
54
|
+
var tag = curr.tagName.toLowerCase();
|
|
55
|
+
if (curr.id) {
|
|
56
|
+
path.unshift('#' + CSS.escape(curr.id));
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
var p = curr.parentElement;
|
|
60
|
+
if (p) {
|
|
61
|
+
var sibs = Array.from(p.children).filter(function(c) { return c.tagName === curr.tagName; });
|
|
62
|
+
if (sibs.length > 1) {
|
|
63
|
+
tag += ':nth-of-type(' + (sibs.indexOf(curr) + 1) + ')';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
path.unshift(tag);
|
|
67
|
+
curr = p;
|
|
68
|
+
}
|
|
69
|
+
sel = path.join(' > ') || match.tagName.toLowerCase();
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
ref: wtId ? ('w:' + wtId) : undefined,
|
|
73
|
+
label: match.getAttribute('aria-label') || (match.textContent||'').trim().slice(0,80) || q,
|
|
74
|
+
tag: match.tagName.toLowerCase(),
|
|
75
|
+
x: Math.round(r.left),
|
|
76
|
+
y: Math.round(r.top),
|
|
77
|
+
width: Math.round(r.width),
|
|
78
|
+
height: Math.round(r.height),
|
|
79
|
+
selector: sel
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return JSON.stringify(out);
|
|
58
84
|
})(${JSON.stringify(query)}, ${JSON.stringify(all)}, ${JSON.stringify(limit)})`,
|
|
59
85
|
returnByValue: true
|
|
60
86
|
}).catch(() => ({ result: { value: null } }));
|
package/dist/tools/highlight.js
CHANGED
|
@@ -7,37 +7,37 @@ export async function browserHighlight(session, options, _config) {
|
|
|
7
7
|
const customColor = options.color;
|
|
8
8
|
// Inject required keyframes once
|
|
9
9
|
await session.Runtime.evaluate({
|
|
10
|
-
expression: `(function(){
|
|
11
|
-
if (!document.getElementById('wt-highlight-styles')) {
|
|
12
|
-
var s = document.createElement('style');
|
|
13
|
-
s.id = 'wt-highlight-styles';
|
|
14
|
-
s.textContent = \`
|
|
15
|
-
@keyframes wt-shimmer {
|
|
16
|
-
0% { opacity: 0; background-position: -200% 0; }
|
|
17
|
-
15% { opacity: 0.9; }
|
|
18
|
-
40% { opacity: 0.7; }
|
|
19
|
-
85% { opacity: 0.3; }
|
|
20
|
-
100% { opacity: 0; background-position: 200% 0; }
|
|
21
|
-
}
|
|
22
|
-
@keyframes wt-consider-pulse {
|
|
23
|
-
0%, 100% { box-shadow: 0 0 0 1px rgba(56,189,248,0.7), 0 0 14px rgba(56,189,248,0.35); opacity: 0.92; }
|
|
24
|
-
50% { box-shadow: 0 0 0 2px rgba(56,189,248,0.95), 0 0 22px rgba(56,189,248,0.6); opacity: 1; }
|
|
25
|
-
}
|
|
26
|
-
@keyframes wt-target-lock {
|
|
27
|
-
0% { transform: scale(1.05); opacity: 0.5; }
|
|
28
|
-
100% { transform: scale(1); opacity: 1; }
|
|
29
|
-
}
|
|
30
|
-
@keyframes wt-danger-pulse {
|
|
31
|
-
0%, 100% { box-shadow: 0 0 0 1px rgba(239,68,68,0.7), 0 0 14px rgba(239,68,68,0.35); opacity: 0.92; }
|
|
32
|
-
50% { box-shadow: 0 0 0 2px rgba(239,68,68,0.95), 0 0 22px rgba(239,68,68,0.6); opacity: 1; }
|
|
33
|
-
}
|
|
34
|
-
@keyframes wt-success-glow {
|
|
35
|
-
0% { opacity: 0.6; box-shadow: 0 0 0 1px rgba(16,185,129,0.7); }
|
|
36
|
-
100% { opacity: 1; box-shadow: 0 0 0 2px rgba(16,185,129,0.9), 0 0 18px rgba(16,185,129,0.45); }
|
|
37
|
-
}
|
|
38
|
-
\`;
|
|
39
|
-
(document.head || document.documentElement).appendChild(s);
|
|
40
|
-
}
|
|
10
|
+
expression: `(function(){
|
|
11
|
+
if (!document.getElementById('wt-highlight-styles')) {
|
|
12
|
+
var s = document.createElement('style');
|
|
13
|
+
s.id = 'wt-highlight-styles';
|
|
14
|
+
s.textContent = \`
|
|
15
|
+
@keyframes wt-shimmer {
|
|
16
|
+
0% { opacity: 0; background-position: -200% 0; }
|
|
17
|
+
15% { opacity: 0.9; }
|
|
18
|
+
40% { opacity: 0.7; }
|
|
19
|
+
85% { opacity: 0.3; }
|
|
20
|
+
100% { opacity: 0; background-position: 200% 0; }
|
|
21
|
+
}
|
|
22
|
+
@keyframes wt-consider-pulse {
|
|
23
|
+
0%, 100% { box-shadow: 0 0 0 1px rgba(56,189,248,0.7), 0 0 14px rgba(56,189,248,0.35); opacity: 0.92; }
|
|
24
|
+
50% { box-shadow: 0 0 0 2px rgba(56,189,248,0.95), 0 0 22px rgba(56,189,248,0.6); opacity: 1; }
|
|
25
|
+
}
|
|
26
|
+
@keyframes wt-target-lock {
|
|
27
|
+
0% { transform: scale(1.05); opacity: 0.5; }
|
|
28
|
+
100% { transform: scale(1); opacity: 1; }
|
|
29
|
+
}
|
|
30
|
+
@keyframes wt-danger-pulse {
|
|
31
|
+
0%, 100% { box-shadow: 0 0 0 1px rgba(239,68,68,0.7), 0 0 14px rgba(239,68,68,0.35); opacity: 0.92; }
|
|
32
|
+
50% { box-shadow: 0 0 0 2px rgba(239,68,68,0.95), 0 0 22px rgba(239,68,68,0.6); opacity: 1; }
|
|
33
|
+
}
|
|
34
|
+
@keyframes wt-success-glow {
|
|
35
|
+
0% { opacity: 0.6; box-shadow: 0 0 0 1px rgba(16,185,129,0.7); }
|
|
36
|
+
100% { opacity: 1; box-shadow: 0 0 0 2px rgba(16,185,129,0.9), 0 0 18px rgba(16,185,129,0.45); }
|
|
37
|
+
}
|
|
38
|
+
\`;
|
|
39
|
+
(document.head || document.documentElement).appendChild(s);
|
|
40
|
+
}
|
|
41
41
|
})()`,
|
|
42
42
|
returnByValue: true,
|
|
43
43
|
}).catch(() => { });
|
|
@@ -66,20 +66,20 @@ export async function browserHighlight(session, options, _config) {
|
|
|
66
66
|
const badgeHtml = escapedBadge
|
|
67
67
|
? `<span style="position:absolute;top:-20px;left:0;background:#09090b;border:1px solid #27272a;color:#f4f4f5;font-size:10px;font-family:-apple-system,BlinkMacSystemFont,\\'Segoe UI\\',sans-serif;font-weight:500;padding:1px 6px;border-radius:4px;white-space:nowrap;pointer-events:none;box-shadow:0 2px 6px rgba(0,0,0,0.5);">${escapedBadge}</span>`
|
|
68
68
|
: '';
|
|
69
|
-
return `(function(){
|
|
70
|
-
var div = document.createElement('div');
|
|
71
|
-
div.setAttribute('data-wt-ignore', 'true');
|
|
72
|
-
div.style.cssText = 'position:fixed;left:${x}px;top:${y}px;width:${w}px;height:${h}px;z-index:2147483647;pointer-events:none;${styleCss}';
|
|
73
|
-
if (${JSON.stringify(badgeHtml)}) {
|
|
74
|
-
div.innerHTML = ${JSON.stringify(badgeHtml)};
|
|
75
|
-
}
|
|
76
|
-
(document.getElementById('Weavetab-root')?.shadowRoot || document.getElementById('Weavetab-root') || document.body).appendChild(div);
|
|
77
|
-
setTimeout(function(){
|
|
78
|
-
div.style.transition = 'opacity 0.2s ease-out';
|
|
79
|
-
div.style.opacity = '0';
|
|
80
|
-
setTimeout(function(){ if(div.parentNode) div.parentNode.removeChild(div); }, 220);
|
|
81
|
-
}, ${duration});
|
|
82
|
-
return true;
|
|
69
|
+
return `(function(){
|
|
70
|
+
var div = document.createElement('div');
|
|
71
|
+
div.setAttribute('data-wt-ignore', 'true');
|
|
72
|
+
div.style.cssText = 'position:fixed;left:${x}px;top:${y}px;width:${w}px;height:${h}px;z-index:2147483647;pointer-events:none;${styleCss}';
|
|
73
|
+
if (${JSON.stringify(badgeHtml)}) {
|
|
74
|
+
div.innerHTML = ${JSON.stringify(badgeHtml)};
|
|
75
|
+
}
|
|
76
|
+
(document.getElementById('Weavetab-root')?.shadowRoot || document.getElementById('Weavetab-root') || document.body).appendChild(div);
|
|
77
|
+
setTimeout(function(){
|
|
78
|
+
div.style.transition = 'opacity 0.2s ease-out';
|
|
79
|
+
div.style.opacity = '0';
|
|
80
|
+
setTimeout(function(){ if(div.parentNode) div.parentNode.removeChild(div); }, 220);
|
|
81
|
+
}, ${duration});
|
|
82
|
+
return true;
|
|
83
83
|
})()`;
|
|
84
84
|
}
|
|
85
85
|
// Draw overlay by querying selector
|
|
@@ -90,28 +90,28 @@ export async function browserHighlight(session, options, _config) {
|
|
|
90
90
|
const badgeHtml = escapedBadge
|
|
91
91
|
? `<span style="position:absolute;top:-20px;left:0;background:#09090b;border:1px solid #27272a;color:#f4f4f5;font-size:10px;font-family:-apple-system,BlinkMacSystemFont,\\'Segoe UI\\',sans-serif;font-weight:500;padding:1px 6px;border-radius:4px;white-space:nowrap;pointer-events:none;box-shadow:0 2px 6px rgba(0,0,0,0.5);">${escapedBadge}</span>`
|
|
92
92
|
: '';
|
|
93
|
-
return `(function(){
|
|
94
|
-
var el;
|
|
95
|
-
try { el = document.querySelector('${escaped}'); } catch(e) {}
|
|
96
|
-
if (!el && window.__Weavetab_shadowQuery) {
|
|
97
|
-
try { el = window.__Weavetab_shadowQuery('${escaped}'); } catch(e) {}
|
|
98
|
-
}
|
|
99
|
-
if (!el) return false;
|
|
100
|
-
var r = el.getBoundingClientRect();
|
|
101
|
-
if (r.width === 0 && r.height === 0) return false;
|
|
102
|
-
var div = document.createElement('div');
|
|
103
|
-
div.setAttribute('data-wt-ignore', 'true');
|
|
104
|
-
div.style.cssText = 'position:fixed;left:'+r.left+'px;top:'+r.top+'px;width:'+r.width+'px;height:'+r.height+'px;z-index:2147483647;pointer-events:none;${styleCss}';
|
|
105
|
-
if (${JSON.stringify(badgeHtml)}) {
|
|
106
|
-
div.innerHTML = ${JSON.stringify(badgeHtml)};
|
|
107
|
-
}
|
|
108
|
-
(document.getElementById('Weavetab-root')?.shadowRoot || document.getElementById('Weavetab-root') || document.body).appendChild(div);
|
|
109
|
-
setTimeout(function(){
|
|
110
|
-
div.style.transition = 'opacity 0.2s ease-out';
|
|
111
|
-
div.style.opacity = '0';
|
|
112
|
-
setTimeout(function(){ if(div.parentNode) div.parentNode.removeChild(div); }, 220);
|
|
113
|
-
}, ${duration});
|
|
114
|
-
return true;
|
|
93
|
+
return `(function(){
|
|
94
|
+
var el;
|
|
95
|
+
try { el = document.querySelector('${escaped}'); } catch(e) {}
|
|
96
|
+
if (!el && window.__Weavetab_shadowQuery) {
|
|
97
|
+
try { el = window.__Weavetab_shadowQuery('${escaped}'); } catch(e) {}
|
|
98
|
+
}
|
|
99
|
+
if (!el) return false;
|
|
100
|
+
var r = el.getBoundingClientRect();
|
|
101
|
+
if (r.width === 0 && r.height === 0) return false;
|
|
102
|
+
var div = document.createElement('div');
|
|
103
|
+
div.setAttribute('data-wt-ignore', 'true');
|
|
104
|
+
div.style.cssText = 'position:fixed;left:'+r.left+'px;top:'+r.top+'px;width:'+r.width+'px;height:'+r.height+'px;z-index:2147483647;pointer-events:none;${styleCss}';
|
|
105
|
+
if (${JSON.stringify(badgeHtml)}) {
|
|
106
|
+
div.innerHTML = ${JSON.stringify(badgeHtml)};
|
|
107
|
+
}
|
|
108
|
+
(document.getElementById('Weavetab-root')?.shadowRoot || document.getElementById('Weavetab-root') || document.body).appendChild(div);
|
|
109
|
+
setTimeout(function(){
|
|
110
|
+
div.style.transition = 'opacity 0.2s ease-out';
|
|
111
|
+
div.style.opacity = '0';
|
|
112
|
+
setTimeout(function(){ if(div.parentNode) div.parentNode.removeChild(div); }, 220);
|
|
113
|
+
}, ${duration});
|
|
114
|
+
return true;
|
|
115
115
|
})()`;
|
|
116
116
|
}
|
|
117
117
|
async function trySelector(sel, badgeLabel) {
|
package/dist/tools/inspect.js
CHANGED
|
@@ -9,24 +9,20 @@ export async function browserInspect(session, options, _config) {
|
|
|
9
9
|
}
|
|
10
10
|
const { DOM, CSS, DOMDebugger } = session;
|
|
11
11
|
await DOM.enable();
|
|
12
|
-
|
|
12
|
+
await DOM.getDocument({ depth: 0 }).catch(() => null);
|
|
13
13
|
await CSS.enable().catch(() => { });
|
|
14
14
|
let resolvedNodeId = nodeId || null;
|
|
15
15
|
// Step 1: Resolve a live nodeId from any input
|
|
16
16
|
if (!resolvedNodeId && ref) {
|
|
17
17
|
const active = sessionRegistry.getActive(getConfigAgentId(_config));
|
|
18
18
|
if (active) {
|
|
19
|
-
// getCachedActionMap returns null when the DOM has mutated since the last
|
|
20
|
-
// read (lastMutationTime > lastReadTime). On a cache miss, rebuild the map
|
|
21
|
-
// so ref IDs remain resolvable after any DOM change instead of silently
|
|
22
|
-
// falling through to "Could not resolve element to a node ID".
|
|
23
19
|
let map = getCachedActionMap(active.targetId);
|
|
24
20
|
if (!map) {
|
|
25
21
|
try {
|
|
26
22
|
map = await buildActionMap(session, { lite: true }, active.targetId);
|
|
27
23
|
cacheActionMap(active.targetId, map);
|
|
28
24
|
}
|
|
29
|
-
catch { /* best-effort
|
|
25
|
+
catch { /* best-effort */ }
|
|
30
26
|
}
|
|
31
27
|
if (map) {
|
|
32
28
|
const el = map.elements.find((e) => e.id === ref || e.id.endsWith(ref.startsWith("w:") ? ref.slice(2) : ref));
|
|
@@ -38,7 +34,6 @@ export async function browserInspect(session, options, _config) {
|
|
|
38
34
|
if (!resolvedNodeId && el?.selector) {
|
|
39
35
|
selector = el.selector;
|
|
40
36
|
}
|
|
41
|
-
// Also try data-wt-id selector directly when backendNodeId lookup fails
|
|
42
37
|
if (!resolvedNodeId && ref) {
|
|
43
38
|
const rawId = ref.startsWith("w:") ? ref.slice(2) : ref;
|
|
44
39
|
selector = selector || `[data-wt-id="${rawId}"]`;
|
|
@@ -48,14 +43,14 @@ export async function browserInspect(session, options, _config) {
|
|
|
48
43
|
}
|
|
49
44
|
if (!resolvedNodeId && selector) {
|
|
50
45
|
const res = await session.Runtime.evaluate({
|
|
51
|
-
expression: `(function(sel) {
|
|
52
|
-
var els = document.querySelectorAll(sel);
|
|
53
|
-
for (var i = 0; i < els.length; i++) {
|
|
54
|
-
if (!els[i].closest('#wt-shadow-host, [data-wt-ignore]')) {
|
|
55
|
-
return els[i];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return els[0] || null;
|
|
46
|
+
expression: `(function(sel) {
|
|
47
|
+
var els = document.querySelectorAll(sel);
|
|
48
|
+
for (var i = 0; i < els.length; i++) {
|
|
49
|
+
if (!els[i].closest('#wt-shadow-host, [data-wt-ignore]')) {
|
|
50
|
+
return els[i];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return els[0] || null;
|
|
59
54
|
})(${JSON.stringify(selector)})`,
|
|
60
55
|
});
|
|
61
56
|
if (res.result?.objectId) {
|
|
@@ -69,26 +64,60 @@ export async function browserInspect(session, options, _config) {
|
|
|
69
64
|
}
|
|
70
65
|
// Step 2: Fetch box model, computed styles, and event listeners in parallel
|
|
71
66
|
const boxModel = await DOM.getBoxModel({ nodeId: resolvedNodeId }).catch(() => null);
|
|
67
|
+
function reconstructShorthand(prefix, styles) {
|
|
68
|
+
const t = styles[`${prefix}-top`];
|
|
69
|
+
const r = styles[`${prefix}-right`];
|
|
70
|
+
const b = styles[`${prefix}-bottom`];
|
|
71
|
+
const l = styles[`${prefix}-left`];
|
|
72
|
+
if (t === undefined && r === undefined && b === undefined && l === undefined)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (t === b && r === l)
|
|
75
|
+
return t === r ? t : `${t} ${r}`;
|
|
76
|
+
if (r === l)
|
|
77
|
+
return `${t} ${r} ${b}`;
|
|
78
|
+
return `${t} ${r} ${b} ${l}`;
|
|
79
|
+
}
|
|
72
80
|
// Try CSS.getComputedStyleForNode first (CDP-native), fall back to Runtime.evaluate
|
|
73
81
|
let computedStylesData = null;
|
|
74
82
|
const cssResult = await CSS.getComputedStyleForNode({ nodeId: resolvedNodeId }).catch(() => null);
|
|
75
83
|
if (cssResult?.computedStyle) {
|
|
76
|
-
const INTERESTING = [
|
|
77
|
-
|
|
84
|
+
const INTERESTING = [
|
|
85
|
+
'display', 'position', 'width', 'height', 'color', 'background-color', 'font-size', 'visibility', 'opacity', 'z-index', 'pointer-events',
|
|
86
|
+
'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
|
|
87
|
+
'padding-top', 'padding-right', 'padding-bottom', 'padding-left'
|
|
88
|
+
];
|
|
89
|
+
const rawStyles = cssResult.computedStyle
|
|
78
90
|
.filter((s) => INTERESTING.includes(s.name))
|
|
79
91
|
.reduce((acc, curr) => ({ ...acc, [curr.name]: curr.value }), {});
|
|
92
|
+
const margin = reconstructShorthand('margin', rawStyles);
|
|
93
|
+
const padding = reconstructShorthand('padding', rawStyles);
|
|
94
|
+
computedStylesData = {
|
|
95
|
+
display: rawStyles.display,
|
|
96
|
+
position: rawStyles.position,
|
|
97
|
+
width: rawStyles.width,
|
|
98
|
+
height: rawStyles.height,
|
|
99
|
+
...(margin ? { margin } : {}),
|
|
100
|
+
...(padding ? { padding } : {}),
|
|
101
|
+
color: rawStyles.color,
|
|
102
|
+
'background-color': rawStyles['background-color'],
|
|
103
|
+
'font-size': rawStyles['font-size'],
|
|
104
|
+
visibility: rawStyles.visibility,
|
|
105
|
+
opacity: rawStyles.opacity,
|
|
106
|
+
'z-index': rawStyles['z-index'],
|
|
107
|
+
'pointer-events': rawStyles['pointer-events']
|
|
108
|
+
};
|
|
80
109
|
}
|
|
81
110
|
if (!computedStylesData && selector) {
|
|
82
111
|
// Fallback: use window.getComputedStyle via Runtime.evaluate
|
|
83
112
|
const { result: fallbackRes } = await session.Runtime.evaluate({
|
|
84
|
-
expression: `(function(sel) {
|
|
85
|
-
var el = document.querySelector(sel);
|
|
86
|
-
if (!el) return null;
|
|
87
|
-
var s = window.getComputedStyle(el);
|
|
88
|
-
var KEYS = ['display','position','width','height','margin','padding','color','background-color','font-size','visibility','opacity','z-index','pointer-events'];
|
|
89
|
-
var r = {};
|
|
90
|
-
for (var i = 0; i < KEYS.length; i++) r[KEYS[i]] = s.getPropertyValue(KEYS[i]);
|
|
91
|
-
return JSON.stringify(r);
|
|
113
|
+
expression: `(function(sel) {
|
|
114
|
+
var el = document.querySelector(sel);
|
|
115
|
+
if (!el) return null;
|
|
116
|
+
var s = window.getComputedStyle(el);
|
|
117
|
+
var KEYS = ['display','position','width','height','margin','padding','color','background-color','font-size','visibility','opacity','z-index','pointer-events'];
|
|
118
|
+
var r = {};
|
|
119
|
+
for (var i = 0; i < KEYS.length; i++) r[KEYS[i]] = s.getPropertyValue(KEYS[i]);
|
|
120
|
+
return JSON.stringify(r);
|
|
92
121
|
})(${JSON.stringify(selector)})`,
|
|
93
122
|
returnByValue: true,
|
|
94
123
|
}).catch(() => ({ result: { value: null } }));
|
package/dist/tools/key.js
CHANGED
|
@@ -90,41 +90,41 @@ export async function weaveKey(session, args, _config) {
|
|
|
90
90
|
if (key === "Enter") {
|
|
91
91
|
// SPA Fallback: direct form submit + submit button click for React/Vue/Google
|
|
92
92
|
// This is needed because Input.dispatchKeyEvent alone doesn't trigger SPA form submission
|
|
93
|
-
await session.Runtime.evaluate({ expression: `
|
|
94
|
-
(function(){
|
|
95
|
-
try {
|
|
96
|
-
var el = document.activeElement;
|
|
97
|
-
if (!el || !el.tagName) return;
|
|
98
|
-
|
|
99
|
-
// Focus the element first to make sure it's active
|
|
100
|
-
if (typeof el.focus === 'function') el.focus();
|
|
101
|
-
|
|
102
|
-
// 1. Try native form submit (Google search, DuckDuckGo, etc.)
|
|
103
|
-
var form = el.closest('form');
|
|
104
|
-
if (form) {
|
|
105
|
-
var submitBtn = form.querySelector('input[type="submit"], button[type="submit"]');
|
|
106
|
-
if (submitBtn && submitBtn.offsetParent !== null) { submitBtn.click(); return; }
|
|
107
|
-
try { form.submit(); return; } catch(e) {}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// 2. Google-specific: find name="q" input and submit its form
|
|
111
|
-
var q = document.querySelector('input[name="q"], textarea[name="q"]');
|
|
112
|
-
if (q) {
|
|
113
|
-
var qForm = q.closest('form');
|
|
114
|
-
if (qForm) { try { qForm.submit(); return; } catch(e) {} }
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// 3. Last resort: find any visible submit/search button near the active element
|
|
118
|
-
var parent = el.parentElement;
|
|
119
|
-
while (parent && parent.tagName !== 'BODY') {
|
|
120
|
-
var btns = parent.querySelectorAll('button, input[type="submit"], input[type="button"]');
|
|
121
|
-
for (var i = 0; i < btns.length; i++) {
|
|
122
|
-
if (btns[i].offsetParent !== null && btns[i].getBoundingClientRect().width > 0) { btns[i].click(); return; }
|
|
123
|
-
}
|
|
124
|
-
parent = parent.parentElement;
|
|
125
|
-
}
|
|
126
|
-
} catch(e) {}
|
|
127
|
-
})();
|
|
93
|
+
await session.Runtime.evaluate({ expression: `
|
|
94
|
+
(function(){
|
|
95
|
+
try {
|
|
96
|
+
var el = document.activeElement;
|
|
97
|
+
if (!el || !el.tagName) return;
|
|
98
|
+
|
|
99
|
+
// Focus the element first to make sure it's active
|
|
100
|
+
if (typeof el.focus === 'function') el.focus();
|
|
101
|
+
|
|
102
|
+
// 1. Try native form submit (Google search, DuckDuckGo, etc.)
|
|
103
|
+
var form = el.closest('form');
|
|
104
|
+
if (form) {
|
|
105
|
+
var submitBtn = form.querySelector('input[type="submit"], button[type="submit"]');
|
|
106
|
+
if (submitBtn && submitBtn.offsetParent !== null) { submitBtn.click(); return; }
|
|
107
|
+
try { form.submit(); return; } catch(e) {}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 2. Google-specific: find name="q" input and submit its form
|
|
111
|
+
var q = document.querySelector('input[name="q"], textarea[name="q"]');
|
|
112
|
+
if (q) {
|
|
113
|
+
var qForm = q.closest('form');
|
|
114
|
+
if (qForm) { try { qForm.submit(); return; } catch(e) {} }
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 3. Last resort: find any visible submit/search button near the active element
|
|
118
|
+
var parent = el.parentElement;
|
|
119
|
+
while (parent && parent.tagName !== 'BODY') {
|
|
120
|
+
var btns = parent.querySelectorAll('button, input[type="submit"], input[type="button"]');
|
|
121
|
+
for (var i = 0; i < btns.length; i++) {
|
|
122
|
+
if (btns[i].offsetParent !== null && btns[i].getBoundingClientRect().width > 0) { btns[i].click(); return; }
|
|
123
|
+
}
|
|
124
|
+
parent = parent.parentElement;
|
|
125
|
+
}
|
|
126
|
+
} catch(e) {}
|
|
127
|
+
})();
|
|
128
128
|
` }).catch(() => { });
|
|
129
129
|
}
|
|
130
130
|
await session.Input.dispatchKeyEvent({ type: "keyUp", key: effectiveKey, modifiers: modMask, windowsVirtualKeyCode: effectiveKey === "Enter" ? 13 : undefined, nativeVirtualKeyCode: effectiveKey === "Enter" ? 13 : undefined });
|
|
@@ -144,6 +144,13 @@ export async function weaveKey(session, args, _config) {
|
|
|
144
144
|
const activeSession = sessionRegistry.getActive(getConfigAgentId(_config));
|
|
145
145
|
if (activeSession)
|
|
146
146
|
activeSession.url = postUrl;
|
|
147
|
+
const titleRes = await session.Runtime.evaluate({ expression: "document.title", returnByValue: true }).catch(() => null);
|
|
148
|
+
if (titleRes?.result?.value) {
|
|
149
|
+
postTitle = String(titleRes.result.value);
|
|
150
|
+
}
|
|
151
|
+
else if (activeSession?.title) {
|
|
152
|
+
postTitle = activeSession.title;
|
|
153
|
+
}
|
|
147
154
|
}
|
|
148
155
|
catch { /* ignore */ }
|
|
149
156
|
const urlChanged = postUrl !== urlBefore;
|
package/dist/tools/navigate.d.ts
CHANGED
package/dist/tools/navigate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Weavetab
|
|
2
|
+
* Weavetab — tools/navigate.ts
|
|
3
3
|
* URL navigation with domain blocklist enforcement and post-navigation DOM stability wait.
|
|
4
4
|
* Weavetab by fy2ne
|
|
5
5
|
*/
|
|
@@ -15,8 +15,8 @@ import { sessionRegistry } from "../state/session.js";
|
|
|
15
15
|
export async function weaveNavigate(session, url, config, targetId = "default", force = false, fast = false, appName) {
|
|
16
16
|
logDebug(`[weaveNavigate] Attempting navigation to: ${url}`);
|
|
17
17
|
let parsed;
|
|
18
|
-
if (url.startsWith('
|
|
19
|
-
const page = url.
|
|
18
|
+
if (url.toLowerCase().startsWith('weavetab://')) {
|
|
19
|
+
const page = url.slice('weavetab://'.length).split('?')[0] || 'dashboard';
|
|
20
20
|
try {
|
|
21
21
|
const { getFromExtension } = await import("../cdp/helpers.js");
|
|
22
22
|
const extUrl = await getFromExtension(session, { type: 'RESOLVE_EXTENSION_URL', page });
|
|
@@ -24,11 +24,11 @@ export async function weaveNavigate(session, url, config, targetId = "default",
|
|
|
24
24
|
parsed = new URL(extUrl);
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
|
-
return { success: false, error_code: "EXTENSION_URL_FAILED", message: `Could not resolve
|
|
27
|
+
return { success: false, error_code: "EXTENSION_URL_FAILED", message: `Could not resolve weavetab://${page}` };
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
catch {
|
|
31
|
-
return { success: false, error_code: "EXTENSION_NOT_AVAILABLE", message: "Extension runtime not available for
|
|
31
|
+
return { success: false, error_code: "EXTENSION_NOT_AVAILABLE", message: "Extension runtime not available for weavetab:// navigation" };
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
@@ -71,10 +71,10 @@ export async function weaveNavigate(session, url, config, targetId = "default",
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
// Extension pages: open in new tab instead of navigating current tab
|
|
74
|
-
// (chrome-extension:// pages use a different process context
|
|
74
|
+
// (chrome-extension:// pages use a different process context — Page.navigate
|
|
75
75
|
// can break the CDP session or not fire loadEventFired properly)
|
|
76
76
|
if (parsed.protocol === 'chrome-extension:') {
|
|
77
|
-
logDebug(`[weaveNavigate] Extension URL detected
|
|
77
|
+
logDebug(`[weaveNavigate] Extension URL detected — opening in new tab: ${parsed.href}`);
|
|
78
78
|
const { sendToExtension } = await import("../cdp/helpers.js");
|
|
79
79
|
await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: `opening extension page...` } });
|
|
80
80
|
const { WeavetabOpen } = await import("./tabs.js");
|
|
@@ -112,20 +112,20 @@ export async function weaveNavigate(session, url, config, targetId = "default",
|
|
|
112
112
|
let isAnchor = false;
|
|
113
113
|
try {
|
|
114
114
|
const res = await session.Runtime.evaluate({
|
|
115
|
-
expression: `new Promise((resolve) => {
|
|
116
|
-
let done = false;
|
|
117
|
-
const finish = (val) => { if (!done) { done = true; resolve(val); } };
|
|
118
|
-
setTimeout(() => finish(false), 30);
|
|
119
|
-
try {
|
|
120
|
-
const browserAPI = typeof browser !== 'undefined' ? browser : (typeof chrome !== 'undefined' ? chrome : null);
|
|
121
|
-
if (browserAPI && browserAPI.runtime && browserAPI.runtime.id) {
|
|
122
|
-
browserAPI.runtime.sendMessage({ type: 'GET_ANCHOR_STATUS' }, (response) => {
|
|
123
|
-
finish(response?.isAnchor || false);
|
|
124
|
-
});
|
|
125
|
-
} else {
|
|
126
|
-
finish(false);
|
|
127
|
-
}
|
|
128
|
-
} catch(e) { finish(false); }
|
|
115
|
+
expression: `new Promise((resolve) => {
|
|
116
|
+
let done = false;
|
|
117
|
+
const finish = (val) => { if (!done) { done = true; resolve(val); } };
|
|
118
|
+
setTimeout(() => finish(false), 30);
|
|
119
|
+
try {
|
|
120
|
+
const browserAPI = typeof browser !== 'undefined' ? browser : (typeof chrome !== 'undefined' ? chrome : null);
|
|
121
|
+
if (browserAPI && browserAPI.runtime && browserAPI.runtime.id) {
|
|
122
|
+
browserAPI.runtime.sendMessage({ type: 'GET_ANCHOR_STATUS' }, (response) => {
|
|
123
|
+
finish(response?.isAnchor || false);
|
|
124
|
+
});
|
|
125
|
+
} else {
|
|
126
|
+
finish(false);
|
|
127
|
+
}
|
|
128
|
+
} catch(e) { finish(false); }
|
|
129
129
|
})`,
|
|
130
130
|
awaitPromise: true,
|
|
131
131
|
returnByValue: true
|
|
@@ -171,20 +171,20 @@ export async function weaveNavigate(session, url, config, targetId = "default",
|
|
|
171
171
|
session.Page.getFrameTree().catch(() => ({ frameTree: { frame: { url: parsed.href } } })),
|
|
172
172
|
session.Runtime.evaluate({ expression: 'document.title', returnByValue: true }).catch(() => null),
|
|
173
173
|
session.Runtime.evaluate({
|
|
174
|
-
expression: `
|
|
175
|
-
(function(){
|
|
176
|
-
var selectors = [
|
|
177
|
-
'[id*="cookie"] button','[class*="cookie"] button',
|
|
178
|
-
'[id*="consent"] button','[class*="consent"] button',
|
|
179
|
-
'[id*="gdpr"] button','[class*="gdpr"] button',
|
|
180
|
-
'[aria-label*="Accept"]','[aria-label*="Agree"]',
|
|
181
|
-
'button[data-cookiebanner]'
|
|
182
|
-
];
|
|
183
|
-
for(var i=0;i<selectors.length;i++){
|
|
184
|
-
var el=document.querySelector(selectors[i]);
|
|
185
|
-
if(el){try{el.click();}catch(e){}break;}
|
|
186
|
-
}
|
|
187
|
-
})()
|
|
174
|
+
expression: `
|
|
175
|
+
(function(){
|
|
176
|
+
var selectors = [
|
|
177
|
+
'[id*="cookie"] button','[class*="cookie"] button',
|
|
178
|
+
'[id*="consent"] button','[class*="consent"] button',
|
|
179
|
+
'[id*="gdpr"] button','[class*="gdpr"] button',
|
|
180
|
+
'[aria-label*="Accept"]','[aria-label*="Agree"]',
|
|
181
|
+
'button[data-cookiebanner]'
|
|
182
|
+
];
|
|
183
|
+
for(var i=0;i<selectors.length;i++){
|
|
184
|
+
var el=document.querySelector(selectors[i]);
|
|
185
|
+
if(el){try{el.click();}catch(e){}break;}
|
|
186
|
+
}
|
|
187
|
+
})()
|
|
188
188
|
`
|
|
189
189
|
}).catch(() => { })
|
|
190
190
|
]);
|