@weavetab/mcp 2.5.0-beta.2 → 2.5.0-beta.5
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 +1 -1
- package/ARCHITECTURE.md +6 -6
- package/LICENSE +216 -631
- package/README.md +153 -1074
- package/SECURITY.md +33 -22
- package/TROUBLESHOOTING.md +2 -2
- package/dist/cdp/bridge.js +2 -1
- package/dist/cdp/connector.d.ts +2 -0
- package/dist/cdp/connector.js +10 -6
- package/dist/cdp/helpers.d.ts +4 -0
- package/dist/cdp/helpers.js +181 -0
- package/dist/cdp/omni_broker.d.ts +1 -1
- package/dist/cdp/omni_broker.js +1 -1
- package/dist/cdp/walker.d.ts +25 -1
- package/dist/cdp/walker.js +304 -7
- package/dist/cli/plugin.d.ts +1 -0
- package/dist/cli/plugin.js +81 -18
- package/dist/cli/updater.d.ts +1 -1
- package/dist/cli/updater.js +27 -7
- package/dist/config/loader.d.ts +9 -1
- package/dist/config/loader.js +42 -3
- package/dist/desktop/discovery.d.ts +44 -0
- package/dist/desktop/discovery.js +364 -0
- package/dist/index.js +137 -21
- package/dist/intelligence/marks.d.ts +36 -0
- package/dist/intelligence/marks.js +30 -0
- package/dist/intelligence/patternCompiler.d.ts +118 -0
- package/dist/intelligence/patternCompiler.js +259 -0
- package/dist/intelligence/sessionMemory.d.ts +2 -0
- package/dist/intelligence/sessionMemory.js +18 -8
- package/dist/overlay/injector.js +2 -2
- package/dist/plugin/interface.d.ts +88 -5
- package/dist/plugin/loader.d.ts +12 -1
- package/dist/plugin/loader.js +280 -70
- package/dist/plugin/pipeline.d.ts +75 -0
- package/dist/plugin/pipeline.js +183 -0
- package/dist/plugin/registry.d.ts +2 -1
- package/dist/plugin/registry.js +24 -14
- package/dist/security/secrets.d.ts +7 -0
- package/dist/security/secrets.js +37 -0
- package/dist/sensors/actionability.js +1 -2
- package/dist/sensors/guard.js +4 -10
- package/dist/sensors/mutations.js +12 -0
- package/dist/sensors/operation_monitor.js +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +453 -178
- package/dist/state/agent.d.ts +1 -0
- package/dist/state/agent.js +3 -0
- package/dist/state/delta.d.ts +12 -4
- package/dist/state/delta.js +67 -14
- package/dist/state/session.d.ts +6 -0
- package/dist/state/session.js +27 -0
- package/dist/tools/browser_detect.d.ts +16 -3
- package/dist/tools/browser_detect.js +52 -7
- package/dist/tools/burst.d.ts +17 -8
- package/dist/tools/burst.js +236 -77
- package/dist/tools/captcha.js +1 -1
- package/dist/tools/checkpoint.d.ts +38 -0
- package/dist/tools/checkpoint.js +271 -0
- package/dist/tools/click.d.ts +1 -0
- package/dist/tools/click.js +74 -70
- package/dist/tools/design_extract.js +1 -1
- package/dist/tools/eval.js +1 -1
- package/dist/tools/fill.d.ts +20 -1
- package/dist/tools/fill.js +199 -40
- package/dist/tools/find.d.ts +16 -0
- package/dist/tools/find.js +67 -44
- package/dist/tools/github/index.d.ts +19 -4
- package/dist/tools/github/index.js +40 -4
- package/dist/tools/highlight.d.ts +6 -2
- package/dist/tools/highlight.js +158 -72
- package/dist/tools/inspect.js +1 -1
- package/dist/tools/key.js +65 -56
- package/dist/tools/navigate.d.ts +1 -1
- package/dist/tools/navigate.js +34 -39
- package/dist/tools/pdf.js +21 -13
- package/dist/tools/pointer.d.ts +18 -3
- package/dist/tools/pointer.js +89 -1
- package/dist/tools/read.d.ts +28 -8
- package/dist/tools/read.js +230 -56
- package/dist/tools/scrape.js +67 -13
- package/dist/tools/screenshot.js +21 -16
- package/dist/tools/scroll.js +6 -11
- package/dist/tools/select.js +8 -2
- package/dist/tools/snapshot.js +3 -34
- package/dist/tools/tabs.js +15 -7
- package/dist/tools/thought.d.ts +2 -0
- package/dist/tools/thought.js +13 -14
- package/dist/tools/type.d.ts +2 -0
- package/dist/tools/type.js +107 -58
- package/dist/tools/type_secret.js +42 -76
- package/dist/tools/upload.js +1 -1
- package/dist/tools/video_compiler.d.ts +1 -1
- package/dist/tools/video_compiler.js +11 -12
- package/dist/version.d.ts +5 -0
- package/dist/version.js +5 -0
- package/docs/DOCUMENTATION.md +37 -41
- package/docs/PLUGINS.md +121 -0
- package/docs/TOOLS.md +54 -0
- package/docs/architecture/blind-injection.md +83 -20
- package/docs/architecture/overview.md +49 -49
- package/docs/architecture/security.md +8 -7
- package/docs/architecture/transport.md +2 -2
- package/docs/cli/cli-commands.md +7 -1
- package/docs/cli/cli-flags.md +15 -7
- package/docs/cli/cli-scripting.md +6 -3
- package/docs/configuration/config-locations.md +3 -4
- package/docs/configuration/env-variables.md +4 -4
- package/docs/configuration/folders.md +55 -54
- package/docs/desktop-automation/electron-apps.md +214 -162
- package/docs/get-started/introduction.md +60 -60
- package/docs/get-started/setup-wizard.md +7 -6
- package/docs/intelligence/site-profiles.md +151 -0
- package/docs/tools/tools.md +631 -293
- package/docs/troubleshooting/trouble-browser.md +1 -1
- package/docs/troubleshooting/trouble-loop.md +31 -31
- package/ext-dist/background.js +10 -62
- package/ext-dist/content.js +333 -920
- package/ext-dist/hud/hud.js +9 -9
- package/ext-dist/manifest.json +2 -6
- package/ext-dist/styles.css +6 -1
- package/icon.png +0 -0
- package/mcp.json +87 -71
- package/package.json +118 -119
- package/server.json +5 -5
- package/ext-dist/sidepanel/sidepanel.js +0 -25
- package/ext-dist/sidepanel.html +0 -547
package/dist/tools/scrape.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { getConfigAgentId } from "../config/loader.js";
|
|
2
|
+
import { SessionSecretTracker } from "../security/secrets.js";
|
|
3
|
+
import { sessionRegistry } from "../state/session.js";
|
|
1
4
|
export async function browserScrape(session, options, _config) {
|
|
2
5
|
const { query, type = "css", attributes = ["textContent"], multiple = true } = options;
|
|
3
6
|
const res = await session.Runtime.evaluate({
|
|
@@ -34,14 +37,20 @@ export async function browserScrape(session, options, _config) {
|
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
const attrs = ${JSON.stringify(attributes)};
|
|
40
|
+
var secretRegex = /password|passcode|pin|passphrase|secret|token|auth.?key|access.?code|mot.?de.?passe|contrase[nñ]a|kennwort|senha/i;
|
|
37
41
|
nodes.forEach(node => {
|
|
38
42
|
const item = {};
|
|
39
43
|
|
|
40
44
|
// Secret containment: redact any element marked as sensitive.
|
|
41
|
-
// data-wt-secret is set by browser_type_secret at injection time.
|
|
42
45
|
const isSecret = node.hasAttribute && (
|
|
43
46
|
node.hasAttribute('data-wt-secret') ||
|
|
44
|
-
(node.tagName === 'INPUT' &&
|
|
47
|
+
(node.tagName === 'INPUT' && (
|
|
48
|
+
node.type === 'password' ||
|
|
49
|
+
secretRegex.test(node.getAttribute('autocomplete') || '') ||
|
|
50
|
+
secretRegex.test(node.getAttribute('name') || '') ||
|
|
51
|
+
secretRegex.test(node.getAttribute('id') || '') ||
|
|
52
|
+
secretRegex.test(node.getAttribute('aria-label') || '')
|
|
53
|
+
))
|
|
45
54
|
);
|
|
46
55
|
|
|
47
56
|
if (isSecret) {
|
|
@@ -53,6 +62,9 @@ export async function browserScrape(session, options, _config) {
|
|
|
53
62
|
item[attr] = node[attr]?.trim() || '';
|
|
54
63
|
} else if (attr === 'outerHTML') {
|
|
55
64
|
item[attr] = node.outerHTML;
|
|
65
|
+
} else if (attr === 'value') {
|
|
66
|
+
// Read live DOM property (not HTML attribute) so getter overrides work
|
|
67
|
+
item[attr] = node.value !== undefined ? String(node.value) : '';
|
|
56
68
|
} else {
|
|
57
69
|
item[attr] = node.getAttribute(attr) || node[attr] || '';
|
|
58
70
|
}
|
|
@@ -98,6 +110,7 @@ export async function browserScrape(session, options, _config) {
|
|
|
98
110
|
const fullExpr = type === 'xpath'
|
|
99
111
|
? `(function(){
|
|
100
112
|
var attrs = ${JSON.stringify(attributes)};
|
|
113
|
+
var secretRegex = /password|passcode|pin|passphrase|secret|token|auth.?key|access.?code|mot.?de.?passe|contrase[nñ]a|kennwort|senha/i;
|
|
101
114
|
var snap = document.evaluate(${JSON.stringify(query)}, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
|
102
115
|
var limit = ${multiple} ? snap.snapshotLength : Math.min(snap.snapshotLength, 1);
|
|
103
116
|
var results = [];
|
|
@@ -105,11 +118,25 @@ export async function browserScrape(session, options, _config) {
|
|
|
105
118
|
var node = snap.snapshotItem(i);
|
|
106
119
|
if (!node || node.nodeType !== 1) continue;
|
|
107
120
|
var item = {};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
var isSecret = node.hasAttribute && (
|
|
122
|
+
node.hasAttribute('data-wt-secret') ||
|
|
123
|
+
(node.tagName === 'INPUT' && (
|
|
124
|
+
node.type === 'password' ||
|
|
125
|
+
secretRegex.test(node.getAttribute('autocomplete') || '') ||
|
|
126
|
+
secretRegex.test(node.getAttribute('name') || '') ||
|
|
127
|
+
secretRegex.test(node.getAttribute('id') || '') ||
|
|
128
|
+
secretRegex.test(node.getAttribute('aria-label') || '')
|
|
129
|
+
))
|
|
130
|
+
);
|
|
131
|
+
if (isSecret) {
|
|
132
|
+
attrs.forEach(function(attr) { item[attr] = '[REDACTED]'; });
|
|
133
|
+
} else {
|
|
134
|
+
attrs.forEach(function(attr) {
|
|
135
|
+
if (attr === 'textContent' || attr === 'innerText') { item[attr] = (node[attr] || '').trim(); }
|
|
136
|
+
else if (attr === 'outerHTML') { item[attr] = node.outerHTML; }
|
|
137
|
+
else { item[attr] = node.getAttribute ? (node.getAttribute(attr) || node[attr] || '') : ''; }
|
|
138
|
+
});
|
|
139
|
+
}
|
|
113
140
|
results.push(item);
|
|
114
141
|
}
|
|
115
142
|
return { data: results };
|
|
@@ -120,13 +147,28 @@ export async function browserScrape(session, options, _config) {
|
|
|
120
147
|
try { nodes = Array.from(window.__Weavetab_shadowQuery_all(${JSON.stringify(query)})); } catch(_){}
|
|
121
148
|
}
|
|
122
149
|
var attrs = ${JSON.stringify(attributes)};
|
|
150
|
+
var secretRegex = /password|passcode|pin|passphrase|secret|token|auth.?key|access.?code|mot.?de.?passe|contrase[nñ]a|kennwort|senha/i;
|
|
123
151
|
return { data: nodes.map(function(node) {
|
|
124
152
|
var item = {};
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
153
|
+
var isSecret = node.hasAttribute && (
|
|
154
|
+
node.hasAttribute('data-wt-secret') ||
|
|
155
|
+
(node.tagName === 'INPUT' && (
|
|
156
|
+
node.type === 'password' ||
|
|
157
|
+
secretRegex.test(node.getAttribute('autocomplete') || '') ||
|
|
158
|
+
secretRegex.test(node.getAttribute('name') || '') ||
|
|
159
|
+
secretRegex.test(node.getAttribute('id') || '') ||
|
|
160
|
+
secretRegex.test(node.getAttribute('aria-label') || '')
|
|
161
|
+
))
|
|
162
|
+
);
|
|
163
|
+
if (isSecret) {
|
|
164
|
+
attrs.forEach(function(attr) { item[attr] = '[REDACTED]'; });
|
|
165
|
+
} else {
|
|
166
|
+
attrs.forEach(function(attr) {
|
|
167
|
+
if (attr === 'textContent' || attr === 'innerText') { item[attr] = (node[attr] || '').trim(); }
|
|
168
|
+
else if (attr === 'outerHTML') { item[attr] = node.outerHTML; }
|
|
169
|
+
else { item[attr] = node.getAttribute(attr) || node[attr] || ''; }
|
|
170
|
+
});
|
|
171
|
+
}
|
|
130
172
|
return item;
|
|
131
173
|
})};
|
|
132
174
|
})()`;
|
|
@@ -136,5 +178,17 @@ export async function browserScrape(session, options, _config) {
|
|
|
136
178
|
}
|
|
137
179
|
}
|
|
138
180
|
}
|
|
139
|
-
|
|
181
|
+
let targetId = "default";
|
|
182
|
+
const active = sessionRegistry.getActive(getConfigAgentId(_config));
|
|
183
|
+
if (active)
|
|
184
|
+
targetId = active.targetId;
|
|
185
|
+
const rawData = (val?.data || []);
|
|
186
|
+
const sanitizedData = rawData.map(item => {
|
|
187
|
+
const sanitizedItem = {};
|
|
188
|
+
for (const [k, v] of Object.entries(item)) {
|
|
189
|
+
sanitizedItem[k] = typeof v === 'string' ? SessionSecretTracker.redact(targetId, v) : v;
|
|
190
|
+
}
|
|
191
|
+
return sanitizedItem;
|
|
192
|
+
});
|
|
193
|
+
return { success: true, data: sanitizedData, message: `Extracted ${sanitizedData.length} elements` };
|
|
140
194
|
}
|
package/dist/tools/screenshot.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hideWeaveTabOverlay, restoreWeaveTabOverlay } from "../cdp/helpers.js";
|
|
1
|
+
import { hideWeaveTabOverlay, restoreWeaveTabOverlay, maskSecretFieldsForCapture, restoreSecretFieldsAfterCapture } from "../cdp/helpers.js";
|
|
2
2
|
export async function browserScreenshot(session, options = {}, _config) {
|
|
3
3
|
const format = options.format ?? "png";
|
|
4
4
|
const quality = format === "jpeg" ? (options.quality ?? 90) : undefined;
|
|
@@ -42,33 +42,38 @@ export async function browserScreenshot(session, options = {}, _config) {
|
|
|
42
42
|
if (clip)
|
|
43
43
|
params.clip = clip;
|
|
44
44
|
}
|
|
45
|
-
// ── AI-blind: hide Weavetab overlay elements before screenshot
|
|
45
|
+
// ── AI-blind: hide Weavetab overlay elements and mask secrets before screenshot ─
|
|
46
46
|
// The chat panel, ghost cursor, thought bubble, HUD iframe, and all scripted
|
|
47
|
-
// UI are FOR THE USER only.
|
|
48
|
-
// hideOverlay defaults to true — only set to false if explicitly requested.
|
|
47
|
+
// UI are FOR THE USER only. Secret values are masked to prevent visual leaks.
|
|
49
48
|
const shouldHide = options.hideOverlay !== false;
|
|
50
49
|
if (shouldHide) {
|
|
51
50
|
await hideWeaveTabOverlay(session);
|
|
52
51
|
}
|
|
52
|
+
await maskSecretFieldsForCapture(session);
|
|
53
53
|
let data;
|
|
54
54
|
try {
|
|
55
|
-
|
|
56
|
-
data = res.data;
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
if (params.captureBeyondViewport) {
|
|
60
|
-
params.captureBeyondViewport = false;
|
|
61
|
-
delete params.clip;
|
|
55
|
+
try {
|
|
62
56
|
const res = await session.Page.captureScreenshot(params);
|
|
63
57
|
data = res.data;
|
|
64
58
|
}
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
catch (e) {
|
|
60
|
+
if (params.captureBeyondViewport) {
|
|
61
|
+
params.captureBeyondViewport = false;
|
|
62
|
+
delete params.clip;
|
|
63
|
+
const res = await session.Page.captureScreenshot(params);
|
|
64
|
+
data = res.data;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
throw e;
|
|
68
|
+
}
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await
|
|
71
|
+
finally {
|
|
72
|
+
// Restore secret fields and overlay visibility immediately after capture
|
|
73
|
+
await restoreSecretFieldsAfterCapture(session);
|
|
74
|
+
if (shouldHide) {
|
|
75
|
+
await restoreWeaveTabOverlay(session);
|
|
76
|
+
}
|
|
72
77
|
}
|
|
73
78
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
74
79
|
const width = clip ? clip.width : vp.w;
|
package/dist/tools/scroll.js
CHANGED
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { buildActionMap, findBestMatch, safeSelector } from "../cdp/walker.js";
|
|
7
7
|
import { getCachedActionMap, cacheActionMap } from "../state/cache.js";
|
|
8
|
-
import {
|
|
9
|
-
import { waitForDOMStable } from "../sensors/guard.js";
|
|
8
|
+
import { storeSnapshot } from "../state/delta.js";
|
|
10
9
|
import { sessionRegistry } from "../state/session.js";
|
|
11
10
|
import { logAction } from "../audit/logger.js";
|
|
12
11
|
import { getConfigAgentId } from "../config/loader.js";
|
|
@@ -175,22 +174,18 @@ export async function browserScroll(session, args, config) {
|
|
|
175
174
|
x: vp.x, y: vp.y,
|
|
176
175
|
deltaX: chunkX, deltaY: chunkY
|
|
177
176
|
});
|
|
178
|
-
await sleep(profile.baseDelay + Math.random() *
|
|
177
|
+
await sleep(profile.baseDelay + Math.random() * 4);
|
|
179
178
|
}
|
|
180
179
|
}
|
|
181
|
-
await
|
|
182
|
-
await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: '' } });
|
|
183
|
-
const nextMap = await buildActionMap(session, { lite: true }, targetId);
|
|
184
|
-
cacheActionMap(targetId, nextMap);
|
|
185
|
-
const diff = computeDelta(targetId, nextMap.url, nextMap.elements);
|
|
186
|
-
const changesCount = diff ? diff.added.length + diff.removed.length + diff.changed.length : 0;
|
|
180
|
+
await sleep(40);
|
|
181
|
+
await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: '' } }).catch(() => { });
|
|
187
182
|
logAction("browser_scroll", direction, `${distance}px`);
|
|
188
183
|
return {
|
|
189
184
|
success: true,
|
|
190
185
|
scrolled: id ?? label ?? "window",
|
|
191
186
|
direction,
|
|
192
187
|
distance,
|
|
193
|
-
new_visible_count:
|
|
194
|
-
dom_changed:
|
|
188
|
+
new_visible_count: 0,
|
|
189
|
+
dom_changed: true,
|
|
195
190
|
};
|
|
196
191
|
}
|
package/dist/tools/select.js
CHANGED
|
@@ -9,6 +9,12 @@ async function getSelector(session, options, config) {
|
|
|
9
9
|
return options.selector;
|
|
10
10
|
if (options.ref || options.id) {
|
|
11
11
|
const ref = (options.ref || options.id);
|
|
12
|
+
if (ref.startsWith("w:")) {
|
|
13
|
+
return `[data-wt-id="${ref.slice(2)}"]`;
|
|
14
|
+
}
|
|
15
|
+
if (ref.startsWith("#") || ref.startsWith(".") || ref.startsWith("[")) {
|
|
16
|
+
return ref;
|
|
17
|
+
}
|
|
12
18
|
let targetId = "default";
|
|
13
19
|
const active = sessionRegistry.getActive(getConfigAgentId(config));
|
|
14
20
|
if (active)
|
|
@@ -20,13 +26,13 @@ async function getSelector(session, options, config) {
|
|
|
20
26
|
map = await buildActionMap(session, { lite: true }, targetId);
|
|
21
27
|
cacheActionMap(targetId, map);
|
|
22
28
|
}
|
|
23
|
-
const element = map.elements.find(el => el.id === ref || el.id.endsWith(ref.startsWith("w:") ? ref.slice(2) : ref));
|
|
29
|
+
const element = map.elements.find(el => el.id === ref || el.label === ref || el.id.endsWith(ref.startsWith("w:") ? ref.slice(2) : ref));
|
|
24
30
|
if (element) {
|
|
25
31
|
const sel = safeSelector(element);
|
|
26
32
|
if (sel)
|
|
27
33
|
return sel;
|
|
28
34
|
}
|
|
29
|
-
|
|
35
|
+
return `[name="${ref}"], #${ref}, [aria-label="${ref}"]`;
|
|
30
36
|
}
|
|
31
37
|
if (options.nodeId) {
|
|
32
38
|
const { nodeIds } = await session.DOM.pushNodesByBackendIdsToFrontend({ backendNodeIds: [options.nodeId] });
|
package/dist/tools/snapshot.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { getOutputDir, getConfigAgentId } from "../config/loader.js";
|
|
4
|
-
import { hideWeaveTabOverlay, restoreWeaveTabOverlay } from "../cdp/helpers.js";
|
|
4
|
+
import { hideWeaveTabOverlay, restoreWeaveTabOverlay, maskSecretFieldsForCapture, restoreSecretFieldsAfterCapture } from "../cdp/helpers.js";
|
|
5
5
|
import { clearTabCache } from "../state/cache.js";
|
|
6
6
|
import { clearSnapshot } from "../state/delta.js";
|
|
7
7
|
import { sessionRegistry } from "../state/session.js";
|
|
@@ -28,22 +28,7 @@ export async function browserSnapshot(session, options, config) {
|
|
|
28
28
|
}
|
|
29
29
|
// ── Blank secret field values before capture ──────────────────────────
|
|
30
30
|
// Prevents credential values from being embedded in the MHTML archive.
|
|
31
|
-
|
|
32
|
-
await session.Runtime.evaluate({
|
|
33
|
-
expression: `(function() {
|
|
34
|
-
var els = document.querySelectorAll('[data-wt-secret], input[type="password"]');
|
|
35
|
-
for (var i = 0; i < els.length; i++) {
|
|
36
|
-
var el = els[i];
|
|
37
|
-
el.__wt_snap_backup = el.value;
|
|
38
|
-
try { el.value = ''; } catch(e) {}
|
|
39
|
-
if (el.isContentEditable) {
|
|
40
|
-
el.__wt_snap_text_backup = el.textContent;
|
|
41
|
-
try { el.textContent = ''; } catch(e) {}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
})()`,
|
|
45
|
-
returnByValue: false,
|
|
46
|
-
}).catch(() => { });
|
|
31
|
+
await maskSecretFieldsForCapture(session);
|
|
47
32
|
let snapshotData;
|
|
48
33
|
try {
|
|
49
34
|
const res = await session.Page.captureSnapshot({ format: "mhtml" });
|
|
@@ -51,26 +36,10 @@ export async function browserSnapshot(session, options, config) {
|
|
|
51
36
|
}
|
|
52
37
|
finally {
|
|
53
38
|
// ── Restore secret field values after capture (always runs) ──────────
|
|
39
|
+
await restoreSecretFieldsAfterCapture(session);
|
|
54
40
|
if (shouldHide) {
|
|
55
41
|
await restoreWeaveTabOverlay(session);
|
|
56
42
|
}
|
|
57
|
-
await session.Runtime.evaluate({
|
|
58
|
-
expression: `(function() {
|
|
59
|
-
var els = document.querySelectorAll('[data-wt-secret], input[type="password"]');
|
|
60
|
-
for (var i = 0; i < els.length; i++) {
|
|
61
|
-
var el = els[i];
|
|
62
|
-
if (el.__wt_snap_backup !== undefined) {
|
|
63
|
-
try { el.value = el.__wt_snap_backup; } catch(e) {}
|
|
64
|
-
delete el.__wt_snap_backup;
|
|
65
|
-
}
|
|
66
|
-
if (el.__wt_snap_text_backup !== undefined) {
|
|
67
|
-
try { el.textContent = el.__wt_snap_text_backup; } catch(e) {}
|
|
68
|
-
delete el.__wt_snap_text_backup;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
})()`,
|
|
72
|
-
returnByValue: false,
|
|
73
|
-
}).catch(() => { });
|
|
74
43
|
}
|
|
75
44
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
76
45
|
await fs.writeFile(filePath, snapshotData, "utf8");
|
package/dist/tools/tabs.js
CHANGED
|
@@ -17,7 +17,7 @@ function resolvePort(_config, appName) {
|
|
|
17
17
|
}
|
|
18
18
|
const port = getPort() || readLock()?.port;
|
|
19
19
|
if (!port)
|
|
20
|
-
throw new Error("[!] No active browser session. Run
|
|
20
|
+
throw new Error("[!] No active browser session. Run browser_navigate first.");
|
|
21
21
|
return port;
|
|
22
22
|
}
|
|
23
23
|
const IDLE_THRESHOLD_MS = 30_000;
|
|
@@ -111,16 +111,24 @@ async function enforceMaxTabs(config) {
|
|
|
111
111
|
}
|
|
112
112
|
// ─── Tools ────────────────────────────────────────────────────────────────────
|
|
113
113
|
export async function WeavetabOpen(url, config, reuse = true, appName) {
|
|
114
|
-
|
|
114
|
+
// Infer appName from active session if omitted
|
|
115
|
+
let resolvedAppName = appName;
|
|
116
|
+
if (!resolvedAppName) {
|
|
117
|
+
const lastApp = sessionRegistry.getLastActiveApp();
|
|
118
|
+
if (lastApp) {
|
|
119
|
+
resolvedAppName = lastApp;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const port = resolvePort(config, resolvedAppName);
|
|
115
123
|
// Tab reuse: if same URL is already open, focus it instead of duplicating
|
|
116
124
|
if (reuse && url) {
|
|
117
125
|
try {
|
|
118
|
-
const targets = await getTabList(getConfigAgentId(config),
|
|
126
|
+
const targets = await getTabList(getConfigAgentId(config), resolvedAppName);
|
|
119
127
|
const existing = targets.find((t) => t.url === url);
|
|
120
128
|
if (existing) {
|
|
121
|
-
const client = await connectToTab(existing.id, undefined, undefined, undefined,
|
|
129
|
+
const client = await connectToTab(existing.id, undefined, undefined, undefined, resolvedAppName);
|
|
122
130
|
await client.session.Target.activateTarget({ targetId: existing.id });
|
|
123
|
-
sessionRegistry.setActive(existing.id, getConfigAgentId(config),
|
|
131
|
+
sessionRegistry.setActive(existing.id, getConfigAgentId(config), resolvedAppName);
|
|
124
132
|
recordTabActivity(existing.id);
|
|
125
133
|
logAction("browser_tabs", url, `reused existing tab ${existing.id}`);
|
|
126
134
|
return { success: true, tabId: existing.id, url, reused: true };
|
|
@@ -128,10 +136,10 @@ export async function WeavetabOpen(url, config, reuse = true, appName) {
|
|
|
128
136
|
}
|
|
129
137
|
catch { /* fall through to open new */ }
|
|
130
138
|
}
|
|
131
|
-
if (!
|
|
139
|
+
if (!resolvedAppName) {
|
|
132
140
|
await enforceMaxTabs(config);
|
|
133
141
|
}
|
|
134
|
-
const bctxId =
|
|
142
|
+
const bctxId = resolvedAppName ? undefined : sessionRegistry.getBrowserContextIdForAgent(getConfigAgentId(config));
|
|
135
143
|
const metaSession = await CDP({ host: "127.0.0.1", port });
|
|
136
144
|
const { targetId } = await metaSession.Target.createTarget({ url, browserContextId: bctxId });
|
|
137
145
|
await metaSession.close();
|
package/dist/tools/thought.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import CDP from "chrome-remote-interface";
|
|
|
2
2
|
export interface ThoughtOptions {
|
|
3
3
|
action: "feedback" | "question";
|
|
4
4
|
message: string;
|
|
5
|
+
anchor?: string;
|
|
6
|
+
style?: "observation" | "decision" | "warning" | "question";
|
|
5
7
|
input?: "sentence" | "paragraph";
|
|
6
8
|
timeout?: number;
|
|
7
9
|
}
|
package/dist/tools/thought.js
CHANGED
|
@@ -7,32 +7,31 @@ function sleep(ms) {
|
|
|
7
7
|
return new Promise(r => setTimeout(r, ms));
|
|
8
8
|
}
|
|
9
9
|
export async function browserThought(session, args) {
|
|
10
|
-
const { action, message, input, timeout } = args;
|
|
10
|
+
const { action, message, input, timeout, anchor, style } = args;
|
|
11
11
|
logAction("browser_thought", action, message);
|
|
12
12
|
if (action === "feedback") {
|
|
13
|
-
|
|
14
|
-
type: 'Weavetab_STATE',
|
|
15
|
-
hud: { action: message },
|
|
16
|
-
stickyFeedback: true,
|
|
17
|
-
}).catch(() => { });
|
|
18
|
-
// Forward to sidepanel thought stream
|
|
13
|
+
// Forward thought event to extension
|
|
19
14
|
await sendToExtension(session, {
|
|
20
15
|
type: 'WT_THOUGHT',
|
|
21
16
|
text: message,
|
|
22
17
|
kind: 'thought',
|
|
18
|
+
anchor,
|
|
19
|
+
style: style || 'observation',
|
|
20
|
+
action: 'feedback',
|
|
23
21
|
}).catch(() => { });
|
|
24
22
|
return { success: true };
|
|
25
23
|
}
|
|
26
24
|
if (action === "question") {
|
|
27
25
|
const QUESTION_TIMEOUT_MS = Math.min((timeout || 20), 20) * 1000;
|
|
28
26
|
await sendToExtension(session, {
|
|
29
|
-
type: '
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
type: 'WT_THOUGHT',
|
|
28
|
+
text: message,
|
|
29
|
+
kind: 'question',
|
|
30
|
+
anchor,
|
|
31
|
+
style: style || 'question',
|
|
32
|
+
action: 'question',
|
|
33
|
+
input: input || "sentence",
|
|
34
|
+
timeout: Math.min((timeout || 20), 20),
|
|
36
35
|
}).catch(() => { });
|
|
37
36
|
const start = Date.now();
|
|
38
37
|
while (Date.now() - start < QUESTION_TIMEOUT_MS + 5000) {
|
package/dist/tools/type.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export declare function detectFramework(session: CDP.Client): Promise<'react' |
|
|
|
48
48
|
export declare function frameworkAwareType(session: CDP.Client, objectId: string, text: string, framework: 'react' | 'vue' | 'angular' | 'vanilla'): Promise<boolean>;
|
|
49
49
|
export declare function weaveType(session: CDP.Client, args: {
|
|
50
50
|
id?: string;
|
|
51
|
+
target?: string;
|
|
52
|
+
selector?: string;
|
|
51
53
|
label?: string;
|
|
52
54
|
intent?: string;
|
|
53
55
|
backendNodeId?: number;
|