@weavetab/mcp 2.5.0-beta.1 → 2.5.0-beta.2
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 -0
- package/LICENSE +2 -2
- package/README.md +208 -43
- package/SECURITY.md +3 -3
- package/TROUBLESHOOTING.md +1 -1
- package/dist/cdp/bridge.d.ts +10 -0
- package/dist/cdp/bridge.js +284 -78
- package/dist/cdp/connector.d.ts +5 -3
- package/dist/cdp/connector.js +188 -71
- package/dist/cdp/lock.d.ts +9 -6
- package/dist/cdp/lock.js +72 -59
- package/dist/cdp/omni_broker.d.ts +1 -0
- package/dist/cdp/omni_broker.js +12 -6
- package/dist/cdp/profiles.d.ts +10 -0
- package/dist/cdp/profiles.js +65 -0
- package/dist/cdp/walker.js +50 -0
- package/dist/cli/plugin.d.ts +0 -2
- package/dist/cli/plugin.js +31 -683
- package/dist/cli/updater.js +2 -2
- package/dist/config/loader.d.ts +25 -6
- package/dist/config/loader.js +133 -20
- package/dist/index.js +48 -52
- package/dist/overlay/ghost.js +2 -2
- package/dist/overlay/injector.js +1 -3
- package/dist/plugin/extension_bridge.d.ts +40 -0
- package/dist/plugin/extension_bridge.js +158 -0
- package/dist/plugin/interface.d.ts +78 -16
- package/dist/plugin/loader.d.ts +4 -0
- package/dist/plugin/loader.js +178 -57
- package/dist/plugin/registry.js +11 -1
- package/dist/plugin/storage.d.ts +51 -0
- package/dist/plugin/storage.js +164 -0
- package/dist/server.js +213 -121
- package/dist/state/session.d.ts +2 -2
- package/dist/state/session.js +33 -13
- package/dist/tools/browser_detect.d.ts +2 -1
- package/dist/tools/browser_detect.js +6 -3
- package/dist/tools/burst.d.ts +1 -0
- package/dist/tools/burst.js +4 -6
- package/dist/tools/click.js +23 -28
- package/dist/tools/clipboard.js +31 -24
- package/dist/tools/navigate.d.ts +1 -1
- package/dist/tools/navigate.js +28 -10
- package/dist/tools/tabs.d.ts +10 -10
- package/dist/tools/tabs.js +47 -39
- package/dist/tools/type.js +2 -2
- package/docs/DOCUMENTATION.md +63 -6
- package/docs/architecture/blind-injection.md +20 -0
- package/docs/architecture/dual-injection.md +32 -0
- package/docs/architecture/overview.md +49 -0
- package/docs/architecture/security.md +35 -0
- package/docs/architecture/transport.md +37 -0
- package/docs/captcha-stealth/captcha-solver.md +75 -0
- package/docs/captcha-stealth/stealth-physics.md +60 -0
- package/docs/cli/cli-commands.md +44 -0
- package/docs/cli/cli-flags.md +20 -0
- package/docs/cli/cli-introduction.md +20 -0
- package/docs/cli/cli-scripting.md +32 -0
- package/docs/cli/g-ide/ide-antigravity.md +24 -0
- package/docs/cli/g-ide/ide-claude-code.md +24 -0
- package/docs/cli/g-ide/ide-claude-desktop.md +32 -0
- package/docs/cli/g-ide/ide-cursor.md +31 -0
- package/docs/cli/g-ide/ide-generic.md +34 -0
- package/docs/cli/g-ide/ide-opencode.md +24 -0
- package/docs/cli/g-ide/ide-vscode-copilot.md +24 -0
- package/docs/cli/g-ide/ide-windsurf.md +24 -0
- package/docs/configuration/config-locations.md +24 -0
- package/docs/configuration/configuration.md +73 -0
- package/docs/configuration/env-variables.md +19 -0
- package/docs/configuration/folders.md +54 -0
- package/docs/desktop-automation/electron-apps.md +162 -0
- package/docs/get-started/installation.md +47 -0
- package/docs/get-started/introduction.md +60 -0
- package/docs/get-started/quickstart.md +54 -0
- package/docs/get-started/setup-wizard.md +26 -0
- package/docs/skills-ecosystem/skills-overview.md +35 -0
- package/docs/skills-ecosystem/skills-recipes.md +36 -0
- package/docs/tools/tools.md +293 -0
- package/docs/troubleshooting/trouble-browser.md +27 -0
- package/docs/troubleshooting/trouble-config.md +20 -0
- package/docs/troubleshooting/trouble-loop.md +31 -0
- package/ext-dist/content.js +0 -1
- package/mcp.json +8 -6
- package/package.json +11 -5
- package/server.json +3 -3
- package/docs/DEV_MODE.md +0 -68
- package/docs/PLUGINS.md +0 -538
- package/docs/TOOLS.md +0 -104
- package/docs/dev_plugin.md +0 -310
package/dist/cdp/omni_broker.js
CHANGED
|
@@ -20,13 +20,16 @@ export async function initOmniBroker(parentSession, parentTargetId, port) {
|
|
|
20
20
|
}
|
|
21
21
|
parentSession.Target.on("attachedToTarget", async (event) => {
|
|
22
22
|
const { targetInfo } = event;
|
|
23
|
-
if (targetInfo.type === 'iframe') {
|
|
23
|
+
if (targetInfo && targetInfo.targetId !== parentTargetId && (targetInfo.type === 'iframe' || targetInfo.type === 'webview' || targetInfo.type === 'page' || targetInfo.type === 'app')) {
|
|
24
24
|
try {
|
|
25
|
-
// Connect a flat session to the iframe target
|
|
26
|
-
const
|
|
27
|
-
await
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
// Connect a flat session to the child iframe/webview target
|
|
26
|
+
const childSession = await CDP({ host: "127.0.0.1", port, target: targetInfo.targetId });
|
|
27
|
+
await Promise.all([
|
|
28
|
+
childSession.Runtime.enable().catch(() => { }),
|
|
29
|
+
childSession.DOM.enable().catch(() => { }),
|
|
30
|
+
childSession.Page.enable().catch(() => { })
|
|
31
|
+
]);
|
|
32
|
+
omniSessions.get(parentTargetId).set(targetInfo.targetId, childSession);
|
|
30
33
|
}
|
|
31
34
|
catch (e) {
|
|
32
35
|
// Fallback or ignore
|
|
@@ -105,6 +108,9 @@ function parseJSON(str) {
|
|
|
105
108
|
return str;
|
|
106
109
|
}
|
|
107
110
|
}
|
|
111
|
+
export function getOmniSessions(parentTargetId) {
|
|
112
|
+
return omniSessions.get(parentTargetId);
|
|
113
|
+
}
|
|
108
114
|
export function cleanupOmniBroker(parentTargetId) {
|
|
109
115
|
const iframeMap = omniSessions.get(parentTargetId);
|
|
110
116
|
if (iframeMap) {
|
package/dist/cdp/profiles.d.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
1
|
export declare function getSessionProfile(cookies: boolean, customProfileDir?: string, syncDataAcrossBrowsers?: boolean, browserPath?: string): string;
|
|
2
|
+
export declare function sanitizeAppName(appName: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Asserts that the given profile directory is NOT a real desktop app's native user data directory.
|
|
5
|
+
* Throws a security block error if it matches root or subdirectory of standard app data paths.
|
|
6
|
+
*/
|
|
7
|
+
export declare function assertNotRealElectronProfile(profileDir: string, appName: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Resolves the isolated profile directory for a specific Electron application.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getElectronProfile(appName: string, customProfileDir?: string): string;
|
package/dist/cdp/profiles.js
CHANGED
|
@@ -85,3 +85,68 @@ export function getSessionProfile(cookies, customProfileDir, syncDataAcrossBrows
|
|
|
85
85
|
}
|
|
86
86
|
return sessionProfile;
|
|
87
87
|
}
|
|
88
|
+
// ─── Electron App Profile Resolver & Safety Guard ─────────────────────────────
|
|
89
|
+
export function sanitizeAppName(appName) {
|
|
90
|
+
const cleaned = appName.trim().replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
|
|
91
|
+
return cleaned || "app";
|
|
92
|
+
}
|
|
93
|
+
// Real application data directories that should NEVER be used directly
|
|
94
|
+
const REAL_DESKTOP_APP_ROOTS = [];
|
|
95
|
+
if (PLATFORM === 'win32') {
|
|
96
|
+
REAL_DESKTOP_APP_ROOTS.push(path.join(HOME, "AppData", "Roaming"), path.join(HOME, "AppData", "Local"), path.join(HOME, "AppData", "LocalLow"));
|
|
97
|
+
}
|
|
98
|
+
else if (PLATFORM === 'darwin') {
|
|
99
|
+
REAL_DESKTOP_APP_ROOTS.push(path.join(HOME, "Library", "Application Support"), path.join(HOME, "Library", "Saved Application State"), path.join(HOME, "Library", "Caches"));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
REAL_DESKTOP_APP_ROOTS.push(path.join(HOME, ".config"), path.join(HOME, ".local", "share"), path.join(HOME, ".cache"));
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Asserts that the given profile directory is NOT a real desktop app's native user data directory.
|
|
106
|
+
* Throws a security block error if it matches root or subdirectory of standard app data paths.
|
|
107
|
+
*/
|
|
108
|
+
export function assertNotRealElectronProfile(profileDir, appName) {
|
|
109
|
+
const resolved = path.resolve(profileDir).toLowerCase();
|
|
110
|
+
// First check against browser profiles
|
|
111
|
+
assertNotRealBrowserProfile(resolved);
|
|
112
|
+
// Check against native desktop app data roots
|
|
113
|
+
for (const rootPath of REAL_DESKTOP_APP_ROOTS) {
|
|
114
|
+
const rootResolved = path.resolve(rootPath).toLowerCase();
|
|
115
|
+
// Direct matches or direct children in %APPDATA%/<appName>
|
|
116
|
+
const appSpecificRealDir = path.join(rootResolved, sanitizeAppName(appName)).toLowerCase();
|
|
117
|
+
if (resolved === appSpecificRealDir || resolved.startsWith(appSpecificRealDir + path.sep)) {
|
|
118
|
+
throw new Error(`[Weavetab] ✗ SECURITY BLOCK: The profileDir "${profileDir}" points to your real ${appName} desktop app data.\n` +
|
|
119
|
+
` Weavetab will never read from or write to your personal desktop app data.\n` +
|
|
120
|
+
` Please use an isolated directory or let Weavetab manage ~/.weavetab-system/apps/${appName}/.\n` +
|
|
121
|
+
` Real app data path detected: ${appSpecificRealDir}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Resolves the isolated profile directory for a specific Electron application.
|
|
127
|
+
*/
|
|
128
|
+
export function getElectronProfile(appName, customProfileDir) {
|
|
129
|
+
const sanitized = sanitizeAppName(appName);
|
|
130
|
+
if (customProfileDir && customProfileDir.trim()) {
|
|
131
|
+
const resolved = path.resolve(customProfileDir.trim());
|
|
132
|
+
assertNotRealElectronProfile(resolved, appName);
|
|
133
|
+
if (!fs.existsSync(resolved)) {
|
|
134
|
+
fs.mkdirSync(resolved, { recursive: true });
|
|
135
|
+
logDebug(`[Weavetab] ✓ Created custom Electron profile directory for ${appName}: ${resolved}`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
logDebug(`[Weavetab] ✓ Using custom Electron profile directory for ${appName}: ${resolved}`);
|
|
139
|
+
}
|
|
140
|
+
return resolved;
|
|
141
|
+
}
|
|
142
|
+
const appProfileDir = path.join(HOME, ".weavetab-system", "apps", sanitized);
|
|
143
|
+
assertNotRealElectronProfile(appProfileDir, appName);
|
|
144
|
+
if (!fs.existsSync(appProfileDir)) {
|
|
145
|
+
fs.mkdirSync(appProfileDir, { recursive: true });
|
|
146
|
+
logDebug(`[Weavetab] ✓ Created isolated Electron profile directory for ${appName}: ${appProfileDir}`);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
logDebug(`[Weavetab] ✓ Using isolated Electron profile directory for ${appName}: ${appProfileDir}`);
|
|
150
|
+
}
|
|
151
|
+
return appProfileDir;
|
|
152
|
+
}
|
package/dist/cdp/walker.js
CHANGED
|
@@ -387,6 +387,56 @@ export async function buildActionMap(session, options = {}, targetId = "default"
|
|
|
387
387
|
}
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
+
// Merge elements from child webviews and iframes managed by OmniBroker
|
|
391
|
+
try {
|
|
392
|
+
const { getOmniSessions } = await import("./omni_broker.js");
|
|
393
|
+
const childSessions = getOmniSessions(targetId);
|
|
394
|
+
if (childSessions && childSessions.size > 0) {
|
|
395
|
+
for (const [, childSession] of childSessions.entries()) {
|
|
396
|
+
try {
|
|
397
|
+
const { result: childResult } = await childSession.Runtime.evaluate({
|
|
398
|
+
expression: `(function() {
|
|
399
|
+
var INTERACTIVE_SEL = 'a, button, input, textarea, select, [role="button"], [role="link"], [role="textbox"], [role="checkbox"], [role="radio"], [role="combobox"], [role="searchbox"], [role="menuitem"], [role="tab"], [contenteditable="true"], [tabindex]:not([tabindex="-1"])';
|
|
400
|
+
var els = document.querySelectorAll(INTERACTIVE_SEL);
|
|
401
|
+
var results = [];
|
|
402
|
+
for (var i = 0; i < els.length; i++) {
|
|
403
|
+
var el = els[i];
|
|
404
|
+
var rect = el.getBoundingClientRect();
|
|
405
|
+
if (rect.width === 0 || rect.height === 0 || rect.bottom < 0 || rect.top > window.innerHeight) continue;
|
|
406
|
+
var id = el.getAttribute('data-wt-id');
|
|
407
|
+
if (!id) {
|
|
408
|
+
id = 'wv_' + Math.random().toString(36).slice(2, 9);
|
|
409
|
+
el.setAttribute('data-wt-id', id);
|
|
410
|
+
}
|
|
411
|
+
results.push({
|
|
412
|
+
id: id,
|
|
413
|
+
role: el.getAttribute('role') || el.tagName.toLowerCase(),
|
|
414
|
+
label: el.getAttribute('aria-label') || el.innerText || el.value || el.placeholder || '',
|
|
415
|
+
value: el.value,
|
|
416
|
+
x: Math.round(rect.left + rect.width / 2),
|
|
417
|
+
y: Math.round(rect.top + rect.height / 2),
|
|
418
|
+
selector: '[data-wt-id="' + id + '"]',
|
|
419
|
+
frameUrl: window.location.href,
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
return JSON.stringify(results);
|
|
423
|
+
})()`,
|
|
424
|
+
returnByValue: true,
|
|
425
|
+
});
|
|
426
|
+
if (childResult && childResult.value) {
|
|
427
|
+
const childEls = JSON.parse(childResult.value);
|
|
428
|
+
if (Array.isArray(childEls) && childEls.length > 0) {
|
|
429
|
+
if (!Array.isArray(extensionMap))
|
|
430
|
+
extensionMap = [];
|
|
431
|
+
extensionMap = extensionMap.concat(childEls);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch { }
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
catch { }
|
|
390
440
|
if (!extensionMap || !Array.isArray(extensionMap)) {
|
|
391
441
|
return { url, title, elements: [], targetId };
|
|
392
442
|
}
|
package/dist/cli/plugin.d.ts
CHANGED
|
@@ -4,6 +4,4 @@ export declare function runPluginSearch(query?: string): Promise<void>;
|
|
|
4
4
|
export declare function runPluginBrowse(): Promise<void>;
|
|
5
5
|
export declare function runPluginRemove(pkgName: string, args?: string[]): Promise<void>;
|
|
6
6
|
export declare function runPluginVerify(pkgName: string): Promise<void>;
|
|
7
|
-
export declare function runPluginInit(args?: string[]): Promise<void>;
|
|
8
|
-
export declare function runPluginBuild(args?: string[]): Promise<void>;
|
|
9
7
|
export declare function runPluginCli(args: string[]): Promise<void>;
|