@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.
Files changed (160) hide show
  1. package/AGENTS.md +49 -49
  2. package/ARCHITECTURE.md +590 -590
  3. package/README.md +216 -100
  4. package/SECURITY.md +207 -207
  5. package/TROUBLESHOOTING.md +373 -365
  6. package/dist/anticaptcha/detector.js +395 -395
  7. package/dist/anticaptcha/solver.js +130 -130
  8. package/dist/cdp/bridge.js +73 -73
  9. package/dist/cdp/connector.js +46 -22
  10. package/dist/cdp/extension.js +34 -34
  11. package/dist/cdp/helpers.js +174 -174
  12. package/dist/cdp/pruner.js +195 -195
  13. package/dist/cdp/ref_cache.js +66 -66
  14. package/dist/cdp/security.js +10 -10
  15. package/dist/cdp/verify.js +57 -57
  16. package/dist/cdp/walker.js +563 -525
  17. package/dist/cli/plugin.js +26 -3
  18. package/dist/config/loader.d.ts +0 -3
  19. package/dist/config/loader.js +0 -9
  20. package/dist/index.js +0 -4
  21. package/dist/intelligence/intent.js +81 -81
  22. package/dist/intelligence/sessionMemory.js +2 -2
  23. package/dist/overlay/ghost.js +22 -22
  24. package/dist/overlay/injector.js +89 -89
  25. package/dist/plugin/extension_bridge.js +54 -54
  26. package/dist/plugin/interface.d.ts +7 -0
  27. package/dist/plugin/loader.js +3 -4
  28. package/dist/plugin/schema.d.ts +11 -0
  29. package/dist/plugin/schema.js +59 -0
  30. package/dist/security/guard.js +18 -18
  31. package/dist/sensors/actionability.js +167 -167
  32. package/dist/sensors/guard.js +29 -29
  33. package/dist/sensors/network.js +15 -17
  34. package/dist/server.d.ts +1 -1
  35. package/dist/server.js +173 -144
  36. package/dist/state/delta.js +6 -7
  37. package/dist/tools/automation.js +85 -85
  38. package/dist/tools/canvas.js +48 -25
  39. package/dist/tools/checkpoint.js +94 -35
  40. package/dist/tools/click.js +52 -41
  41. package/dist/tools/clipboard.js +80 -74
  42. package/dist/tools/design_extract.js +441 -441
  43. package/dist/tools/dialog.js +13 -13
  44. package/dist/tools/emulation.d.ts +2 -0
  45. package/dist/tools/emulation.js +7 -0
  46. package/dist/tools/fill.js +344 -347
  47. package/dist/tools/find.js +78 -52
  48. package/dist/tools/highlight.js +67 -67
  49. package/dist/tools/inspect.js +54 -25
  50. package/dist/tools/key.js +42 -35
  51. package/dist/tools/navigate.d.ts +1 -1
  52. package/dist/tools/navigate.js +35 -35
  53. package/dist/tools/office/parse.js +62 -18
  54. package/dist/tools/pdf.d.ts +9 -0
  55. package/dist/tools/pdf.js +7 -4
  56. package/dist/tools/performance.d.ts +11 -4
  57. package/dist/tools/performance.js +94 -42
  58. package/dist/tools/performance_test.d.ts +2 -2
  59. package/dist/tools/performance_test.js +69 -69
  60. package/dist/tools/pointer.js +116 -116
  61. package/dist/tools/read.js +99 -67
  62. package/dist/tools/recording.js +9 -0
  63. package/dist/tools/scrape.js +146 -146
  64. package/dist/tools/screenshot.d.ts +2 -0
  65. package/dist/tools/screenshot.js +46 -4
  66. package/dist/tools/scroll.d.ts +3 -1
  67. package/dist/tools/scroll.js +13 -15
  68. package/dist/tools/select.d.ts +3 -0
  69. package/dist/tools/select.js +131 -124
  70. package/dist/tools/snapshot.js +8 -6
  71. package/dist/tools/storage.d.ts +5 -1
  72. package/dist/tools/storage.js +16 -0
  73. package/dist/tools/tabs.d.ts +7 -5
  74. package/dist/tools/tabs.js +79 -26
  75. package/dist/tools/thought.js +8 -8
  76. package/dist/tools/type.js +274 -274
  77. package/dist/tools/type_secret.js +23 -23
  78. package/dist/tools/upload.js +3 -3
  79. package/dist/tools/video_compiler.js +9 -0
  80. package/dist/tools/wait.js +35 -35
  81. package/dist/version.d.ts +1 -1
  82. package/dist/version.js +1 -1
  83. package/docs/DOCUMENTATION.md +583 -585
  84. package/docs/PLUGINS.md +139 -121
  85. package/docs/TOOLS.md +3 -4
  86. package/docs/architecture/blind-injection.md +83 -83
  87. package/docs/architecture/overview.md +49 -49
  88. package/docs/configuration/configuration.md +39 -27
  89. package/docs/configuration/folders.md +62 -55
  90. package/docs/desktop-automation/electron-apps.md +225 -214
  91. package/docs/get-started/installation.md +1 -1
  92. package/docs/get-started/introduction.md +60 -60
  93. package/docs/get-started/quickstart.md +2 -2
  94. package/docs/get-started/setup-wizard.md +1 -1
  95. package/docs/intelligence/site-profiles.md +151 -151
  96. package/docs/tools/tools.md +582 -631
  97. package/docs/troubleshooting/trouble-loop.md +31 -31
  98. package/ext-dist/background.js +415 -415
  99. package/ext-dist/content.js +2527 -2527
  100. package/ext-dist/dashboard.html +583 -583
  101. package/ext-dist/hud/hud.js +3 -3
  102. package/ext-dist/hud/index.html +20 -20
  103. package/ext-dist/manifest.json +73 -73
  104. package/ext-dist/styles.css +223 -223
  105. package/mcp.json +796 -805
  106. package/package.json +8 -8
  107. package/server.json +23 -23
  108. package/smithery.yaml +7 -11
  109. package/dist/cdp/walker.test.d.ts +0 -2
  110. package/dist/cdp/walker.test.js +0 -172
  111. package/dist/intelligence/sessionMemory.test.d.ts +0 -2
  112. package/dist/intelligence/sessionMemory.test.js +0 -62
  113. package/dist/intelligence/trail.test.d.ts +0 -2
  114. package/dist/intelligence/trail.test.js +0 -110
  115. package/dist/state/cache.test.d.ts +0 -2
  116. package/dist/state/cache.test.js +0 -76
  117. package/dist/state/delta.test.d.ts +0 -2
  118. package/dist/state/delta.test.js +0 -279
  119. package/dist/state/groups.d.ts +0 -15
  120. package/dist/state/groups.js +0 -80
  121. package/dist/tools/accessibility.d.ts +0 -14
  122. package/dist/tools/accessibility.js +0 -32
  123. package/dist/tools/ask.d.ts +0 -14
  124. package/dist/tools/ask.js +0 -49
  125. package/dist/tools/click_and_wait.d.ts +0 -33
  126. package/dist/tools/click_and_wait.js +0 -149
  127. package/dist/tools/drag.d.ts +0 -15
  128. package/dist/tools/drag.js +0 -29
  129. package/dist/tools/geo.d.ts +0 -19
  130. package/dist/tools/geo.js +0 -29
  131. package/dist/tools/github/analyze.d.ts +0 -4
  132. package/dist/tools/github/analyze.js +0 -113
  133. package/dist/tools/github/cache.d.ts +0 -21
  134. package/dist/tools/github/cache.js +0 -28
  135. package/dist/tools/github/index.d.ts +0 -19
  136. package/dist/tools/github/index.js +0 -40
  137. package/dist/tools/github/issues.d.ts +0 -9
  138. package/dist/tools/github/issues.js +0 -88
  139. package/dist/tools/github/pr.d.ts +0 -5
  140. package/dist/tools/github/pr.js +0 -88
  141. package/dist/tools/github/rateLimiter.d.ts +0 -4
  142. package/dist/tools/github/rateLimiter.js +0 -46
  143. package/dist/tools/github/read.d.ts +0 -34
  144. package/dist/tools/github/read.js +0 -74
  145. package/dist/tools/github/repoContext.d.ts +0 -20
  146. package/dist/tools/github/repoContext.js +0 -129
  147. package/dist/tools/hover.d.ts +0 -19
  148. package/dist/tools/hover.js +0 -57
  149. package/dist/tools/integration.test.d.ts +0 -2
  150. package/dist/tools/integration.test.js +0 -96
  151. package/dist/tools/macro_compiler.d.ts +0 -7
  152. package/dist/tools/macro_compiler.js +0 -82
  153. package/dist/tools/mouse.d.ts +0 -21
  154. package/dist/tools/mouse.js +0 -62
  155. package/dist/tools/response.d.ts +0 -129
  156. package/dist/tools/response.js +0 -5
  157. package/dist/tools/wait_for.d.ts +0 -23
  158. package/dist/tools/wait_for.js +0 -30
  159. package/dist/tools/windows.d.ts +0 -22
  160. package/dist/tools/windows.js +0 -57
