aurix-ai 2.7.3 → 2.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/bin/aurix.js +2 -2
  2. package/dist/agent/AgentLoop.d.ts.map +1 -1
  3. package/dist/agent/AgentLoop.js +1 -52
  4. package/dist/agent/AgentLoop.js.map +1 -1
  5. package/dist/cli/App.d.ts.map +1 -1
  6. package/dist/cli/App.js +6 -0
  7. package/dist/cli/App.js.map +1 -1
  8. package/dist/cli/commands.d.ts.map +1 -1
  9. package/dist/cli/commands.js +7 -0
  10. package/dist/cli/commands.js.map +1 -1
  11. package/dist/tools/Browser.d.ts.map +1 -1
  12. package/dist/tools/Browser.js +44 -615
  13. package/dist/tools/Browser.js.map +1 -1
  14. package/dist/tools/captcha/CaptchaRouter.d.ts +6 -0
  15. package/dist/tools/captcha/CaptchaRouter.d.ts.map +1 -0
  16. package/dist/tools/captcha/CaptchaRouter.js +371 -0
  17. package/dist/tools/captcha/CaptchaRouter.js.map +1 -0
  18. package/dist/tools/captcha/RecaptchaSolver.d.ts +2 -0
  19. package/dist/tools/captcha/RecaptchaSolver.d.ts.map +1 -0
  20. package/dist/tools/captcha/RecaptchaSolver.js +1114 -0
  21. package/dist/tools/captcha/RecaptchaSolver.js.map +1 -0
  22. package/dist/tools/captcha/common.d.ts +35 -0
  23. package/dist/tools/captcha/common.d.ts.map +1 -0
  24. package/dist/tools/captcha/common.js +445 -0
  25. package/dist/tools/captcha/common.js.map +1 -0
  26. package/dist/tools/captcha/index.d.ts +5 -0
  27. package/dist/tools/captcha/index.d.ts.map +1 -0
  28. package/dist/tools/captcha/index.js +4 -0
  29. package/dist/tools/captcha/index.js.map +1 -0
  30. package/package.json +2 -2
  31. package/scripts/build.cjs +0 -15
  32. package/scripts/run-task.mjs +86 -0
  33. package/training/captcha-training.json +930 -0
  34. package/native/token-counter/index.d.ts +0 -7
  35. package/native/token-counter/index.js +0 -316
  36. package/native/token-counter/node_modules/.package-lock.json +0 -568
  37. package/native/token-counter/node_modules/2/array.js +0 -25
  38. package/native/token-counter/node_modules/2/index.js +0 -12
  39. package/native/token-counter/node_modules/2/iterator.js +0 -13
  40. package/native/token-counter/node_modules/2/license.txt +0 -21
  41. package/native/token-counter/node_modules/2/map.js +0 -27
  42. package/native/token-counter/node_modules/2/number.js +0 -109
  43. package/native/token-counter/node_modules/2/object.js +0 -23
  44. package/native/token-counter/node_modules/2/package.json +0 -60
  45. package/native/token-counter/node_modules/2/readme.md +0 -246
  46. package/native/token-counter/node_modules/2/string.js +0 -11
  47. package/native/token-counter/node_modules/2/test.js +0 -520
  48. package/native/token-counter/node_modules/@lamansky/every/index.js +0 -16
  49. package/native/token-counter/node_modules/@lamansky/every/license.txt +0 -21
  50. package/native/token-counter/node_modules/@lamansky/every/package.json +0 -38
  51. package/native/token-counter/node_modules/@lamansky/every/readme.md +0 -46
  52. package/native/token-counter/node_modules/@lamansky/flatten/index.js +0 -5
  53. package/native/token-counter/node_modules/@lamansky/flatten/license.txt +0 -21
  54. package/native/token-counter/node_modules/@lamansky/flatten/package.json +0 -35
  55. package/native/token-counter/node_modules/@lamansky/flatten/readme.md +0 -41
  56. package/native/token-counter/node_modules/@napi-rs/cli/LICENSE +0 -21
  57. package/native/token-counter/node_modules/@napi-rs/cli/README.md +0 -96
  58. package/native/token-counter/node_modules/@napi-rs/cli/package.json +0 -65
  59. package/native/token-counter/node_modules/@napi-rs/cli/scripts/index.js +0 -51371
  60. package/native/token-counter/node_modules/add-counter/index.js +0 -3
  61. package/native/token-counter/node_modules/add-counter/license.txt +0 -21
  62. package/native/token-counter/node_modules/add-counter/package.json +0 -34
  63. package/native/token-counter/node_modules/add-counter/readme.md +0 -36
  64. package/native/token-counter/node_modules/array-pad/LICENSE +0 -22
  65. package/native/token-counter/node_modules/array-pad/README.md +0 -80
  66. package/native/token-counter/node_modules/array-pad/index.js +0 -30
  67. package/native/token-counter/node_modules/array-pad/package.json +0 -28
  68. package/native/token-counter/node_modules/arrify/index.js +0 -8
  69. package/native/token-counter/node_modules/arrify/license +0 -21
  70. package/native/token-counter/node_modules/arrify/package.json +0 -33
  71. package/native/token-counter/node_modules/arrify/readme.md +0 -36
  72. package/native/token-counter/node_modules/case-insensitive/index.js +0 -72
  73. package/native/token-counter/node_modules/case-insensitive/license.txt +0 -21
  74. package/native/token-counter/node_modules/case-insensitive/package.json +0 -39
  75. package/native/token-counter/node_modules/case-insensitive/readme.md +0 -39
  76. package/native/token-counter/node_modules/case-insensitive/test.js +0 -114
  77. package/native/token-counter/node_modules/class-chain/index.js +0 -32
  78. package/native/token-counter/node_modules/class-chain/license.txt +0 -21
  79. package/native/token-counter/node_modules/class-chain/package.json +0 -39
  80. package/native/token-counter/node_modules/class-chain/readme.md +0 -23
  81. package/native/token-counter/node_modules/class-chain/test.js +0 -77
  82. package/native/token-counter/node_modules/copy-own/index.js +0 -10
  83. package/native/token-counter/node_modules/copy-own/license.txt +0 -21
  84. package/native/token-counter/node_modules/copy-own/package.json +0 -37
  85. package/native/token-counter/node_modules/copy-own/readme.md +0 -67
  86. package/native/token-counter/node_modules/def-props/index.js +0 -43
  87. package/native/token-counter/node_modules/def-props/license.txt +0 -21
  88. package/native/token-counter/node_modules/def-props/node_modules/is-obj/index.d.ts +0 -22
  89. package/native/token-counter/node_modules/def-props/node_modules/is-obj/index.js +0 -6
  90. package/native/token-counter/node_modules/def-props/node_modules/is-obj/license +0 -9
  91. package/native/token-counter/node_modules/def-props/node_modules/is-obj/package.json +0 -34
  92. package/native/token-counter/node_modules/def-props/node_modules/is-obj/readme.md +0 -39
  93. package/native/token-counter/node_modules/def-props/package.json +0 -51
  94. package/native/token-counter/node_modules/def-props/readme.md +0 -117
  95. package/native/token-counter/node_modules/empty-iterator/index.js +0 -3
  96. package/native/token-counter/node_modules/empty-iterator/license.txt +0 -21
  97. package/native/token-counter/node_modules/empty-iterator/package.json +0 -33
  98. package/native/token-counter/node_modules/empty-iterator/readme.md +0 -23
  99. package/native/token-counter/node_modules/enforce-range/index.js +0 -15
  100. package/native/token-counter/node_modules/enforce-range/license.txt +0 -21
  101. package/native/token-counter/node_modules/enforce-range/node_modules/2/array.js +0 -43
  102. package/native/token-counter/node_modules/enforce-range/node_modules/2/index.js +0 -10
  103. package/native/token-counter/node_modules/enforce-range/node_modules/2/iterator.js +0 -26
  104. package/native/token-counter/node_modules/enforce-range/node_modules/2/license.txt +0 -21
  105. package/native/token-counter/node_modules/enforce-range/node_modules/2/map.js +0 -47
  106. package/native/token-counter/node_modules/enforce-range/node_modules/2/number.js +0 -33
  107. package/native/token-counter/node_modules/enforce-range/node_modules/2/object.js +0 -61
  108. package/native/token-counter/node_modules/enforce-range/node_modules/2/package.json +0 -41
  109. package/native/token-counter/node_modules/enforce-range/node_modules/2/readme.md +0 -210
  110. package/native/token-counter/node_modules/enforce-range/node_modules/2/string.js +0 -37
  111. package/native/token-counter/node_modules/enforce-range/node_modules/2/test.js +0 -413
  112. package/native/token-counter/node_modules/enforce-range/package.json +0 -36
  113. package/native/token-counter/node_modules/enforce-range/readme.md +0 -53
  114. package/native/token-counter/node_modules/english-list/.travis.yml +0 -6
  115. package/native/token-counter/node_modules/english-list/LICENSE +0 -22
  116. package/native/token-counter/node_modules/english-list/README.md +0 -44
  117. package/native/token-counter/node_modules/english-list/index.js +0 -34
  118. package/native/token-counter/node_modules/english-list/package.json +0 -31
  119. package/native/token-counter/node_modules/english-list/test.log +0 -6
  120. package/native/token-counter/node_modules/errate/index.js +0 -19
  121. package/native/token-counter/node_modules/errate/license.txt +0 -21
  122. package/native/token-counter/node_modules/errate/package.json +0 -39
  123. package/native/token-counter/node_modules/errate/readme.md +0 -79
  124. package/native/token-counter/node_modules/ffn/index.js +0 -9
  125. package/native/token-counter/node_modules/ffn/license.txt +0 -21
  126. package/native/token-counter/node_modules/ffn/package.json +0 -34
  127. package/native/token-counter/node_modules/ffn/readme.md +0 -51
  128. package/native/token-counter/node_modules/get-own-property/index.js +0 -5
  129. package/native/token-counter/node_modules/get-own-property/license.txt +0 -21
  130. package/native/token-counter/node_modules/get-own-property/package.json +0 -31
  131. package/native/token-counter/node_modules/get-own-property/readme.md +0 -22
  132. package/native/token-counter/node_modules/has-duplicates/index.js +0 -11
  133. package/native/token-counter/node_modules/has-duplicates/license.txt +0 -21
  134. package/native/token-counter/node_modules/has-duplicates/package.json +0 -32
  135. package/native/token-counter/node_modules/has-duplicates/readme.md +0 -23
  136. package/native/token-counter/node_modules/has-duplicates/test.js +0 -30
  137. package/native/token-counter/node_modules/if-else-throw/index.js +0 -8
  138. package/native/token-counter/node_modules/if-else-throw/license.txt +0 -21
  139. package/native/token-counter/node_modules/if-else-throw/package.json +0 -37
  140. package/native/token-counter/node_modules/if-else-throw/readme.md +0 -32
  141. package/native/token-counter/node_modules/is-array-of-length/index.js +0 -7
  142. package/native/token-counter/node_modules/is-array-of-length/license.txt +0 -21
  143. package/native/token-counter/node_modules/is-array-of-length/package.json +0 -42
  144. package/native/token-counter/node_modules/is-array-of-length/readme.md +0 -41
  145. package/native/token-counter/node_modules/is-class-of/index.js +0 -7
  146. package/native/token-counter/node_modules/is-class-of/license.txt +0 -21
  147. package/native/token-counter/node_modules/is-class-of/package.json +0 -35
  148. package/native/token-counter/node_modules/is-class-of/readme.md +0 -57
  149. package/native/token-counter/node_modules/is-global-object/index.js +0 -6
  150. package/native/token-counter/node_modules/is-global-object/license.txt +0 -21
  151. package/native/token-counter/node_modules/is-global-object/package.json +0 -34
  152. package/native/token-counter/node_modules/is-global-object/readme.md +0 -22
  153. package/native/token-counter/node_modules/is-instance-of/index.js +0 -28
  154. package/native/token-counter/node_modules/is-instance-of/license.txt +0 -21
  155. package/native/token-counter/node_modules/is-instance-of/package.json +0 -44
  156. package/native/token-counter/node_modules/is-instance-of/readme.md +0 -55
  157. package/native/token-counter/node_modules/is-iterable/index.js +0 -5
  158. package/native/token-counter/node_modules/is-iterable/license +0 -21
  159. package/native/token-counter/node_modules/is-iterable/package.json +0 -30
  160. package/native/token-counter/node_modules/is-iterable/readme.md +0 -23
  161. package/native/token-counter/node_modules/is-nil/LICENSE +0 -21
  162. package/native/token-counter/node_modules/is-nil/README.md +0 -47
  163. package/native/token-counter/node_modules/is-nil/index.js +0 -6
  164. package/native/token-counter/node_modules/is-nil/package.json +0 -46
  165. package/native/token-counter/node_modules/is-obj/index.js +0 -5
  166. package/native/token-counter/node_modules/is-obj/license +0 -21
  167. package/native/token-counter/node_modules/is-obj/package.json +0 -33
  168. package/native/token-counter/node_modules/is-obj/readme.md +0 -34
  169. package/native/token-counter/node_modules/is-object/.eslintignore +0 -1
  170. package/native/token-counter/node_modules/is-object/.eslintrc +0 -5
  171. package/native/token-counter/node_modules/is-object/.nycrc +0 -13
  172. package/native/token-counter/node_modules/is-object/.testem.json +0 -14
  173. package/native/token-counter/node_modules/is-object/CHANGELOG.md +0 -121
  174. package/native/token-counter/node_modules/is-object/LICENSE +0 -19
  175. package/native/token-counter/node_modules/is-object/README.md +0 -48
  176. package/native/token-counter/node_modules/is-object/index.js +0 -5
  177. package/native/token-counter/node_modules/is-object/package.json +0 -78
  178. package/native/token-counter/node_modules/is-object/test/index.js +0 -44
  179. package/native/token-counter/node_modules/is-plain-object/LICENSE +0 -21
  180. package/native/token-counter/node_modules/is-plain-object/README.md +0 -104
  181. package/native/token-counter/node_modules/is-plain-object/index.d.ts +0 -5
  182. package/native/token-counter/node_modules/is-plain-object/index.js +0 -37
  183. package/native/token-counter/node_modules/is-plain-object/package.json +0 -79
  184. package/native/token-counter/node_modules/isobject/LICENSE +0 -21
  185. package/native/token-counter/node_modules/isobject/README.md +0 -122
  186. package/native/token-counter/node_modules/isobject/index.d.ts +0 -5
  187. package/native/token-counter/node_modules/isobject/index.js +0 -12
  188. package/native/token-counter/node_modules/isobject/package.json +0 -74
  189. package/native/token-counter/node_modules/lodash.set/LICENSE +0 -47
  190. package/native/token-counter/node_modules/lodash.set/README.md +0 -18
  191. package/native/token-counter/node_modules/lodash.set/index.js +0 -990
  192. package/native/token-counter/node_modules/lodash.set/package.json +0 -17
  193. package/native/token-counter/node_modules/longest-first/index.js +0 -3
  194. package/native/token-counter/node_modules/longest-first/license.txt +0 -21
  195. package/native/token-counter/node_modules/longest-first/package.json +0 -36
  196. package/native/token-counter/node_modules/longest-first/readme.md +0 -29
  197. package/native/token-counter/node_modules/m-o/index.js +0 -27
  198. package/native/token-counter/node_modules/m-o/license.txt +0 -21
  199. package/native/token-counter/node_modules/m-o/node_modules/new-object/index.js +0 -23
  200. package/native/token-counter/node_modules/m-o/node_modules/new-object/license.txt +0 -21
  201. package/native/token-counter/node_modules/m-o/node_modules/new-object/package.json +0 -40
  202. package/native/token-counter/node_modules/m-o/node_modules/new-object/readme.md +0 -55
  203. package/native/token-counter/node_modules/m-o/package.json +0 -45
  204. package/native/token-counter/node_modules/m-o/readme.md +0 -87
  205. package/native/token-counter/node_modules/map-iter/index.js +0 -6
  206. package/native/token-counter/node_modules/map-iter/license.txt +0 -21
  207. package/native/token-counter/node_modules/map-iter/package.json +0 -40
  208. package/native/token-counter/node_modules/map-iter/readme.md +0 -46
  209. package/native/token-counter/node_modules/new-object/index.js +0 -5
  210. package/native/token-counter/node_modules/new-object/license.txt +0 -21
  211. package/native/token-counter/node_modules/new-object/package.json +0 -49
  212. package/native/token-counter/node_modules/new-object/readme.md +0 -145
  213. package/native/token-counter/node_modules/ofn/index.js +0 -22
  214. package/native/token-counter/node_modules/ofn/license.txt +0 -21
  215. package/native/token-counter/node_modules/ofn/package.json +0 -40
  216. package/native/token-counter/node_modules/ofn/readme.md +0 -63
  217. package/native/token-counter/node_modules/otherwise/index.js +0 -11
  218. package/native/token-counter/node_modules/otherwise/license.txt +0 -21
  219. package/native/token-counter/node_modules/otherwise/package.json +0 -38
  220. package/native/token-counter/node_modules/otherwise/readme.md +0 -29
  221. package/native/token-counter/node_modules/parser-factory/index.js +0 -138
  222. package/native/token-counter/node_modules/parser-factory/license.txt +0 -21
  223. package/native/token-counter/node_modules/parser-factory/node_modules/arrify/index.d.ts +0 -38
  224. package/native/token-counter/node_modules/parser-factory/node_modules/arrify/index.js +0 -23
  225. package/native/token-counter/node_modules/parser-factory/node_modules/arrify/license +0 -9
  226. package/native/token-counter/node_modules/parser-factory/node_modules/arrify/package.json +0 -35
  227. package/native/token-counter/node_modules/parser-factory/node_modules/arrify/readme.md +0 -39
  228. package/native/token-counter/node_modules/parser-factory/package.json +0 -38
  229. package/native/token-counter/node_modules/parser-factory/readme.md +0 -15
  230. package/native/token-counter/node_modules/pfn/index.js +0 -5
  231. package/native/token-counter/node_modules/pfn/license.txt +0 -21
  232. package/native/token-counter/node_modules/pfn/package.json +0 -41
  233. package/native/token-counter/node_modules/pfn/readme.md +0 -111
  234. package/native/token-counter/node_modules/pfn/strict.js +0 -8
  235. package/native/token-counter/node_modules/plainify/index.js +0 -5
  236. package/native/token-counter/node_modules/plainify/license.txt +0 -21
  237. package/native/token-counter/node_modules/plainify/package.json +0 -36
  238. package/native/token-counter/node_modules/plainify/readme.md +0 -47
  239. package/native/token-counter/node_modules/possible-function/changelog.md +0 -7
  240. package/native/token-counter/node_modules/possible-function/index.js +0 -43
  241. package/native/token-counter/node_modules/possible-function/license.txt +0 -21
  242. package/native/token-counter/node_modules/possible-function/package.json +0 -34
  243. package/native/token-counter/node_modules/possible-function/readme.md +0 -77
  244. package/native/token-counter/node_modules/possible-function/test.js +0 -32
  245. package/native/token-counter/node_modules/qfn/index.js +0 -11
  246. package/native/token-counter/node_modules/qfn/license.txt +0 -21
  247. package/native/token-counter/node_modules/qfn/package.json +0 -40
  248. package/native/token-counter/node_modules/qfn/readme.md +0 -45
  249. package/native/token-counter/node_modules/roadblock/index.js +0 -3
  250. package/native/token-counter/node_modules/roadblock/license.txt +0 -21
  251. package/native/token-counter/node_modules/roadblock/package.json +0 -40
  252. package/native/token-counter/node_modules/roadblock/readme.md +0 -59
  253. package/native/token-counter/node_modules/round-to/index.d.ts +0 -56
  254. package/native/token-counter/node_modules/round-to/index.js +0 -37
  255. package/native/token-counter/node_modules/round-to/license +0 -9
  256. package/native/token-counter/node_modules/round-to/package.json +0 -38
  257. package/native/token-counter/node_modules/round-to/readme.md +0 -71
  258. package/native/token-counter/node_modules/rtrim-array/index.js +0 -10
  259. package/native/token-counter/node_modules/rtrim-array/license.txt +0 -21
  260. package/native/token-counter/node_modules/rtrim-array/package.json +0 -41
  261. package/native/token-counter/node_modules/rtrim-array/readme.md +0 -75
  262. package/native/token-counter/node_modules/sbo/index.js +0 -25
  263. package/native/token-counter/node_modules/sbo/license.txt +0 -21
  264. package/native/token-counter/node_modules/sbo/package.json +0 -50
  265. package/native/token-counter/node_modules/sbo/readme.md +0 -105
  266. package/native/token-counter/node_modules/sorp/index.js +0 -3
  267. package/native/token-counter/node_modules/sorp/license.txt +0 -21
  268. package/native/token-counter/node_modules/sorp/package.json +0 -34
  269. package/native/token-counter/node_modules/sorp/readme.md +0 -25
  270. package/native/token-counter/node_modules/trim-call/index.js +0 -6
  271. package/native/token-counter/node_modules/trim-call/license.txt +0 -21
  272. package/native/token-counter/node_modules/trim-call/package.json +0 -40
  273. package/native/token-counter/node_modules/trim-call/readme.md +0 -80
  274. package/native/token-counter/node_modules/type-error/LICENSE +0 -21
  275. package/native/token-counter/node_modules/type-error/README.md +0 -24
  276. package/native/token-counter/node_modules/type-error/index.js +0 -35
  277. package/native/token-counter/node_modules/type-error/package.json +0 -11
  278. package/native/token-counter/node_modules/vfn/index.js +0 -21
  279. package/native/token-counter/node_modules/vfn/license.txt +0 -21
  280. package/native/token-counter/node_modules/vfn/package.json +0 -40
  281. package/native/token-counter/node_modules/vfn/readme.md +0 -81
  282. package/native/token-counter/node_modules/wfn/index.js +0 -43
  283. package/native/token-counter/node_modules/wfn/license.txt +0 -21
  284. package/native/token-counter/node_modules/wfn/package.json +0 -38
  285. package/native/token-counter/node_modules/wfn/readme.md +0 -81
  286. package/native/token-counter/package-lock.json +0 -578
  287. package/native/token-counter/package.json +0 -21
  288. package/native/token-counter/token-counter.linux-x64-gnu.node +0 -0
