@weavetab/mcp 2.5.0-beta.5 → 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/README.md +216 -100
- 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/configuration/configuration.md +39 -27
- 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 +1 -1
- package/docs/intelligence/site-profiles.md +151 -151
- package/docs/tools/tools.md +582 -631
- 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 +8 -8
- package/server.json +23 -23
- package/smithery.yaml +7 -11
- 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/cdp/pruner.js
CHANGED
|
@@ -64,200 +64,200 @@ function buildEvalExpression(rawIds, structuralIdioms = []) {
|
|
|
64
64
|
// We JSON-encode the id list so the script can build a lookup Set.
|
|
65
65
|
const idsJson = JSON.stringify(rawIds);
|
|
66
66
|
const idiomsJson = JSON.stringify(structuralIdioms);
|
|
67
|
-
return `(function() {
|
|
68
|
-
var t0 = performance.now();
|
|
69
|
-
|
|
70
|
-
// ── Interactive selector (mirrors walker.ts) ─────────────────────────────
|
|
71
|
-
var INTERACTIVE_SEL = [
|
|
72
|
-
'a', 'button', 'input', 'textarea', 'select',
|
|
73
|
-
'[role="button"]', '[role="link"]', '[role="textbox"]',
|
|
74
|
-
'[role="checkbox"]', '[role="radio"]', '[role="combobox"]',
|
|
75
|
-
'[role="searchbox"]', '[role="menuitem"]', '[role="tab"]',
|
|
76
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
77
|
-
].join(', ');
|
|
78
|
-
|
|
79
|
-
// SVG ancestor selector (includes menuitem + tab for Jira/AWS patterns)
|
|
80
|
-
var SVG_ANCESTOR_SEL = 'button, a, [role="button"], [role="menuitem"], [role="tab"]';
|
|
81
|
-
|
|
82
|
-
var targetIds = new Set(${idsJson});
|
|
83
|
-
|
|
84
|
-
// ── Assign synthetic ids to any element missing data-wt-id ──
|
|
85
|
-
// data-wt-secret guard fires on the ATTRIBUTE (not the id), so secret fields
|
|
86
|
-
// are safe even when running on a synthetic id.
|
|
87
|
-
var syntheticPrefix = '__prune_idx_';
|
|
88
|
-
var syntheticEls = [];
|
|
89
|
-
var allEls = document.querySelectorAll('[data-wt-id], [data-wt-secret]');
|
|
90
|
-
var synIdx = 0;
|
|
91
|
-
for (var si = 0; si < allEls.length; si++) {
|
|
92
|
-
var sel = allEls[si];
|
|
93
|
-
if (!sel.getAttribute('data-wt-id')) {
|
|
94
|
-
var synthId = syntheticPrefix + (synIdx++);
|
|
95
|
-
sel.setAttribute('data-wt-id', synthId);
|
|
96
|
-
syntheticEls.push(sel);
|
|
97
|
-
targetIds.add(synthId);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ── Pass 1: Document-level controls map ──────────────────────────────────
|
|
102
|
-
// Built from the WHOLE document — stale or unrelated aria-controls values
|
|
103
|
-
// can force-keep unrelated targets. Accepted over-keep bias: prefer recall
|
|
104
|
-
// over precision so the agent never loses a toggle target it needs.
|
|
105
|
-
var controlsMap = new Set();
|
|
106
|
-
var CONTROLS_ATTRS = ['aria-controls', 'aria-owns', 'data-target', 'data-bs-target'];
|
|
107
|
-
var extraIdioms = ${idiomsJson};
|
|
108
|
-
for (var ei = 0; ei < extraIdioms.length; ei++) {
|
|
109
|
-
if (CONTROLS_ATTRS.indexOf(extraIdioms[ei]) === -1) {
|
|
110
|
-
CONTROLS_ATTRS.push(extraIdioms[ei]);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
try {
|
|
114
|
-
var allNodes = document.querySelectorAll(CONTROLS_ATTRS.map(function(a) { return '[' + a + ']'; }).join(', '));
|
|
115
|
-
for (var ci = 0; ci < allNodes.length; ci++) {
|
|
116
|
-
for (var ai = 0; ai < CONTROLS_ATTRS.length; ai++) {
|
|
117
|
-
var val = allNodes[ci].getAttribute(CONTROLS_ATTRS[ai]);
|
|
118
|
-
if (!val) continue;
|
|
119
|
-
var tokens = val.split(/\\s+/);
|
|
120
|
-
for (var ti = 0; ti < tokens.length; ti++) {
|
|
121
|
-
if (tokens[ti]) controlsMap.add(tokens[ti]);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
} catch(e) {}
|
|
126
|
-
|
|
127
|
-
// ── Pass 2: Post-order hasInteractiveDescendant annotation ───────────────
|
|
128
|
-
// Single bottom-up pass — O(n). Each hidden-element check is then O(1).
|
|
129
|
-
try {
|
|
130
|
-
var walker = document.createTreeWalker(document.body || document, NodeFilter.SHOW_ELEMENT, null, false);
|
|
131
|
-
var nodeStack = [];
|
|
132
|
-
var node = walker.nextNode();
|
|
133
|
-
while (node) {
|
|
134
|
-
nodeStack.push(node);
|
|
135
|
-
node = walker.nextNode();
|
|
136
|
-
}
|
|
137
|
-
// Process in reverse (post-order)
|
|
138
|
-
for (var ni = nodeStack.length - 1; ni >= 0; ni--) {
|
|
139
|
-
var n = nodeStack[ni];
|
|
140
|
-
var isInteractive = false;
|
|
141
|
-
try { isInteractive = n.matches(INTERACTIVE_SEL); } catch(e) {}
|
|
142
|
-
var childHas = false;
|
|
143
|
-
try {
|
|
144
|
-
var children = n.children;
|
|
145
|
-
for (var ki = 0; ki < children.length; ki++) {
|
|
146
|
-
if (children[ki].__wtHasInteractive) { childHas = true; break; }
|
|
147
|
-
}
|
|
148
|
-
} catch(e) {}
|
|
149
|
-
n.__wtHasInteractive = isInteractive || childHas;
|
|
150
|
-
}
|
|
151
|
-
} catch(e) {}
|
|
152
|
-
|
|
153
|
-
// ── Pass 3: Per-element prune decision ───────────────────────────────────
|
|
154
|
-
var keptIds = [];
|
|
155
|
-
var svgLabels = {};
|
|
156
|
-
var prunedCount = 0;
|
|
157
|
-
var svgCount = 0;
|
|
158
|
-
|
|
159
|
-
targetIds.forEach(function(wtId) {
|
|
160
|
-
var el;
|
|
161
|
-
try {
|
|
162
|
-
el = document.querySelector('[data-wt-id="' + wtId + '"]');
|
|
163
|
-
} catch(e) {}
|
|
164
|
-
if (!el) { prunedCount++; return; }
|
|
165
|
-
|
|
166
|
-
// Secret guard — fires on ATTRIBUTE, independent of whether id is synthetic
|
|
167
|
-
if (el.hasAttribute('data-wt-secret')) {
|
|
168
|
-
keptIds.push(String(wtId));
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Visibility check
|
|
173
|
-
var hidden = false;
|
|
174
|
-
try {
|
|
175
|
-
var rect = el.getBoundingClientRect();
|
|
176
|
-
if (rect.width === 0 && rect.height === 0) {
|
|
177
|
-
hidden = true;
|
|
178
|
-
} else {
|
|
179
|
-
var cs = window.getComputedStyle(el);
|
|
180
|
-
if (cs.visibility === 'hidden' || cs.display === 'none') hidden = true;
|
|
181
|
-
}
|
|
182
|
-
} catch(e) {}
|
|
183
|
-
|
|
184
|
-
if (!hidden) {
|
|
185
|
-
// Visible — keep; handle SVG label replacement
|
|
186
|
-
keptIds.push(String(wtId));
|
|
187
|
-
if (el.tagName && el.tagName.toLowerCase() === 'svg') {
|
|
188
|
-
var label = resolveSvgLabel(el, SVG_ANCESTOR_SEL);
|
|
189
|
-
svgLabels[String(wtId)] = label;
|
|
190
|
-
svgCount++;
|
|
191
|
-
}
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Hidden — keep if has interactive descendant
|
|
196
|
-
if (el.__wtHasInteractive) {
|
|
197
|
-
keptIds.push(String(wtId));
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// Hidden — keep if referenced by a known toggle trigger (controlsMap)
|
|
202
|
-
var elId = el.getAttribute('id');
|
|
203
|
-
if (elId && controlsMap.has(elId)) {
|
|
204
|
-
keptIds.push(String(wtId));
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Drop
|
|
209
|
-
prunedCount++;
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// ── Strip synthetic ids from DOM ─────────────────────────────────────────
|
|
213
|
-
for (var ri = 0; ri < syntheticEls.length; ri++) {
|
|
214
|
-
try { syntheticEls[ri].removeAttribute('data-wt-id'); } catch(e) {}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// ── SVG label resolution helper ──────────────────────────────────────────
|
|
218
|
-
function resolveSvgLabel(svg, ancestorSel) {
|
|
219
|
-
// 1. SVG's own aria-label
|
|
220
|
-
var label = svg.getAttribute('aria-label');
|
|
221
|
-
if (label && label.trim()) return '[SVG Icon: ' + label.trim() + ']';
|
|
222
|
-
|
|
223
|
-
// 2. SVG's own <title> child
|
|
224
|
-
try {
|
|
225
|
-
var title = svg.querySelector('title');
|
|
226
|
-
if (title && title.textContent && title.textContent.trim()) {
|
|
227
|
-
return '[SVG Icon: ' + title.textContent.trim() + ']';
|
|
228
|
-
}
|
|
229
|
-
} catch(e) {}
|
|
230
|
-
|
|
231
|
-
// 3. Closest interactive ancestor's aria-label
|
|
232
|
-
// Covers: <button aria-label="Delete"><svg/></button>
|
|
233
|
-
// <a role="menuitem" aria-label="More actions"><svg/></a> (Jira)
|
|
234
|
-
// <div role="tab" aria-label="Overview"><svg/></div> (AWS)
|
|
235
|
-
try {
|
|
236
|
-
var ancestor = svg.closest(ancestorSel);
|
|
237
|
-
if (ancestor) {
|
|
238
|
-
var aLabel = ancestor.getAttribute('aria-label');
|
|
239
|
-
if (aLabel && aLabel.trim()) return '[SVG Icon: ' + aLabel.trim() + ']';
|
|
240
|
-
}
|
|
241
|
-
} catch(e) {}
|
|
242
|
-
|
|
243
|
-
return '[SVG Icon]';
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
var elapsedMs = performance.now() - t0;
|
|
247
|
-
|
|
248
|
-
// ── Perf-gate: if this took > 5ms, flag it — caller will decide on split ─
|
|
249
|
-
// (In this single-evaluate path we can only report, not split retroactively.
|
|
250
|
-
// The split path would be invoked by the caller on a second evaluate call.)
|
|
251
|
-
return JSON.stringify({
|
|
252
|
-
keptIds: keptIds,
|
|
253
|
-
svgLabels: svgLabels,
|
|
254
|
-
stats: {
|
|
255
|
-
total: targetIds.size,
|
|
256
|
-
pruned: prunedCount,
|
|
257
|
-
svgReplaced: svgCount,
|
|
258
|
-
elapsedMs: elapsedMs,
|
|
259
|
-
splitPath: false
|
|
260
|
-
}
|
|
261
|
-
});
|
|
67
|
+
return `(function() {
|
|
68
|
+
var t0 = performance.now();
|
|
69
|
+
|
|
70
|
+
// ── Interactive selector (mirrors walker.ts) ─────────────────────────────
|
|
71
|
+
var INTERACTIVE_SEL = [
|
|
72
|
+
'a', 'button', 'input', 'textarea', 'select',
|
|
73
|
+
'[role="button"]', '[role="link"]', '[role="textbox"]',
|
|
74
|
+
'[role="checkbox"]', '[role="radio"]', '[role="combobox"]',
|
|
75
|
+
'[role="searchbox"]', '[role="menuitem"]', '[role="tab"]',
|
|
76
|
+
'[tabindex]:not([tabindex="-1"])'
|
|
77
|
+
].join(', ');
|
|
78
|
+
|
|
79
|
+
// SVG ancestor selector (includes menuitem + tab for Jira/AWS patterns)
|
|
80
|
+
var SVG_ANCESTOR_SEL = 'button, a, [role="button"], [role="menuitem"], [role="tab"]';
|
|
81
|
+
|
|
82
|
+
var targetIds = new Set(${idsJson});
|
|
83
|
+
|
|
84
|
+
// ── Assign synthetic ids to any element missing data-wt-id ──
|
|
85
|
+
// data-wt-secret guard fires on the ATTRIBUTE (not the id), so secret fields
|
|
86
|
+
// are safe even when running on a synthetic id.
|
|
87
|
+
var syntheticPrefix = '__prune_idx_';
|
|
88
|
+
var syntheticEls = [];
|
|
89
|
+
var allEls = document.querySelectorAll('[data-wt-id], [data-wt-secret]');
|
|
90
|
+
var synIdx = 0;
|
|
91
|
+
for (var si = 0; si < allEls.length; si++) {
|
|
92
|
+
var sel = allEls[si];
|
|
93
|
+
if (!sel.getAttribute('data-wt-id')) {
|
|
94
|
+
var synthId = syntheticPrefix + (synIdx++);
|
|
95
|
+
sel.setAttribute('data-wt-id', synthId);
|
|
96
|
+
syntheticEls.push(sel);
|
|
97
|
+
targetIds.add(synthId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ── Pass 1: Document-level controls map ──────────────────────────────────
|
|
102
|
+
// Built from the WHOLE document — stale or unrelated aria-controls values
|
|
103
|
+
// can force-keep unrelated targets. Accepted over-keep bias: prefer recall
|
|
104
|
+
// over precision so the agent never loses a toggle target it needs.
|
|
105
|
+
var controlsMap = new Set();
|
|
106
|
+
var CONTROLS_ATTRS = ['aria-controls', 'aria-owns', 'data-target', 'data-bs-target'];
|
|
107
|
+
var extraIdioms = ${idiomsJson};
|
|
108
|
+
for (var ei = 0; ei < extraIdioms.length; ei++) {
|
|
109
|
+
if (CONTROLS_ATTRS.indexOf(extraIdioms[ei]) === -1) {
|
|
110
|
+
CONTROLS_ATTRS.push(extraIdioms[ei]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
var allNodes = document.querySelectorAll(CONTROLS_ATTRS.map(function(a) { return '[' + a + ']'; }).join(', '));
|
|
115
|
+
for (var ci = 0; ci < allNodes.length; ci++) {
|
|
116
|
+
for (var ai = 0; ai < CONTROLS_ATTRS.length; ai++) {
|
|
117
|
+
var val = allNodes[ci].getAttribute(CONTROLS_ATTRS[ai]);
|
|
118
|
+
if (!val) continue;
|
|
119
|
+
var tokens = val.split(/\\s+/);
|
|
120
|
+
for (var ti = 0; ti < tokens.length; ti++) {
|
|
121
|
+
if (tokens[ti]) controlsMap.add(tokens[ti]);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch(e) {}
|
|
126
|
+
|
|
127
|
+
// ── Pass 2: Post-order hasInteractiveDescendant annotation ───────────────
|
|
128
|
+
// Single bottom-up pass — O(n). Each hidden-element check is then O(1).
|
|
129
|
+
try {
|
|
130
|
+
var walker = document.createTreeWalker(document.body || document, NodeFilter.SHOW_ELEMENT, null, false);
|
|
131
|
+
var nodeStack = [];
|
|
132
|
+
var node = walker.nextNode();
|
|
133
|
+
while (node) {
|
|
134
|
+
nodeStack.push(node);
|
|
135
|
+
node = walker.nextNode();
|
|
136
|
+
}
|
|
137
|
+
// Process in reverse (post-order)
|
|
138
|
+
for (var ni = nodeStack.length - 1; ni >= 0; ni--) {
|
|
139
|
+
var n = nodeStack[ni];
|
|
140
|
+
var isInteractive = false;
|
|
141
|
+
try { isInteractive = n.matches(INTERACTIVE_SEL); } catch(e) {}
|
|
142
|
+
var childHas = false;
|
|
143
|
+
try {
|
|
144
|
+
var children = n.children;
|
|
145
|
+
for (var ki = 0; ki < children.length; ki++) {
|
|
146
|
+
if (children[ki].__wtHasInteractive) { childHas = true; break; }
|
|
147
|
+
}
|
|
148
|
+
} catch(e) {}
|
|
149
|
+
n.__wtHasInteractive = isInteractive || childHas;
|
|
150
|
+
}
|
|
151
|
+
} catch(e) {}
|
|
152
|
+
|
|
153
|
+
// ── Pass 3: Per-element prune decision ───────────────────────────────────
|
|
154
|
+
var keptIds = [];
|
|
155
|
+
var svgLabels = {};
|
|
156
|
+
var prunedCount = 0;
|
|
157
|
+
var svgCount = 0;
|
|
158
|
+
|
|
159
|
+
targetIds.forEach(function(wtId) {
|
|
160
|
+
var el;
|
|
161
|
+
try {
|
|
162
|
+
el = document.querySelector('[data-wt-id="' + wtId + '"]');
|
|
163
|
+
} catch(e) {}
|
|
164
|
+
if (!el) { prunedCount++; return; }
|
|
165
|
+
|
|
166
|
+
// Secret guard — fires on ATTRIBUTE, independent of whether id is synthetic
|
|
167
|
+
if (el.hasAttribute('data-wt-secret')) {
|
|
168
|
+
keptIds.push(String(wtId));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Visibility check
|
|
173
|
+
var hidden = false;
|
|
174
|
+
try {
|
|
175
|
+
var rect = el.getBoundingClientRect();
|
|
176
|
+
if (rect.width === 0 && rect.height === 0) {
|
|
177
|
+
hidden = true;
|
|
178
|
+
} else {
|
|
179
|
+
var cs = window.getComputedStyle(el);
|
|
180
|
+
if (cs.visibility === 'hidden' || cs.display === 'none') hidden = true;
|
|
181
|
+
}
|
|
182
|
+
} catch(e) {}
|
|
183
|
+
|
|
184
|
+
if (!hidden) {
|
|
185
|
+
// Visible — keep; handle SVG label replacement
|
|
186
|
+
keptIds.push(String(wtId));
|
|
187
|
+
if (el.tagName && el.tagName.toLowerCase() === 'svg') {
|
|
188
|
+
var label = resolveSvgLabel(el, SVG_ANCESTOR_SEL);
|
|
189
|
+
svgLabels[String(wtId)] = label;
|
|
190
|
+
svgCount++;
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Hidden — keep if has interactive descendant
|
|
196
|
+
if (el.__wtHasInteractive) {
|
|
197
|
+
keptIds.push(String(wtId));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Hidden — keep if referenced by a known toggle trigger (controlsMap)
|
|
202
|
+
var elId = el.getAttribute('id');
|
|
203
|
+
if (elId && controlsMap.has(elId)) {
|
|
204
|
+
keptIds.push(String(wtId));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Drop
|
|
209
|
+
prunedCount++;
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// ── Strip synthetic ids from DOM ─────────────────────────────────────────
|
|
213
|
+
for (var ri = 0; ri < syntheticEls.length; ri++) {
|
|
214
|
+
try { syntheticEls[ri].removeAttribute('data-wt-id'); } catch(e) {}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ── SVG label resolution helper ──────────────────────────────────────────
|
|
218
|
+
function resolveSvgLabel(svg, ancestorSel) {
|
|
219
|
+
// 1. SVG's own aria-label
|
|
220
|
+
var label = svg.getAttribute('aria-label');
|
|
221
|
+
if (label && label.trim()) return '[SVG Icon: ' + label.trim() + ']';
|
|
222
|
+
|
|
223
|
+
// 2. SVG's own <title> child
|
|
224
|
+
try {
|
|
225
|
+
var title = svg.querySelector('title');
|
|
226
|
+
if (title && title.textContent && title.textContent.trim()) {
|
|
227
|
+
return '[SVG Icon: ' + title.textContent.trim() + ']';
|
|
228
|
+
}
|
|
229
|
+
} catch(e) {}
|
|
230
|
+
|
|
231
|
+
// 3. Closest interactive ancestor's aria-label
|
|
232
|
+
// Covers: <button aria-label="Delete"><svg/></button>
|
|
233
|
+
// <a role="menuitem" aria-label="More actions"><svg/></a> (Jira)
|
|
234
|
+
// <div role="tab" aria-label="Overview"><svg/></div> (AWS)
|
|
235
|
+
try {
|
|
236
|
+
var ancestor = svg.closest(ancestorSel);
|
|
237
|
+
if (ancestor) {
|
|
238
|
+
var aLabel = ancestor.getAttribute('aria-label');
|
|
239
|
+
if (aLabel && aLabel.trim()) return '[SVG Icon: ' + aLabel.trim() + ']';
|
|
240
|
+
}
|
|
241
|
+
} catch(e) {}
|
|
242
|
+
|
|
243
|
+
return '[SVG Icon]';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
var elapsedMs = performance.now() - t0;
|
|
247
|
+
|
|
248
|
+
// ── Perf-gate: if this took > 5ms, flag it — caller will decide on split ─
|
|
249
|
+
// (In this single-evaluate path we can only report, not split retroactively.
|
|
250
|
+
// The split path would be invoked by the caller on a second evaluate call.)
|
|
251
|
+
return JSON.stringify({
|
|
252
|
+
keptIds: keptIds,
|
|
253
|
+
svgLabels: svgLabels,
|
|
254
|
+
stats: {
|
|
255
|
+
total: targetIds.size,
|
|
256
|
+
pruned: prunedCount,
|
|
257
|
+
svgReplaced: svgCount,
|
|
258
|
+
elapsedMs: elapsedMs,
|
|
259
|
+
splitPath: false
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
262
|
})()`;
|
|
263
263
|
}
|
package/dist/cdp/ref_cache.js
CHANGED
|
@@ -125,72 +125,72 @@ export function urcPopulate(targetId, elements) {
|
|
|
125
125
|
export async function atomicResolve(session, selector, fingerprint, hostname) {
|
|
126
126
|
try {
|
|
127
127
|
const { result } = await session.Runtime.evaluate({
|
|
128
|
-
expression: `(function(sel, fp) {
|
|
129
|
-
try {
|
|
130
|
-
// Primary: standard querySelector
|
|
131
|
-
var el = document.querySelector(sel);
|
|
132
|
-
|
|
133
|
-
// Shadow DOM fallback
|
|
134
|
-
if (!el && typeof window.__Weavetab_shadowQuery === 'function') {
|
|
135
|
-
el = window.__Weavetab_shadowQuery(sel);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// WeakMap registry fallback: re-derive selector from stored data
|
|
139
|
-
if (!el && window.__wt_registry) {
|
|
140
|
-
// Walk the registry to find the element whose stored id matches
|
|
141
|
-
// (only feasible for small pages — skip for large DOMs by checking size)
|
|
142
|
-
try {
|
|
143
|
-
var allEls = document.querySelectorAll('[data-wt-id]');
|
|
144
|
-
for (var i = 0; i < allEls.length; i++) {
|
|
145
|
-
var candidate = allEls[i];
|
|
146
|
-
var entry = window.__wt_registry.get(candidate);
|
|
147
|
-
if (entry && ('[data-wt-id="' + entry.id + '"]' === sel ||
|
|
148
|
-
entry.selector === sel)) {
|
|
149
|
-
el = candidate;
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
} catch (e) {}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (!el) return { status: 'NOT_FOUND' };
|
|
157
|
-
|
|
158
|
-
// Fingerprint check: "role:type:labelPrefix"
|
|
159
|
-
if (fp) {
|
|
160
|
-
var parts = fp.split(':');
|
|
161
|
-
var fpRole = parts[0];
|
|
162
|
-
var fpType = parts[1];
|
|
163
|
-
var elRole = el.getAttribute('role') || el.tagName.toLowerCase();
|
|
164
|
-
var elType = (el.type || '').toLowerCase();
|
|
165
|
-
if (fpRole && fpRole !== '' && elRole !== fpRole && elType !== fpRole) {
|
|
166
|
-
return { status: 'STALE' };
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
var rect = el.getBoundingClientRect();
|
|
171
|
-
if (!rect.width || !rect.height) return { status: 'INVISIBLE' };
|
|
172
|
-
|
|
173
|
-
// Scroll into view if out of viewport
|
|
174
|
-
if (rect.top < 0 || rect.bottom > window.innerHeight ||
|
|
175
|
-
rect.left < 0 || rect.right > window.innerWidth) {
|
|
176
|
-
el.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' });
|
|
177
|
-
rect = el.getBoundingClientRect();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Re-hydrate data-wt-id attribute if stripped by SPA reconciliation
|
|
181
|
-
var idMatch = sel.match(/\\[data-wt-id="([^"]+)"\\]/);
|
|
182
|
-
if (idMatch && !el.hasAttribute('data-wt-id')) {
|
|
183
|
-
try { el.setAttribute('data-wt-id', idMatch[1]); } catch(e) {}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return {
|
|
187
|
-
status: 'OK',
|
|
188
|
-
x: Math.round(rect.left + rect.width / 2),
|
|
189
|
-
y: Math.round(rect.top + rect.height / 2)
|
|
190
|
-
};
|
|
191
|
-
} catch (e) {
|
|
192
|
-
return { status: 'NOT_FOUND' };
|
|
193
|
-
}
|
|
128
|
+
expression: `(function(sel, fp) {
|
|
129
|
+
try {
|
|
130
|
+
// Primary: standard querySelector
|
|
131
|
+
var el = document.querySelector(sel);
|
|
132
|
+
|
|
133
|
+
// Shadow DOM fallback
|
|
134
|
+
if (!el && typeof window.__Weavetab_shadowQuery === 'function') {
|
|
135
|
+
el = window.__Weavetab_shadowQuery(sel);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// WeakMap registry fallback: re-derive selector from stored data
|
|
139
|
+
if (!el && window.__wt_registry) {
|
|
140
|
+
// Walk the registry to find the element whose stored id matches
|
|
141
|
+
// (only feasible for small pages — skip for large DOMs by checking size)
|
|
142
|
+
try {
|
|
143
|
+
var allEls = document.querySelectorAll('[data-wt-id]');
|
|
144
|
+
for (var i = 0; i < allEls.length; i++) {
|
|
145
|
+
var candidate = allEls[i];
|
|
146
|
+
var entry = window.__wt_registry.get(candidate);
|
|
147
|
+
if (entry && ('[data-wt-id="' + entry.id + '"]' === sel ||
|
|
148
|
+
entry.selector === sel)) {
|
|
149
|
+
el = candidate;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} catch (e) {}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (!el) return { status: 'NOT_FOUND' };
|
|
157
|
+
|
|
158
|
+
// Fingerprint check: "role:type:labelPrefix"
|
|
159
|
+
if (fp) {
|
|
160
|
+
var parts = fp.split(':');
|
|
161
|
+
var fpRole = parts[0];
|
|
162
|
+
var fpType = parts[1];
|
|
163
|
+
var elRole = el.getAttribute('role') || el.tagName.toLowerCase();
|
|
164
|
+
var elType = (el.type || '').toLowerCase();
|
|
165
|
+
if (fpRole && fpRole !== '' && elRole !== fpRole && elType !== fpRole) {
|
|
166
|
+
return { status: 'STALE' };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
var rect = el.getBoundingClientRect();
|
|
171
|
+
if (!rect.width || !rect.height) return { status: 'INVISIBLE' };
|
|
172
|
+
|
|
173
|
+
// Scroll into view if out of viewport
|
|
174
|
+
if (rect.top < 0 || rect.bottom > window.innerHeight ||
|
|
175
|
+
rect.left < 0 || rect.right > window.innerWidth) {
|
|
176
|
+
el.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' });
|
|
177
|
+
rect = el.getBoundingClientRect();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Re-hydrate data-wt-id attribute if stripped by SPA reconciliation
|
|
181
|
+
var idMatch = sel.match(/\\[data-wt-id="([^"]+)"\\]/);
|
|
182
|
+
if (idMatch && !el.hasAttribute('data-wt-id')) {
|
|
183
|
+
try { el.setAttribute('data-wt-id', idMatch[1]); } catch(e) {}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
status: 'OK',
|
|
188
|
+
x: Math.round(rect.left + rect.width / 2),
|
|
189
|
+
y: Math.round(rect.top + rect.height / 2)
|
|
190
|
+
};
|
|
191
|
+
} catch (e) {
|
|
192
|
+
return { status: 'NOT_FOUND' };
|
|
193
|
+
}
|
|
194
194
|
})(${JSON.stringify(selector)}, ${JSON.stringify(fingerprint ?? null)})`,
|
|
195
195
|
returnByValue: true,
|
|
196
196
|
awaitPromise: false,
|
package/dist/cdp/security.js
CHANGED
|
@@ -216,16 +216,16 @@ async function getProfileFromProcess(session, config) {
|
|
|
216
216
|
try {
|
|
217
217
|
// Use extension-based method to check profile directory
|
|
218
218
|
const result = await session.Runtime.evaluate({
|
|
219
|
-
expression: `
|
|
220
|
-
(() => {
|
|
221
|
-
try {
|
|
222
|
-
// Check if we can read the user data directory from browser internals
|
|
223
|
-
if (window.__wt_profile_dir) return window.__wt_profile_dir;
|
|
224
|
-
return null;
|
|
225
|
-
} catch (e) {
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
})()
|
|
219
|
+
expression: `
|
|
220
|
+
(() => {
|
|
221
|
+
try {
|
|
222
|
+
// Check if we can read the user data directory from browser internals
|
|
223
|
+
if (window.__wt_profile_dir) return window.__wt_profile_dir;
|
|
224
|
+
return null;
|
|
225
|
+
} catch (e) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
})()
|
|
229
229
|
`,
|
|
230
230
|
returnByValue: true,
|
|
231
231
|
});
|