@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.
Files changed (89) hide show
  1. package/AGENTS.md +1 -0
  2. package/LICENSE +2 -2
  3. package/README.md +208 -43
  4. package/SECURITY.md +3 -3
  5. package/TROUBLESHOOTING.md +1 -1
  6. package/dist/cdp/bridge.d.ts +10 -0
  7. package/dist/cdp/bridge.js +284 -78
  8. package/dist/cdp/connector.d.ts +5 -3
  9. package/dist/cdp/connector.js +188 -71
  10. package/dist/cdp/lock.d.ts +9 -6
  11. package/dist/cdp/lock.js +72 -59
  12. package/dist/cdp/omni_broker.d.ts +1 -0
  13. package/dist/cdp/omni_broker.js +12 -6
  14. package/dist/cdp/profiles.d.ts +10 -0
  15. package/dist/cdp/profiles.js +65 -0
  16. package/dist/cdp/walker.js +50 -0
  17. package/dist/cli/plugin.d.ts +0 -2
  18. package/dist/cli/plugin.js +31 -683
  19. package/dist/cli/updater.js +2 -2
  20. package/dist/config/loader.d.ts +25 -6
  21. package/dist/config/loader.js +133 -20
  22. package/dist/index.js +48 -52
  23. package/dist/overlay/ghost.js +2 -2
  24. package/dist/overlay/injector.js +1 -3
  25. package/dist/plugin/extension_bridge.d.ts +40 -0
  26. package/dist/plugin/extension_bridge.js +158 -0
  27. package/dist/plugin/interface.d.ts +78 -16
  28. package/dist/plugin/loader.d.ts +4 -0
  29. package/dist/plugin/loader.js +178 -57
  30. package/dist/plugin/registry.js +11 -1
  31. package/dist/plugin/storage.d.ts +51 -0
  32. package/dist/plugin/storage.js +164 -0
  33. package/dist/server.js +213 -121
  34. package/dist/state/session.d.ts +2 -2
  35. package/dist/state/session.js +33 -13
  36. package/dist/tools/browser_detect.d.ts +2 -1
  37. package/dist/tools/browser_detect.js +6 -3
  38. package/dist/tools/burst.d.ts +1 -0
  39. package/dist/tools/burst.js +4 -6
  40. package/dist/tools/click.js +23 -28
  41. package/dist/tools/clipboard.js +31 -24
  42. package/dist/tools/navigate.d.ts +1 -1
  43. package/dist/tools/navigate.js +28 -10
  44. package/dist/tools/tabs.d.ts +10 -10
  45. package/dist/tools/tabs.js +47 -39
  46. package/dist/tools/type.js +2 -2
  47. package/docs/DOCUMENTATION.md +63 -6
  48. package/docs/architecture/blind-injection.md +20 -0
  49. package/docs/architecture/dual-injection.md +32 -0
  50. package/docs/architecture/overview.md +49 -0
  51. package/docs/architecture/security.md +35 -0
  52. package/docs/architecture/transport.md +37 -0
  53. package/docs/captcha-stealth/captcha-solver.md +75 -0
  54. package/docs/captcha-stealth/stealth-physics.md +60 -0
  55. package/docs/cli/cli-commands.md +44 -0
  56. package/docs/cli/cli-flags.md +20 -0
  57. package/docs/cli/cli-introduction.md +20 -0
  58. package/docs/cli/cli-scripting.md +32 -0
  59. package/docs/cli/g-ide/ide-antigravity.md +24 -0
  60. package/docs/cli/g-ide/ide-claude-code.md +24 -0
  61. package/docs/cli/g-ide/ide-claude-desktop.md +32 -0
  62. package/docs/cli/g-ide/ide-cursor.md +31 -0
  63. package/docs/cli/g-ide/ide-generic.md +34 -0
  64. package/docs/cli/g-ide/ide-opencode.md +24 -0
  65. package/docs/cli/g-ide/ide-vscode-copilot.md +24 -0
  66. package/docs/cli/g-ide/ide-windsurf.md +24 -0
  67. package/docs/configuration/config-locations.md +24 -0
  68. package/docs/configuration/configuration.md +73 -0
  69. package/docs/configuration/env-variables.md +19 -0
  70. package/docs/configuration/folders.md +54 -0
  71. package/docs/desktop-automation/electron-apps.md +162 -0
  72. package/docs/get-started/installation.md +47 -0
  73. package/docs/get-started/introduction.md +60 -0
  74. package/docs/get-started/quickstart.md +54 -0
  75. package/docs/get-started/setup-wizard.md +26 -0
  76. package/docs/skills-ecosystem/skills-overview.md +35 -0
  77. package/docs/skills-ecosystem/skills-recipes.md +36 -0
  78. package/docs/tools/tools.md +293 -0
  79. package/docs/troubleshooting/trouble-browser.md +27 -0
  80. package/docs/troubleshooting/trouble-config.md +20 -0
  81. package/docs/troubleshooting/trouble-loop.md +31 -0
  82. package/ext-dist/content.js +0 -1
  83. package/mcp.json +8 -6
  84. package/package.json +11 -5
  85. package/server.json +3 -3
  86. package/docs/DEV_MODE.md +0 -68
  87. package/docs/PLUGINS.md +0 -538
  88. package/docs/TOOLS.md +0 -104
  89. package/docs/dev_plugin.md +0 -310
@@ -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 iframeSession = await CDP({ host: "127.0.0.1", port, target: targetInfo.targetId });
27
- await iframeSession.Runtime.enable();
28
- await iframeSession.DOM.enable();
29
- omniSessions.get(parentTargetId).set(targetInfo.targetId, iframeSession);
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) {
@@ -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;
@@ -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
+ }
@@ -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
  }
@@ -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>;