@@ -1,8 +1,8 @@
1
1
  import { launchPersistentContext, ensureBinary } from 'cloakbrowser';
2
2
  import { homedir } from 'os';
3
3
  import { join } from 'path';
4
- import { readdirSync, readFileSync, unlinkSync } from 'fs';
5
4
  import { loadConfig } from '../agent/Config.js';
5
+ import { visionClassify, readFileBase64, findGridTiles, humanClick, humanMove, humanHold, warmupBehavior, solveCaptchaGrid, autoSolveCaptcha, analyzeImageChallenge, _lastGridAnalyzeTime, bezierPoint, easeInOut, } from './captcha/index.js';
6
6
  function ok(msg, details) {
7
7
  const lines = [`[OK] ${msg}`];
8
8
  if (details)
@@ -33,323 +33,6 @@ async function autoScreenshot(p, label) {
33
33
  catch { }
34
34
  return path;
35
35
  }
36
- // ─── Vision-Based Captcha Auto-Solve ──────────────────────────────────────
37
- let _lastGridAnalyzeTime = 0;
38
- function readFileBase64(path) {
39
- return readFileSync(path).toString('base64');
40
- }
41
- async function visionClassify(imageBase64, prompt) {
42
- const config = loadConfig();
43
- const visionModel = config.visionModel || config.model || 'gpt-4o';
44
- const visionBaseUrl = config.visionBaseUrl || config.baseUrl;
45
- const visionApiKey = config.visionApiKey || config.apiKey;
46
- const body = {
47
- model: visionModel,
48
- messages: [{
49
- role: 'user',
50
- content: [
51
- { type: 'text', text: prompt },
52
- { type: 'image_url', image_url: { url: `data:image/png;base64,${imageBase64}` } },
53
- ],
54
- }],
55
- max_tokens: 100,
56
- };
57
- const controller = new AbortController();
58
- const fetchTimeout = setTimeout(() => controller.abort(), 15_000);
59
- try {
60
- const resp = await fetch(`${visionBaseUrl}/chat/completions`, {
61
- method: 'POST',
62
- headers: {
63
- 'Content-Type': 'application/json',
64
- ...(visionApiKey ? { Authorization: `Bearer ${visionApiKey}` } : {}),
65
- },
66
- body: JSON.stringify(body),
67
- signal: controller.signal,
68
- });
69
- if (!resp.ok)
70
- throw new Error(`Vision API error: ${resp.status}`);
71
- const text = await resp.text();
72
- if (text.includes('data: ')) {
73
- let content = '';
74
- for (const line of text.split('\n')) {
75
- if (line.startsWith('data: ') && line.trim() !== 'data: [DONE]') {
76
- try {
77
- const ev = JSON.parse(line.slice(6));
78
- const delta = ev.choices?.[0]?.delta;
79
- if (delta?.content)
80
- content += delta.content;
81
- if (delta?.text)
82
- content += delta.text;
83
- if (ev.choices?.[0]?.message?.content)
84
- content += ev.choices[0].message.content;
85
- }
86
- catch { }
87
- }
88
- }
89
- return content.trim();
90
- }
91
- const json = JSON.parse(text);
92
- return (json.choices?.[0]?.message?.content || '').trim();
93
- }
94
- finally {
95
- clearTimeout(fetchTimeout);
96
- }
97
- }
98
- async function solveCaptchaGrid(page, frame, provider) {
99
- const results = [];
100
- const isRecaptcha = provider === 'recaptcha';
101
- const _t0 = Date.now();
102
- const _elapsed = () => ((Date.now() - _t0) / 1000).toFixed(1);
103
- let instruction = '';
104
- try {
105
- const instrEl = frame.locator('.rc-imageselect-instructions, .prompt-text, .prompt-text-h, .geetest_tip_content, .mtcaptcha-label');
106
- if (await instrEl.count() > 0) {
107
- instruction = (await instrEl.first().textContent() || '').trim();
108
- }
109
- if (!instruction) {
110
- const strongText = frame.locator('strong').first();
111
- if (await strongText.count() > 0)
112
- instruction = (await strongText.textContent() || '').trim();
113
- }
114
- }
115
- catch { }
116
- if (!instruction) {
117
- results.push('[WARN] Could not extract captcha instruction, cannot auto-solve');
118
- return results.join('\n');
119
- }
120
- results.push(`Auto-solving: "${instruction}"`);
121
- results.push(`[timing] instruction: ${_elapsed()}s`);
122
- try {
123
- const home = homedir();
124
- for (const f of readdirSync(home)) {
125
- if (/^\.aurix-tile-(\d+|after-\d+)\.png$/.test(f)) {
126
- try {
127
- unlinkSync(join(home, f));
128
- }
129
- catch { }
130
- }
131
- }
132
- }
133
- catch { }
134
- const tiles = await findGridTiles(frame, provider);
135
- const gridScreenshotPath = join(homedir(), '.aurix-captcha-grid.png');
136
- try {
137
- const gridEl = frame.locator('.rc-imageselect-table-33, .rc-imageselect-table-44, .task, .challenge-view, table').first();
138
- if (await gridEl.count() > 0)
139
- await gridEl.screenshot({ path: gridScreenshotPath });
140
- else
141
- await frame.locator('body').screenshot({ path: gridScreenshotPath });
142
- }
143
- catch {
144
- try {
145
- await page.screenshot({ path: gridScreenshotPath });
146
- }
147
- catch { }
148
- }
149
- results.push(`[timing] grid screenshot: ${_elapsed()}s (${tiles.length} tiles)`);
150
- const classifyPrompt = `Look at this captcha grid image. The instruction is: "${instruction}". Which tile images match this instruction? Reply with ONLY the 0-based indices separated by commas (e.g. "0,3,5"). If none match, reply "none".`;
151
- let matchedIndices = [];
152
- try {
153
- const gridBase64 = readFileBase64(gridScreenshotPath);
154
- const response = await visionClassify(gridBase64, classifyPrompt);
155
- results.push(`Vision model: "${response}"`);
156
- if (response.toLowerCase().includes('none')) {
157
- results.push('Vision: no matching tiles, clicking verify directly');
158
- }
159
- else {
160
- matchedIndices = response.split(',')
161
- .map(s => parseInt(s.trim()))
162
- .filter(n => !isNaN(n) && n >= 0 && n < tiles.length);
163
- }
164
- }
165
- catch (e) {
166
- results.push(`[WARN] Vision model failed: ${e.message}`);
167
- results.push('Auto-solve requires a vision-capable model. Falling back to manual mode.');
168
- results.push('Use "captcha-grid" to see tiles and "click-tile" to select them manually.');
169
- return results.join('\n');
170
- }
171
- if (matchedIndices.length === 0) {
172
- results.push('No matching tiles found, attempting verify directly');
173
- }
174
- results.push(`[timing] before clicks: ${_elapsed()}s, clicking ${matchedIndices.length} tiles`);
175
- for (const idx of matchedIndices) {
176
- try {
177
- if (idx >= tiles.length)
178
- continue;
179
- await tiles[idx].click({ force: true, timeout: 3000 });
180
- await page.waitForTimeout(200 + Math.random() * 200);
181
- results.push(` Clicked tile ${idx}`);
182
- }
183
- catch (e) {
184
- try {
185
- const currentTiles = await findGridTiles(frame, provider);
186
- if (idx < currentTiles.length) {
187
- await currentTiles[idx].click({ force: true, timeout: 3000 });
188
- await page.waitForTimeout(200 + Math.random() * 200);
189
- results.push(` Clicked tile ${idx} (re-fetched)`);
190
- }
191
- }
192
- catch (e2) {
193
- results.push(` Failed to click tile ${idx}: ${e2.message}`);
194
- }
195
- }
196
- }
197
- if (isRecaptcha && matchedIndices.length > 0) {
198
- await page.waitForTimeout(800 + Math.random() * 400);
199
- }
200
- results.push(`Clicking verify... [${_elapsed()}s]`);
201
- try {
202
- let verifyBtn = frame.locator('#recaptcha-verify-button, .rc-button-submit, .button-submit, [id*="verify"]');
203
- if (await verifyBtn.count() === 0) {
204
- verifyBtn = frame.locator('button:has-text("Verify"), button:has-text("Next"), button:has-text("Submit")');
205
- }
206
- if (await verifyBtn.count() > 0) {
207
- await verifyBtn.click({ force: true, timeout: 5000 });
208
- await page.waitForTimeout(2000);
209
- const errorText = await frame.locator('.rc-imageselect-incorrect-response, .error-message, .incorrect').count();
210
- if (errorText > 0) {
211
- results.push('Verification failed, challenge will retry');
212
- return results.join('\n');
213
- }
214
- const newChallenge = await frame.locator('.rc-imageselect-instructions, .prompt-text').count();
215
- if (newChallenge > 0) {
216
- const newInstr = (await frame.locator('.rc-imageselect-instructions, .prompt-text').first().textContent() || '').trim();
217
- if (newInstr !== instruction) {
218
- results.push(`New challenge appeared: "${newInstr}"`);
219
- return results.join('\n');
220
- }
221
- results.push('Same challenge still present');
222
- return results.join('\n');
223
- }
224
- const verifyResultPath = join(homedir(), '.aurix-captcha-verify-result.png');
225
- await page.screenshot({ path: verifyResultPath }).catch(() => { });
226
- results.push(`[OK] Captcha solved! Screenshot: ${verifyResultPath}`);
227
- return results.join('\n');
228
- }
229
- else {
230
- results.push('[WARN] No verify button found');
231
- return results.join('\n');
232
- }
233
- }
234
- catch (e) {
235
- results.push(`Verify failed: ${e.message}`);
236
- return results.join('\n');
237
- }
238
- }
239
- // ─── Human-Like Mouse Utilities ────────────────────────────────────────────
240
- function bezierPoint(t, points) {
241
- if (points.length === 1)
242
- return points[0];
243
- const next = [];
244
- for (let i = 0; i < points.length - 1; i++) {
245
- next.push([
246
- points[i][0] + (points[i + 1][0] - points[i][0]) * t,
247
- points[i][1] + (points[i + 1][1] - points[i][1]) * t,
248
- ]);
249
- }
250
- return bezierPoint(t, next);
251
- }
252
- function easeInOut(t) {
253
- return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
254
- }
255
- async function humanMove(x, y, page) {
256
- const mouse = page.mouse;
257
- const vp = page.viewportSize() || { width: 1280, height: 720 };
258
- // Start from a random position if we don't know current pos
259
- const startX = Math.random() * vp.width * 0.3;
260
- const startY = Math.random() * vp.height * 0.3;
261
- // Generate 2-4 control points for bezier curve
262
- const numControls = 2 + Math.floor(Math.random() * 3);
263
- const controlPoints = [[startX, startY]];
264
- for (let i = 0; i < numControls; i++) {
265
- const frac = (i + 1) / (numControls + 1);
266
- const cx = startX + (x - startX) * frac + (Math.random() - 0.5) * 80;
267
- const cy = startY + (y - startY) * frac + (Math.random() - 0.5) * 60;
268
- controlPoints.push([cx, cy]);
269
- }
270
- controlPoints.push([x, y]);
271
- // Step through the curve with eased timing
272
- const totalSteps = 25 + Math.floor(Math.random() * 20);
273
- for (let step = 0; step <= totalSteps; step++) {
274
- const rawT = step / totalSteps;
275
- const t = easeInOut(rawT);
276
- const [px, py] = bezierPoint(t, controlPoints);
277
- // Sine-wave micro-tremor (not uniform random)
278
- const tremor = Math.sin(step * 0.3 + Math.random() * 0.5) * 0.4;
279
- const tremorY = Math.cos(step * 0.25 + Math.random() * 0.5) * 0.3;
280
- await mouse.move(px + tremor, py + tremorY);
281
- // Variable step delay: faster in middle, slower at start/end
282
- const speedFactor = 1 - Math.abs(rawT - 0.5) * 2;
283
- const delay = 8 + Math.random() * 12 + speedFactor * 5;
284
- await page.waitForTimeout(delay);
285
- }
286
- // Occasional overshoot + correction
287
- if (Math.random() > 0.6) {
288
- const overX = x + (Math.random() - 0.5) * 8;
289
- const overY = y + (Math.random() - 0.5) * 8;
290
- await mouse.move(overX, overY);
291
- await page.waitForTimeout(30 + Math.random() * 40);
292
- await mouse.move(x, y);
293
- await page.waitForTimeout(20 + Math.random() * 30);
294
- }
295
- }
296
- let lastWarmupTime = 0;
297
- async function warmupBehavior(page) {
298
- const now = Date.now();
299
- if (now - lastWarmupTime < 30000)
300
- return;
301
- lastWarmupTime = now;
302
- const vp = page.viewportSize() || { width: 1280, height: 720 };
303
- const spots = 1 + Math.floor(Math.random() * 2);
304
- for (let i = 0; i < spots; i++) {
305
- const rx = Math.random() * vp.width;
306
- const ry = Math.random() * vp.height;
307
- await humanMove(rx, ry, page);
308
- await page.waitForTimeout(150 + Math.random() * 300);
309
- }
310
- if (Math.random() > 0.5) {
311
- const scrollDelta = Math.floor(Math.random() * 150) - 75;
312
- await page.mouse.wheel(0, scrollDelta);
313
- await page.waitForTimeout(200 + Math.random() * 300);
314
- }
315
- }
316
- async function humanHold(x, y, duration, page) {
317
- const mouse = page.mouse;
318
- const holdSteps = Math.floor(duration / 80);
319
- const breathFreq = 0.15 + Math.random() * 0.1;
320
- const breathAmpX = 0.3 + Math.random() * 0.4;
321
- const breathAmpY = 0.2 + Math.random() * 0.3;
322
- await mouse.down();
323
- for (let i = 0; i < holdSteps; i++) {
324
- // Sine-wave breathing movement (natural hand tremor)
325
- const breathX = Math.sin(i * breathFreq) * breathAmpX;
326
- const breathY = Math.cos(i * breathFreq * 0.7) * breathAmpY;
327
- // Occasional micro-adjustment
328
- const adjX = Math.random() > 0.95 ? (Math.random() - 0.5) * 2 : 0;
329
- const adjY = Math.random() > 0.95 ? (Math.random() - 0.5) * 2 : 0;
330
- await mouse.move(x + breathX + adjX, y + breathY + adjY);
331
- await page.waitForTimeout(60 + Math.random() * 40);
332
- }
333
- // Release with slight upward drift
334
- await mouse.move(x + (Math.random() - 0.5) * 3, y - 1 - Math.random() * 2);
335
- await page.waitForTimeout(30 + Math.random() * 50);
336
- await mouse.up();
337
- }
338
- async function humanClick(locator, page) {
339
- const box = await locator.first().boundingBox();
340
- if (box) {
341
- const clickX = box.x + box.width * (0.3 + Math.random() * 0.4);
342
- const clickY = box.y + box.height * (0.3 + Math.random() * 0.4);
343
- await humanMove(clickX, clickY, page);
344
- await page.waitForTimeout(60 + Math.random() * 100);
345
- await page.mouse.down();
346
- await page.waitForTimeout(50 + Math.random() * 80);
347
- await page.mouse.up();
348
- }
349
- else {
350
- await locator.first().click({ force: true });
351
- }
352
- }
353
36
  const sessions = new Map();
354
37
  const sessionProxies = new Map();
355
38
  const MAX_BROWSER_SESSIONS = 3;
@@ -697,283 +380,6 @@ async function resolveLocator(p, target) {
697
380
  }
698
381
  return locator;
699
382
  }