@@ -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.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, false);
10
- var matchedNodes = [];
11
- var seenElements = new Set();
12
-
13
- while (walker.nextNode()) {
14
- var node = walker.currentNode;
15
- var el = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
16
- if (!el || seenElements.has(el)) continue;
17
-
18
- var text = norm(node.textContent);
19
- var aria = norm(el.getAttribute('aria-label') || el.getAttribute('title') || el.getAttribute('placeholder') || '');
20
-
21
- if ((text && text.includes(qLow)) || (aria && aria.includes(qLow))) {
22
- seenElements.add(el);
23
- matchedNodes.push(el);
24
- if (!returnAll && matchedNodes.length >= 1) break;
25
- if (matchedNodes.length >= maxMatches) break;
26
- }
27
- }
28
-
29
- if (matchedNodes.length === 0) return null;
30
-
31
- var out = matchedNodes.map(function(match, i) {
32
- var r = match.getBoundingClientRect();
33
- var wtId = match.getAttribute('data-wt-id');
34
- var sel = '';
35
- if (wtId) {
36
- sel = '[data-wt-id="' + wtId + '"]';
37
- } else if (match.id) {
38
- sel = '#' + CSS.escape(match.id);
39
- } else {
40
- var tmp = 'wt-find-' + i + '-' + Math.random().toString(36).slice(2,6);
41
- match.setAttribute('data-wt-id', tmp);
42
- sel = '[data-wt-id="' + tmp + '"]';
43
- wtId = tmp;
44
- }
45
- return {
46
- ref: 'w:' + wtId,
47
- label: match.getAttribute('aria-label') || (match.textContent||'').trim().slice(0,80) || q,
48
- tag: match.tagName.toLowerCase(),
49
- x: Math.round(r.left),
50
- y: Math.round(r.top),
51
- width: Math.round(r.width),
52
- height: Math.round(r.height),
53
- selector: sel
54
- };
55
- });
56
-
57
- return JSON.stringify(out);
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 } }));
@@ -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) {
@@ -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
- const doc = await DOM.getDocument({ depth: -1 }).catch(() => null);
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; will fall through to selector strategies */ }
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 = ['display', 'position', 'width', 'height', 'margin', 'padding', 'color', 'background-color', 'font-size', 'visibility', 'opacity', 'z-index', 'pointer-events'];
77
- computedStylesData = cssResult.computedStyle
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;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Weavetab — tools/navigate.ts
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
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Weavetab — tools/navigate.ts
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('Weavetab://')) {
19
- const page = url.replace('Weavetab://', '').split('?')[0] || 'dashboard';
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 Weavetab://${page}` };
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 Weavetab:// navigation" };
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 — Page.navigate
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 — opening in new tab: ${parsed.href}`);
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
  ]);