@taodigital/crawler 0.0.0-stage → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. package/Dockerfile +82 -0
  2. package/README.md +10 -2
  3. package/dist/accessibility-auditor.d.ts +29 -0
  4. package/dist/accessibility-auditor.js +57 -0
  5. package/dist/accessibility-auditor.js.map +7 -0
  6. package/dist/accessibility-tree-crawler.d.ts +44 -0
  7. package/dist/accessibility-tree-crawler.js +156 -0
  8. package/dist/accessibility-tree-crawler.js.map +7 -0
  9. package/dist/advanced-ui-probes.d.ts +47 -0
  10. package/dist/advanced-ui-probes.js +310 -0
  11. package/dist/advanced-ui-probes.js.map +7 -0
  12. package/dist/ai-login.d.ts +32 -0
  13. package/dist/ai-login.js +250 -0
  14. package/dist/ai-login.js.map +7 -0
  15. package/dist/auth-token-rotator.d.ts +47 -0
  16. package/dist/auth-token-rotator.js +58 -0
  17. package/dist/auth-token-rotator.js.map +7 -0
  18. package/dist/auth.d.ts +20 -0
  19. package/dist/auth.js +348 -0
  20. package/dist/auth.js.map +7 -0
  21. package/dist/browser-extension.d.ts +37 -0
  22. package/dist/browser-extension.js +113 -0
  23. package/dist/browser-extension.js.map +7 -0
  24. package/dist/captcha-solver.d.ts +16 -0
  25. package/dist/captcha-solver.js +105 -0
  26. package/dist/captcha-solver.js.map +7 -0
  27. package/dist/color-contrast.d.ts +30 -0
  28. package/dist/color-contrast.js +78 -0
  29. package/dist/color-contrast.js.map +7 -0
  30. package/dist/content-chunker.d.ts +18 -0
  31. package/dist/content-chunker.js +152 -0
  32. package/dist/content-chunker.js.map +7 -0
  33. package/dist/content-dedup.d.ts +23 -0
  34. package/dist/content-dedup.js +60 -0
  35. package/dist/content-dedup.js.map +7 -0
  36. package/dist/cookie-consent.d.ts +25 -0
  37. package/dist/cookie-consent.js +78 -0
  38. package/dist/cookie-consent.js.map +7 -0
  39. package/dist/cookie-jar.d.ts +20 -0
  40. package/dist/cookie-jar.js +61 -0
  41. package/dist/cookie-jar.js.map +7 -0
  42. package/dist/crawl-session-manager.d.ts +44 -0
  43. package/dist/crawl-session-manager.js +145 -0
  44. package/dist/crawl-session-manager.js.map +7 -0
  45. package/dist/crawler.d.ts +233 -0
  46. package/dist/crawler.js +6239 -0
  47. package/dist/crawler.js.map +7 -0
  48. package/dist/crud-interaction.d.ts +31 -0
  49. package/dist/crud-interaction.js +264 -0
  50. package/dist/crud-interaction.js.map +7 -0
  51. package/dist/custom-js-injector.d.ts +42 -0
  52. package/dist/custom-js-injector.js +50 -0
  53. package/dist/custom-js-injector.js.map +7 -0
  54. package/dist/dark-mode-capture.d.ts +23 -0
  55. package/dist/dark-mode-capture.js +75 -0
  56. package/dist/dark-mode-capture.js.map +7 -0
  57. package/dist/dead-link-detector.d.ts +37 -0
  58. package/dist/dead-link-detector.js +50 -0
  59. package/dist/dead-link-detector.js.map +7 -0
  60. package/dist/dropdown-enumerator.d.ts +20 -0
  61. package/dist/dropdown-enumerator.js +230 -0
  62. package/dist/dropdown-enumerator.js.map +7 -0
  63. package/dist/element-hash.d.ts +9 -0
  64. package/dist/element-hash.js +9 -0
  65. package/dist/element-hash.js.map +7 -0
  66. package/dist/email-otp.d.ts +42 -0
  67. package/dist/email-otp.js +177 -0
  68. package/dist/email-otp.js.map +7 -0
  69. package/dist/engine-router.d.ts +47 -0
  70. package/dist/engine-router.js +94 -0
  71. package/dist/engine-router.js.map +7 -0
  72. package/dist/export/bulk-export.d.ts +26 -0
  73. package/dist/export/bulk-export.js +76 -0
  74. package/dist/export/bulk-export.js.map +7 -0
  75. package/dist/export/vector-export.d.ts +76 -0
  76. package/dist/export/vector-export.js +85 -0
  77. package/dist/export/vector-export.js.map +7 -0
  78. package/dist/extractors/advanced.d.ts +64 -0
  79. package/dist/extractors/advanced.js +265 -0
  80. package/dist/extractors/advanced.js.map +7 -0
  81. package/dist/extractors/artifact-envelope.d.ts +63 -0
  82. package/dist/extractors/artifact-envelope.js +63 -0
  83. package/dist/extractors/artifact-envelope.js.map +7 -0
  84. package/dist/extractors/branding-extractor.d.ts +46 -0
  85. package/dist/extractors/branding-extractor.js +104 -0
  86. package/dist/extractors/branding-extractor.js.map +7 -0
  87. package/dist/extractors/summary-extractor.d.ts +10 -0
  88. package/dist/extractors/summary-extractor.js +36 -0
  89. package/dist/extractors/summary-extractor.js.map +7 -0
  90. package/dist/failure-analysis-agent.d.ts +16 -0
  91. package/dist/failure-analysis-agent.js +42 -0
  92. package/dist/failure-analysis-agent.js.map +7 -0
  93. package/dist/feature-flag-detector.d.ts +30 -0
  94. package/dist/feature-flag-detector.js +55 -0
  95. package/dist/feature-flag-detector.js.map +7 -0
  96. package/dist/filter-pagination-crawler.d.ts +52 -0
  97. package/dist/filter-pagination-crawler.js +299 -0
  98. package/dist/filter-pagination-crawler.js.map +7 -0
  99. package/dist/form-detector.d.ts +34 -0
  100. package/dist/form-detector.js +58 -0
  101. package/dist/form-detector.js.map +7 -0
  102. package/dist/frontier.d.ts +40 -0
  103. package/dist/frontier.js +103 -0
  104. package/dist/frontier.js.map +7 -0
  105. package/dist/gap-pass.d.ts +36 -0
  106. package/dist/gap-pass.js +115 -0
  107. package/dist/gap-pass.js.map +7 -0
  108. package/dist/graphql-detector.d.ts +39 -0
  109. package/dist/graphql-detector.js +86 -0
  110. package/dist/graphql-detector.js.map +7 -0
  111. package/dist/http-engine.d.ts +80 -0
  112. package/dist/http-engine.js +318 -0
  113. package/dist/http-engine.js.map +7 -0
  114. package/dist/incremental-diff.d.ts +116 -0
  115. package/dist/incremental-diff.js +137 -0
  116. package/dist/incremental-diff.js.map +7 -0
  117. package/dist/index.d.ts +52 -0
  118. package/dist/index.js +83 -0
  119. package/dist/index.js.map +7 -0
  120. package/dist/input-fuzzer.d.ts +30 -0
  121. package/dist/input-fuzzer.js +105 -0
  122. package/dist/input-fuzzer.js.map +7 -0
  123. package/dist/interactive-probe.d.ts +144 -0
  124. package/dist/interactive-probe.js +865 -0
  125. package/dist/interactive-probe.js.map +7 -0
  126. package/dist/job-queue.d.ts +297 -0
  127. package/dist/job-queue.js +3812 -0
  128. package/dist/job-queue.js.map +7 -0
  129. package/dist/js-coverage.d.ts +29 -0
  130. package/dist/js-coverage.js +56 -0
  131. package/dist/js-coverage.js.map +7 -0
  132. package/dist/js-router-detector.d.ts +17 -0
  133. package/dist/js-router-detector.js +90 -0
  134. package/dist/js-router-detector.js.map +7 -0
  135. package/dist/language-detector.d.ts +22 -0
  136. package/dist/language-detector.js +57 -0
  137. package/dist/language-detector.js.map +7 -0
  138. package/dist/link-classifier.d.ts +23 -0
  139. package/dist/link-classifier.js +40 -0
  140. package/dist/link-classifier.js.map +7 -0
  141. package/dist/live-view.d.ts +36 -0
  142. package/dist/live-view.js +105 -0
  143. package/dist/live-view.js.map +7 -0
  144. package/dist/locator-extractor.d.ts +46 -0
  145. package/dist/locator-extractor.js +220 -0
  146. package/dist/locator-extractor.js.map +7 -0
  147. package/dist/logger.d.ts +2 -0
  148. package/dist/logger.js +10 -0
  149. package/dist/logger.js.map +7 -0
  150. package/dist/markdown-extract.d.ts +8 -0
  151. package/dist/markdown-extract.js +54 -0
  152. package/dist/markdown-extract.js.map +7 -0
  153. package/dist/multi-context-handler.d.ts +55 -0
  154. package/dist/multi-context-handler.js +182 -0
  155. package/dist/multi-context-handler.js.map +7 -0
  156. package/dist/native-crawler.d.ts +69 -0
  157. package/dist/native-crawler.js +839 -0
  158. package/dist/native-crawler.js.map +7 -0
  159. package/dist/nested-window-crawler.d.ts +41 -0
  160. package/dist/nested-window-crawler.js +172 -0
  161. package/dist/nested-window-crawler.js.map +7 -0
  162. package/dist/network-action-correlator.d.ts +47 -0
  163. package/dist/network-action-correlator.js +209 -0
  164. package/dist/network-action-correlator.js.map +7 -0
  165. package/dist/network-observer.d.ts +49 -0
  166. package/dist/network-observer.js +149 -0
  167. package/dist/network-observer.js.map +7 -0
  168. package/dist/network-throttle.d.ts +25 -0
  169. package/dist/network-throttle.js +34 -0
  170. package/dist/network-throttle.js.map +7 -0
  171. package/dist/openapi-generator.d.ts +49 -0
  172. package/dist/openapi-generator.js +89 -0
  173. package/dist/openapi-generator.js.map +7 -0
  174. package/dist/pdf-extractor.d.ts +28 -0
  175. package/dist/pdf-extractor.js +81 -0
  176. package/dist/pdf-extractor.js.map +7 -0
  177. package/dist/performance-metrics-collector.d.ts +50 -0
  178. package/dist/performance-metrics-collector.js +155 -0
  179. package/dist/performance-metrics-collector.js.map +7 -0
  180. package/dist/performance-metrics.d.ts +52 -0
  181. package/dist/performance-metrics.js +83 -0
  182. package/dist/performance-metrics.js.map +7 -0
  183. package/dist/phash.d.ts +50 -0
  184. package/dist/phash.js +136 -0
  185. package/dist/phash.js.map +7 -0
  186. package/dist/pii-scrubber.d.ts +21 -0
  187. package/dist/pii-scrubber.js +75 -0
  188. package/dist/pii-scrubber.js.map +7 -0
  189. package/dist/playwright-recorder.d.ts +39 -0
  190. package/dist/playwright-recorder.js +123 -0
  191. package/dist/playwright-recorder.js.map +7 -0
  192. package/dist/policies/crawl-safety.d.ts +9 -0
  193. package/dist/policies/crawl-safety.js +41 -0
  194. package/dist/policies/crawl-safety.js.map +7 -0
  195. package/dist/profiles/domain-profile.d.ts +19 -0
  196. package/dist/profiles/domain-profile.js +160 -0
  197. package/dist/profiles/domain-profile.js.map +7 -0
  198. package/dist/proxy.d.ts +50 -0
  199. package/dist/proxy.js +165 -0
  200. package/dist/proxy.js.map +7 -0
  201. package/dist/rate-limiter.d.ts +31 -0
  202. package/dist/rate-limiter.js +64 -0
  203. package/dist/rate-limiter.js.map +7 -0
  204. package/dist/redirect-tracker.d.ts +37 -0
  205. package/dist/redirect-tracker.js +65 -0
  206. package/dist/redirect-tracker.js.map +7 -0
  207. package/dist/redis-frontier.d.ts +48 -0
  208. package/dist/redis-frontier.js +126 -0
  209. package/dist/redis-frontier.js.map +7 -0
  210. package/dist/redis-queue.d.ts +48 -0
  211. package/dist/redis-queue.js +165 -0
  212. package/dist/redis-queue.js.map +7 -0
  213. package/dist/response-cache.d.ts +38 -0
  214. package/dist/response-cache.js +140 -0
  215. package/dist/response-cache.js.map +7 -0
  216. package/dist/responsive-detector.d.ts +29 -0
  217. package/dist/responsive-detector.js +46 -0
  218. package/dist/responsive-detector.js.map +7 -0
  219. package/dist/retry-policy.d.ts +20 -0
  220. package/dist/retry-policy.js +54 -0
  221. package/dist/retry-policy.js.map +7 -0
  222. package/dist/robots-txt.d.ts +9 -0
  223. package/dist/robots-txt.js +77 -0
  224. package/dist/robots-txt.js.map +7 -0
  225. package/dist/screen-reader.d.ts +15 -0
  226. package/dist/screen-reader.js +48 -0
  227. package/dist/screen-reader.js.map +7 -0
  228. package/dist/screenshot-masker.d.ts +28 -0
  229. package/dist/screenshot-masker.js +62 -0
  230. package/dist/screenshot-masker.js.map +7 -0
  231. package/dist/seo-checker.d.ts +33 -0
  232. package/dist/seo-checker.js +91 -0
  233. package/dist/seo-checker.js.map +7 -0
  234. package/dist/service-worker-interceptor.d.ts +36 -0
  235. package/dist/service-worker-interceptor.js +136 -0
  236. package/dist/service-worker-interceptor.js.map +7 -0
  237. package/dist/session-capture.d.ts +39 -0
  238. package/dist/session-capture.js +274 -0
  239. package/dist/session-capture.js.map +7 -0
  240. package/dist/session-export.d.ts +49 -0
  241. package/dist/session-export.js +117 -0
  242. package/dist/session-export.js.map +7 -0
  243. package/dist/shadow-dom-crawler.d.ts +35 -0
  244. package/dist/shadow-dom-crawler.js +132 -0
  245. package/dist/shadow-dom-crawler.js.map +7 -0
  246. package/dist/sitemap-writer.d.ts +21 -0
  247. package/dist/sitemap-writer.js +47 -0
  248. package/dist/sitemap-writer.js.map +7 -0
  249. package/dist/sitemap.d.ts +51 -0
  250. package/dist/sitemap.js +160 -0
  251. package/dist/sitemap.js.map +7 -0
  252. package/dist/skyvern.d.ts +56 -0
  253. package/dist/skyvern.js +129 -0
  254. package/dist/skyvern.js.map +7 -0
  255. package/dist/sqs-queue.d.ts +13 -0
  256. package/dist/sqs-queue.js +115 -0
  257. package/dist/sqs-queue.js.map +7 -0
  258. package/dist/sso-token.d.ts +29 -0
  259. package/dist/sso-token.js +76 -0
  260. package/dist/sso-token.js.map +7 -0
  261. package/dist/state-graph.d.ts +59 -0
  262. package/dist/state-graph.js +193 -0
  263. package/dist/state-graph.js.map +7 -0
  264. package/dist/stealth/human-behavior.d.ts +20 -0
  265. package/dist/stealth/human-behavior.js +202 -0
  266. package/dist/stealth/human-behavior.js.map +7 -0
  267. package/dist/telemetry.d.ts +34 -0
  268. package/dist/telemetry.js +77 -0
  269. package/dist/telemetry.js.map +7 -0
  270. package/dist/test-executor.d.ts +81 -0
  271. package/dist/test-executor.js +443 -0
  272. package/dist/test-executor.js.map +7 -0
  273. package/dist/tls-fingerprint.d.ts +50 -0
  274. package/dist/tls-fingerprint.js +81 -0
  275. package/dist/tls-fingerprint.js.map +7 -0
  276. package/dist/url-pattern-completer.d.ts +28 -0
  277. package/dist/url-pattern-completer.js +122 -0
  278. package/dist/url-pattern-completer.js.map +7 -0
  279. package/dist/visual-diff-verdict.d.ts +40 -0
  280. package/dist/visual-diff-verdict.js +27 -0
  281. package/dist/visual-diff-verdict.js.map +7 -0
  282. package/dist/webhook-notifier.d.ts +30 -0
  283. package/dist/webhook-notifier.js +76 -0
  284. package/dist/webhook-notifier.js.map +7 -0
  285. package/dist/websocket-detector.d.ts +24 -0
  286. package/dist/websocket-detector.js +60 -0
  287. package/dist/websocket-detector.js.map +7 -0
  288. package/dist/worker.d.ts +1 -0
  289. package/dist/worker.js +33 -0
  290. package/dist/worker.js.map +7 -0
  291. package/package.json +49 -4
  292. package/src/accessibility-auditor.ts +102 -0
  293. package/src/accessibility-tree-crawler.ts +246 -0
  294. package/src/advanced-ui-probes.ts +470 -0
  295. package/src/ai-login.ts +298 -0
  296. package/src/auth-token-rotator.ts +89 -0
  297. package/src/auth.ts +418 -0
  298. package/src/browser-extension.ts +186 -0
  299. package/src/captcha-solver.ts +143 -0
  300. package/src/color-contrast.ts +116 -0
  301. package/src/content-chunker.ts +170 -0
  302. package/src/content-dedup.ts +99 -0
  303. package/src/cookie-consent.ts +106 -0
  304. package/src/cookie-jar.ts +91 -0
  305. package/src/crawl-session-manager.ts +231 -0
  306. package/src/crawler.ts +7123 -0
  307. package/src/crawler.ts.rej +12 -0
  308. package/src/crud-interaction.ts +386 -0
  309. package/src/custom-js-injector.ts +93 -0
  310. package/src/dark-mode-capture.ts +110 -0
  311. package/src/dead-link-detector.ts +76 -0
  312. package/src/dropdown-enumerator.ts +312 -0
  313. package/src/element-hash.ts +16 -0
  314. package/src/email-otp.ts +252 -0
  315. package/src/engine-router.ts +141 -0
  316. package/src/export/bulk-export.ts +85 -0
  317. package/src/export/vector-export.ts +160 -0
  318. package/src/extractors/advanced.ts +309 -0
  319. package/src/extractors/artifact-envelope.ts +111 -0
  320. package/src/extractors/branding-extractor.ts +159 -0
  321. package/src/extractors/summary-extractor.ts +49 -0
  322. package/src/failure-analysis-agent.ts +51 -0
  323. package/src/feature-flag-detector.ts +97 -0
  324. package/src/filter-pagination-crawler.ts +500 -0
  325. package/src/form-detector.ts +103 -0
  326. package/src/frontier.test.ts +64 -0
  327. package/src/frontier.ts +144 -0
  328. package/src/gap-pass.ts +165 -0
  329. package/src/graphql-detector.ts +129 -0
  330. package/src/http-engine.ts +453 -0
  331. package/src/incremental-diff.ts +259 -0
  332. package/src/index.ts +52 -0
  333. package/src/input-fuzzer.ts +129 -0
  334. package/src/interactive-probe.ts +1136 -0
  335. package/src/job-queue.test.ts +187 -0
  336. package/src/job-queue.ts +4504 -0
  337. package/src/js-coverage.ts +87 -0
  338. package/src/js-router-detector.ts +112 -0
  339. package/src/language-detector.ts +82 -0
  340. package/src/link-classifier.ts +65 -0
  341. package/src/live-view.ts +146 -0
  342. package/src/locator-extractor.ts +309 -0
  343. package/src/logger.ts +9 -0
  344. package/src/markdown-extract.test.ts +73 -0
  345. package/src/markdown-extract.ts +76 -0
  346. package/src/multi-context-handler.ts +296 -0
  347. package/src/native-crawler.ts +1108 -0
  348. package/src/nested-window-crawler.ts +310 -0
  349. package/src/network-action-correlator.ts +320 -0
  350. package/src/network-observer.ts +204 -0
  351. package/src/network-throttle.ts +69 -0
  352. package/src/openapi-generator.ts +135 -0
  353. package/src/pdf-extractor.ts +123 -0
  354. package/src/performance-metrics-collector.ts +243 -0
  355. package/src/performance-metrics.ts +134 -0
  356. package/src/phash.ts +184 -0
  357. package/src/pii-scrubber.ts +99 -0
  358. package/src/playwright-recorder.ts +170 -0
  359. package/src/policies/crawl-safety.ts +52 -0
  360. package/src/profiles/domain-profile.ts +190 -0
  361. package/src/proxy.ts +238 -0
  362. package/src/rate-limiter.ts +87 -0
  363. package/src/redirect-tracker.ts +97 -0
  364. package/src/redis-frontier.ts +143 -0
  365. package/src/redis-queue.ts +208 -0
  366. package/src/response-cache.ts +150 -0
  367. package/src/responsive-detector.ts +92 -0
  368. package/src/retry-policy.ts +87 -0
  369. package/src/robots-txt.ts +96 -0
  370. package/src/screen-reader.ts +98 -0
  371. package/src/screenshot-masker.ts +98 -0
  372. package/src/seo-checker.ts +134 -0
  373. package/src/service-worker-interceptor.ts +185 -0
  374. package/src/session-capture.ts +335 -0
  375. package/src/session-export.test.ts +75 -0
  376. package/src/session-export.ts +172 -0
  377. package/src/shadow-dom-crawler.ts +198 -0
  378. package/src/sitemap-writer.ts +65 -0
  379. package/src/sitemap.test.ts +127 -0
  380. package/src/sitemap.ts +233 -0
  381. package/src/skyvern.ts +199 -0
  382. package/src/sqs-queue.ts +129 -0
  383. package/src/sso-token.ts +120 -0
  384. package/src/state-graph.ts +280 -0
  385. package/src/stealth/human-behavior.ts +227 -0
  386. package/src/telemetry.ts +122 -0
  387. package/src/test-executor.test.ts +72 -0
  388. package/src/test-executor.ts +578 -0
  389. package/src/tls-fingerprint.ts +111 -0
  390. package/src/url-pattern-completer.ts +161 -0
  391. package/src/vendor.d.ts +20 -0
  392. package/src/visual-diff-verdict.test.ts +80 -0
  393. package/src/visual-diff-verdict.ts +59 -0
  394. package/src/webhook-notifier.ts +109 -0
  395. package/src/websocket-detector.ts +83 -0
  396. package/src/worker.ts +50 -0
  397. package/tsconfig.json +13 -0
  398. package/types/accessibility-auditor.d.ts +29 -0
  399. package/types/accessibility-tree-crawler.d.ts +44 -0
  400. package/types/advanced-ui-probes.d.ts +47 -0
  401. package/types/ai-login.d.ts +32 -0
  402. package/types/auth-token-rotator.d.ts +47 -0
  403. package/types/auth.d.ts +20 -0
  404. package/types/browser-extension.d.ts +37 -0
  405. package/types/bull-worker.d.ts +6 -0
  406. package/types/captcha-solver.d.ts +16 -0
  407. package/types/color-contrast.d.ts +30 -0
  408. package/types/content-chunker.d.ts +18 -0
  409. package/types/content-dedup.d.ts +23 -0
  410. package/types/cookie-consent.d.ts +25 -0
  411. package/types/cookie-jar.d.ts +20 -0
  412. package/types/crawl-session-manager.d.ts +44 -0
  413. package/types/crawler.d.ts +233 -0
  414. package/types/crud-interaction.d.ts +31 -0
  415. package/types/custom-js-injector.d.ts +42 -0
  416. package/types/dark-mode-capture.d.ts +23 -0
  417. package/types/dead-link-detector.d.ts +37 -0
  418. package/types/dropdown-enumerator.d.ts +20 -0
  419. package/types/element-hash.d.ts +9 -0
  420. package/types/email-otp.d.ts +42 -0
  421. package/types/engine-router.d.ts +47 -0
  422. package/types/export/bulk-export.d.ts +26 -0
  423. package/types/export/vector-export.d.ts +76 -0
  424. package/types/extractors/advanced.d.ts +64 -0
  425. package/types/extractors/artifact-envelope.d.ts +63 -0
  426. package/types/extractors/branding-extractor.d.ts +46 -0
  427. package/types/extractors/summary-extractor.d.ts +10 -0
  428. package/types/failure-analysis-agent.d.ts +16 -0
  429. package/types/feature-flag-detector.d.ts +30 -0
  430. package/types/filter-pagination-crawler.d.ts +52 -0
  431. package/types/form-detector.d.ts +34 -0
  432. package/types/frontier.d.ts +40 -0
  433. package/types/gap-pass.d.ts +36 -0
  434. package/types/graphql-detector.d.ts +39 -0
  435. package/types/http-engine.d.ts +80 -0
  436. package/types/incremental-diff.d.ts +116 -0
  437. package/types/index.d.ts +52 -0
  438. package/types/input-fuzzer.d.ts +30 -0
  439. package/types/interactive-probe.d.ts +144 -0
  440. package/types/job-queue.d.ts +308 -0
  441. package/types/js-coverage.d.ts +29 -0
  442. package/types/js-router-detector.d.ts +17 -0
  443. package/types/language-detector.d.ts +22 -0
  444. package/types/link-classifier.d.ts +23 -0
  445. package/types/live-view.d.ts +36 -0
  446. package/types/locator-extractor.d.ts +46 -0
  447. package/types/logger.d.ts +2 -0
  448. package/types/markdown-extract.d.ts +8 -0
  449. package/types/multi-context-handler.d.ts +55 -0
  450. package/types/native-crawler.d.ts +69 -0
  451. package/types/nested-window-crawler.d.ts +41 -0
  452. package/types/network-action-correlator.d.ts +47 -0
  453. package/types/network-observer.d.ts +49 -0
  454. package/types/network-throttle.d.ts +25 -0
  455. package/types/openapi-generator.d.ts +49 -0
  456. package/types/pdf-extractor.d.ts +28 -0
  457. package/types/performance-metrics-collector.d.ts +50 -0
  458. package/types/performance-metrics.d.ts +52 -0
  459. package/types/phash.d.ts +50 -0
  460. package/types/pii-scrubber.d.ts +21 -0
  461. package/types/playwright-recorder.d.ts +39 -0
  462. package/types/policies/crawl-safety.d.ts +9 -0
  463. package/types/profiles/domain-profile.d.ts +19 -0
  464. package/types/proxy.d.ts +50 -0
  465. package/types/rate-limiter.d.ts +31 -0
  466. package/types/redirect-tracker.d.ts +37 -0
  467. package/types/redis-frontier.d.ts +48 -0
  468. package/types/redis-queue.d.ts +48 -0
  469. package/types/response-cache.d.ts +38 -0
  470. package/types/responsive-detector.d.ts +29 -0
  471. package/types/retry-policy.d.ts +20 -0
  472. package/types/robots-txt.d.ts +9 -0
  473. package/types/screen-reader.d.ts +15 -0
  474. package/types/screenshot-masker.d.ts +28 -0
  475. package/types/seo-checker.d.ts +33 -0
  476. package/types/service-worker-interceptor.d.ts +36 -0
  477. package/types/session-capture.d.ts +39 -0
  478. package/types/session-export.d.ts +49 -0
  479. package/types/shadow-dom-crawler.d.ts +35 -0
  480. package/types/sitemap-writer.d.ts +21 -0
  481. package/types/sitemap.d.ts +51 -0
  482. package/types/skyvern.d.ts +56 -0
  483. package/types/sqs-queue.d.ts +13 -0
  484. package/types/sso-token.d.ts +29 -0
  485. package/types/state-graph.d.ts +59 -0
  486. package/types/stealth/human-behavior.d.ts +20 -0
  487. package/types/telemetry.d.ts +34 -0
  488. package/types/test-executor.d.ts +84 -0
  489. package/types/tls-fingerprint.d.ts +50 -0
  490. package/types/url-pattern-completer.d.ts +28 -0
  491. package/types/visual-diff-verdict.d.ts +40 -0
  492. package/types/webhook-notifier.d.ts +30 -0
  493. package/types/websocket-detector.d.ts +24 -0
  494. package/types/worker.d.ts +1 -0