700
- async function autoSolveCaptcha(p) {
701
- const results = [];
702
- const frames = p.frames();
703
- let recaptchaAnchor = null;
704
- let recaptchaBframe = null;
705
- let geetestSlider = null;
706
- let turnstileFrame = null;
707
- for (const frame of frames) {
708
- const url = frame.url();
709
- if (url.includes('/recaptcha/') && url.includes('/anchor'))
710
- recaptchaAnchor = frame;
711
- if (url.includes('/recaptcha/') && url.includes('/bframe'))
712
- recaptchaBframe = frame;
713
- if (url.includes('geetest.com') || url.includes('captcha.com')) {
714
- const hasSlider = await frame.locator('.geetest_slider_button, .geetest_slider').count();
715
- if (hasSlider > 0)
716
- geetestSlider = frame;
717
- }
718
- if (url.includes('challenges.cloudflare') || url.includes('turnstile'))
719
- turnstileFrame = frame;
720
- }
721
- if (turnstileFrame) {
722
- try {
723
- const checkbox = turnstileFrame.locator('input[type="checkbox"], .cf-turnstile, [role="checkbox"]').first();
724
- if (await checkbox.count() > 0) {
725
- await checkbox.click({ timeout: 5000 });
726
- await p.waitForTimeout(3000);
727
- // Don't claim "solved" — verify the widget actually reported success.
728
- const tsOk = await turnstileFrame.locator('input[type="hidden"][name="cf-turnstile-response"], [data-state="success"], .success').count().catch(() => 0);
729
- const tsError = await turnstileFrame.locator('.error, [data-state="error"], [data-state="failed"]').count().catch(() => 0);
730
- if (tsOk > 0)
731
- results.push('Turnstile: checkbox clicked, widget reports success');
732
- else if (tsError > 0)
733
- results.push('Turnstile: checkbox clicked but widget shows an error — may need a screenshot to inspect');
734
- else
735
- results.push('Turnstile: checkbox clicked, outcome unconfirmed — take a screenshot to verify the page advanced before submitting');
736
- }
737
- }
738
- catch (e) {
739
- results.push(`Turnstile: auto-click attempted (${e.message?.slice(0, 80)})`);
740
- }
741
- }
742
- if (recaptchaAnchor && !recaptchaBframe) {
743
- try {
744
- const checkbox = recaptchaAnchor.locator('#recaptcha-anchor, .recaptcha-checkbox-border, .rc-anchor-checkbox').first();
745
- if (await checkbox.count() > 0) {
746
- await checkbox.click({ timeout: 5000 });
747
- await p.waitForTimeout(2000);
748
- // The checkbox click may pass instantly OR pop an image challenge.
749
- // Report which actually happened instead of claiming success.
750
- const checked = await recaptchaAnchor.locator('.recaptcha-checkbox-checked, .rc-anchor-checkbox-checked').count().catch(() => 0);
751
- const challengeOpened = p.frames().some((f) => f.url().includes('/recaptcha/') && f.url().includes('/bframe'));
752
- if (checked > 0)
753
- results.push('reCAPTCHA: checkbox verified (checked) — no image challenge');
754
- else if (challengeOpened)
755
- results.push('reCAPTCHA: checkbox clicked, image challenge appeared — use captcha-grid to solve it');
756
- else
757
- results.push('reCAPTCHA: checkbox clicked, outcome unconfirmed — take a screenshot to verify before submitting');
758
- }
759
- }
760
- catch (e) {
761
- results.push(`reCAPTCHA checkbox: auto-click attempted (${e.message?.slice(0, 80)})`);
762
- }
763
- }
764
- if (geetestSlider) {
765
- try {
766
- const sliderInfo = await geetestSlider.evaluate(() => {
767
- const info = {};
768
- const cut = document.querySelector('.geetest_cut, .geetest_piece_bg, [class*="geetest_cut"], [class*="slider_cut"]');
769
- if (cut) {
770
- const cutRect = cut.getBoundingClientRect();
771
- const style = window.getComputedStyle(cut);
772
- info.cut = { left: cutRect.left, width: cutRect.width, styleLeft: parseFloat(style.left) || null, transform: style.transform || null };
773
- }
774
- const bg = document.querySelector('.geetest_canvas_bg, .geetest_bg, [class*="geetest_canvas"], canvas[class*="bg"]');
775
- if (bg)
776
- info.bg = { left: bg.getBoundingClientRect().left, width: bg.getBoundingClientRect().width };
777
- const piece = document.querySelector('.geetest_piece, [class*="slider_piece"]');
778
- if (piece)
779
- info.piece = { width: piece.getBoundingClientRect().width };
780
- const slider = document.querySelector('.geetest_slider_button, [class*="slider_button"]');
781
- if (slider) {
782
- const r = slider.getBoundingClientRect();
783
- info.slider = { left: r.left, width: r.width, centerX: r.left + r.width / 2, centerY: r.top + r.height / 2 };
784
- }
785
- return info;
786
- });
787
- let gapOffset = null;
788
- if (sliderInfo.cut && sliderInfo.bg) {
789
- if (sliderInfo.cut.styleLeft && sliderInfo.cut.styleLeft > 0)
790
- gapOffset = Math.round(sliderInfo.cut.styleLeft);
791
- else
792
- gapOffset = Math.round(sliderInfo.cut.left - sliderInfo.bg.left);
793
- }
794
- if (gapOffset === null && sliderInfo.cut?.transform && sliderInfo.cut.transform !== 'none') {
795
- const match = sliderInfo.cut.transform.match(/matrix\(.*?,\s*([\d.]+)/);
796
- if (match)
797
- gapOffset = Math.round(parseFloat(match[1]));
798
- }
799
- if (gapOffset !== null && sliderInfo.slider) {
800
- const pieceHalf = Math.round((sliderInfo.piece?.width || 44) / 2);
801
- const dragDistance = gapOffset - pieceHalf;
802
- const startX = sliderInfo.slider.centerX;
803
- const startY = sliderInfo.slider.centerY;
804
- const endX = startX + dragDistance;
805
- await p.mouse.move(startX, startY);
806
- await p.waitForTimeout(150);
807
- await p.mouse.down();
808
- await p.waitForTimeout(200);
809
- const steps = 18 + Math.floor(Math.random() * 8);
810
- for (let i = 1; i <= steps; i++) {
811
- const progress = i / steps;
812
- const eased = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
813
- const x = startX + dragDistance * eased + (Math.random() - 0.5) * 2;
814
- const y = startY + (Math.random() - 0.5) * 2;
815
- await p.mouse.move(x, y);
816
- await p.waitForTimeout(10 + Math.random() * 20);
817
- }
818
- await p.mouse.move(endX, startY);
819
- await p.waitForTimeout(150);
820
- await p.mouse.up();
821
- await p.waitForTimeout(2000);
822
- results.push(`GeeTest: slider dragged ${dragDistance}px — outcome unconfirmed, take a screenshot to verify the gap was matched`);
823
- }
824
- else {
825
- results.push('GeeTest slider detected but gap position could not be auto-detected');
826
- }
827
- }
828
- catch (e) {
829
- results.push(`GeeTest slider: auto-solve attempted (${e.message?.slice(0, 80)})`);
830
- }
831
- }
832
- if (recaptchaBframe) {
833
- const gridResult = await analyzeImageChallenge(p, recaptchaBframe, 'recaptcha');
834
- results.push('reCAPTCHA image challenge detected — grid analysis:');
835
- results.push(gridResult);
836
- }
837
- const funcaptchaFrame = frames.find(f => f.url().includes('funcaptcha') || f.url().includes('arkoselabs'));
838
- if (funcaptchaFrame) {
839
- results.push('FunCaptcha detected — screenshotting puzzle...');
840
- try {
841
- const fcScreenshotPath = join(homedir(), '.aurix-funcaptcha-puzzle.png');
842
- await funcaptchaFrame.locator('body').screenshot({ path: fcScreenshotPath }).catch(() => p.screenshot({ path: fcScreenshotPath }));
843
- results.push(`Puzzle screenshot: ${fcScreenshotPath}`);
844
- results.push('Analyze the puzzle image and determine the correct answer, then use click/evaluate to solve it.');
845
- }
846
- catch {
847
- results.push('REQUIRES_VISION: FunCaptcha detected — needs image analysis to solve');
848
- }
849
- }
850
- return results;
851
- }
852
- async function findGridTiles(frame, provider) {
853
- switch (provider) {
854
- case 'recaptcha': {
855
- const tiles33 = frame.locator('.rc-imageselect-table-33 td, .rc-image-tile-33 td');
856
- if (await tiles33.count() > 0)
857
- return tiles33.all();
858
- const tiles44 = frame.locator('.rc-imageselect-table-44 td, .rc-image-tile-44 td');
859
- if (await tiles44.count() > 0)
860
- return tiles44.all();
861
- const generic = frame.locator('table td');
862
- if (await generic.count() > 0)
863
- return generic.all();
864
- return [];
865
- }
866
- case 'hcaptcha': {
867
- const tiles = frame.locator('.task-image, .image, .task .answer');
868
- if (await tiles.count() > 0)
869
- return tiles.all();
870
- return [];
871
- }
872
- case 'mtcaptcha':
873
- case 'geetest': {
874
- const items = frame.locator('.geetest_item_wrap, .geetest_ques_tips img, .mtcaptcha-item');
875
- if (await items.count() > 0)
876
- return items.all();
877
- return [];
878
- }
879
- default: {
880
- const tiles = frame.locator('.task-image, .rc-imageselect-table-33 td, .rc-imageselect-table-44 td, table td');
881
- if (await tiles.count() > 0)
882
- return tiles.all();
883
- return [];
884
- }
885
- }
886
- }
887
- async function analyzeImageChallenge(page, frame, provider) {
888
- const results = [];
889
- let instruction = '';
890
- try {
891
- const instrEl = frame.locator('.rc-imageselect-instructions, .prompt-text, .prompt-text-h, .geetest_tip_content, .mtcaptcha-label');
892
- if (await instrEl.count() > 0) {
893
- instruction = (await instrEl.first().textContent()) || '';
894
- instruction = instruction.trim();
895
- }
896
- if (!instruction) {
897
- const strongText = frame.locator('strong').first();
898
- if (await strongText.count() > 0) {
899
- instruction = (await strongText.textContent()) || '';
900
- }
901
- }
902
- }
903
- catch { }
904
- if (instruction) {
905
- results.push(`Instruction: "${instruction}"`);
906
- }
907
- else {
908
- results.push('Instruction: (could not extract — check screenshot)');
909
- }
910
- const tiles = await findGridTiles(frame, provider);
911
- const gridSize = tiles.length <= 9 ? '3x3' : tiles.length <= 16 ? '4x4' : `${tiles.length}-tile`;
912
- results.push(`Grid: ${gridSize} (${tiles.length} tiles found, valid indices: 0-${tiles.length - 1})`);
913
- _lastGridAnalyzeTime = Date.now();
914
- // Clear stale tile screenshots from a previous challenge so the model never
915
- // reads an old .aurix-tile-N.png that no longer matches the current grid.
916
- try {
917
- const home = homedir();
918
- for (const f of readdirSync(home)) {
919
- if (/^\.aurix-tile-(\d+|after-\d+)\.png$/.test(f)) {
920
- try {
921
- unlinkSync(join(home, f));
922
- }
923
- catch { }
924
- }
925
- }
926
- }
927
- catch { }
928
- const screenshotPath = join(homedir(), '.aurix-captcha-grid.png');
929
- try {
930
- const gridEl = frame.locator('.rc-imageselect-table-33, .rc-imageselect-table-44, .task, .challenge-view, .geetest_panel, table').first();
931
- if (await gridEl.count() > 0) {
932
- await gridEl.screenshot({ path: screenshotPath });
933
- }
934
- else {
935
- await frame.locator('body').screenshot({ path: screenshotPath });
936
- }
937
- }
938
- catch {
939
- try {
940
- await page.screenshot({ path: screenshotPath });
941
- }
942
- catch { }
943
- }
944
- results.push(`Grid screenshot: ${screenshotPath}`);
945
- for (let i = 0; i < tiles.length; i++) {
946
- const tilePath = join(homedir(), `.aurix-tile-${i}.png`);
947
- try {
948
- await tiles[i].screenshot({ path: tilePath });
949
- results.push(` Tile ${i}: ${tilePath}`);
950
- }
951
- catch {
952
- results.push(` Tile ${i}: (screenshot failed)`);
953
- }
954
- }
955
- const isRecaptcha = provider === 'recaptcha';
956
- const selectedClass = isRecaptcha ? '.rc-imageselect-dynamic-selected' : '.task-image.selected, .task .selected';
957
- const selectedCount = await frame.locator(selectedClass).count();
958
- if (selectedCount > 0) {
959
- results.push(`Already selected: ${selectedCount} tile(s)`);
960
- }
961
- results.push('');
962
- results.push('=== IMAGE SELECTION STEPS ===');
963
- results.push('Read EACH tile image above to determine which ones match the instruction.');
964
- results.push('Then execute these actions IN ORDER:');
965
- results.push('');
966
- results.push('Step 1: For each matching tile, call: browser action="click-tile" value="<index>"');
967
- results.push(' Example: if tiles 0, 3, and 5 match → click-tile 0, then click-tile 3, then click-tile 5');
968
- if (provider === 'recaptcha') {
969
- results.push(' IMPORTANT: After clicking a tile, a NEW tile replaces it. Read the new tile screenshot to check if it also matches.');
970
- }
971
- results.push('Step 2: After clicking ALL matching tiles, call: browser action="captcha-verify"');
972
- results.push('Step 3: If the grid refreshes with new tiles, call captcha-grid again and repeat from Step 1');
973
- results.push('');
974
- results.push('Do NOT skip any step. Start by reading the tile images now.');
975
- return results.join('\n');
976
- }
977
383
  export const browserTool = {
978
384
  name: 'browser',
979
385
  description: `Persistent Chromium browser. Profile: ~/.aurix-browser-profile.
@@ -1538,7 +944,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1538
944
  case 'solve-captcha': {
1539
945
  const p = await ensureBrowser();
1540
946
  const results = [];
1541
- const _solveTimeout = 60_000;
947
+ const _solveTimeout = 120_000;
1542
948
  const _solveLogic = async () => {
1543
949
  const frames = p.frames();
1544
950
  let captchaType = 'unknown';
@@ -1590,14 +996,14 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1590
996
  try {
1591
997
  if (recaptchaBframe) {
1592
998
  results.push('Image challenge already visible. Auto-solving...');
1593
- const maxRetries = 2;
999
+ const maxRetries = 5;
1594
1000
  let solved = false;
1595
1001
  for (let attempt = 0; attempt < maxRetries; attempt++) {
1596
1002
  if (attempt > 0)
1597
1003
  results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
1598
1004
  const solveResult = await solveCaptchaGrid(p, recaptchaBframe, 'recaptcha');
1599
1005
  results.push(solveResult);
1600
- if (solveResult.includes('Captcha solved!')) {
1006
+ if (solveResult.includes('CAPTCHA SOLVED')) {
1601
1007
  solved = true;
1602
1008
  break;
1603
1009
  }
@@ -1611,6 +1017,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1611
1017
  solved = true;
1612
1018
  break;
1613
1019
  }
1020
+ recaptchaBframe = newChallenge;
1614
1021
  }
1615
1022
  if (!solved && !results.some(r => r.includes('Falling back'))) {
1616
1023
  results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
@@ -1634,17 +1041,17 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1634
1041
  await humanClick(checkbox, p);
1635
1042
  await p.waitForTimeout(3000);
1636
1043
  const updatedFrames = p.frames();
1637
- const challengeFrame = updatedFrames.find(f => f.url().includes('/recaptcha/') && f.url().includes('/bframe'));
1044
+ let challengeFrame = updatedFrames.find(f => f.url().includes('/recaptcha/') && f.url().includes('/bframe'));
1638
1045
  if (challengeFrame) {
1639
1046
  results.push('Image challenge appeared. Auto-solving...');
1640
- const maxRetries = 2;
1047
+ const maxRetries = 5;
1641
1048
  let solved = false;
1642
1049
  for (let attempt = 0; attempt < maxRetries; attempt++) {
1643
1050
  if (attempt > 0)
1644
1051
  results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
1645
1052
  const solveResult = await solveCaptchaGrid(p, challengeFrame, 'recaptcha');
1646
1053
  results.push(solveResult);
1647
- if (solveResult.includes('Captcha solved!')) {
1054
+ if (solveResult.includes('CAPTCHA SOLVED')) {
1648
1055
  solved = true;
1649
1056
  break;
1650
1057
  }
@@ -1659,6 +1066,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1659
1066
  solved = true;
1660
1067
  break;
1661
1068
  }
1069
+ challengeFrame = newChallenge;
1662
1070
  }
1663
1071
  if (!solved && !results.some(r => r.includes('Falling back'))) {
1664
1072
  results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
@@ -1689,14 +1097,14 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1689
1097
  }
1690
1098
  if (challengeFrame) {
1691
1099
  results.push('Image challenge appeared after clicking anchor. Auto-solving...');
1692
- const maxRetries = 2;
1100
+ const maxRetries = 5;
1693
1101
  let solved = false;
1694
1102
  for (let attempt = 0; attempt < maxRetries; attempt++) {
1695
1103
  if (attempt > 0)
1696
1104
  results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
1697
1105
  const solveResult = await solveCaptchaGrid(p, challengeFrame, 'recaptcha');
1698
1106
  results.push(solveResult);
1699
- if (solveResult.includes('Captcha solved!')) {
1107
+ if (solveResult.includes('CAPTCHA SOLVED')) {
1700
1108
  solved = true;
1701
1109
  break;
1702
1110
  }
@@ -1710,6 +1118,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1710
1118
  solved = true;
1711
1119
  break;
1712
1120
  }
1121
+ challengeFrame = newChallenge;
1713
1122
  }
1714
1123
  if (!solved && !results.some(r => r.includes('Falling back'))) {
1715
1124
  results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
@@ -1749,17 +1158,17 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1749
1158
  await humanClick(checkbox, p);
1750
1159
  await p.waitForTimeout(3000);
1751
1160
  const updatedFrames = p.frames();
1752
- const challengeFrame = updatedFrames.find((f) => f.url().includes('hcaptcha') && f.url().includes('challenge'));
1161
+ let challengeFrame = updatedFrames.find((f) => f.url().includes('hcaptcha') && f.url().includes('challenge'));
1753
1162
  if (challengeFrame) {
1754
1163
  results.push('Image challenge appeared. Auto-solving...');
1755
- const maxRetries = 2;
1164
+ const maxRetries = 5;
1756
1165
  let solved = false;
1757
1166
  for (let attempt = 0; attempt < maxRetries; attempt++) {
1758
1167
  if (attempt > 0)
1759
1168
  results.push(`\nRetry attempt ${attempt}/${maxRetries - 1}...`);
1760
1169
  const solveResult = await solveCaptchaGrid(p, challengeFrame, 'hcaptcha');
1761
1170
  results.push(solveResult);
1762
- if (solveResult.includes('Captcha solved!')) {
1171
+ if (solveResult.includes('CAPTCHA SOLVED')) {
1763
1172
  solved = true;
1764
1173
  break;
1765
1174
  }
@@ -1774,6 +1183,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
1774
1183
  solved = true;
1775
1184
  break;
1776
1185
  }
1186
+ challengeFrame = newChallenge;
1777
1187
  }
1778
1188
  if (!solved && !results.some(r => r.includes('Falling back'))) {
1779
1189
  results.push(`\nAuto-solve exhausted after ${maxRetries} attempts. Use "captcha-grid" and "click-tile" for manual solving.`);
@@ -2168,7 +1578,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
2168
1578
  try {
2169
1579
  return await Promise.race([
2170
1580
  _solveLogic(),
2171
- new Promise((_, rej) => setTimeout(() => rej(new Error('solve-captcha timed out (60s)')), _solveTimeout)),
1581
+ new Promise((_, rej) => setTimeout(() => rej(new Error('solve-captcha timed out (120s)')), _solveTimeout)),
2172
1582
  ]);
2173
1583
  }
2174
1584
  catch (e) {
@@ -2280,7 +1690,16 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
2280
1690
  }
2281
1691
  const tile = initialTiles[tileIndex];
2282
1692
  const selectedBefore = await challengeFrame.locator(selectedClass).count().catch(() => 0);
2283
- await tile.click({ force: true, timeout: 3000 });
1693
+ try {
1694
+ await challengeFrame.evaluate((idx) => {
1695
+ const tds = document.querySelectorAll('table td');
1696
+ if (tds[idx])
1697
+ tds[idx].click();
1698
+ }, tileIndex);
1699
+ }
1700
+ catch {
1701
+ await tile.click({ force: true, timeout: 3000 });
1702
+ }
2284
1703
  await p.waitForTimeout(300 + Math.random() * 300);
2285
1704
  const selectedCount = await challengeFrame.locator(selectedClass).count().catch(() => 0);
2286
1705
  const clickStatus = selectedCount !== selectedBefore
@@ -2351,16 +1770,26 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
2351
1770
  if (await verifyBtn.count() === 0) {
2352
1771
  return err('No verify button found', 'Use "captcha-grid" to analyze the challenge first');
2353
1772
  }
2354
- await humanClick(verifyBtn, p);
1773
+ try {
1774
+ await challengeFrame.evaluate(() => {
1775
+ const btn = document.querySelector('#recaptcha-verify-button, .rc-button-submit, .button-submit, [id*="verify"]');
1776
+ if (btn)
1777
+ btn.click();
1778
+ });
1779
+ }
1780
+ catch {
1781
+ await humanClick(verifyBtn, p);
1782
+ }
2355
1783
  await p.waitForTimeout(3000);
2356
1784
  const screenshotPath = join(homedir(), '.aurix-captcha-verify-result.png');
2357
- const errorText = await challengeFrame.locator('.rc-imageselect-incorrect-response, .error-message, .incorrect').count();
2358
- if (errorText > 0) {
1785
+ const errorEl2 = challengeFrame.locator('.rc-imageselect-incorrect-response, .error-message, .incorrect').first();
1786
+ const errorVisible2 = await errorEl2.count() > 0 && await errorEl2.isVisible().catch(() => false);
1787
+ if (errorVisible2) {
2359
1788
  const errorMsg = await challengeFrame.locator('.rc-imageselect-incorrect-response, .error-message').first().textContent().catch(() => 'Incorrect answer');
2360
1789
  await p.screenshot({ path: screenshotPath });
2361
1790
  const results = [];
2362
1791
  results.push(`Verification failed: "${errorMsg}". Auto-retrying...`);
2363
- const maxRetries = 2;
1792
+ const maxRetries = 3;
2364
1793
  for (let attempt = 0; attempt < maxRetries; attempt++) {
2365
1794
  results.push(`\nRetry ${attempt + 1}/${maxRetries}...`);
2366
1795
  await p.waitForTimeout(2000);
@@ -2378,7 +1807,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
2378
1807
  const retryProvider = retryFrame.url().includes('hcaptcha') ? 'hcaptcha' : 'recaptcha';
2379
1808
  const solveResult = await solveCaptchaGrid(p, retryFrame, retryProvider);
2380
1809
  results.push(solveResult);
2381
- if (solveResult.includes('Captcha solved!')) {
1810
+ if (solveResult.includes('CAPTCHA SOLVED')) {
2382
1811
  return results.join('\n');
2383
1812
  }
2384
1813
  }
@@ -2391,7 +1820,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
2391
1820
  await p.screenshot({ path: screenshotPath });
2392
1821
  const results = [];
2393
1822
  results.push(`New challenge appeared: "${instruction}". Auto-solving...`);
2394
- const maxRetries = 2;
1823
+ const maxRetries = 3;
2395
1824
  for (let attempt = 0; attempt < maxRetries; attempt++) {
2396
1825
  if (attempt > 0)
2397
1826
  results.push(`\nRetry ${attempt}/${maxRetries - 1}...`);
@@ -2408,7 +1837,7 @@ Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass"
2408
1837
  const retryProvider = retryFrame.url().includes('hcaptcha') ? 'hcaptcha' : 'recaptcha';
2409
1838
  const solveResult = await solveCaptchaGrid(p, retryFrame, retryProvider);
2410
1839
  results.push(solveResult);
2411
- if (solveResult.includes('Captcha solved!'))
1840
+ if (solveResult.includes('CAPTCHA SOLVED'))
2412
1841
  return results.join('\n');
2413
1842
  await p.waitForTimeout(2000);
2414
1843
  }