aurix-ai 2.7.2 → 2.7.4

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