@@ -0,0 +1,193 @@
1
+ function fnv1a32(token) {
2
+ let h = 2166136261;
3
+ for (let i = 0; i < token.length; i++) {
4
+ h = Math.imul(h ^ token.charCodeAt(i), 16777619);
5
+ h = h >>> 0;
6
+ }
7
+ return h;
8
+ }
9
+ function simHash32(text) {
10
+ const tokens = text.split(/\W+/).filter((t) => t.length > 2).slice(0, 500);
11
+ const vec = new Array(32).fill(0);
12
+ for (const token of tokens) {
13
+ const h = fnv1a32(token);
14
+ for (let b = 0; b < 32; b++) {
15
+ vec[b] += h >>> b & 1 ? 1 : -1;
16
+ }
17
+ }
18
+ let result = 0;
19
+ for (let b = 0; b < 32; b++) {
20
+ if (vec[b] > 0) result |= 1 << b;
21
+ }
22
+ return result >>> 0;
23
+ }
24
+ function hammingDistance32(a, b) {
25
+ let n = (a ^ b) >>> 0;
26
+ n = n - (n >>> 1 & 1431655765);
27
+ n = (n & 858993459) + (n >>> 2 & 858993459);
28
+ n = n + (n >>> 4) & 252645135;
29
+ return Math.imul(n, 16843009) >>> 24;
30
+ }
31
+ const STRIP_PARAMS = /* @__PURE__ */ new Set([
32
+ "utm_source",
33
+ "utm_medium",
34
+ "utm_campaign",
35
+ "ref",
36
+ "_ga",
37
+ "fbclid",
38
+ "session_id"
39
+ ]);
40
+ function normalizeUrl(raw) {
41
+ try {
42
+ const u = new URL(raw);
43
+ u.hash = "";
44
+ const keep = [];
45
+ u.searchParams.forEach((v, k) => {
46
+ if (!STRIP_PARAMS.has(k)) keep.push([k, v]);
47
+ });
48
+ keep.sort((a, b) => a[0].localeCompare(b[0]));
49
+ u.search = keep.length ? "?" + keep.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&") : "";
50
+ return u.toString();
51
+ } catch {
52
+ return raw;
53
+ }
54
+ }
55
+ function computeStateId(normalizedUrl, hash) {
56
+ let path = normalizedUrl.slice(0, 40).replace(/[^a-zA-Z0-9]/g, "_");
57
+ const hex = hash.toString(16).padStart(8, "0");
58
+ return `${path}_${hex}`;
59
+ }
60
+ async function fingerprintPage(page, visitedAt) {
61
+ let visibleText = "";
62
+ let interactiveCount = 0;
63
+ try {
64
+ visibleText = await page.evaluate(() => {
65
+ const el = document.querySelector("main") ?? document.body;
66
+ return el.innerText ?? "";
67
+ });
68
+ } catch {
69
+ visibleText = "";
70
+ }
71
+ try {
72
+ interactiveCount = await page.evaluate(
73
+ () => document.querySelectorAll(
74
+ 'a[href], button, input, select, textarea, [role="button"], [role="link"], [tabindex]'
75
+ ).length
76
+ );
77
+ } catch {
78
+ interactiveCount = 0;
79
+ }
80
+ const simHashValue = simHash32(visibleText + visitedAt.slice(0, 10));
81
+ const fingerprint = simHashValue.toString(16).padStart(8, "0");
82
+ return { fingerprint, visibleText, interactiveCount, simHashValue };
83
+ }
84
+ class ScreenTransitionGraph {
85
+ states = /* @__PURE__ */ new Map();
86
+ transitions = [];
87
+ /** Maps simHash value → array of state ids with that hash (for near-dup lookup) */
88
+ hashIndex = /* @__PURE__ */ new Map();
89
+ // -------------------------------------------------------------------------
90
+ // State management
91
+ // -------------------------------------------------------------------------
92
+ addState(node) {
93
+ if (this.states.has(node.id)) {
94
+ return { added: false, duplicateOf: node.id };
95
+ }
96
+ for (const [indexedHash, ids] of this.hashIndex) {
97
+ if (hammingDistance32(node.simHashValue, indexedHash) < 3) {
98
+ return { added: false, duplicateOf: ids[0] };
99
+ }
100
+ }
101
+ this.states.set(node.id, node);
102
+ const bucket = this.hashIndex.get(node.simHashValue);
103
+ if (bucket) {
104
+ bucket.push(node.id);
105
+ } else {
106
+ this.hashIndex.set(node.simHashValue, [node.id]);
107
+ }
108
+ return { added: true };
109
+ }
110
+ addTransition(fromId, toId, action, label, triggeredAt) {
111
+ this.transitions.push({ fromId, toId, action, label, triggeredAt });
112
+ }
113
+ isDuplicate(url, visibleText, threshold = 3) {
114
+ const normalized = normalizeUrl(url);
115
+ const hash = simHash32(visibleText);
116
+ for (const [indexedHash] of this.hashIndex) {
117
+ if (hammingDistance32(hash, indexedHash) < threshold) return true;
118
+ }
119
+ for (const node of this.states.values()) {
120
+ if (node.normalizedUrl === normalized) return true;
121
+ }
122
+ return false;
123
+ }
124
+ // -------------------------------------------------------------------------
125
+ // Reporting
126
+ // -------------------------------------------------------------------------
127
+ getCoverageReport() {
128
+ const totalStates = this.states.size;
129
+ const totalTransitions = this.transitions.length;
130
+ const uniqueUrls = new Set(
131
+ Array.from(this.states.values()).map((n) => n.normalizedUrl)
132
+ ).size;
133
+ const interactiveElementsTotal = Array.from(this.states.values()).reduce(
134
+ (sum, n) => sum + n.interactiveElementCount,
135
+ 0
136
+ );
137
+ const estimatedCoveragePercent = Math.min(
138
+ 100,
139
+ totalTransitions / Math.max(1, totalStates) * 50
140
+ );
141
+ return {
142
+ totalStates,
143
+ totalTransitions,
144
+ uniqueUrls,
145
+ interactiveElementsTotal,
146
+ estimatedCoveragePercent
147
+ };
148
+ }
149
+ // -------------------------------------------------------------------------
150
+ // Serialisation
151
+ // -------------------------------------------------------------------------
152
+ toJSON() {
153
+ return {
154
+ states: Array.from(this.states.values()),
155
+ transitions: this.transitions
156
+ };
157
+ }
158
+ static fromJSON(data) {
159
+ const graph = new ScreenTransitionGraph();
160
+ for (const node of data.states) {
161
+ graph.states.set(node.id, node);
162
+ const bucket = graph.hashIndex.get(node.simHashValue);
163
+ if (bucket) {
164
+ bucket.push(node.id);
165
+ } else {
166
+ graph.hashIndex.set(node.simHashValue, [node.id]);
167
+ }
168
+ }
169
+ graph.transitions = [...data.transitions];
170
+ return graph;
171
+ }
172
+ // -------------------------------------------------------------------------
173
+ // Accessors
174
+ // -------------------------------------------------------------------------
175
+ getState(id) {
176
+ return this.states.get(id);
177
+ }
178
+ getAllStates() {
179
+ return Array.from(this.states.values());
180
+ }
181
+ getTransitionsFrom(id) {
182
+ return this.transitions.filter((t) => t.fromId === id);
183
+ }
184
+ }
185
+ export {
186
+ ScreenTransitionGraph,
187
+ computeStateId,
188
+ fingerprintPage,
189
+ hammingDistance32,
190
+ normalizeUrl,
191
+ simHash32
192
+ };
193
+ //# sourceMappingURL=state-graph.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/state-graph.ts"],
4
+ "sourcesContent": ["import type { Page } from 'playwright';\n\n// ---------------------------------------------------------------------------\n// Internal: FNV-1a 32-bit SimHash\n// ---------------------------------------------------------------------------\n\nfunction fnv1a32(token: string): number {\n let h = 2166136261;\n for (let i = 0; i < token.length; i++) {\n h = Math.imul(h ^ token.charCodeAt(i), 16777619);\n h = h >>> 0;\n }\n return h;\n}\n\nexport function simHash32(text: string): number {\n const tokens = text\n .split(/\\W+/)\n .filter((t) => t.length > 2)\n .slice(0, 500);\n\n const vec = new Array<number>(32).fill(0);\n\n for (const token of tokens) {\n const h = fnv1a32(token);\n for (let b = 0; b < 32; b++) {\n vec[b] += (h >>> b) & 1 ? 1 : -1;\n }\n }\n\n let result = 0;\n for (let b = 0; b < 32; b++) {\n if (vec[b] > 0) result |= 1 << b;\n }\n return result >>> 0;\n}\n\nexport function hammingDistance32(a: number, b: number): number {\n let n = (a ^ b) >>> 0;\n n = n - ((n >>> 1) & 0x55555555);\n n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);\n n = (n + (n >>> 4)) & 0x0f0f0f0f;\n return Math.imul(n, 0x01010101) >>> 24;\n}\n\n// ---------------------------------------------------------------------------\n// URL normalisation\n// ---------------------------------------------------------------------------\n\nconst STRIP_PARAMS = new Set([\n 'utm_source', 'utm_medium', 'utm_campaign',\n 'ref', '_ga', 'fbclid', 'session_id',\n]);\n\nexport function normalizeUrl(raw: string): string {\n try {\n const u = new URL(raw);\n u.hash = '';\n const keep: Array<[string, string]> = [];\n u.searchParams.forEach((v, k) => {\n if (!STRIP_PARAMS.has(k)) keep.push([k, v]);\n });\n keep.sort((a, b) => a[0].localeCompare(b[0]));\n u.search = keep.length\n ? '?' + keep.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&')\n : '';\n return u.toString();\n } catch {\n return raw;\n }\n}\n\nexport function computeStateId(normalizedUrl: string, hash: number): string {\n let path = normalizedUrl.slice(0, 40).replace(/[^a-zA-Z0-9]/g, '_');\n const hex = hash.toString(16).padStart(8, '0');\n return `${path}_${hex}`;\n}\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface UIStateNode {\n id: string;\n url: string;\n normalizedUrl: string;\n title: string;\n interactiveElementCount: number;\n domFingerprint: string;\n simHashValue: number;\n visitedAt: string;\n}\n\nexport interface StateTransition {\n fromId: string;\n toId: string;\n action: string;\n label: string;\n triggeredAt: string;\n}\n\nexport interface CoverageReport {\n totalStates: number;\n totalTransitions: number;\n uniqueUrls: number;\n interactiveElementsTotal: number;\n estimatedCoveragePercent: number;\n}\n\n// ---------------------------------------------------------------------------\n// Page fingerprinting\n// ---------------------------------------------------------------------------\n\nexport async function fingerprintPage(\n page: Page,\n visitedAt: string,\n): Promise<{\n fingerprint: string;\n visibleText: string;\n interactiveCount: number;\n simHashValue: number;\n}> {\n let visibleText = '';\n let interactiveCount = 0;\n\n try {\n visibleText = await page.evaluate(() => {\n const el = document.querySelector('main') ?? document.body;\n return (el as HTMLElement).innerText ?? '';\n });\n } catch {\n visibleText = '';\n }\n\n try {\n interactiveCount = await page.evaluate(() =>\n document.querySelectorAll(\n 'a[href], button, input, select, textarea, [role=\"button\"], [role=\"link\"], [tabindex]',\n ).length,\n );\n } catch {\n interactiveCount = 0;\n }\n\n const simHashValue = simHash32(visibleText + visitedAt.slice(0, 10));\n const fingerprint = simHashValue.toString(16).padStart(8, '0');\n\n return { fingerprint, visibleText, interactiveCount, simHashValue };\n}\n\n// ---------------------------------------------------------------------------\n// ScreenTransitionGraph\n// ---------------------------------------------------------------------------\n\nexport class ScreenTransitionGraph {\n private states = new Map<string, UIStateNode>();\n private transitions: StateTransition[] = [];\n /** Maps simHash value \u2192 array of state ids with that hash (for near-dup lookup) */\n private hashIndex = new Map<number, string[]>();\n\n // -------------------------------------------------------------------------\n // State management\n // -------------------------------------------------------------------------\n\n addState(node: UIStateNode): { added: boolean; duplicateOf?: string } {\n if (this.states.has(node.id)) {\n return { added: false, duplicateOf: node.id };\n }\n\n // Check near-duplicate via hamming distance across all indexed hashes\n for (const [indexedHash, ids] of this.hashIndex) {\n if (hammingDistance32(node.simHashValue, indexedHash) < 3) {\n return { added: false, duplicateOf: ids[0] };\n }\n }\n\n this.states.set(node.id, node);\n\n const bucket = this.hashIndex.get(node.simHashValue);\n if (bucket) {\n bucket.push(node.id);\n } else {\n this.hashIndex.set(node.simHashValue, [node.id]);\n }\n\n return { added: true };\n }\n\n addTransition(\n fromId: string,\n toId: string,\n action: string,\n label: string,\n triggeredAt: string,\n ): void {\n this.transitions.push({ fromId, toId, action, label, triggeredAt });\n }\n\n isDuplicate(url: string, visibleText: string, threshold = 3): boolean {\n const normalized = normalizeUrl(url);\n const hash = simHash32(visibleText);\n for (const [indexedHash] of this.hashIndex) {\n if (hammingDistance32(hash, indexedHash) < threshold) return true;\n }\n // Also check exact normalized URL match\n for (const node of this.states.values()) {\n if (node.normalizedUrl === normalized) return true;\n }\n return false;\n }\n\n // -------------------------------------------------------------------------\n // Reporting\n // -------------------------------------------------------------------------\n\n getCoverageReport(): CoverageReport {\n const totalStates = this.states.size;\n const totalTransitions = this.transitions.length;\n const uniqueUrls = new Set(\n Array.from(this.states.values()).map((n) => n.normalizedUrl),\n ).size;\n const interactiveElementsTotal = Array.from(this.states.values()).reduce(\n (sum, n) => sum + n.interactiveElementCount,\n 0,\n );\n const estimatedCoveragePercent = Math.min(\n 100,\n (totalTransitions / Math.max(1, totalStates)) * 50,\n );\n return {\n totalStates,\n totalTransitions,\n uniqueUrls,\n interactiveElementsTotal,\n estimatedCoveragePercent,\n };\n }\n\n // -------------------------------------------------------------------------\n // Serialisation\n // -------------------------------------------------------------------------\n\n toJSON(): { states: UIStateNode[]; transitions: StateTransition[] } {\n return {\n states: Array.from(this.states.values()),\n transitions: this.transitions,\n };\n }\n\n static fromJSON(data: { states: UIStateNode[]; transitions: StateTransition[] }): ScreenTransitionGraph {\n const graph = new ScreenTransitionGraph();\n for (const node of data.states) {\n graph.states.set(node.id, node);\n const bucket = graph.hashIndex.get(node.simHashValue);\n if (bucket) {\n bucket.push(node.id);\n } else {\n graph.hashIndex.set(node.simHashValue, [node.id]);\n }\n }\n graph.transitions = [...data.transitions];\n return graph;\n }\n\n // -------------------------------------------------------------------------\n // Accessors\n // -------------------------------------------------------------------------\n\n getState(id: string): UIStateNode | undefined {\n return this.states.get(id);\n }\n\n getAllStates(): UIStateNode[] {\n return Array.from(this.states.values());\n }\n\n getTransitionsFrom(id: string): StateTransition[] {\n return this.transitions.filter((t) => t.fromId === id);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,20 @@
1
+ import type { Page } from 'playwright';
2
+ export declare function humanDelay(min?: number, max?: number): Promise<void>;
3
+ export declare function simulateMouseMovement(page: Page, targetX: number, targetY: number): Promise<void>;
4
+ export declare function simulateMouseHover(page: Page, selector: string): Promise<void>;
5
+ export declare function simulateClick(page: Page, selector: string): Promise<void>;
6
+ export declare function injectFingerprintOverrides(page: Page): Promise<void>;
7
+ export declare function infiniteScrollToBottom(page: Page, opts?: {
8
+ maxScrolls?: number;
9
+ scrollDelay?: number;
10
+ stabilizeMs?: number;
11
+ }, rawPage?: any): Promise<{
12
+ scrollCount: number;
13
+ heightReached: number;
14
+ }>;
15
+ export declare function extractIframeContent(page: Page): Promise<Array<{
16
+ src: string;
17
+ content: string;
18
+ markdown: string;
19
+ }>>;
20
+ export declare function pierceShadowDom(page: Page): Promise<string>;
@@ -0,0 +1,202 @@
1
+ function gaussian(mean, sigma) {
2
+ const u1 = Math.random();
3
+ const u2 = Math.random();
4
+ const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
5
+ return mean + z * sigma;
6
+ }
7
+ async function humanDelay(min = 80, max = 450) {
8
+ const mean = (min + max) / 2;
9
+ const sigma = (max - min) / 6;
10
+ const delay = Math.max(min, Math.min(max, gaussian(mean, sigma)));
11
+ await new Promise((r) => setTimeout(r, Math.round(delay)));
12
+ }
13
+ async function simulateMouseMovement(page, targetX, targetY) {
14
+ try {
15
+ const mouse = page.mouse;
16
+ const steps = 8 + Math.floor(Math.random() * 8);
17
+ const startX = targetX - 100 + Math.random() * 200;
18
+ const startY = targetY - 100 + Math.random() * 200;
19
+ const cpX = (startX + targetX) / 2 + (Math.random() - 0.5) * 80;
20
+ const cpY = (startY + targetY) / 2 + (Math.random() - 0.5) * 80;
21
+ for (let i = 0; i <= steps; i++) {
22
+ const t = i / steps;
23
+ const x = (1 - t) * (1 - t) * startX + 2 * (1 - t) * t * cpX + t * t * targetX;
24
+ const y = (1 - t) * (1 - t) * startY + 2 * (1 - t) * t * cpY + t * t * targetY;
25
+ await mouse.move(x + (Math.random() - 0.5) * 2, y + (Math.random() - 0.5) * 2);
26
+ if (i < steps) await humanDelay(8, 25);
27
+ }
28
+ await mouse.move(targetX + (Math.random() - 0.5) * 4, targetY + (Math.random() - 0.5) * 4);
29
+ await humanDelay(30, 80);
30
+ await mouse.move(targetX, targetY);
31
+ } catch {
32
+ }
33
+ }
34
+ async function simulateMouseHover(page, selector) {
35
+ try {
36
+ const el = await page.$(selector);
37
+ if (!el) return;
38
+ const box = await el.boundingBox();
39
+ if (!box) return;
40
+ const cx = box.x + box.width / 2;
41
+ const cy = box.y + box.height / 2;
42
+ await simulateMouseMovement(page, cx, cy);
43
+ await humanDelay(100, 300);
44
+ } catch {
45
+ }
46
+ }
47
+ async function simulateClick(page, selector) {
48
+ try {
49
+ await simulateMouseHover(page, selector);
50
+ await humanDelay(50, 150);
51
+ await page.click(selector, { delay: Math.round(gaussian(80, 30)) });
52
+ } catch {
53
+ }
54
+ }
55
+ async function injectFingerprintOverrides(page) {
56
+ await page.addInitScript(() => {
57
+ const origToDataURL = HTMLCanvasElement.prototype.toDataURL;
58
+ HTMLCanvasElement.prototype.toDataURL = function(...args) {
59
+ const ctx = this.getContext("2d");
60
+ if (ctx) {
61
+ const imageData = ctx.getImageData(0, 0, this.width, this.height);
62
+ for (let i = 0; i < imageData.data.length; i += 4) {
63
+ imageData.data[i] = Math.max(0, Math.min(255, imageData.data[i] + (Math.random() < 0.01 ? Math.random() > 0.5 ? 1 : -1 : 0)));
64
+ }
65
+ ctx.putImageData(imageData, 0, 0);
66
+ }
67
+ return origToDataURL.apply(this, args);
68
+ };
69
+ const origGetParam = WebGLRenderingContext.prototype.getParameter;
70
+ WebGLRenderingContext.prototype.getParameter = function(parameter) {
71
+ const UNMASKED_VENDOR_WEBGL = 37445;
72
+ const UNMASKED_RENDERER_WEBGL = 37446;
73
+ if (parameter === UNMASKED_VENDOR_WEBGL) return "Intel Inc.";
74
+ if (parameter === UNMASKED_RENDERER_WEBGL) return "Intel Iris OpenGL Engine";
75
+ return origGetParam.call(this, parameter);
76
+ };
77
+ const cpuCounts = [4, 6, 8, 8];
78
+ Object.defineProperty(navigator, "hardwareConcurrency", {
79
+ get: () => cpuCounts[Math.floor(Math.random() * cpuCounts.length)],
80
+ configurable: true
81
+ });
82
+ Object.defineProperty(navigator, "deviceMemory", {
83
+ get: () => [4, 8][Math.floor(Math.random() * 2)],
84
+ configurable: true
85
+ });
86
+ }).catch(() => {
87
+ });
88
+ }
89
+ async function infiniteScrollToBottom(page, opts = {}, rawPage) {
90
+ const { maxScrolls = 50, scrollDelay = 400, stabilizeMs = 600 } = opts;
91
+ let scrollCount = 0;
92
+ let stableScrollCount = 0;
93
+ let previousHeight = 0;
94
+ let cdpForWheel = null;
95
+ let viewW = 1280;
96
+ let viewH = 800;
97
+ if (rawPage && typeof rawPage.context === "function") {
98
+ try {
99
+ const ctx = rawPage.context();
100
+ if (typeof ctx?.newCDPSession === "function") {
101
+ cdpForWheel = await ctx.newCDPSession(rawPage);
102
+ const { result } = await cdpForWheel.send("Runtime.evaluate", {
103
+ expression: `({"w":window.innerWidth,"h":window.innerHeight})`,
104
+ returnByValue: true
105
+ }).catch(() => ({ result: { value: null } }));
106
+ if (result?.value) {
107
+ viewW = result.value.w ?? 1280;
108
+ viewH = result.value.h ?? 800;
109
+ }
110
+ }
111
+ } catch {
112
+ cdpForWheel = null;
113
+ }
114
+ }
115
+ try {
116
+ while (scrollCount < maxScrolls) {
117
+ previousHeight = await page.evaluate(() => document.documentElement.scrollHeight).catch(() => 0);
118
+ const scrollBy = 500 + Math.floor(Math.random() * 300);
119
+ await page.evaluate((by) => window.scrollBy(0, by), scrollBy).catch(() => {
120
+ });
121
+ if (cdpForWheel) {
122
+ await cdpForWheel.send("Input.dispatchMouseEvent", {
123
+ type: "mouseWheel",
124
+ x: Math.floor(viewW / 2),
125
+ y: Math.floor(viewH / 2),
126
+ deltaX: 0,
127
+ deltaY: scrollBy,
128
+ modifiers: 0
129
+ }).catch(() => {
130
+ });
131
+ }
132
+ await humanDelay(scrollDelay - 100, scrollDelay + 200);
133
+ await new Promise((r) => setTimeout(r, stabilizeMs));
134
+ scrollCount++;
135
+ const newHeight = await page.evaluate(() => document.documentElement.scrollHeight).catch(() => 0);
136
+ if (newHeight - previousHeight < 10) {
137
+ stableScrollCount++;
138
+ if (stableScrollCount >= 3) break;
139
+ } else {
140
+ stableScrollCount = 0;
141
+ }
142
+ previousHeight = newHeight;
143
+ }
144
+ } catch {
145
+ }
146
+ if (cdpForWheel) cdpForWheel.detach().catch(() => {
147
+ });
148
+ return { scrollCount, heightReached: previousHeight };
149
+ }
150
+ async function extractIframeContent(page) {
151
+ const results = [];
152
+ try {
153
+ const iframeSrcs = await page.evaluate(
154
+ () => Array.from(document.querySelectorAll("iframe")).map((f) => f.getAttribute("src") ?? f.getAttribute("data-src") ?? "")
155
+ ).catch(() => []);
156
+ for (const frame of page.frames()) {
157
+ const src = frame.url();
158
+ if (!src || src === "about:blank" || src === page.url()) continue;
159
+ try {
160
+ const content = await frame.content().catch(() => "");
161
+ if (!content || content.length < 50) continue;
162
+ const text = content.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
163
+ results.push({ src, content: content.slice(0, 1e4), markdown: text.slice(0, 5e3) });
164
+ } catch {
165
+ }
166
+ }
167
+ } catch {
168
+ }
169
+ return results;
170
+ }
171
+ async function pierceShadowDom(page) {
172
+ try {
173
+ return await page.evaluate(() => {
174
+ const parts = [];
175
+ function walkShadow(root) {
176
+ const shadow = root.shadowRoot;
177
+ if (shadow) {
178
+ parts.push(shadow.innerHTML ?? "");
179
+ for (const child of [...shadow.querySelectorAll("*")]) walkShadow(child);
180
+ }
181
+ for (const child of Array.from(root.querySelectorAll(":not(script):not(style)"))) {
182
+ if (child.shadowRoot) walkShadow(child);
183
+ }
184
+ }
185
+ walkShadow(document.body);
186
+ return parts.join("\n").replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "").replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 1e4);
187
+ }).catch(() => "");
188
+ } catch {
189
+ return "";
190
+ }
191
+ }
192
+ export {
193
+ extractIframeContent,
194
+ humanDelay,
195
+ infiniteScrollToBottom,
196
+ injectFingerprintOverrides,
197
+ pierceShadowDom,
198
+ simulateClick,
199
+ simulateMouseHover,
200
+ simulateMouseMovement
201
+ };
202
+ //# sourceMappingURL=human-behavior.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/stealth/human-behavior.ts"],
4
+ "sourcesContent": ["import type { Page } from 'playwright';\n\n// Gaussian random using Box-Muller transform\nfunction gaussian(mean: number, sigma: number): number {\n const u1 = Math.random();\n const u2 = Math.random();\n const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);\n return mean + z * sigma;\n}\n\nexport async function humanDelay(min = 80, max = 450): Promise<void> {\n const mean = (min + max) / 2;\n const sigma = (max - min) / 6;\n const delay = Math.max(min, Math.min(max, gaussian(mean, sigma)));\n await new Promise(r => setTimeout(r, Math.round(delay)));\n}\n\nexport async function simulateMouseMovement(page: Page, targetX: number, targetY: number): Promise<void> {\n try {\n const mouse = page.mouse;\n const steps = 8 + Math.floor(Math.random() * 8);\n // Generate Bezier control points with slight perpendicular offset\n const startX = targetX - 100 + Math.random() * 200;\n const startY = targetY - 100 + Math.random() * 200;\n const cpX = (startX + targetX) / 2 + (Math.random() - 0.5) * 80;\n const cpY = (startY + targetY) / 2 + (Math.random() - 0.5) * 80;\n\n for (let i = 0; i <= steps; i++) {\n const t = i / steps;\n // Quadratic Bezier: B(t) = (1-t)^2 * P0 + 2(1-t)t * P1 + t^2 * P2\n const x = (1 - t) * (1 - t) * startX + 2 * (1 - t) * t * cpX + t * t * targetX;\n const y = (1 - t) * (1 - t) * startY + 2 * (1 - t) * t * cpY + t * t * targetY;\n await mouse.move(x + (Math.random() - 0.5) * 2, y + (Math.random() - 0.5) * 2);\n if (i < steps) await humanDelay(8, 25);\n }\n // Small overshoot correction\n await mouse.move(targetX + (Math.random() - 0.5) * 4, targetY + (Math.random() - 0.5) * 4);\n await humanDelay(30, 80);\n await mouse.move(targetX, targetY);\n } catch { /* non-fatal */ }\n}\n\nexport async function simulateMouseHover(page: Page, selector: string): Promise<void> {\n try {\n const el = await page.$(selector);\n if (!el) return;\n const box = await el.boundingBox();\n if (!box) return;\n const cx = box.x + box.width / 2;\n const cy = box.y + box.height / 2;\n await simulateMouseMovement(page, cx, cy);\n await humanDelay(100, 300);\n } catch { /* non-fatal */ }\n}\n\nexport async function simulateClick(page: Page, selector: string): Promise<void> {\n try {\n await simulateMouseHover(page, selector);\n await humanDelay(50, 150);\n await page.click(selector, { delay: Math.round(gaussian(80, 30)) });\n } catch { /* non-fatal */ }\n}\n\nexport async function injectFingerprintOverrides(page: Page): Promise<void> {\n await page.addInitScript(() => {\n // Canvas noise \u2014 subtle per-pixel perturbation\n const origToDataURL = HTMLCanvasElement.prototype.toDataURL;\n HTMLCanvasElement.prototype.toDataURL = function(this: HTMLCanvasElement, ...args: any[]) {\n const ctx = this.getContext('2d');\n if (ctx) {\n const imageData = ctx.getImageData(0, 0, this.width, this.height);\n for (let i = 0; i < imageData.data.length; i += 4) {\n imageData.data[i] = Math.max(0, Math.min(255, imageData.data[i] + (Math.random() < 0.01 ? (Math.random() > 0.5 ? 1 : -1) : 0)));\n }\n ctx.putImageData(imageData, 0, 0);\n }\n return origToDataURL.apply(this, args as [type?: string, quality?: number]);\n };\n\n // WebGL parameter spoofing\n const origGetParam = WebGLRenderingContext.prototype.getParameter;\n WebGLRenderingContext.prototype.getParameter = function(this: WebGLRenderingContext, parameter: number) {\n const UNMASKED_VENDOR_WEBGL = 0x9245;\n const UNMASKED_RENDERER_WEBGL = 0x9246;\n if (parameter === UNMASKED_VENDOR_WEBGL) return 'Intel Inc.';\n if (parameter === UNMASKED_RENDERER_WEBGL) return 'Intel Iris OpenGL Engine';\n return origGetParam.call(this, parameter);\n };\n\n // Hardware concurrency \u2014 pick from common values\n const cpuCounts = [4, 6, 8, 8];\n Object.defineProperty(navigator, 'hardwareConcurrency', {\n get: () => cpuCounts[Math.floor(Math.random() * cpuCounts.length)],\n configurable: true,\n });\n\n // Device memory\n Object.defineProperty(navigator, 'deviceMemory', {\n get: () => [4, 8][Math.floor(Math.random() * 2)],\n configurable: true,\n });\n }).catch(() => {});\n}\n\nexport async function infiniteScrollToBottom(\n page: Page,\n opts: { maxScrolls?: number; scrollDelay?: number; stabilizeMs?: number } = {},\n rawPage?: any,\n): Promise<{ scrollCount: number; heightReached: number }> {\n const { maxScrolls = 50, scrollDelay = 400, stabilizeMs = 600 } = opts;\n let scrollCount = 0;\n let stableScrollCount = 0;\n let previousHeight = 0;\n\n // One CDP session for wheel events (triggers IntersectionObserver-based virtual scrollers).\n // React-window / react-virtualized / TanStack Virtual ignore window.scrollBy but respond to\n // wheel events because they attach their own scroll listeners to the list container.\n let cdpForWheel: any = null;\n let viewW = 1280;\n let viewH = 800;\n if (rawPage && typeof rawPage.context === 'function') {\n try {\n const ctx = rawPage.context();\n if (typeof ctx?.newCDPSession === 'function') {\n cdpForWheel = await ctx.newCDPSession(rawPage);\n const { result } = await cdpForWheel.send('Runtime.evaluate', {\n expression: `({\"w\":window.innerWidth,\"h\":window.innerHeight})`,\n returnByValue: true,\n }).catch(() => ({ result: { value: null } }));\n if (result?.value) { viewW = result.value.w ?? 1280; viewH = result.value.h ?? 800; }\n }\n } catch { cdpForWheel = null; }\n }\n\n try {\n while (scrollCount < maxScrolls) {\n previousHeight = await page.evaluate(() => document.documentElement.scrollHeight).catch(() => 0);\n\n const scrollBy = 500 + Math.floor(Math.random() * 300);\n // window.scrollBy handles standard scroll containers\n await page.evaluate((by: number) => window.scrollBy(0, by), scrollBy).catch(() => {});\n // CDP wheel event triggers IntersectionObserver + virtual list scroll listeners\n if (cdpForWheel) {\n await cdpForWheel.send('Input.dispatchMouseEvent', {\n type: 'mouseWheel',\n x: Math.floor(viewW / 2),\n y: Math.floor(viewH / 2),\n deltaX: 0,\n deltaY: scrollBy,\n modifiers: 0,\n }).catch(() => {});\n }\n await humanDelay(scrollDelay - 100, scrollDelay + 200);\n\n // Use Node.js setTimeout \u2014 page.waitForTimeout may not be available on Stagehand proxy\n await new Promise<void>(r => setTimeout(r, stabilizeMs));\n scrollCount++;\n\n const newHeight: number = await page.evaluate(() => document.documentElement.scrollHeight).catch(() => 0);\n if (newHeight - previousHeight < 10) {\n stableScrollCount++;\n if (stableScrollCount >= 3) break; // no new content after 3 consecutive non-growing scrolls\n } else {\n stableScrollCount = 0;\n }\n previousHeight = newHeight;\n }\n } catch { /* non-fatal */ }\n\n if (cdpForWheel) cdpForWheel.detach().catch(() => {});\n return { scrollCount, heightReached: previousHeight };\n}\n\nexport async function extractIframeContent(page: Page): Promise<Array<{ src: string; content: string; markdown: string }>> {\n const results: Array<{ src: string; content: string; markdown: string }> = [];\n try {\n const iframeSrcs: string[] = await page.evaluate(() =>\n Array.from(document.querySelectorAll('iframe')).map(f => f.getAttribute('src') ?? f.getAttribute('data-src') ?? '')\n ).catch(() => []);\n\n for (const frame of page.frames()) {\n const src = frame.url();\n if (!src || src === 'about:blank' || src === page.url()) continue;\n try {\n const content = await frame.content().catch(() => '');\n if (!content || content.length < 50) continue;\n // Simple text extraction from iframe HTML\n const text = content.replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n results.push({ src, content: content.slice(0, 10_000), markdown: text.slice(0, 5_000) });\n } catch { /* skip this frame */ }\n }\n } catch { /* non-fatal */ }\n return results;\n}\n\nexport async function pierceShadowDom(page: Page): Promise<string> {\n try {\n return await page.evaluate(() => {\n const parts: string[] = [];\n function walkShadow(root: Element | ShadowRoot): void {\n const shadow = (root as any).shadowRoot;\n if (shadow) {\n parts.push(shadow.innerHTML ?? '');\n for (const child of [...shadow.querySelectorAll('*')]) walkShadow(child);\n }\n for (const child of Array.from(root.querySelectorAll(':not(script):not(style)'))) {\n if ((child as any).shadowRoot) walkShadow(child);\n }\n }\n walkShadow(document.body);\n return parts\n .join('\\n')\n .replace(/<script[^>]*>[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, 10_000);\n }).catch(() => '');\n } catch {\n return '';\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Lightweight OTel-compatible tracing for Zeta crawler.
3
+ *
4
+ * Emits spans as structured JSON logs compatible with OpenTelemetry format.
5
+ * Drop-in upgrade path: replace this module with @opentelemetry/sdk-node when needed.
6
+ *
7
+ * Usage:
8
+ * const span = startSpan('crawl.url', { url, engine });
9
+ * // ... do work ...
10
+ * endSpan(span, { screensFound: 3 });
11
+ */
12
+ export interface Span {
13
+ traceId: string;
14
+ spanId: string;
15
+ parentSpanId?: string;
16
+ name: string;
17
+ startTimeMs: number;
18
+ attributes: Record<string, string | number | boolean>;
19
+ }
20
+ export interface FinishedSpan extends Span {
21
+ endTimeMs: number;
22
+ durationMs: number;
23
+ status: 'ok' | 'error';
24
+ error?: string;
25
+ }
26
+ /** Start a new span. If a trace is already active, the new span is a child. */
27
+ export declare function startSpan(name: string, attributes?: Record<string, string | number | boolean>): Span;
28
+ /** End a span and emit it as a structured log line. */
29
+ export declare function endSpan(span: Span, extraAttributes?: Record<string, string | number | boolean>, error?: Error): FinishedSpan;
30
+ /** Convenience: wrap an async function in a span. */
31
+ export declare function withSpan<T>(name: string, attributes: Record<string, string | number | boolean>, fn: (span: Span) => Promise<T>): Promise<T>;
32
+ export declare function increment(metric: string, value?: number, tags?: Record<string, string>): void;
33
+ /** Flush counters as a structured log — call periodically (e.g. at job end). */
34
+ export declare function flushMetrics(): Record<string, number>;
@@ -0,0 +1,77 @@
1
+ import { randomBytes } from "node:crypto";
2
+ let currentTraceId = null;
3
+ let currentSpanId = null;
4
+ function genId(bytes) {
5
+ return randomBytes(bytes).toString("hex");
6
+ }
7
+ function startSpan(name, attributes = {}) {
8
+ const traceId = currentTraceId ?? genId(16);
9
+ const spanId = genId(8);
10
+ const parentSpanId = currentSpanId ?? void 0;
11
+ if (!currentTraceId) currentTraceId = traceId;
12
+ currentSpanId = spanId;
13
+ return { traceId, spanId, parentSpanId, name, startTimeMs: Date.now(), attributes };
14
+ }
15
+ function endSpan(span, extraAttributes = {}, error) {
16
+ const endTimeMs = Date.now();
17
+ const durationMs = endTimeMs - span.startTimeMs;
18
+ const finished = {
19
+ ...span,
20
+ attributes: { ...span.attributes, ...extraAttributes },
21
+ endTimeMs,
22
+ durationMs,
23
+ status: error ? "error" : "ok",
24
+ error: error?.message
25
+ };
26
+ if (!span.parentSpanId) {
27
+ currentTraceId = null;
28
+ currentSpanId = span.parentSpanId ?? null;
29
+ } else {
30
+ currentSpanId = span.parentSpanId ?? null;
31
+ }
32
+ console.log(JSON.stringify({
33
+ ts: new Date(endTimeMs).toISOString(),
34
+ level: error ? "error" : "info",
35
+ msg: `span:${finished.name}`,
36
+ trace_id: finished.traceId,
37
+ span_id: finished.spanId,
38
+ parent_span_id: finished.parentSpanId,
39
+ duration_ms: durationMs,
40
+ status: finished.status,
41
+ error: finished.error,
42
+ ...finished.attributes
43
+ }));
44
+ return finished;
45
+ }
46
+ async function withSpan(name, attributes, fn) {
47
+ const span = startSpan(name, attributes);
48
+ try {
49
+ const result = await fn(span);
50
+ endSpan(span);
51
+ return result;
52
+ } catch (err) {
53
+ endSpan(span, {}, err);
54
+ throw err;
55
+ }
56
+ }
57
+ const counters = /* @__PURE__ */ new Map();
58
+ function increment(metric, value = 1, tags = {}) {
59
+ const key = metric + (Object.keys(tags).length ? ":" + Object.entries(tags).map(([k, v]) => `${k}=${v}`).join(",") : "");
60
+ counters.set(key, (counters.get(key) ?? 0) + value);
61
+ }
62
+ function flushMetrics() {
63
+ const snapshot = Object.fromEntries(counters);
64
+ if (Object.keys(snapshot).length > 0) {
65
+ console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "metrics:flush", ...snapshot }));
66
+ counters.clear();
67
+ }
68
+ return snapshot;
69
+ }
70
+ export {
71
+ endSpan,
72
+ flushMetrics,
73
+ increment,
74
+ startSpan,
75
+ withSpan
76
+ };
77
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/telemetry.ts"],
4
+ "sourcesContent": ["/**\n * Lightweight OTel-compatible tracing for Zeta crawler.\n *\n * Emits spans as structured JSON logs compatible with OpenTelemetry format.\n * Drop-in upgrade path: replace this module with @opentelemetry/sdk-node when needed.\n *\n * Usage:\n * const span = startSpan('crawl.url', { url, engine });\n * // ... do work ...\n * endSpan(span, { screensFound: 3 });\n */\n\nimport { randomBytes } from 'node:crypto';\n\nexport interface Span {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n name: string;\n startTimeMs: number;\n attributes: Record<string, string | number | boolean>;\n}\n\nexport interface FinishedSpan extends Span {\n endTimeMs: number;\n durationMs: number;\n status: 'ok' | 'error';\n error?: string;\n}\n\n// Active trace context \u2014 per async execution context (simplified: per-process global)\nlet currentTraceId: string | null = null;\nlet currentSpanId: string | null = null;\n\nfunction genId(bytes: number): string {\n return randomBytes(bytes).toString('hex');\n}\n\n/** Start a new span. If a trace is already active, the new span is a child. */\nexport function startSpan(name: string, attributes: Record<string, string | number | boolean> = {}): Span {\n const traceId = currentTraceId ?? genId(16);\n const spanId = genId(8);\n const parentSpanId = currentSpanId ?? undefined;\n\n if (!currentTraceId) currentTraceId = traceId;\n currentSpanId = spanId;\n\n return { traceId, spanId, parentSpanId, name, startTimeMs: Date.now(), attributes };\n}\n\n/** End a span and emit it as a structured log line. */\nexport function endSpan(span: Span, extraAttributes: Record<string, string | number | boolean> = {}, error?: Error): FinishedSpan {\n const endTimeMs = Date.now();\n const durationMs = endTimeMs - span.startTimeMs;\n const finished: FinishedSpan = {\n ...span,\n attributes: { ...span.attributes, ...extraAttributes },\n endTimeMs,\n durationMs,\n status: error ? 'error' : 'ok',\n error: error?.message,\n };\n\n // Reset context when root span ends\n if (!span.parentSpanId) {\n currentTraceId = null;\n currentSpanId = span.parentSpanId ?? null;\n } else {\n currentSpanId = span.parentSpanId ?? null;\n }\n\n // Emit as structured JSON \u2014 compatible with Datadog/Grafana log parsing\n console.log(JSON.stringify({\n ts: new Date(endTimeMs).toISOString(),\n level: error ? 'error' : 'info',\n msg: `span:${finished.name}`,\n trace_id: finished.traceId,\n span_id: finished.spanId,\n parent_span_id: finished.parentSpanId,\n duration_ms: durationMs,\n status: finished.status,\n error: finished.error,\n ...finished.attributes,\n }));\n\n return finished;\n}\n\n/** Convenience: wrap an async function in a span. */\nexport async function withSpan<T>(\n name: string,\n attributes: Record<string, string | number | boolean>,\n fn: (span: Span) => Promise<T>,\n): Promise<T> {\n const span = startSpan(name, attributes);\n try {\n const result = await fn(span);\n endSpan(span);\n return result;\n } catch (err: any) {\n endSpan(span, {}, err);\n throw err;\n }\n}\n\n/** Counter metrics \u2014 increment and log on flush. */\nconst counters: Map<string, number> = new Map();\n\nexport function increment(metric: string, value = 1, tags: Record<string, string> = {}): void {\n const key = metric + (Object.keys(tags).length ? ':' + Object.entries(tags).map(([k, v]) => `${k}=${v}`).join(',') : '');\n counters.set(key, (counters.get(key) ?? 0) + value);\n}\n\n/** Flush counters as a structured log \u2014 call periodically (e.g. at job end). */\nexport function flushMetrics(): Record<string, number> {\n const snapshot = Object.fromEntries(counters);\n if (Object.keys(snapshot).length > 0) {\n console.log(JSON.stringify({ ts: new Date().toISOString(), level: 'info', msg: 'metrics:flush', ...snapshot }));\n counters.clear();\n }\n return snapshot;\n}\n"],
5
+ "mappings": "AAYA,SAAS,mBAAmB;AAmB5B,IAAI,iBAAgC;AACpC,IAAI,gBAA+B;AAEnC,SAAS,MAAM,OAAuB;AACpC,SAAO,YAAY,KAAK,EAAE,SAAS,KAAK;AAC1C;AAGO,SAAS,UAAU,MAAc,aAAwD,CAAC,GAAS;AACxG,QAAM,UAAU,kBAAkB,MAAM,EAAE;AAC1C,QAAM,SAAS,MAAM,CAAC;AACtB,QAAM,eAAe,iBAAiB;AAEtC,MAAI,CAAC,eAAgB,kBAAiB;AACtC,kBAAgB;AAEhB,SAAO,EAAE,SAAS,QAAQ,cAAc,MAAM,aAAa,KAAK,IAAI,GAAG,WAAW;AACpF;AAGO,SAAS,QAAQ,MAAY,kBAA6D,CAAC,GAAG,OAA6B;AAChI,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,aAAa,YAAY,KAAK;AACpC,QAAM,WAAyB;AAAA,IAC7B,GAAG;AAAA,IACH,YAAY,EAAE,GAAG,KAAK,YAAY,GAAG,gBAAgB;AAAA,IACrD;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ,UAAU;AAAA,IAC1B,OAAO,OAAO;AAAA,EAChB;AAGA,MAAI,CAAC,KAAK,cAAc;AACtB,qBAAiB;AACjB,oBAAgB,KAAK,gBAAgB;AAAA,EACvC,OAAO;AACL,oBAAgB,KAAK,gBAAgB;AAAA,EACvC;AAGA,UAAQ,IAAI,KAAK,UAAU;AAAA,IACzB,IAAI,IAAI,KAAK,SAAS,EAAE,YAAY;AAAA,IACpC,OAAO,QAAQ,UAAU;AAAA,IACzB,KAAK,QAAQ,SAAS,IAAI;AAAA,IAC1B,UAAU,SAAS;AAAA,IACnB,SAAS,SAAS;AAAA,IAClB,gBAAgB,SAAS;AAAA,IACzB,aAAa;AAAA,IACb,QAAQ,SAAS;AAAA,IACjB,OAAO,SAAS;AAAA,IAChB,GAAG,SAAS;AAAA,EACd,CAAC,CAAC;AAEF,SAAO;AACT;AAGA,eAAsB,SACpB,MACA,YACA,IACY;AACZ,QAAM,OAAO,UAAU,MAAM,UAAU;AACvC,MAAI;AACF,UAAM,SAAS,MAAM,GAAG,IAAI;AAC5B,YAAQ,IAAI;AACZ,WAAO;AAAA,EACT,SAAS,KAAU;AACjB,YAAQ,MAAM,CAAC,GAAG,GAAG;AACrB,UAAM;AAAA,EACR;AACF;AAGA,MAAM,WAAgC,oBAAI,IAAI;AAEvC,SAAS,UAAU,QAAgB,QAAQ,GAAG,OAA+B,CAAC,GAAS;AAC5F,QAAM,MAAM,UAAU,OAAO,KAAK,IAAI,EAAE,SAAS,MAAM,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,IAAI;AACrH,WAAS,IAAI,MAAM,SAAS,IAAI,GAAG,KAAK,KAAK,KAAK;AACpD;AAGO,SAAS,eAAuC;AACrD,QAAM,WAAW,OAAO,YAAY,QAAQ;AAC5C,MAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,GAAG;AACpC,YAAQ,IAAI,KAAK,UAAU,EAAE,KAAI,oBAAI,KAAK,GAAE,YAAY,GAAG,OAAO,QAAQ,KAAK,iBAAiB,GAAG,SAAS,CAAC,CAAC;AAC9G,aAAS,MAAM;AAAA,EACjB;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }