@weavetab/mcp 2.5.0-beta.0

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 (281) hide show
  1. package/AGENTS.md +48 -0
  2. package/ARCHITECTURE.md +590 -0
  3. package/LICENSE +631 -0
  4. package/README.md +909 -0
  5. package/SECURITY.md +196 -0
  6. package/TROUBLESHOOTING.md +365 -0
  7. package/dist/anticaptcha/detector.d.ts +49 -0
  8. package/dist/anticaptcha/detector.js +465 -0
  9. package/dist/anticaptcha/integration.d.ts +36 -0
  10. package/dist/anticaptcha/integration.js +123 -0
  11. package/dist/anticaptcha/solver.d.ts +27 -0
  12. package/dist/anticaptcha/solver.js +552 -0
  13. package/dist/audit/logger.d.ts +13 -0
  14. package/dist/audit/logger.js +177 -0
  15. package/dist/audit/telemetry.d.ts +36 -0
  16. package/dist/audit/telemetry.js +162 -0
  17. package/dist/cdp/bridge.d.ts +16 -0
  18. package/dist/cdp/bridge.js +826 -0
  19. package/dist/cdp/confirm.d.ts +26 -0
  20. package/dist/cdp/confirm.js +79 -0
  21. package/dist/cdp/connector.d.ts +37 -0
  22. package/dist/cdp/connector.js +661 -0
  23. package/dist/cdp/extension.d.ts +36 -0
  24. package/dist/cdp/extension.js +118 -0
  25. package/dist/cdp/finder.d.ts +1 -0
  26. package/dist/cdp/finder.js +2 -0
  27. package/dist/cdp/helpers.d.ts +11 -0
  28. package/dist/cdp/helpers.js +195 -0
  29. package/dist/cdp/label_cache.d.ts +12 -0
  30. package/dist/cdp/label_cache.js +51 -0
  31. package/dist/cdp/lock.d.ts +33 -0
  32. package/dist/cdp/lock.js +206 -0
  33. package/dist/cdp/omni_broker.d.ts +17 -0
  34. package/dist/cdp/omni_broker.js +119 -0
  35. package/dist/cdp/profiles.d.ts +1 -0
  36. package/dist/cdp/profiles.js +87 -0
  37. package/dist/cdp/pruner.d.ts +41 -0
  38. package/dist/cdp/pruner.js +263 -0
  39. package/dist/cdp/ref_cache.d.ts +101 -0
  40. package/dist/cdp/ref_cache.js +234 -0
  41. package/dist/cdp/retry.d.ts +5 -0
  42. package/dist/cdp/retry.js +39 -0
  43. package/dist/cdp/retry_enhanced.d.ts +44 -0
  44. package/dist/cdp/retry_enhanced.js +102 -0
  45. package/dist/cdp/security.d.ts +50 -0
  46. package/dist/cdp/security.js +237 -0
  47. package/dist/cdp/verify.d.ts +39 -0
  48. package/dist/cdp/verify.js +143 -0
  49. package/dist/cdp/walker.d.ts +91 -0
  50. package/dist/cdp/walker.js +896 -0
  51. package/dist/cdp/walker.test.d.ts +2 -0
  52. package/dist/cdp/walker.test.js +172 -0
  53. package/dist/cdp/websocket_transport.d.ts +15 -0
  54. package/dist/cdp/websocket_transport.js +118 -0
  55. package/dist/cli/plugin.d.ts +9 -0
  56. package/dist/cli/plugin.js +1134 -0
  57. package/dist/cli/updater.d.ts +1 -0
  58. package/dist/cli/updater.js +72 -0
  59. package/dist/config/loader.d.ts +120 -0
  60. package/dist/config/loader.js +704 -0
  61. package/dist/index.d.ts +2 -0
  62. package/dist/index.js +1248 -0
  63. package/dist/intelligence/hints.d.ts +11 -0
  64. package/dist/intelligence/hints.js +39 -0
  65. package/dist/intelligence/intent.d.ts +33 -0
  66. package/dist/intelligence/intent.js +171 -0
  67. package/dist/intelligence/sessionMemory.d.ts +66 -0
  68. package/dist/intelligence/sessionMemory.js +284 -0
  69. package/dist/intelligence/sessionMemory.test.d.ts +2 -0
  70. package/dist/intelligence/sessionMemory.test.js +62 -0
  71. package/dist/intelligence/trail.d.ts +64 -0
  72. package/dist/intelligence/trail.js +233 -0
  73. package/dist/intelligence/trail.test.d.ts +2 -0
  74. package/dist/intelligence/trail.test.js +110 -0
  75. package/dist/intelligence/vision.d.ts +24 -0
  76. package/dist/intelligence/vision.js +151 -0
  77. package/dist/lifecycle/mission_manager.d.ts +16 -0
  78. package/dist/lifecycle/mission_manager.js +44 -0
  79. package/dist/overlay/bubble.d.ts +16 -0
  80. package/dist/overlay/bubble.js +37 -0
  81. package/dist/overlay/ghost.d.ts +35 -0
  82. package/dist/overlay/ghost.js +508 -0
  83. package/dist/overlay/injector.d.ts +22 -0
  84. package/dist/overlay/injector.js +198 -0
  85. package/dist/plugin/interface.d.ts +134 -0
  86. package/dist/plugin/interface.js +1 -0
  87. package/dist/plugin/loader.d.ts +18 -0
  88. package/dist/plugin/loader.js +155 -0
  89. package/dist/plugin/registry.d.ts +50 -0
  90. package/dist/plugin/registry.js +234 -0
  91. package/dist/security/blacklist.d.ts +24 -0
  92. package/dist/security/blacklist.js +80 -0
  93. package/dist/security/filter.d.ts +2 -0
  94. package/dist/security/filter.js +20 -0
  95. package/dist/security/guard.d.ts +8 -0
  96. package/dist/security/guard.js +35 -0
  97. package/dist/security/ratelimit.d.ts +11 -0
  98. package/dist/security/ratelimit.js +57 -0
  99. package/dist/security/secrets.d.ts +75 -0
  100. package/dist/security/secrets.js +365 -0
  101. package/dist/sensors/actionability.d.ts +81 -0
  102. package/dist/sensors/actionability.js +303 -0
  103. package/dist/sensors/guard.d.ts +25 -0
  104. package/dist/sensors/guard.js +168 -0
  105. package/dist/sensors/mutations.d.ts +23 -0
  106. package/dist/sensors/mutations.js +93 -0
  107. package/dist/sensors/network.d.ts +67 -0
  108. package/dist/sensors/network.js +193 -0
  109. package/dist/sensors/operation_monitor.d.ts +80 -0
  110. package/dist/sensors/operation_monitor.js +203 -0
  111. package/dist/sensors/pacing.d.ts +44 -0
  112. package/dist/sensors/pacing.js +111 -0
  113. package/dist/sensors/thoughts.d.ts +2 -0
  114. package/dist/sensors/thoughts.js +59 -0
  115. package/dist/sensors/wait.d.ts +12 -0
  116. package/dist/sensors/wait.js +44 -0
  117. package/dist/server.d.ts +7 -0
  118. package/dist/server.js +1687 -0
  119. package/dist/state/agent.d.ts +36 -0
  120. package/dist/state/agent.js +101 -0
  121. package/dist/state/cache.d.ts +16 -0
  122. package/dist/state/cache.js +92 -0
  123. package/dist/state/cache.test.d.ts +2 -0
  124. package/dist/state/cache.test.js +76 -0
  125. package/dist/state/delta.d.ts +71 -0
  126. package/dist/state/delta.js +234 -0
  127. package/dist/state/delta.test.d.ts +2 -0
  128. package/dist/state/delta.test.js +279 -0
  129. package/dist/state/groups.d.ts +15 -0
  130. package/dist/state/groups.js +80 -0
  131. package/dist/state/session.d.ts +30 -0
  132. package/dist/state/session.js +155 -0
  133. package/dist/tools/accessibility.d.ts +14 -0
  134. package/dist/tools/accessibility.js +32 -0
  135. package/dist/tools/ask.d.ts +14 -0
  136. package/dist/tools/ask.js +49 -0
  137. package/dist/tools/automation.d.ts +36 -0
  138. package/dist/tools/automation.js +218 -0
  139. package/dist/tools/browser_detect.d.ts +13 -0
  140. package/dist/tools/browser_detect.js +73 -0
  141. package/dist/tools/burst.d.ts +35 -0
  142. package/dist/tools/burst.js +344 -0
  143. package/dist/tools/canvas.d.ts +25 -0
  144. package/dist/tools/canvas.js +132 -0
  145. package/dist/tools/captcha.d.ts +38 -0
  146. package/dist/tools/captcha.js +209 -0
  147. package/dist/tools/click.d.ts +36 -0
  148. package/dist/tools/click.js +561 -0
  149. package/dist/tools/click_and_wait.d.ts +33 -0
  150. package/dist/tools/click_and_wait.js +149 -0
  151. package/dist/tools/clipboard.d.ts +29 -0
  152. package/dist/tools/clipboard.js +279 -0
  153. package/dist/tools/console.d.ts +21 -0
  154. package/dist/tools/console.js +107 -0
  155. package/dist/tools/cookies.d.ts +67 -0
  156. package/dist/tools/cookies.js +121 -0
  157. package/dist/tools/design_extract.d.ts +109 -0
  158. package/dist/tools/design_extract.js +641 -0
  159. package/dist/tools/dialog.d.ts +24 -0
  160. package/dist/tools/dialog.js +109 -0
  161. package/dist/tools/drag.d.ts +15 -0
  162. package/dist/tools/drag.js +29 -0
  163. package/dist/tools/emulation.d.ts +33 -0
  164. package/dist/tools/emulation.js +69 -0
  165. package/dist/tools/eval.d.ts +20 -0
  166. package/dist/tools/eval.js +92 -0
  167. package/dist/tools/fill.d.ts +41 -0
  168. package/dist/tools/fill.js +667 -0
  169. package/dist/tools/find.d.ts +30 -0
  170. package/dist/tools/find.js +60 -0
  171. package/dist/tools/geo.d.ts +19 -0
  172. package/dist/tools/geo.js +29 -0
  173. package/dist/tools/github/analyze.d.ts +4 -0
  174. package/dist/tools/github/analyze.js +113 -0
  175. package/dist/tools/github/cache.d.ts +21 -0
  176. package/dist/tools/github/cache.js +28 -0
  177. package/dist/tools/github/index.d.ts +4 -0
  178. package/dist/tools/github/index.js +4 -0
  179. package/dist/tools/github/issues.d.ts +9 -0
  180. package/dist/tools/github/issues.js +88 -0
  181. package/dist/tools/github/pr.d.ts +5 -0
  182. package/dist/tools/github/pr.js +88 -0
  183. package/dist/tools/github/rateLimiter.d.ts +4 -0
  184. package/dist/tools/github/rateLimiter.js +46 -0
  185. package/dist/tools/github/read.d.ts +34 -0
  186. package/dist/tools/github/read.js +74 -0
  187. package/dist/tools/github/repoContext.d.ts +20 -0
  188. package/dist/tools/github/repoContext.js +129 -0
  189. package/dist/tools/highlight.d.ts +20 -0
  190. package/dist/tools/highlight.js +140 -0
  191. package/dist/tools/hover.d.ts +19 -0
  192. package/dist/tools/hover.js +57 -0
  193. package/dist/tools/inspect.d.ts +17 -0
  194. package/dist/tools/inspect.js +125 -0
  195. package/dist/tools/integration.test.d.ts +2 -0
  196. package/dist/tools/integration.test.js +96 -0
  197. package/dist/tools/key.d.ts +25 -0
  198. package/dist/tools/key.js +173 -0
  199. package/dist/tools/macro_compiler.d.ts +7 -0
  200. package/dist/tools/macro_compiler.js +82 -0
  201. package/dist/tools/mouse.d.ts +21 -0
  202. package/dist/tools/mouse.js +62 -0
  203. package/dist/tools/navigate.d.ts +16 -0
  204. package/dist/tools/navigate.js +188 -0
  205. package/dist/tools/network_intercept.d.ts +17 -0
  206. package/dist/tools/network_intercept.js +151 -0
  207. package/dist/tools/office/index.d.ts +9 -0
  208. package/dist/tools/office/index.js +7 -0
  209. package/dist/tools/office/list.d.ts +15 -0
  210. package/dist/tools/office/list.js +41 -0
  211. package/dist/tools/office/parse.d.ts +20 -0
  212. package/dist/tools/office/parse.js +172 -0
  213. package/dist/tools/pdf.d.ts +22 -0
  214. package/dist/tools/pdf.js +42 -0
  215. package/dist/tools/performance.d.ts +12 -0
  216. package/dist/tools/performance.js +47 -0
  217. package/dist/tools/performance_test.d.ts +70 -0
  218. package/dist/tools/performance_test.js +128 -0
  219. package/dist/tools/plan.d.ts +39 -0
  220. package/dist/tools/plan.js +161 -0
  221. package/dist/tools/pointer.d.ts +35 -0
  222. package/dist/tools/pointer.js +522 -0
  223. package/dist/tools/read.d.ts +30 -0
  224. package/dist/tools/read.js +488 -0
  225. package/dist/tools/recording.d.ts +45 -0
  226. package/dist/tools/recording.js +124 -0
  227. package/dist/tools/response.d.ts +129 -0
  228. package/dist/tools/response.js +5 -0
  229. package/dist/tools/scrape.d.ts +24 -0
  230. package/dist/tools/scrape.js +140 -0
  231. package/dist/tools/screenshot.d.ts +40 -0
  232. package/dist/tools/screenshot.js +79 -0
  233. package/dist/tools/scroll.d.ts +23 -0
  234. package/dist/tools/scroll.js +196 -0
  235. package/dist/tools/select.d.ts +13 -0
  236. package/dist/tools/select.js +217 -0
  237. package/dist/tools/snapshot.d.ts +27 -0
  238. package/dist/tools/snapshot.js +99 -0
  239. package/dist/tools/storage.d.ts +18 -0
  240. package/dist/tools/storage.js +29 -0
  241. package/dist/tools/tabs.d.ts +77 -0
  242. package/dist/tools/tabs.js +342 -0
  243. package/dist/tools/thought.d.ts +16 -0
  244. package/dist/tools/thought.js +79 -0
  245. package/dist/tools/type.d.ts +65 -0
  246. package/dist/tools/type.js +1061 -0
  247. package/dist/tools/type_secret.d.ts +23 -0
  248. package/dist/tools/type_secret.js +229 -0
  249. package/dist/tools/upload.d.ts +19 -0
  250. package/dist/tools/upload.js +103 -0
  251. package/dist/tools/video_compiler.d.ts +24 -0
  252. package/dist/tools/video_compiler.js +199 -0
  253. package/dist/tools/viewport.d.ts +44 -0
  254. package/dist/tools/viewport.js +230 -0
  255. package/dist/tools/wait.d.ts +19 -0
  256. package/dist/tools/wait.js +202 -0
  257. package/dist/tools/wait_for.d.ts +23 -0
  258. package/dist/tools/wait_for.js +30 -0
  259. package/dist/tools/windows.d.ts +22 -0
  260. package/dist/tools/windows.js +57 -0
  261. package/dist/ui/index.d.ts +1 -0
  262. package/dist/ui/index.js +12 -0
  263. package/docs/DEV_MODE.md +68 -0
  264. package/docs/DOCUMENTATION.md +532 -0
  265. package/docs/PLUGINS.md +538 -0
  266. package/docs/TOOLS.md +104 -0
  267. package/docs/dev_plugin.md +310 -0
  268. package/ext-dist/background.js +467 -0
  269. package/ext-dist/content.js +3089 -0
  270. package/ext-dist/dashboard.html +583 -0
  271. package/ext-dist/hud/hud.js +73 -0
  272. package/ext-dist/hud/index.html +20 -0
  273. package/ext-dist/manifest.json +77 -0
  274. package/ext-dist/sidepanel/sidepanel.js +25 -0
  275. package/ext-dist/sidepanel.html +547 -0
  276. package/ext-dist/styles.css +218 -0
  277. package/icon.png +0 -0
  278. package/mcp.json +796 -0
  279. package/package.json +113 -0
  280. package/server.json +23 -0
  281. package/smithery.yaml +11 -0
@@ -0,0 +1,552 @@
1
+ import { logDebug } from "../audit/logger.js";
2
+ // ─── Main dispatcher ─────────────────────────────────────────────────────────
3
+ export async function solveCaptcha(session, detection) {
4
+ const t0 = Date.now();
5
+ try {
6
+ logDebug(`[Weavetab AntiCaptcha] Solving ${detection.type} (${detection.interactionType})`);
7
+ switch (detection.interactionType) {
8
+ case "drag":
9
+ return await solveSliderDrag(session, detection, t0);
10
+ case "hold":
11
+ return await solvePressAndHold(session, detection, t0);
12
+ case "checkbox":
13
+ return await solveCheckbox(session, detection, t0);
14
+ case "none":
15
+ return await solveInvisible(session, detection, t0);
16
+ case "math":
17
+ return await solveMathCaptcha(session, detection, t0);
18
+ case "text":
19
+ return await solveTextCaptcha(session, detection, t0);
20
+ case "image_select":
21
+ return await solveImageSelect(session, detection, t0);
22
+ default:
23
+ // Unknown type — try generic approaches in order
24
+ return await solveGenericFallback(session, detection, t0);
25
+ }
26
+ }
27
+ catch (err) {
28
+ logDebug("[Weavetab AntiCaptcha] Solver threw:", err);
29
+ return {
30
+ solved: false,
31
+ method: "failed",
32
+ confidence: 0,
33
+ requiresUserIntervention: true,
34
+ userInstructions: `Automated CAPTCHA solving encountered an error. ${getHumanInstructions(detection)}`,
35
+ timeToSolve: Date.now() - t0,
36
+ };
37
+ }
38
+ }
39
+ // ─── 1. Slider / Drag CAPTCHA ────────────────────────────────────────────────
40
+ async function solveSliderDrag(session, detection, t0) {
41
+ try {
42
+ // Locate slider thumb and track
43
+ const sliderInfo = await session.Runtime.evaluate({
44
+ expression: `(function() {
45
+ // Priority selectors for slider thumb
46
+ var thumbSels = [
47
+ '.geetest_slider_button', '.geetest_drag_thumb', '.geetest-slider-btn',
48
+ '.slide-verify-slider', '[class*="slider-btn"]', '[class*="slider-thumb"]',
49
+ '[class*="drag-btn"]', '[class*="slide-btn"]', '[class*="slider_button"]',
50
+ '.nc-lang-cnt [class*="btn"]', '.btn_slide', '.handler',
51
+ '[class*="verify"][class*="btn"]',
52
+ ];
53
+ var trackSels = [
54
+ '.geetest_slider_bar', '.geetest_track', '.slide-verify-bar',
55
+ '[class*="slider-bar"]', '[class*="track"]', '[class*="slider-wrap"]',
56
+ '.nc-tpl [class*="bg"]', '[class*="verify"][class*="bar"]',
57
+ ];
58
+
59
+ var thumb = null, track = null;
60
+
61
+ // Also try the provided selector
62
+ ${detection.selector ? `thumb = document.querySelector(${JSON.stringify(detection.selector)});` : ''}
63
+
64
+ if (!thumb) {
65
+ for (var i = 0; i < thumbSels.length; i++) {
66
+ var el = document.querySelector(thumbSels[i]);
67
+ if (el && el.getBoundingClientRect().width > 0) {
68
+ thumb = el;
69
+ break;
70
+ }
71
+ }
72
+ }
73
+ for (var j = 0; j < trackSels.length; j++) {
74
+ var el2 = document.querySelector(trackSels[j]);
75
+ if (el2 && el2.getBoundingClientRect().width > 20) {
76
+ track = el2;
77
+ break;
78
+ }
79
+ }
80
+
81
+ if (!thumb) return null;
82
+ var tr = thumb.getBoundingClientRect();
83
+ var trackWidth = track ? track.getBoundingClientRect().width : window.innerWidth * 0.6;
84
+ return {
85
+ thumbX: Math.round(tr.left + tr.width / 2),
86
+ thumbY: Math.round(tr.top + tr.height / 2),
87
+ thumbWidth: Math.round(tr.width),
88
+ trackWidth: Math.round(trackWidth),
89
+ };
90
+ })()`,
91
+ returnByValue: true,
92
+ });
93
+ const info = sliderInfo.result?.value;
94
+ if (!info) {
95
+ logDebug("[Weavetab AntiCaptcha] Slider thumb not found");
96
+ return manualFallback(detection, t0, "Could not locate the slider handle.");
97
+ }
98
+ const { thumbX, thumbY, thumbWidth, trackWidth } = info;
99
+ // Target drag distance: track width minus thumb half-width minus small margin
100
+ // We don't know the exact gap position, so we attempt full-width drag
101
+ // (most slider CAPTCHAs need drag to a specific notch — we overshoot & correct)
102
+ const dragDistance = Math.round((detection.sliderTrackWidth || trackWidth) - thumbWidth - 8);
103
+ logDebug(`[Weavetab AntiCaptcha] Slider: thumb=(${thumbX},${thumbY}), drag=${dragDistance}px`);
104
+ // Human-like bezier drag sequence
105
+ await humanSliderDrag(session, thumbX, thumbY, dragDistance);
106
+ // Wait for CAPTCHA to verify
107
+ await sleep(1200);
108
+ const stillBlocking = await checkCaptchaGone(session, detection);
109
+ if (stillBlocking === false) {
110
+ return {
111
+ solved: true,
112
+ method: "automated",
113
+ confidence: 0.88,
114
+ requiresUserIntervention: false,
115
+ timeToSolve: Date.now() - t0,
116
+ };
117
+ }
118
+ // If still present, try a partial drag (maybe the gap is not at the end)
119
+ // Retry with 60% of track width
120
+ const partialDist = Math.round(dragDistance * 0.6);
121
+ await sleep(500);
122
+ await humanSliderDrag(session, thumbX, thumbY, partialDist);
123
+ await sleep(1200);
124
+ const stillBlockingRetry = await checkCaptchaGone(session, detection);
125
+ if (stillBlockingRetry === false) {
126
+ return {
127
+ solved: true,
128
+ method: "automated",
129
+ confidence: 0.78,
130
+ requiresUserIntervention: false,
131
+ timeToSolve: Date.now() - t0,
132
+ };
133
+ }
134
+ return manualFallback(detection, t0, "Slider drag attempted but CAPTCHA is still present. The puzzle piece position may require visual verification.");
135
+ }
136
+ catch (err) {
137
+ logDebug("[Weavetab AntiCaptcha] Slider drag error:", err);
138
+ return manualFallback(detection, t0);
139
+ }
140
+ }
141
+ /**
142
+ * Simulate a human-like slider drag using CDP Input events.
143
+ * Uses a multi-phase motion: slow start → fast middle → slow end with overshoot + correction.
144
+ */
145
+ async function humanSliderDrag(session, startX, startY, dragPixels) {
146
+ const { Input } = session;
147
+ const endX = startX + dragPixels;
148
+ // Phase 1: hover over thumb
149
+ await Input.dispatchMouseEvent({ type: "mouseMoved", x: startX, y: startY });
150
+ await sleep(80 + rand(40));
151
+ // Phase 2: mouse down
152
+ await Input.dispatchMouseEvent({
153
+ type: "mousePressed", x: startX, y: startY,
154
+ button: "left", clickCount: 1,
155
+ });
156
+ await sleep(60 + rand(40));
157
+ // Phase 3: Human bezier motion
158
+ // Build waypoints: slow start, accelerate, decelerate at end with slight overshoot
159
+ const totalSteps = 28 + rand(8);
160
+ const overshoot = 6 + rand(4); // pixels past target before correcting
161
+ for (let i = 1; i <= totalSteps + 2; i++) {
162
+ let t;
163
+ if (i <= totalSteps) {
164
+ // Ease-in-out + slight overshoot at end
165
+ const raw = i / totalSteps;
166
+ t = raw < 0.5
167
+ ? 2 * raw * raw
168
+ : -1 + (4 - 2 * raw) * raw;
169
+ // Add overshoot near the end
170
+ if (i === totalSteps)
171
+ t = 1 + (overshoot / dragPixels);
172
+ }
173
+ else {
174
+ // Correction back to target after overshoot
175
+ t = 1.0;
176
+ }
177
+ const cx = Math.round(startX + t * dragPixels);
178
+ const cy = startY + rand(3) - 1; // tiny vertical jitter
179
+ await Input.dispatchMouseEvent({
180
+ type: "mouseMoved", x: cx, y: cy, button: "left",
181
+ });
182
+ // Variable inter-step delay: faster in middle, slower at start/end
183
+ const stepProgress = i / totalSteps;
184
+ const delay = stepProgress < 0.2 || stepProgress > 0.85
185
+ ? 18 + rand(12)
186
+ : 8 + rand(8);
187
+ await sleep(delay);
188
+ }
189
+ // Final position
190
+ await Input.dispatchMouseEvent({
191
+ type: "mouseMoved", x: endX, y: startY, button: "left",
192
+ });
193
+ await sleep(80 + rand(40));
194
+ // Phase 4: mouse up
195
+ await Input.dispatchMouseEvent({
196
+ type: "mouseReleased", x: endX, y: startY,
197
+ button: "left", clickCount: 1,
198
+ });
199
+ }
200
+ // ─── 2. Press-and-Hold CAPTCHA ───────────────────────────────────────────────
201
+ async function solvePressAndHold(session, detection, t0) {
202
+ try {
203
+ const holdMs = detection.holdDurationMs || 2500;
204
+ // Locate the hold button
205
+ const btnInfo = await session.Runtime.evaluate({
206
+ expression: `(function() {
207
+ var sels = [
208
+ ${detection.selector ? JSON.stringify(detection.selector) + ',' : ''}
209
+ '#px-captcha', '._pxCaptcha',
210
+ '[class*="press-hold"]', '[class*="hold-btn"]', '[class*="presshold"]',
211
+ 'button[class*="verify"]',
212
+ ];
213
+ for (var i = 0; i < sels.length; i++) {
214
+ var el = document.querySelector(sels[i]);
215
+ if (el) {
216
+ var r = el.getBoundingClientRect();
217
+ if (r.width > 0 && r.height > 0) {
218
+ return { x: Math.round(r.left + r.width/2), y: Math.round(r.top + r.height/2) };
219
+ }
220
+ }
221
+ }
222
+ // Last resort: find any visible button with "hold" in text
223
+ var btns = document.querySelectorAll('button, [role="button"]');
224
+ for (var j = 0; j < btns.length; j++) {
225
+ if (/hold|press/i.test(btns[j].textContent || '')) {
226
+ var br = btns[j].getBoundingClientRect();
227
+ if (br.width > 0) return { x: Math.round(br.left+br.width/2), y: Math.round(br.top+br.height/2) };
228
+ }
229
+ }
230
+ return null;
231
+ })()`,
232
+ returnByValue: true,
233
+ });
234
+ const btn = btnInfo.result?.value;
235
+ if (!btn) {
236
+ return manualFallback(detection, t0, "Could not locate the press-and-hold button.");
237
+ }
238
+ logDebug(`[Weavetab AntiCaptcha] Hold button at (${btn.x},${btn.y}), hold=${holdMs}ms`);
239
+ const { Input } = session;
240
+ // Move to button
241
+ await Input.dispatchMouseEvent({ type: "mouseMoved", x: btn.x, y: btn.y });
242
+ await sleep(120 + rand(60));
243
+ // Press down
244
+ await Input.dispatchMouseEvent({
245
+ type: "mousePressed", x: btn.x, y: btn.y,
246
+ button: "left", clickCount: 1,
247
+ });
248
+ // Hold with micro-jitter to simulate real human pressure
249
+ const jitterInterval = 80 + rand(40);
250
+ const jitterSteps = Math.floor(holdMs / jitterInterval);
251
+ for (let i = 0; i < jitterSteps; i++) {
252
+ const jx = btn.x + (rand(3) - 1);
253
+ const jy = btn.y + (rand(3) - 1);
254
+ await Input.dispatchMouseEvent({ type: "mouseMoved", x: jx, y: jy, button: "left" });
255
+ await sleep(jitterInterval);
256
+ }
257
+ // Release
258
+ await Input.dispatchMouseEvent({
259
+ type: "mouseReleased", x: btn.x, y: btn.y,
260
+ button: "left", clickCount: 1,
261
+ });
262
+ await sleep(1000);
263
+ const stillBlocking = await checkCaptchaGone(session, detection);
264
+ if (stillBlocking === false) {
265
+ return {
266
+ solved: true,
267
+ method: "automated",
268
+ confidence: 0.88,
269
+ requiresUserIntervention: false,
270
+ timeToSolve: Date.now() - t0,
271
+ };
272
+ }
273
+ // PerimeterX sometimes needs a longer hold — retry with 2x duration
274
+ logDebug("[Weavetab AntiCaptcha] Hold captcha still present, retrying with longer hold");
275
+ await sleep(500);
276
+ await Input.dispatchMouseEvent({ type: "mousePressed", x: btn.x, y: btn.y, button: "left", clickCount: 1 });
277
+ await sleep(holdMs * 2 + rand(500));
278
+ await Input.dispatchMouseEvent({ type: "mouseReleased", x: btn.x, y: btn.y, button: "left", clickCount: 1 });
279
+ await sleep(1200);
280
+ const final = await checkCaptchaGone(session, detection);
281
+ if (final === false) {
282
+ return { solved: true, method: "automated", confidence: 0.75, requiresUserIntervention: false, timeToSolve: Date.now() - t0 };
283
+ }
284
+ return manualFallback(detection, t0, "Press-and-hold executed but CAPTCHA did not dismiss. Try holding the button manually for 3-5 seconds.");
285
+ }
286
+ catch (err) {
287
+ logDebug("[Weavetab AntiCaptcha] Hold error:", err);
288
+ return manualFallback(detection, t0);
289
+ }
290
+ }
291
+ // ─── 3. Checkbox CAPTCHA (reCAPTCHA v2 simple, hCaptcha simple) ─────────────
292
+ async function solveCheckbox(session, detection, t0) {
293
+ try {
294
+ // Find the iframe and click the checkbox inside it via coordinates
295
+ const frameInfo = await session.Runtime.evaluate({
296
+ expression: `(function() {
297
+ var frames = document.querySelectorAll('iframe[src*="recaptcha"], iframe[src*="hcaptcha"]');
298
+ for (var i = 0; i < frames.length; i++) {
299
+ var r = frames[i].getBoundingClientRect();
300
+ if (r.width > 0 && r.height > 0) {
301
+ // Checkbox is typically at 20px from left, center vertically
302
+ return { x: Math.round(r.left + 20), y: Math.round(r.top + r.height/2) };
303
+ }
304
+ }
305
+ return null;
306
+ })()`,
307
+ returnByValue: true,
308
+ });
309
+ const coords = frameInfo.result?.value;
310
+ if (!coords) {
311
+ return manualFallback(detection, t0, "Could not locate the CAPTCHA checkbox iframe.");
312
+ }
313
+ const { Input } = session;
314
+ await Input.dispatchMouseEvent({ type: "mouseMoved", x: coords.x, y: coords.y });
315
+ await sleep(150 + rand(100));
316
+ await Input.dispatchMouseEvent({ type: "mousePressed", x: coords.x, y: coords.y, button: "left", clickCount: 1 });
317
+ await sleep(80 + rand(40));
318
+ await Input.dispatchMouseEvent({ type: "mouseReleased", x: coords.x, y: coords.y, button: "left", clickCount: 1 });
319
+ // Wait for the CAPTCHA to either solve (simple) or present a challenge
320
+ await sleep(2000);
321
+ // Check if a challenge appeared (image grid)
322
+ const challengeAppeared = await session.Runtime.evaluate({
323
+ expression: `!!document.querySelector('iframe[src*="bframe"], iframe[src*="challenge"]')`,
324
+ returnByValue: true,
325
+ });
326
+ if (challengeAppeared.result?.value === true) {
327
+ // A visual challenge appeared — this requires image selection, escalate to AI agent
328
+ return {
329
+ solved: false,
330
+ method: "vision_assisted",
331
+ confidence: 0.5,
332
+ requiresUserIntervention: true,
333
+ userInstructions: "reCAPTCHA / hCaptcha image challenge appeared. Please take a screenshot, use browser_click to select the matching images, and click Verify.",
334
+ timeToSolve: Date.now() - t0,
335
+ };
336
+ }
337
+ const stillBlocking = await checkCaptchaGone(session, detection);
338
+ if (stillBlocking === false) {
339
+ return { solved: true, method: "automated", confidence: 0.9, requiresUserIntervention: false, timeToSolve: Date.now() - t0 };
340
+ }
341
+ return manualFallback(detection, t0, "Clicked the CAPTCHA checkbox but it did not verify. A visual challenge may be required — please complete it manually.");
342
+ }
343
+ catch (err) {
344
+ logDebug("[Weavetab AntiCaptcha] Checkbox error:", err);
345
+ return manualFallback(detection, t0);
346
+ }
347
+ }
348
+ // ─── 4. Invisible CAPTCHA (reCAPTCHA v3, Turnstile) ─────────────────────────
349
+ async function solveInvisible(session, detection, t0) {
350
+ try {
351
+ // Invisible CAPTCHAs score based on user interaction signals.
352
+ // Simulate natural page interaction to boost the score.
353
+ await session.Runtime.evaluate({
354
+ expression: `(function() {
355
+ // Scroll slightly to simulate reading
356
+ window.scrollBy({ top: 120, behavior: 'smooth' });
357
+ // Move mouse (won't dispatch but registers user-intent in page context)
358
+ document.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: 400, clientY: 300 }));
359
+ // Trigger focus/blur cycle on any form input
360
+ var inputs = document.querySelectorAll('input:not([type="hidden"]), textarea');
361
+ if (inputs.length > 0) {
362
+ inputs[0].focus();
363
+ setTimeout(function() { inputs[0].blur(); }, 200);
364
+ }
365
+ })()`,
366
+ returnByValue: false,
367
+ });
368
+ await sleep(1500);
369
+ // Try to programmatically trigger grecaptcha execute (v3)
370
+ if (detection.type === "recaptcha_v3") {
371
+ await session.Runtime.evaluate({
372
+ expression: `(function() {
373
+ try {
374
+ if (window.grecaptcha && window.grecaptcha.execute) {
375
+ window.grecaptcha.ready(function() {
376
+ window.grecaptcha.execute().catch(function(){});
377
+ });
378
+ }
379
+ } catch(e) {}
380
+ })()`,
381
+ returnByValue: false,
382
+ });
383
+ }
384
+ // Turnstile: just wait, it auto-verifies with good browser signals
385
+ await sleep(2000);
386
+ return {
387
+ solved: true,
388
+ method: "automated",
389
+ confidence: 0.7,
390
+ requiresUserIntervention: false,
391
+ userInstructions: "Invisible CAPTCHA — interaction signals sent. If the form still fails, wait 2-3 more seconds.",
392
+ timeToSolve: Date.now() - t0,
393
+ };
394
+ }
395
+ catch (err) {
396
+ return manualFallback(detection, t0, "Invisible CAPTCHA interaction failed. Wait 2-3 seconds and retry the form submission.");
397
+ }
398
+ }
399
+ // ─── 5. Math CAPTCHA ─────────────────────────────────────────────────────────
400
+ async function solveMathCaptcha(session, detection, t0) {
401
+ try {
402
+ const result = await session.Runtime.evaluate({
403
+ expression: `(function(sel) {
404
+ var container = document.querySelector(sel) || document.body;
405
+ var text = container.textContent || '';
406
+ // Match expressions like "3 + 7 =", "12 - 4 =", "6 × 3", "8 ÷ 2"
407
+ var m = text.match(/(\\d+)\\s*([+\\-*×x÷/])\\s*(\\d+)/);
408
+ if (!m) return null;
409
+ var a = parseInt(m[1]), op = m[2], b = parseInt(m[3]);
410
+ var ans;
411
+ if (op === '+') ans = a + b;
412
+ else if (op === '-') ans = a - b;
413
+ else if (op === '*' || op === '×' || op === 'x') ans = a * b;
414
+ else if (op === '/' || op === '÷') ans = Math.floor(a / b);
415
+ else return null;
416
+ // Fill the answer input
417
+ var inp = container.querySelector('input[type="text"], input[type="number"]');
418
+ if (!inp) inp = document.querySelector('input[name*="captcha"], input[id*="captcha"]');
419
+ if (inp) {
420
+ inp.focus();
421
+ var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value')?.set;
422
+ if (nativeInputValueSetter) nativeInputValueSetter.call(inp, String(ans));
423
+ inp.dispatchEvent(new Event('input', { bubbles: true }));
424
+ inp.dispatchEvent(new Event('change', { bubbles: true }));
425
+ return { solved: true, answer: ans };
426
+ }
427
+ return { solved: false, answer: ans };
428
+ })(${JSON.stringify(detection.selector || 'body')})`,
429
+ returnByValue: true,
430
+ });
431
+ const val = result.result?.value;
432
+ if (val?.solved) {
433
+ return { solved: true, method: "automated", confidence: 0.95, requiresUserIntervention: false, solution: String(val.answer), timeToSolve: Date.now() - t0 };
434
+ }
435
+ return manualFallback(detection, t0, val ? `Math answer is ${val.answer} — please type it in the CAPTCHA field.` : "Could not parse the math CAPTCHA expression.");
436
+ }
437
+ catch {
438
+ return manualFallback(detection, t0);
439
+ }
440
+ }
441
+ // ─── 6. Text CAPTCHA (OCR-free best-effort) ──────────────────────────────────
442
+ async function solveTextCaptcha(session, detection, t0) {
443
+ // No OCR API — we can't read distorted images automatically.
444
+ // Delegate to the AI agent to use its vision capabilities.
445
+ return {
446
+ solved: false,
447
+ method: "vision_assisted",
448
+ confidence: 0,
449
+ requiresUserIntervention: true,
450
+ userInstructions: "Text CAPTCHA detected. Please take a screenshot to read the distorted characters, and use browser_type to enter them into the input field.",
451
+ timeToSolve: Date.now() - t0,
452
+ };
453
+ }
454
+ // ─── 7. Image Select CAPTCHA ─────────────────────────────────────────────────
455
+ async function solveImageSelect(session, detection, t0) {
456
+ // Without a vision API, we can't reliably identify the correct images.
457
+ // Delegate to the AI agent to use its vision capabilities.
458
+ const instructions = detection.type === "recaptcha_v2"
459
+ ? "reCAPTCHA image challenge: Take a screenshot, identify the requested category, and use browser_click to select the matching images, then click Verify."
460
+ : detection.type === "hcaptcha"
461
+ ? "hCaptcha challenge: Take a screenshot, look at the visual puzzle, use browser_click to select the correct images, and click Verify."
462
+ : "Image selection CAPTCHA: Take a screenshot and use browser_click to select all images that match the description shown.";
463
+ return {
464
+ solved: false,
465
+ method: "vision_assisted",
466
+ confidence: 0,
467
+ requiresUserIntervention: true,
468
+ userInstructions: instructions,
469
+ timeToSolve: Date.now() - t0,
470
+ };
471
+ }
472
+ // ─── 8. Generic fallback ─────────────────────────────────────────────────────
473
+ async function solveGenericFallback(session, detection, t0) {
474
+ // Try slider first (most common interactive CAPTCHA)
475
+ if (detection.selector) {
476
+ const sliderAttempt = await solveSliderDrag(session, { ...detection, interactionType: "drag" }, t0);
477
+ if (sliderAttempt.solved)
478
+ return sliderAttempt;
479
+ }
480
+ // Try checkbox
481
+ const cbAttempt = await solveCheckbox(session, detection, t0);
482
+ if (cbAttempt.solved)
483
+ return cbAttempt;
484
+ return manualFallback(detection, t0);
485
+ }
486
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
487
+ /**
488
+ * Returns true if the CAPTCHA is STILL present, false if it's gone (= solved).
489
+ * null = undetermined.
490
+ */
491
+ async function checkCaptchaGone(session, detection) {
492
+ try {
493
+ if (!detection.selector)
494
+ return null;
495
+ const check = await session.Runtime.evaluate({
496
+ expression: `(function(sel) {
497
+ var el = document.querySelector(sel);
498
+ if (!el) return false; // gone = solved
499
+ var r = el.getBoundingClientRect();
500
+ return r.width > 0 && r.height > 0 && r.top < window.innerHeight;
501
+ })(${JSON.stringify(detection.selector)})`,
502
+ returnByValue: true,
503
+ });
504
+ return check.result?.value;
505
+ }
506
+ catch {
507
+ return null;
508
+ }
509
+ }
510
+ function manualFallback(detection, t0, customMsg) {
511
+ return {
512
+ solved: false,
513
+ method: "manual_guidance",
514
+ confidence: 0,
515
+ requiresUserIntervention: true,
516
+ userInstructions: customMsg || getHumanInstructions(detection),
517
+ timeToSolve: Date.now() - t0,
518
+ };
519
+ }
520
+ function getHumanInstructions(detection) {
521
+ switch (detection.type) {
522
+ case "recaptcha_v2":
523
+ return "Click the 'I'm not a robot' checkbox. If images appear, select all matching ones and click Verify.";
524
+ case "recaptcha_v3":
525
+ return "Invisible CAPTCHA — wait 2-3 seconds and retry. If it fails again, interact with the page first (scroll, move mouse).";
526
+ case "hcaptcha":
527
+ return "Click the hCaptcha checkbox. If a visual challenge appears, complete it by clicking the matching images.";
528
+ case "turnstile":
529
+ return "Cloudflare Turnstile detected. Wait a few seconds for automatic verification.";
530
+ case "geetest":
531
+ case "geetest_v4":
532
+ return "GeeTest CAPTCHA: Drag the slider to the right until the puzzle piece fits into the gap.";
533
+ case "funcaptcha":
534
+ return "FunCaptcha: Rotate the image shown until it matches the correct orientation, then click Next.";
535
+ case "slider":
536
+ return "Drag the slider all the way to the right to verify.";
537
+ case "press_and_hold":
538
+ return "Press and hold the verification button for 2-3 seconds until it completes.";
539
+ case "datadome":
540
+ return "DataDome CAPTCHA: Drag the slider to complete the verification.";
541
+ case "perimeter_x":
542
+ return "PerimeterX CAPTCHA: Press and hold the button for 3 seconds.";
543
+ default:
544
+ return "CAPTCHA detected. Please complete the challenge shown on screen to continue.";
545
+ }
546
+ }
547
+ function sleep(ms) {
548
+ return new Promise((r) => setTimeout(r, ms));
549
+ }
550
+ function rand(max) {
551
+ return Math.floor(Math.random() * max);
552
+ }
@@ -0,0 +1,13 @@
1
+ export interface AuditEntry {
2
+ timestamp: string;
3
+ sessionId?: string;
4
+ tool: string;
5
+ parameters?: Record<string, unknown>;
6
+ duration?: number;
7
+ result: string;
8
+ pageUrl?: string;
9
+ tabTitle?: string;
10
+ }
11
+ export declare function logAction(action: string, target: string, result: string): void;
12
+ export declare function logActionStructured(entry: AuditEntry): void;
13
+ export declare function logDebug(message: string | any, ...optionalParams: any[]): void;