@wenathlan/saddle 1.8.17 → 2.0.2

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 (1005) hide show
  1. package/Dockerfile +1339 -0
  2. package/README.md +68 -22
  3. package/alternatives.ts +1218 -0
  4. package/biome.json +153 -0
  5. package/boards.json +1517 -0
  6. package/compute.ts +3144 -0
  7. package/cores.json +1801 -0
  8. package/dist/acquisition.d.ts +359 -0
  9. package/dist/acquisition.d.ts.map +1 -0
  10. package/dist/acquisition.js +629 -0
  11. package/dist/acquisition.js.map +1 -0
  12. package/dist/alternatives.d.ts +509 -0
  13. package/dist/alternatives.d.ts.map +1 -0
  14. package/dist/alternatives.js +951 -0
  15. package/dist/alternatives.js.map +1 -0
  16. package/dist/automation.d.ts +426 -0
  17. package/dist/automation.d.ts.map +1 -0
  18. package/dist/automation.js +561 -0
  19. package/dist/automation.js.map +1 -0
  20. package/dist/browser.d.ts +562 -0
  21. package/dist/browser.d.ts.map +1 -0
  22. package/dist/browser.js +1057 -0
  23. package/dist/browser.js.map +1 -0
  24. package/dist/capacitor.config.d.ts +13 -0
  25. package/dist/capacitor.config.d.ts.map +1 -0
  26. package/dist/capacitor.config.js +26 -0
  27. package/dist/capacitor.config.js.map +1 -0
  28. package/dist/cli.d.ts +17 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +111 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/communication.d.ts +192 -0
  33. package/dist/communication.d.ts.map +1 -0
  34. package/dist/communication.js +418 -0
  35. package/dist/communication.js.map +1 -0
  36. package/dist/compute.d.ts +1161 -0
  37. package/dist/compute.d.ts.map +1 -0
  38. package/dist/compute.js +2273 -0
  39. package/dist/compute.js.map +1 -0
  40. package/dist/distribution.d.ts +529 -0
  41. package/dist/distribution.d.ts.map +1 -0
  42. package/dist/distribution.js +811 -0
  43. package/dist/distribution.js.map +1 -0
  44. package/dist/execution.d.ts +530 -0
  45. package/dist/execution.d.ts.map +1 -0
  46. package/dist/execution.js +761 -0
  47. package/dist/execution.js.map +1 -0
  48. package/dist/format.d.ts +19 -0
  49. package/dist/format.d.ts.map +1 -0
  50. package/dist/format.js +60 -0
  51. package/dist/format.js.map +1 -0
  52. package/dist/foundation.d.ts +176 -0
  53. package/dist/foundation.d.ts.map +1 -0
  54. package/dist/foundation.js +309 -0
  55. package/dist/foundation.js.map +1 -0
  56. package/dist/index.d.ts +733 -122
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +1018 -122
  59. package/dist/index.js.map +1 -1
  60. package/dist/integration.d.ts +236 -0
  61. package/dist/integration.d.ts.map +1 -0
  62. package/dist/integration.js +236 -0
  63. package/dist/integration.js.map +1 -0
  64. package/dist/intelligence.d.ts +94 -0
  65. package/dist/intelligence.d.ts.map +1 -0
  66. package/dist/intelligence.js +145 -0
  67. package/dist/intelligence.js.map +1 -0
  68. package/dist/isolation.d.ts +129 -0
  69. package/dist/isolation.d.ts.map +1 -0
  70. package/dist/isolation.js +96 -0
  71. package/dist/isolation.js.map +1 -0
  72. package/dist/media.d.ts +344 -0
  73. package/dist/media.d.ts.map +1 -0
  74. package/dist/media.js +986 -0
  75. package/dist/media.js.map +1 -0
  76. package/dist/modes.d.ts +359 -0
  77. package/dist/modes.d.ts.map +1 -0
  78. package/dist/modes.js +134 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/{library/public.d.ts → operations.d.ts} +15 -1
  81. package/dist/operations.d.ts.map +1 -0
  82. package/dist/{library/public.js → operations.js} +18 -7
  83. package/dist/operations.js.map +1 -0
  84. package/dist/orchestrator.d.ts +1339 -0
  85. package/dist/orchestrator.d.ts.map +1 -0
  86. package/dist/orchestrator.js +4308 -0
  87. package/dist/orchestrator.js.map +1 -0
  88. package/dist/performance.d.ts +416 -0
  89. package/dist/performance.d.ts.map +1 -0
  90. package/dist/performance.js +827 -0
  91. package/dist/performance.js.map +1 -0
  92. package/dist/quantum.d.ts +810 -0
  93. package/dist/quantum.d.ts.map +1 -0
  94. package/dist/quantum.js +2073 -0
  95. package/dist/quantum.js.map +1 -0
  96. package/dist/render.d.ts +381 -0
  97. package/dist/render.d.ts.map +1 -0
  98. package/dist/render.js +1073 -0
  99. package/dist/render.js.map +1 -0
  100. package/dist/scheduler.d.ts +596 -0
  101. package/dist/scheduler.d.ts.map +1 -0
  102. package/dist/scheduler.js +1259 -0
  103. package/dist/scheduler.js.map +1 -0
  104. package/dist/security.d.ts +501 -0
  105. package/dist/security.d.ts.map +1 -0
  106. package/dist/security.js +1170 -0
  107. package/dist/security.js.map +1 -0
  108. package/dist/server.d.ts +21 -0
  109. package/dist/server.d.ts.map +1 -0
  110. package/dist/{server/node.js → server.js} +16 -2
  111. package/dist/server.js.map +1 -0
  112. package/dist/tiers.d.ts +1002 -0
  113. package/dist/tiers.d.ts.map +1 -0
  114. package/dist/tiers.js +2165 -0
  115. package/dist/tiers.js.map +1 -0
  116. package/dist/virtual.d.ts +641 -0
  117. package/dist/virtual.d.ts.map +1 -0
  118. package/dist/virtual.js +1285 -0
  119. package/dist/virtual.js.map +1 -0
  120. package/dist/virtualcpu.d.ts +316 -0
  121. package/dist/virtualcpu.d.ts.map +1 -0
  122. package/dist/virtualcpu.js +1180 -0
  123. package/dist/virtualcpu.js.map +1 -0
  124. package/dist/virtualgpu.d.ts +345 -0
  125. package/dist/virtualgpu.d.ts.map +1 -0
  126. package/dist/virtualgpu.js +1000 -0
  127. package/dist/virtualgpu.js.map +1 -0
  128. package/dist/virtualization.d.ts +607 -0
  129. package/dist/virtualization.d.ts.map +1 -0
  130. package/dist/virtualization.js +1187 -0
  131. package/dist/virtualization.js.map +1 -0
  132. package/dist/virtualmemory.d.ts +818 -0
  133. package/dist/virtualmemory.d.ts.map +1 -0
  134. package/dist/virtualmemory.js +1796 -0
  135. package/dist/virtualmemory.js.map +1 -0
  136. package/dist/webscrape.d.ts +720 -0
  137. package/dist/webscrape.d.ts.map +1 -0
  138. package/dist/webscrape.js +2697 -0
  139. package/dist/webscrape.js.map +1 -0
  140. package/docker.config +769 -0
  141. package/docs/CONVERSA.txt +1523 -0
  142. package/docs/alternatives.md +499 -0
  143. package/docs/architecture-1.8.19.md +76 -0
  144. package/docs/architecture-1.8.19.mmd +33 -0
  145. package/docs/architecture-1.8.19.png +0 -0
  146. package/docs/architecture.md +355 -0
  147. package/docs/artifactavailability.md +6 -0
  148. package/docs/brancharchive-2026-08-18.md +18 -0
  149. package/docs/browser.md +7 -0
  150. package/docs/consolidation.md +70 -0
  151. package/docs/e2ugh-engine.md +528 -0
  152. package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
  153. package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
  154. package/docs/hardware.md +342 -0
  155. package/docs/optimization.md +126 -0
  156. package/docs/performance.md +499 -0
  157. package/docs/planning.1.8.18.md +94 -0
  158. package/docs/planning.1.8.19.md +49 -0
  159. package/docs/releasenotes-1.8.17.md +6 -0
  160. package/docs/releasenotes-1.8.18.md +32 -0
  161. package/docs/releasenotes-1.8.19.md +35 -0
  162. package/docs/research-1.8.18-isolation.md +43 -0
  163. package/docs/research-1.8.19-virtual-browser.md +27 -0
  164. package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
  165. package/docs/security.md +454 -0
  166. package/docs/todo-1.8.16.md +56 -1
  167. package/docs/todo-1.8.18.md +164 -0
  168. package/docs/todo-1.8.19.md +241 -0
  169. package/docs/viability.md +777 -0
  170. package/docs/virtualization.md +335 -0
  171. package/docs/web-duplicatecleanup.md +9 -0
  172. package/docs/web-ideas.md +106 -0
  173. package/docs/workflowimprovements-2026-08-19.md +70 -0
  174. package/gpumonitor.cpp +1543 -0
  175. package/gpus.json +2408 -0
  176. package/index.ts +1478 -0
  177. package/media.ts +1337 -0
  178. package/mttg.config +1549 -0
  179. package/orchestrator.ts +5462 -0
  180. package/package.json +304 -55
  181. package/passage.config +1331 -0
  182. package/performance.ts +1049 -0
  183. package/processors.json +2217 -0
  184. package/qemu.config +1062 -0
  185. package/qemubridge.py +1340 -0
  186. package/quantum.ts +2393 -0
  187. package/render.ts +1325 -0
  188. package/scheduler.ts +1600 -0
  189. package/security.ts +1449 -0
  190. package/tiers.ts +2871 -0
  191. package/tsconfig.json +29 -0
  192. package/virtualcpu.ts +1273 -0
  193. package/virtualgpu.ts +1181 -0
  194. package/virtualhardware.c +1011 -0
  195. package/virtualhardware.json +739 -0
  196. package/virtualization.ts +1628 -0
  197. package/virtualizationcore.cpp +4635 -0
  198. package/virtualmemory.ts +2303 -0
  199. package/vm.config.json +1910 -0
  200. package/{extension → web/extension}/manifest.json +1 -1
  201. package/web/readme.md +382 -0
  202. package/web/tsconfig.json +25 -0
  203. package/dist/adapters/forge.d.ts +0 -17
  204. package/dist/adapters/forge.d.ts.map +0 -1
  205. package/dist/adapters/forge.js +0 -19
  206. package/dist/adapters/forge.js.map +0 -1
  207. package/dist/adapters/forgejo.d.ts +0 -49
  208. package/dist/adapters/forgejo.d.ts.map +0 -1
  209. package/dist/adapters/forgejo.js +0 -8
  210. package/dist/adapters/forgejo.js.map +0 -1
  211. package/dist/adapters/github.d.ts +0 -12
  212. package/dist/adapters/github.d.ts.map +0 -1
  213. package/dist/adapters/github.js +0 -20
  214. package/dist/adapters/github.js.map +0 -1
  215. package/dist/adapters/gitlab.d.ts +0 -17
  216. package/dist/adapters/gitlab.d.ts.map +0 -1
  217. package/dist/adapters/gitlab.js +0 -10
  218. package/dist/adapters/gitlab.js.map +0 -1
  219. package/dist/adapters/huggingface.d.ts +0 -17
  220. package/dist/adapters/huggingface.d.ts.map +0 -1
  221. package/dist/adapters/huggingface.js +0 -6
  222. package/dist/adapters/huggingface.js.map +0 -1
  223. package/dist/adapters/socket.d.ts +0 -11
  224. package/dist/adapters/socket.d.ts.map +0 -1
  225. package/dist/adapters/socket.js +0 -17
  226. package/dist/adapters/socket.js.map +0 -1
  227. package/dist/adapters/transport.d.ts +0 -7
  228. package/dist/adapters/transport.d.ts.map +0 -1
  229. package/dist/adapters/transport.js +0 -36
  230. package/dist/adapters/transport.js.map +0 -1
  231. package/dist/ai/chunk.d.ts +0 -2
  232. package/dist/ai/chunk.d.ts.map +0 -1
  233. package/dist/ai/chunk.js +0 -36
  234. package/dist/ai/chunk.js.map +0 -1
  235. package/dist/ai/llmstxt.d.ts +0 -6
  236. package/dist/ai/llmstxt.d.ts.map +0 -1
  237. package/dist/ai/llmstxt.js +0 -12
  238. package/dist/ai/llmstxt.js.map +0 -1
  239. package/dist/ai/provenance.d.ts +0 -22
  240. package/dist/ai/provenance.d.ts.map +0 -1
  241. package/dist/ai/provenance.js +0 -25
  242. package/dist/ai/provenance.js.map +0 -1
  243. package/dist/ai/rag.d.ts +0 -26
  244. package/dist/ai/rag.d.ts.map +0 -1
  245. package/dist/ai/rag.js +0 -22
  246. package/dist/ai/rag.js.map +0 -1
  247. package/dist/ai/tokens.d.ts +0 -15
  248. package/dist/ai/tokens.d.ts.map +0 -1
  249. package/dist/ai/tokens.js +0 -9
  250. package/dist/ai/tokens.js.map +0 -1
  251. package/dist/api/auth.d.ts +0 -16
  252. package/dist/api/auth.d.ts.map +0 -1
  253. package/dist/api/auth.js +0 -19
  254. package/dist/api/auth.js.map +0 -1
  255. package/dist/api/contracts.d.ts +0 -28
  256. package/dist/api/contracts.d.ts.map +0 -1
  257. package/dist/api/contracts.js +0 -14
  258. package/dist/api/contracts.js.map +0 -1
  259. package/dist/api/control.d.ts +0 -10
  260. package/dist/api/control.d.ts.map +0 -1
  261. package/dist/api/control.js +0 -35
  262. package/dist/api/control.js.map +0 -1
  263. package/dist/api/http.d.ts +0 -7
  264. package/dist/api/http.d.ts.map +0 -1
  265. package/dist/api/http.js +0 -12
  266. package/dist/api/http.js.map +0 -1
  267. package/dist/api/rate.d.ts +0 -28
  268. package/dist/api/rate.d.ts.map +0 -1
  269. package/dist/api/rate.js +0 -36
  270. package/dist/api/rate.js.map +0 -1
  271. package/dist/api/security.d.ts +0 -12
  272. package/dist/api/security.d.ts.map +0 -1
  273. package/dist/api/security.js +0 -56
  274. package/dist/api/security.js.map +0 -1
  275. package/dist/api/service.d.ts +0 -5
  276. package/dist/api/service.d.ts.map +0 -1
  277. package/dist/api/service.js +0 -70
  278. package/dist/api/service.js.map +0 -1
  279. package/dist/apps/registry.d.ts +0 -33
  280. package/dist/apps/registry.d.ts.map +0 -1
  281. package/dist/apps/registry.js +0 -24
  282. package/dist/apps/registry.js.map +0 -1
  283. package/dist/binary/archive.d.ts +0 -27
  284. package/dist/binary/archive.d.ts.map +0 -1
  285. package/dist/binary/archive.js +0 -46
  286. package/dist/binary/archive.js.map +0 -1
  287. package/dist/binary/build.d.ts +0 -29
  288. package/dist/binary/build.d.ts.map +0 -1
  289. package/dist/binary/build.js +0 -17
  290. package/dist/binary/build.js.map +0 -1
  291. package/dist/binary/transform.d.ts +0 -70
  292. package/dist/binary/transform.d.ts.map +0 -1
  293. package/dist/binary/transform.js +0 -105
  294. package/dist/binary/transform.js.map +0 -1
  295. package/dist/bot/adapter.d.ts +0 -5
  296. package/dist/bot/adapter.d.ts.map +0 -1
  297. package/dist/bot/adapter.js +0 -11
  298. package/dist/bot/adapter.js.map +0 -1
  299. package/dist/bot/bot.d.ts +0 -28
  300. package/dist/bot/bot.d.ts.map +0 -1
  301. package/dist/bot/bot.js +0 -52
  302. package/dist/bot/bot.js.map +0 -1
  303. package/dist/bot/commands.d.ts +0 -8
  304. package/dist/bot/commands.d.ts.map +0 -1
  305. package/dist/bot/commands.js +0 -19
  306. package/dist/bot/commands.js.map +0 -1
  307. package/dist/bot/permissions.d.ts +0 -13
  308. package/dist/bot/permissions.d.ts.map +0 -1
  309. package/dist/bot/permissions.js +0 -16
  310. package/dist/bot/permissions.js.map +0 -1
  311. package/dist/browser/actions.d.ts +0 -33
  312. package/dist/browser/actions.d.ts.map +0 -1
  313. package/dist/browser/actions.js +0 -44
  314. package/dist/browser/actions.js.map +0 -1
  315. package/dist/browser/agent.d.ts +0 -21
  316. package/dist/browser/agent.d.ts.map +0 -1
  317. package/dist/browser/agent.js +0 -13
  318. package/dist/browser/agent.js.map +0 -1
  319. package/dist/browser/context.d.ts +0 -43
  320. package/dist/browser/context.d.ts.map +0 -1
  321. package/dist/browser/context.js +0 -54
  322. package/dist/browser/context.js.map +0 -1
  323. package/dist/browser/fingerprint.d.ts +0 -4
  324. package/dist/browser/fingerprint.d.ts.map +0 -1
  325. package/dist/browser/fingerprint.js +0 -12
  326. package/dist/browser/fingerprint.js.map +0 -1
  327. package/dist/browser/index.d.ts +0 -11
  328. package/dist/browser/index.d.ts.map +0 -1
  329. package/dist/browser/index.js +0 -11
  330. package/dist/browser/index.js.map +0 -1
  331. package/dist/browser/playwright.d.ts +0 -11
  332. package/dist/browser/playwright.d.ts.map +0 -1
  333. package/dist/browser/playwright.js +0 -24
  334. package/dist/browser/playwright.js.map +0 -1
  335. package/dist/browser/recorder.d.ts +0 -21
  336. package/dist/browser/recorder.d.ts.map +0 -1
  337. package/dist/browser/recorder.js +0 -58
  338. package/dist/browser/recorder.js.map +0 -1
  339. package/dist/browser/session.d.ts +0 -14
  340. package/dist/browser/session.d.ts.map +0 -1
  341. package/dist/browser/session.js +0 -21
  342. package/dist/browser/session.js.map +0 -1
  343. package/dist/browser/snapshot.d.ts +0 -69
  344. package/dist/browser/snapshot.d.ts.map +0 -1
  345. package/dist/browser/snapshot.js +0 -133
  346. package/dist/browser/snapshot.js.map +0 -1
  347. package/dist/captcha/contract.d.ts +0 -35
  348. package/dist/captcha/contract.d.ts.map +0 -1
  349. package/dist/captcha/contract.js +0 -17
  350. package/dist/captcha/contract.js.map +0 -1
  351. package/dist/captcha/evidence.d.ts +0 -10
  352. package/dist/captcha/evidence.d.ts.map +0 -1
  353. package/dist/captcha/evidence.js +0 -9
  354. package/dist/captcha/evidence.js.map +0 -1
  355. package/dist/captcha/guard.d.ts +0 -23
  356. package/dist/captcha/guard.d.ts.map +0 -1
  357. package/dist/captcha/guard.js +0 -12
  358. package/dist/captcha/guard.js.map +0 -1
  359. package/dist/cli/main.d.ts +0 -4
  360. package/dist/cli/main.d.ts.map +0 -1
  361. package/dist/cli/main.js +0 -46
  362. package/dist/cli/main.js.map +0 -1
  363. package/dist/core/errors.d.ts +0 -84
  364. package/dist/core/errors.d.ts.map +0 -1
  365. package/dist/core/errors.js +0 -54
  366. package/dist/core/errors.js.map +0 -1
  367. package/dist/core/events.d.ts +0 -9
  368. package/dist/core/events.d.ts.map +0 -1
  369. package/dist/core/events.js +0 -21
  370. package/dist/core/events.js.map +0 -1
  371. package/dist/core/hash.d.ts +0 -10
  372. package/dist/core/hash.d.ts.map +0 -1
  373. package/dist/core/hash.js +0 -82
  374. package/dist/core/hash.js.map +0 -1
  375. package/dist/core/ids.d.ts +0 -10
  376. package/dist/core/ids.d.ts.map +0 -1
  377. package/dist/core/ids.js +0 -15
  378. package/dist/core/ids.js.map +0 -1
  379. package/dist/delivery/manifest.d.ts +0 -35
  380. package/dist/delivery/manifest.d.ts.map +0 -1
  381. package/dist/delivery/manifest.js +0 -68
  382. package/dist/delivery/manifest.js.map +0 -1
  383. package/dist/deploy/index.d.ts +0 -6
  384. package/dist/deploy/index.d.ts.map +0 -1
  385. package/dist/deploy/index.js +0 -6
  386. package/dist/deploy/index.js.map +0 -1
  387. package/dist/dispatch/resumable.d.ts +0 -102
  388. package/dist/dispatch/resumable.d.ts.map +0 -1
  389. package/dist/dispatch/resumable.js +0 -64
  390. package/dist/dispatch/resumable.js.map +0 -1
  391. package/dist/dispatch/workflow.d.ts +0 -6
  392. package/dist/dispatch/workflow.d.ts.map +0 -1
  393. package/dist/dispatch/workflow.js +0 -37
  394. package/dist/dispatch/workflow.js.map +0 -1
  395. package/dist/domain/artifacts.d.ts +0 -12
  396. package/dist/domain/artifacts.d.ts.map +0 -1
  397. package/dist/domain/artifacts.js +0 -14
  398. package/dist/domain/artifacts.js.map +0 -1
  399. package/dist/domain/jobs.d.ts +0 -12
  400. package/dist/domain/jobs.d.ts.map +0 -1
  401. package/dist/domain/jobs.js +0 -20
  402. package/dist/domain/jobs.js.map +0 -1
  403. package/dist/domain/providers.d.ts +0 -10
  404. package/dist/domain/providers.d.ts.map +0 -1
  405. package/dist/domain/providers.js +0 -8
  406. package/dist/domain/providers.js.map +0 -1
  407. package/dist/domain/runtime.d.ts +0 -14
  408. package/dist/domain/runtime.d.ts.map +0 -1
  409. package/dist/domain/runtime.js +0 -10
  410. package/dist/domain/runtime.js.map +0 -1
  411. package/dist/domain/sessions.d.ts +0 -12
  412. package/dist/domain/sessions.d.ts.map +0 -1
  413. package/dist/domain/sessions.js +0 -57
  414. package/dist/domain/sessions.js.map +0 -1
  415. package/dist/examples/localjob.d.ts +0 -2
  416. package/dist/examples/localjob.d.ts.map +0 -1
  417. package/dist/examples/localjob.js.map +0 -1
  418. package/dist/examples/publicapi.d.ts +0 -2
  419. package/dist/examples/publicapi.d.ts.map +0 -1
  420. package/dist/examples/publicapi.js.map +0 -1
  421. package/dist/extension/build.d.ts +0 -9
  422. package/dist/extension/build.d.ts.map +0 -1
  423. package/dist/extension/build.js +0 -85
  424. package/dist/extension/build.js.map +0 -1
  425. package/dist/extension/content.d.ts +0 -6
  426. package/dist/extension/content.d.ts.map +0 -1
  427. package/dist/extension/content.js +0 -135
  428. package/dist/extension/content.js.map +0 -1
  429. package/dist/extension/index.d.ts +0 -7
  430. package/dist/extension/index.d.ts.map +0 -1
  431. package/dist/extension/index.js +0 -7
  432. package/dist/extension/index.js.map +0 -1
  433. package/dist/extension/pagebridge.d.ts +0 -6
  434. package/dist/extension/pagebridge.d.ts.map +0 -1
  435. package/dist/extension/pagebridge.js +0 -42
  436. package/dist/extension/pagebridge.js.map +0 -1
  437. package/dist/extension/permissions.d.ts +0 -26
  438. package/dist/extension/permissions.d.ts.map +0 -1
  439. package/dist/extension/permissions.js +0 -28
  440. package/dist/extension/permissions.js.map +0 -1
  441. package/dist/extension/popup.d.ts +0 -5
  442. package/dist/extension/popup.d.ts.map +0 -1
  443. package/dist/extension/popup.js +0 -26
  444. package/dist/extension/popup.js.map +0 -1
  445. package/dist/extension/protocol.d.ts +0 -58
  446. package/dist/extension/protocol.d.ts.map +0 -1
  447. package/dist/extension/protocol.js +0 -101
  448. package/dist/extension/protocol.js.map +0 -1
  449. package/dist/extension/serviceworker.d.ts +0 -25
  450. package/dist/extension/serviceworker.d.ts.map +0 -1
  451. package/dist/extension/serviceworker.js +0 -102
  452. package/dist/extension/serviceworker.js.map +0 -1
  453. package/dist/extension/worker.d.ts +0 -28
  454. package/dist/extension/worker.d.ts.map +0 -1
  455. package/dist/extension/worker.js +0 -22
  456. package/dist/extension/worker.js.map +0 -1
  457. package/dist/format/check.d.ts +0 -8
  458. package/dist/format/check.d.ts.map +0 -1
  459. package/dist/format/check.js +0 -38
  460. package/dist/format/check.js.map +0 -1
  461. package/dist/library/public.d.ts.map +0 -1
  462. package/dist/library/public.js.map +0 -1
  463. package/dist/mcp/browser.d.ts +0 -9
  464. package/dist/mcp/browser.d.ts.map +0 -1
  465. package/dist/mcp/browser.js +0 -13
  466. package/dist/mcp/browser.js.map +0 -1
  467. package/dist/mcp/server.d.ts +0 -35
  468. package/dist/mcp/server.d.ts.map +0 -1
  469. package/dist/mcp/server.js +0 -40
  470. package/dist/mcp/server.js.map +0 -1
  471. package/dist/mcp/transport.d.ts +0 -7
  472. package/dist/mcp/transport.d.ts.map +0 -1
  473. package/dist/mcp/transport.js +0 -17
  474. package/dist/mcp/transport.js.map +0 -1
  475. package/dist/memory/bridge.d.ts +0 -14
  476. package/dist/memory/bridge.d.ts.map +0 -1
  477. package/dist/memory/bridge.js +0 -16
  478. package/dist/memory/bridge.js.map +0 -1
  479. package/dist/memory/engine.d.ts +0 -38
  480. package/dist/memory/engine.d.ts.map +0 -1
  481. package/dist/memory/engine.js +0 -109
  482. package/dist/memory/engine.js.map +0 -1
  483. package/dist/memory/modes.d.ts +0 -43
  484. package/dist/memory/modes.d.ts.map +0 -1
  485. package/dist/memory/modes.js +0 -66
  486. package/dist/memory/modes.js.map +0 -1
  487. package/dist/memory/objects.d.ts +0 -21
  488. package/dist/memory/objects.d.ts.map +0 -1
  489. package/dist/memory/objects.js +0 -20
  490. package/dist/memory/objects.js.map +0 -1
  491. package/dist/memory/planner.d.ts +0 -66
  492. package/dist/memory/planner.d.ts.map +0 -1
  493. package/dist/memory/planner.js +0 -108
  494. package/dist/memory/planner.js.map +0 -1
  495. package/dist/memory/targets.d.ts +0 -78
  496. package/dist/memory/targets.d.ts.map +0 -1
  497. package/dist/memory/targets.js +0 -29
  498. package/dist/memory/targets.js.map +0 -1
  499. package/dist/memory/transforms.d.ts +0 -19
  500. package/dist/memory/transforms.d.ts.map +0 -1
  501. package/dist/memory/transforms.js +0 -14
  502. package/dist/memory/transforms.js.map +0 -1
  503. package/dist/modes/matrix.d.ts +0 -23
  504. package/dist/modes/matrix.d.ts.map +0 -1
  505. package/dist/modes/matrix.js +0 -18
  506. package/dist/modes/matrix.js.map +0 -1
  507. package/dist/modes/modes.d.ts +0 -33
  508. package/dist/modes/modes.d.ts.map +0 -1
  509. package/dist/modes/modes.js +0 -15
  510. package/dist/modes/modes.js.map +0 -1
  511. package/dist/modes/resolve.d.ts +0 -96
  512. package/dist/modes/resolve.d.ts.map +0 -1
  513. package/dist/modes/resolve.js +0 -48
  514. package/dist/modes/resolve.js.map +0 -1
  515. package/dist/observability/metrics.d.ts +0 -14
  516. package/dist/observability/metrics.d.ts.map +0 -1
  517. package/dist/observability/metrics.js +0 -18
  518. package/dist/observability/metrics.js.map +0 -1
  519. package/dist/packager/manifest.d.ts +0 -66
  520. package/dist/packager/manifest.d.ts.map +0 -1
  521. package/dist/packager/manifest.js +0 -94
  522. package/dist/packager/manifest.js.map +0 -1
  523. package/dist/packager/publish.d.ts +0 -51
  524. package/dist/packager/publish.d.ts.map +0 -1
  525. package/dist/packager/publish.js +0 -18
  526. package/dist/packager/publish.js.map +0 -1
  527. package/dist/packager/targetcli.d.ts +0 -7
  528. package/dist/packager/targetcli.d.ts.map +0 -1
  529. package/dist/packager/targetcli.js +0 -22
  530. package/dist/packager/targetcli.js.map +0 -1
  531. package/dist/persistence/adapter.d.ts +0 -5
  532. package/dist/persistence/adapter.d.ts.map +0 -1
  533. package/dist/persistence/adapter.js +0 -11
  534. package/dist/persistence/adapter.js.map +0 -1
  535. package/dist/persistence/drizzle.d.ts +0 -2
  536. package/dist/persistence/drizzle.d.ts.map +0 -1
  537. package/dist/persistence/drizzle.js +0 -12
  538. package/dist/persistence/drizzle.js.map +0 -1
  539. package/dist/persistence/memory.d.ts +0 -2
  540. package/dist/persistence/memory.d.ts.map +0 -1
  541. package/dist/persistence/memory.js +0 -27
  542. package/dist/persistence/memory.js.map +0 -1
  543. package/dist/persistence/migrations.d.ts +0 -19
  544. package/dist/persistence/migrations.d.ts.map +0 -1
  545. package/dist/persistence/migrations.js +0 -13
  546. package/dist/persistence/migrations.js.map +0 -1
  547. package/dist/persistence/prisma.d.ts +0 -2
  548. package/dist/persistence/prisma.d.ts.map +0 -1
  549. package/dist/persistence/prisma.js +0 -25
  550. package/dist/persistence/prisma.js.map +0 -1
  551. package/dist/persistence/schema.d.ts +0 -63
  552. package/dist/persistence/schema.d.ts.map +0 -1
  553. package/dist/persistence/schema.js +0 -28
  554. package/dist/persistence/schema.js.map +0 -1
  555. package/dist/persistence/sql.d.ts +0 -3
  556. package/dist/persistence/sql.d.ts.map +0 -1
  557. package/dist/persistence/sql.js +0 -37
  558. package/dist/persistence/sql.js.map +0 -1
  559. package/dist/protocol/blocks.d.ts +0 -10
  560. package/dist/protocol/blocks.d.ts.map +0 -1
  561. package/dist/protocol/blocks.js +0 -26
  562. package/dist/protocol/blocks.js.map +0 -1
  563. package/dist/protocol/json.d.ts +0 -6
  564. package/dist/protocol/json.d.ts.map +0 -1
  565. package/dist/protocol/json.js +0 -6
  566. package/dist/protocol/json.js.map +0 -1
  567. package/dist/protocol/ndjson.d.ts +0 -3
  568. package/dist/protocol/ndjson.d.ts.map +0 -1
  569. package/dist/protocol/ndjson.js +0 -20
  570. package/dist/protocol/ndjson.js.map +0 -1
  571. package/dist/protocol/sse.d.ts +0 -7
  572. package/dist/protocol/sse.d.ts.map +0 -1
  573. package/dist/protocol/sse.js +0 -25
  574. package/dist/protocol/sse.js.map +0 -1
  575. package/dist/proxy/pool.d.ts +0 -9
  576. package/dist/proxy/pool.d.ts.map +0 -1
  577. package/dist/proxy/pool.js +0 -27
  578. package/dist/proxy/pool.js.map +0 -1
  579. package/dist/queue/idempotency.d.ts +0 -10
  580. package/dist/queue/idempotency.d.ts.map +0 -1
  581. package/dist/queue/idempotency.js +0 -13
  582. package/dist/queue/idempotency.js.map +0 -1
  583. package/dist/queue/persistent.d.ts +0 -14
  584. package/dist/queue/persistent.d.ts.map +0 -1
  585. package/dist/queue/persistent.js +0 -66
  586. package/dist/queue/persistent.js.map +0 -1
  587. package/dist/queue/queue.d.ts +0 -7
  588. package/dist/queue/queue.d.ts.map +0 -1
  589. package/dist/queue/queue.js +0 -55
  590. package/dist/queue/queue.js.map +0 -1
  591. package/dist/queue/saga.d.ts +0 -5
  592. package/dist/queue/saga.d.ts.map +0 -1
  593. package/dist/queue/saga.js +0 -20
  594. package/dist/queue/saga.js.map +0 -1
  595. package/dist/release/assets.d.ts +0 -144
  596. package/dist/release/assets.d.ts.map +0 -1
  597. package/dist/release/assets.js +0 -157
  598. package/dist/release/assets.js.map +0 -1
  599. package/dist/release/evidence.d.ts +0 -92
  600. package/dist/release/evidence.d.ts.map +0 -1
  601. package/dist/release/evidence.js +0 -148
  602. package/dist/release/evidence.js.map +0 -1
  603. package/dist/release/verify.d.ts +0 -12
  604. package/dist/release/verify.d.ts.map +0 -1
  605. package/dist/release/verify.js +0 -112
  606. package/dist/release/verify.js.map +0 -1
  607. package/dist/runners/chain.d.ts +0 -125
  608. package/dist/runners/chain.d.ts.map +0 -1
  609. package/dist/runners/chain.js +0 -95
  610. package/dist/runners/chain.js.map +0 -1
  611. package/dist/runners/health.d.ts +0 -36
  612. package/dist/runners/health.d.ts.map +0 -1
  613. package/dist/runners/health.js +0 -26
  614. package/dist/runners/health.js.map +0 -1
  615. package/dist/runners/heartbeat.d.ts +0 -23
  616. package/dist/runners/heartbeat.d.ts.map +0 -1
  617. package/dist/runners/heartbeat.js +0 -29
  618. package/dist/runners/heartbeat.js.map +0 -1
  619. package/dist/runners/inprocess.d.ts +0 -17
  620. package/dist/runners/inprocess.d.ts.map +0 -1
  621. package/dist/runners/inprocess.js +0 -20
  622. package/dist/runners/inprocess.js.map +0 -1
  623. package/dist/runners/scheduler.d.ts +0 -5
  624. package/dist/runners/scheduler.d.ts.map +0 -1
  625. package/dist/runners/scheduler.js +0 -19
  626. package/dist/runners/scheduler.js.map +0 -1
  627. package/dist/runtime/abort.d.ts +0 -8
  628. package/dist/runtime/abort.d.ts.map +0 -1
  629. package/dist/runtime/abort.js +0 -13
  630. package/dist/runtime/abort.js.map +0 -1
  631. package/dist/runtime/compatibility.d.ts +0 -37
  632. package/dist/runtime/compatibility.d.ts.map +0 -1
  633. package/dist/runtime/compatibility.js +0 -10
  634. package/dist/runtime/compatibility.js.map +0 -1
  635. package/dist/runtime/detect.d.ts +0 -13
  636. package/dist/runtime/detect.d.ts.map +0 -1
  637. package/dist/runtime/detect.js +0 -18
  638. package/dist/runtime/detect.js.map +0 -1
  639. package/dist/runtime/engine.d.ts +0 -20
  640. package/dist/runtime/engine.d.ts.map +0 -1
  641. package/dist/runtime/engine.js +0 -61
  642. package/dist/runtime/engine.js.map +0 -1
  643. package/dist/runtime/retry.d.ts +0 -19
  644. package/dist/runtime/retry.d.ts.map +0 -1
  645. package/dist/runtime/retry.js +0 -54
  646. package/dist/runtime/retry.js.map +0 -1
  647. package/dist/runtime/worker.d.ts +0 -10
  648. package/dist/runtime/worker.d.ts.map +0 -1
  649. package/dist/runtime/worker.js +0 -25
  650. package/dist/runtime/worker.js.map +0 -1
  651. package/dist/scrape/cache.d.ts +0 -45
  652. package/dist/scrape/cache.d.ts.map +0 -1
  653. package/dist/scrape/cache.js +0 -45
  654. package/dist/scrape/cache.js.map +0 -1
  655. package/dist/scrape/crawl.d.ts +0 -47
  656. package/dist/scrape/crawl.d.ts.map +0 -1
  657. package/dist/scrape/crawl.js +0 -114
  658. package/dist/scrape/crawl.js.map +0 -1
  659. package/dist/scrape/extract.d.ts +0 -63
  660. package/dist/scrape/extract.d.ts.map +0 -1
  661. package/dist/scrape/extract.js +0 -47
  662. package/dist/scrape/extract.js.map +0 -1
  663. package/dist/scrape/normalize.d.ts +0 -52
  664. package/dist/scrape/normalize.d.ts.map +0 -1
  665. package/dist/scrape/normalize.js +0 -102
  666. package/dist/scrape/normalize.js.map +0 -1
  667. package/dist/scrape/robots.d.ts +0 -37
  668. package/dist/scrape/robots.d.ts.map +0 -1
  669. package/dist/scrape/robots.js +0 -71
  670. package/dist/scrape/robots.js.map +0 -1
  671. package/dist/scrape/schema.d.ts +0 -23
  672. package/dist/scrape/schema.d.ts.map +0 -1
  673. package/dist/scrape/schema.js +0 -92
  674. package/dist/scrape/schema.js.map +0 -1
  675. package/dist/scrape/scraper.d.ts +0 -6
  676. package/dist/scrape/scraper.d.ts.map +0 -1
  677. package/dist/scrape/scraper.js +0 -46
  678. package/dist/scrape/scraper.js.map +0 -1
  679. package/dist/scrape/semantic.d.ts +0 -25
  680. package/dist/scrape/semantic.d.ts.map +0 -1
  681. package/dist/scrape/semantic.js +0 -27
  682. package/dist/scrape/semantic.js.map +0 -1
  683. package/dist/server/node.d.ts +0 -7
  684. package/dist/server/node.d.ts.map +0 -1
  685. package/dist/server/node.js.map +0 -1
  686. package/dist/sessions/file.d.ts +0 -25
  687. package/dist/sessions/file.d.ts.map +0 -1
  688. package/dist/sessions/file.js +0 -13
  689. package/dist/sessions/file.js.map +0 -1
  690. package/dist/sessions/replay.d.ts +0 -9
  691. package/dist/sessions/replay.d.ts.map +0 -1
  692. package/dist/sessions/replay.js +0 -70
  693. package/dist/sessions/replay.js.map +0 -1
  694. package/dist/sessions/store.d.ts +0 -25
  695. package/dist/sessions/store.d.ts.map +0 -1
  696. package/dist/sessions/store.js +0 -13
  697. package/dist/sessions/store.js.map +0 -1
  698. package/dist/storage/adapter.d.ts +0 -5
  699. package/dist/storage/adapter.d.ts.map +0 -1
  700. package/dist/storage/adapter.js +0 -11
  701. package/dist/storage/adapter.js.map +0 -1
  702. package/dist/storage/cache.d.ts +0 -23
  703. package/dist/storage/cache.d.ts.map +0 -1
  704. package/dist/storage/cache.js +0 -79
  705. package/dist/storage/cache.js.map +0 -1
  706. package/dist/storage/checksum.d.ts +0 -3
  707. package/dist/storage/checksum.d.ts.map +0 -1
  708. package/dist/storage/checksum.js +0 -19
  709. package/dist/storage/checksum.js.map +0 -1
  710. package/dist/storage/chunked.d.ts +0 -21
  711. package/dist/storage/chunked.d.ts.map +0 -1
  712. package/dist/storage/chunked.js +0 -67
  713. package/dist/storage/chunked.js.map +0 -1
  714. package/dist/storage/content.d.ts +0 -24
  715. package/dist/storage/content.d.ts.map +0 -1
  716. package/dist/storage/content.js +0 -44
  717. package/dist/storage/content.js.map +0 -1
  718. package/dist/storage/filehosting.d.ts +0 -2
  719. package/dist/storage/filehosting.d.ts.map +0 -1
  720. package/dist/storage/filehosting.js +0 -24
  721. package/dist/storage/filehosting.js.map +0 -1
  722. package/dist/storage/githubcontents.d.ts +0 -2
  723. package/dist/storage/githubcontents.d.ts.map +0 -1
  724. package/dist/storage/githubcontents.js +0 -29
  725. package/dist/storage/githubcontents.js.map +0 -1
  726. package/dist/storage/index.d.ts +0 -12
  727. package/dist/storage/index.d.ts.map +0 -1
  728. package/dist/storage/index.js +0 -12
  729. package/dist/storage/index.js.map +0 -1
  730. package/dist/storage/local.d.ts +0 -2
  731. package/dist/storage/local.d.ts.map +0 -1
  732. package/dist/storage/local.js +0 -72
  733. package/dist/storage/local.js.map +0 -1
  734. package/dist/storage/memory.d.ts +0 -6
  735. package/dist/storage/memory.d.ts.map +0 -1
  736. package/dist/storage/memory.js +0 -36
  737. package/dist/storage/memory.js.map +0 -1
  738. package/dist/storage/pool.d.ts +0 -95
  739. package/dist/storage/pool.d.ts.map +0 -1
  740. package/dist/storage/pool.js +0 -202
  741. package/dist/storage/pool.js.map +0 -1
  742. package/dist/storage/s3compatible.d.ts +0 -3
  743. package/dist/storage/s3compatible.d.ts.map +0 -1
  744. package/dist/storage/s3compatible.js +0 -70
  745. package/dist/storage/s3compatible.js.map +0 -1
  746. package/dist/storage/sync.d.ts +0 -47
  747. package/dist/storage/sync.d.ts.map +0 -1
  748. package/dist/storage/sync.js +0 -75
  749. package/dist/storage/sync.js.map +0 -1
  750. package/dist/surfaces/adapters.d.ts +0 -97
  751. package/dist/surfaces/adapters.d.ts.map +0 -1
  752. package/dist/surfaces/adapters.js +0 -50
  753. package/dist/surfaces/adapters.js.map +0 -1
  754. package/dist/surfaces/controls.d.ts +0 -18
  755. package/dist/surfaces/controls.d.ts.map +0 -1
  756. package/dist/surfaces/controls.js +0 -45
  757. package/dist/surfaces/controls.js.map +0 -1
  758. package/dist/surfaces/manifest.d.ts +0 -68
  759. package/dist/surfaces/manifest.d.ts.map +0 -1
  760. package/dist/surfaces/manifest.js +0 -42
  761. package/dist/surfaces/manifest.js.map +0 -1
  762. package/dist/surfaces/n8n.d.ts +0 -25
  763. package/dist/surfaces/n8n.d.ts.map +0 -1
  764. package/dist/surfaces/n8n.js +0 -31
  765. package/dist/surfaces/n8n.js.map +0 -1
  766. package/dist/surfaces/operations.d.ts +0 -32
  767. package/dist/surfaces/operations.d.ts.map +0 -1
  768. package/dist/surfaces/operations.js +0 -53
  769. package/dist/surfaces/operations.js.map +0 -1
  770. package/dist/surfaces/requirements.d.ts +0 -29
  771. package/dist/surfaces/requirements.d.ts.map +0 -1
  772. package/dist/surfaces/requirements.js +0 -50
  773. package/dist/surfaces/requirements.js.map +0 -1
  774. package/dist/surfaces/targets.d.ts +0 -196
  775. package/dist/surfaces/targets.d.ts.map +0 -1
  776. package/dist/surfaces/targets.js +0 -27
  777. package/dist/surfaces/targets.js.map +0 -1
  778. package/dist/webhook/delivery.d.ts +0 -18
  779. package/dist/webhook/delivery.d.ts.map +0 -1
  780. package/dist/webhook/delivery.js +0 -36
  781. package/dist/webhook/delivery.js.map +0 -1
  782. package/dist/webhook/receiver.d.ts +0 -26
  783. package/dist/webhook/receiver.d.ts.map +0 -1
  784. package/dist/webhook/receiver.js +0 -24
  785. package/dist/webhook/receiver.js.map +0 -1
  786. package/dist/webhook/signature.d.ts +0 -3
  787. package/dist/webhook/signature.d.ts.map +0 -1
  788. package/dist/webhook/signature.js +0 -7
  789. package/dist/webhook/signature.js.map +0 -1
  790. package/dist/workflow/manifest.d.ts +0 -22
  791. package/dist/workflow/manifest.d.ts.map +0 -1
  792. package/dist/workflow/manifest.js +0 -21
  793. package/dist/workflow/manifest.js.map +0 -1
  794. package/dist/workflow/registry.d.ts +0 -7
  795. package/dist/workflow/registry.d.ts.map +0 -1
  796. package/dist/workflow/registry.js +0 -18
  797. package/dist/workflow/registry.js.map +0 -1
  798. package/dist/workflow/templates.d.ts +0 -6
  799. package/dist/workflow/templates.d.ts.map +0 -1
  800. package/dist/workflow/templates.js +0 -18
  801. package/dist/workflow/templates.js.map +0 -1
  802. package/dist/workflow/triggers.d.ts +0 -64
  803. package/dist/workflow/triggers.d.ts.map +0 -1
  804. package/dist/workflow/triggers.js +0 -99
  805. package/dist/workflow/triggers.js.map +0 -1
  806. package/docs/logs/.gitkeep +0 -0
  807. package/docs/plans/00.index.md +0 -50
  808. package/docs/plans/01.architecture.md +0 -86
  809. package/docs/plans/02.research.computer.use.md +0 -58
  810. package/docs/plans/03.research.captcha.bypass.md +0 -68
  811. package/docs/plans/04.research.sandbox.ai.md +0 -52
  812. package/docs/plans/05.capture.platform.md +0 -57
  813. package/docs/plans/06.dependencies.md +0 -97
  814. package/docs/plans/07.captcha.test.page.md +0 -41
  815. package/docs/plans/08.production.infra.md +0 -70
  816. package/docs/plans/09.database.schema.md +0 -121
  817. package/docs/plans/10.cloudinary.storage.md +0 -57
  818. package/docs/plans/11.movement.logs.json.md +0 -72
  819. package/docs/plans/12.research.atlas.agent.browser.md +0 -79
  820. package/docs/plans/13.research.anti.detection.md +0 -898
  821. package/docs/plans/14.research.proxy.md +0 -1495
  822. package/docs/plans/15.research.retry.rate.limit.md +0 -1958
  823. package/docs/plans/16.research.crawling.md +0 -1417
  824. package/docs/plans/17.research.caching.md +0 -1610
  825. package/docs/plans/18.research.content.extraction.md +0 -1952
  826. package/docs/plans/19.research.errors.events.md +0 -1523
  827. package/docs/plans/20.research.zod.validation.md +0 -1350
  828. package/docs/plans/21.research.batch.concurrency.md +0 -1888
  829. package/docs/plans/22.research.universal.runtime.md +0 -944
  830. package/docs/plans/23.research.ai.integration.md +0 -1465
  831. package/docs/plans/24.research.memory.persistence.md +0 -1979
  832. package/docs/plans/25.research.server.api.md +0 -342
  833. package/docs/plans/26.research.compilation.md +0 -249
  834. package/docs/plans/27.research.html.parsing.md +0 -251
  835. package/docs/plans/28.action.plan.md +0 -50
  836. package/docs/plans/29.api.reference.md +0 -174
  837. package/docs/plans/30.architecture.plan.md +0 -94
  838. package/docs/plans/31.auditoria.dados.md +0 -163
  839. package/docs/plans/32.bots.automacao.computacional.md +0 -214
  840. package/docs/plans/33.bots.codigo.revisao.md +0 -220
  841. package/docs/plans/34.bots.seguranca.cicd.md +0 -366
  842. package/docs/plans/35.comparativo.concorrencia.md +0 -464
  843. package/docs/plans/36.computational.memory.md +0 -340
  844. package/docs/plans/37.deploystrategy.md +0 -394
  845. package/docs/plans/38.flow.md +0 -155
  846. package/docs/plans/39.multi.platform.bot.md +0 -252
  847. package/docs/plans/40.npm.publish.md +0 -250
  848. package/docs/plans/41.o.que.falta.md +0 -407
  849. package/docs/plans/42.pesquisa.concorrencia.md +0 -721
  850. package/docs/plans/43.plan.universal.architecture.md +0 -496
  851. package/docs/plans/44.reference.md +0 -100
  852. package/docs/plans/45.robotarchitecture.md +0 -237
  853. package/docs/plans/46.scdnintegration.md +0 -284
  854. package/docs/plans/47.multiforge.readme.md +0 -129
  855. package/docs/plans/48.theory.v4.repo.os.md +0 -152
  856. package/docs/plans/49.third.party.infra.md +0 -12
  857. package/docs/plans/50.file.as.compute.md +0 -39
  858. package/docs/plans/51.architecture.virtual.processor.md +0 -80
  859. package/docs/plans/52.manifesto.v8.md +0 -11
  860. package/docs/plans/58.cdn.list.md +0 -23
  861. package/docs/plans/59.sql.frameworks.md +0 -33
  862. package/docs/plans/60.sql.thirdparty.md +0 -26
  863. package/docs/plans/61.objective.multiforge.md +0 -63
  864. package/docs/plans/62.huggingface.upload.md +0 -26
  865. package/docs/plans/63.kaggle.upload.md +0 -24
  866. package/docs/plans/64.npm.storage.md +0 -30
  867. package/docs/plans/65.rclone.terabox.md +0 -32
  868. package/docs/plans/66.buckets.and.models.todo.md +0 -14
  869. package/docs/plans/67.database.todo.md +0 -13
  870. package/docs/plans/68.deploy.packages.todo.md +0 -12
  871. package/docs/plans/69.report.human.operator.md +0 -133
  872. package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
  873. package/docs/plans/71.report.hd.infinito.vram.md +0 -155
  874. package/docs/plans/72.plan.hd.infinito.node.md +0 -146
  875. package/docs/plans/73.plan.scifi.repos.md +0 -125
  876. package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
  877. package/docs/plans/README.md +0 -489
  878. package/docs/plans/aggregate_platforms.mjs +0 -146
  879. package/docs/plans/examplesession.json +0 -36
  880. package/docs/plans/missing-facts.md +0 -192
  881. package/docs/plans/models.md +0 -64
  882. package/docs/plans/organize.cjs +0 -270
  883. package/docs/plans/platforms.md +0 -2887
  884. package/docs/plans/sites.md +0 -31322
  885. package/docs/sources/farm.py +0 -117
  886. package/docs/sources/html/saddle1.html +0 -132
  887. package/docs/sources/html/saddle2.html +0 -157
  888. package/docs/sources/html/saddle3.html +0 -119
  889. package/docs/sources/html/saddle4.html +0 -144
  890. package/docs/sources/html/saddle5.html +0 -72
  891. package/docs/sources/html/saddle6.html +0 -171
  892. package/docs/sources/html/saddle7.html +0 -236
  893. package/docs/sources/saddle.ts +0 -74
  894. package/docs/sources/schema.prisma +0 -88
  895. package/docs/sources/script.sh +0 -64
  896. package/docs/sources/workflows.yml +0 -458
  897. package/docs/talks1/_body.txt +0 -14
  898. package/docs/talks1/_index.md +0 -15
  899. package/docs/talks1/_screenshot.png +0 -0
  900. package/docs/talks1/assistant-01.md +0 -5
  901. package/docs/talks1/assistant-02.md +0 -5
  902. package/docs/talks1/assistant-03.md +0 -531
  903. package/docs/talks1/assistant-04.md +0 -26
  904. package/docs/talks1/assistant-05.md +0 -774
  905. package/docs/talks1/assistant-06.md +0 -1718
  906. package/docs/talks1/scrape-share.cjs +0 -185
  907. package/docs/talks1/scrape-share.ts +0 -183
  908. package/docs/talks1/user-01.md +0 -3
  909. package/docs/talks1/user-02.md +0 -3
  910. package/docs/talks1/user-03.md +0 -88
  911. package/docs/talks1/user-04.md +0 -3
  912. package/docs/talks1/user-05.md +0 -3
  913. package/docs/talks1/user-06.md +0 -88
  914. package/docs/talks1/user-07.md +0 -88
  915. package/docs/talks2/_body.txt +0 -14
  916. package/docs/talks2/_index.md +0 -16
  917. package/docs/talks2/_screenshot.png +0 -0
  918. package/docs/talks2/assistant-01.md +0 -5
  919. package/docs/talks2/assistant-02.md +0 -5
  920. package/docs/talks2/assistant-03.md +0 -424
  921. package/docs/talks2/assistant-04.md +0 -598
  922. package/docs/talks2/assistant-05.md +0 -1280
  923. package/docs/talks2/assistant-06.md +0 -1227
  924. package/docs/talks2/assistant-07.md +0 -1252
  925. package/docs/talks2/user-01.md +0 -3
  926. package/docs/talks2/user-02.md +0 -3
  927. package/docs/talks2/user-03.md +0 -88
  928. package/docs/talks2/user-04.md +0 -88
  929. package/docs/talks2/user-05.md +0 -88
  930. package/docs/talks2/user-06.md +0 -88
  931. package/docs/talks2/user-07.md +0 -3
  932. package/docs/talks3/_body.txt +0 -467
  933. package/docs/talks3/_index.md +0 -10
  934. package/docs/talks3/_screenshot.png +0 -0
  935. package/docs/talks3/assistant-01.md +0 -417
  936. package/docs/talks3/assistant-02.md +0 -417
  937. package/docs/talks3/assistant-03.md +0 -29
  938. package/docs/talks3/assistant-04.md +0 -727
  939. package/docs/talks3/user-01.md +0 -88
  940. package/docs/talks3/user-02.md +0 -88
  941. package/docs/talks3/user-03.md +0 -3
  942. package/docs/talks3/user-04.md +0 -3
  943. package/docs/talks4/_body.txt +0 -14
  944. package/docs/talks4/_index.md +0 -12
  945. package/docs/talks4/_screenshot.png +0 -0
  946. package/docs/talks4/assistant-01.md +0 -5
  947. package/docs/talks4/assistant-02.md +0 -5
  948. package/docs/talks4/assistant-03.md +0 -35
  949. package/docs/talks4/assistant-04.md +0 -512
  950. package/docs/talks4/assistant-05.md +0 -599
  951. package/docs/talks4/user-01.md +0 -3
  952. package/docs/talks4/user-02.md +0 -3
  953. package/docs/talks4/user-03.md +0 -88
  954. package/docs/talks4/user-04.md +0 -88
  955. package/docs/talks4/user-05.md +0 -7
  956. package/docs/talks5/_body.txt +0 -14
  957. package/docs/talks5/_index.md +0 -13
  958. package/docs/talks5/_screenshot.png +0 -0
  959. package/docs/talks5/assistant-01.md +0 -5
  960. package/docs/talks5/assistant-02.md +0 -5
  961. package/docs/talks5/assistant-03.md +0 -690
  962. package/docs/talks5/assistant-04.md +0 -758
  963. package/docs/talks5/assistant-05.md +0 -974
  964. package/docs/talks5/user-01.md +0 -3
  965. package/docs/talks5/user-02.md +0 -3
  966. package/docs/talks5/user-03.md +0 -105
  967. package/docs/talks5/user-04.md +0 -105
  968. package/docs/talks5/user-05.md +0 -63
  969. package/docs/talks5/user-06.md +0 -105
  970. package/docs/talks6/_body.txt +0 -14
  971. package/docs/talks6/_index.md +0 -9
  972. package/docs/talks6/_screenshot.png +0 -0
  973. package/docs/talks6/assistant-01.md +0 -5
  974. package/docs/talks6/assistant-02.md +0 -5
  975. package/docs/talks6/assistant-03.md +0 -1499
  976. package/docs/talks6/user-01.md +0 -3
  977. package/docs/talks6/user-02.md +0 -3
  978. package/docs/talks6/user-03.md +0 -88
  979. package/docs/talks6/user-04.md +0 -88
  980. package/docs/talks7/_body.txt +0 -14
  981. package/docs/talks7/_index.md +0 -10
  982. package/docs/talks7/_screenshot.png +0 -0
  983. package/docs/talks7/assistant-01.md +0 -5
  984. package/docs/talks7/assistant-02.md +0 -5
  985. package/docs/talks7/assistant-03.md +0 -523
  986. package/docs/talks7/assistant-04.md +0 -617
  987. package/docs/talks7/user-01.md +0 -3
  988. package/docs/talks7/user-02.md +0 -3
  989. package/docs/talks7/user-03.md +0 -105
  990. package/docs/talks7/user-04.md +0 -67
  991. package/docs/talks8/conversa1.txt +0 -1322
  992. package/docs/talks8/conversa2.txt +0 -237
  993. package/docs/talks9/Beyond the Obvious_ 50 Plataformas Auto-Hospedadas de Forja de C/303/263digo para Al/303/251m de Gitea e GitLab.md" +0 -174
  994. package/docs/talks9/De NPM a Multi-Linguagem_ Uma Arquitetura T/303/251cnica para a Execu/303/247/303/243o Integrada de C/303/263digo no Ecossistema Node.js.md" +0 -59
  995. package/docs/talks9/De NPM a VMs Virtuais_ Uma An/303/241lise Arquitet/303/264nica para a Realiza/303/247/303/243o do Ciclo de Vida do Projeto SADDLE.md" +0 -91
  996. package/docs/talks9/Mapeamento da Engrenagem Computacional_ Uma Arquitetura para Execu/303/247/303/243o Isolada e Persist/303/252ncia em Ambientes Distribu/303/255dos.md" +0 -116
  997. package/docs/talks9/O Cen/303/241rio Pr/303/241tico do SADDLE_ Uma An/303/241lise de Viabilidade e Modelo de Ciclo de Vida Integrado.md" +0 -128
  998. package/docs/talks9/README (2).md +0 -489
  999. package/docs/talks9/README.md +0 -198
  1000. package/docs/talks9/Viabilidade do Saddle_ Uma An/303/241lise T/303/251cnica da Transforma/303/247/303/243o de Armazenamento Remoto em Mem/303/263ria Computacional.md" +0 -80
  1001. package/docs/talks9/conversa.txt +0 -544
  1002. package/docs/talks9/other (2).md +0 -39
  1003. package/docs/talks9/other.md +0 -57
  1004. package/docs/talks9/outro.txt +0 -24
  1005. /package/{extension/README.md → docs/extension.md} +0 -0
@@ -1,1417 +0,0 @@
1
- # Pesquisa: Web Crawling Patterns (2026)
2
-
3
- ## Table of Contents
4
-
5
- - [Visão Geral](#visão-geral)
6
- - [BFS vs DFS Crawling](#bfs-vs-dfs-crawling)
7
- - [robots.txt Parsing](#robotstxt-parsing)
8
- - [Sitemap Parsing](#sitemap-parsing)
9
- - [URL Frontier com Prioridade](#url-frontier-com-prioridade)
10
- - [URL Normalization](#url-normalization)
11
- - [Depth-Limited Crawling](#depth-limited-crawling)
12
- - [Domain-Specific Crawl Rules](#domain-specific-crawl-rules)
13
- - [Canonical URLs e Redirect Handling](#canonical-urls-e-redirect-handling)
14
- - [Código Completo](#código-completo)
15
-
16
- ---
17
-
18
- ## Visão Geral
19
-
20
- Web crawling patterns define como um crawler descobre, prioriza e acessa URLs em um site. A escolha entre BFS (Breadth-First Search) e DFS (Depth-First Search), combined com normalização de URLs, respeito a robots.txt, e limitação de profundidade, determina a eficiência e robustez do crawler.
21
-
22
- ### Bibliotecas Principais (2026)
23
-
24
- | Biblioteca | Versão | Uso |
25
- |---|---|---|
26
- | `crawlee` | 3.x | Framework completo de crawling |
27
- | `robots-parser` | 3.0.1 | Parsing de robots.txt (RFC 9309) |
28
- | `sitemapper` | 4.1.6 | Parsing de sitemaps XML |
29
- | `p-queue` | 9.3.0 | Fila com prioridade |
30
- | `normalize-url` | 9.0.0 | Normalização de URLs |
31
- | `ufo` | latest | Normalização leve de URLs |
32
-
33
- ---
34
-
35
- ## BFS vs DFS Crawling
36
-
37
- ### Breadth-First Search (BFS)
38
-
39
- BFS visita todas as URLs de um nível antes de descer para o próximo nível. É o padrão em Crawlee porque garante cobertura uniforme e evita ficar preso em sub-árvores profundas.
40
-
41
- ```
42
- Level 0: [https://example.com]
43
-
44
- Level 1: [A] [B] [C]
45
- │ │
46
- Level 2: [D] [E] [F] [G]
47
- ```
48
-
49
- **Por que BFS é o padrão:**
50
- - Cobertura uniforme de todas as seções do site
51
- - Menor risco de ficar preso em páginas infinitas
52
- - Distribuição mais equilibrada de carga
53
- - Mais previsível para controle de taxa
54
-
55
- ### Depth-First Search (DFS)
56
-
57
- DFS explora um caminho completo antes de voltar. Útil para crawl de árvores de navegação, categorias, ou quando se quer explorar um sub-site completamente.
58
-
59
- ```
60
- Start → [A] → [D] → [H] → backtrack → [E] → backtrack → [B] → [F] → ...
61
- ```
62
-
63
- **Quando usar DFS:**
64
- - Crawl de documentação hierárquica
65
- - Exploração de categorias/subcategorias
66
- - Quando a prioridade é profundidade sobre amplitude
67
-
68
- ### Crawlee: RequestQueue
69
-
70
- O `RequestQueue` do Crawlee é a fila persistente que gerencia URLs. Por padrão, opera em BFS. A ordem de inserção determina a ordem de processamento.
71
-
72
- ```ts
73
- import { RequestQueue, PlaywrightCrawler } from 'crawlee';
74
-
75
- const requestQueue = await RequestQueue.open('my-queue');
76
-
77
- // Inserir URLs — ordem de inserção = ordem de processamento (BFS)
78
- await requestQueue.addRequest({ url: 'https://example.com' }); // Nível 0
79
- await requestQueue.addRequest({ url: 'https://example.com/a' }); // Nível 1
80
- await requestQueue.addRequest({ url: 'https://example.com/b' }); // Nível 1
81
- await requestQueue.addRequest({ url: 'https://example.com/a/d' }); // Nível 2
82
- await requestQueue.addRequest({ url: 'https://example.com/a/e' }); // Nível 2
83
- ```
84
-
85
- ### Crawlee: enqueueLinks
86
-
87
- `enqueueLinks()` extrai e enfileira links da página atual. Por padrão usa BFS (insere no final da fila).
88
-
89
- ```ts
90
- import { PlaywrightCrawler } from 'crawlee';
91
-
92
- const crawler = new PlaywrightCrawler({
93
- requestQueue,
94
- async requestHandler({ page, enqueueLinks }) {
95
- // BFS padrão — links vão para o FINAL da fila
96
- await enqueueLinks();
97
- },
98
- });
99
-
100
- await crawler.run(['https://example.com']);
101
- ```
102
-
103
- ### DFS com forefront: true
104
-
105
- Para DFS, use `forefront: true` na `enqueueLinks()`. Isso insere os novos links no INÍCIO da fila, fazendo o crawler explorar profundidade antes de largura.
106
-
107
- ```ts
108
- const crawler = new PlaywrightCrawler({
109
- requestQueue,
110
- async requestHandler({ page, enqueueLinks }) {
111
- // DFS — links vão para o INÍCIO da fila
112
- await enqueueLinks({ forefront: true });
113
- },
114
- });
115
-
116
- await crawler.run(['https://example.com']);
117
- ```
118
-
119
- ### Comparação BFS vs DFS
120
-
121
- | Característica | BFS | DFS |
122
- |---|---|---|
123
- | Cobertura | Uniforme, amplo | Profundo, focado |
124
- | Risco de loop | Baixo | Alto |
125
- | Uso de memória | Médio (muitas URLs pendentes) | Baixo (poucas URLs pendentes) |
126
- | Velocidade de descoberta | Lenta (explora tudo) | Rápida (explora fundo) |
127
- | Uso ideal | Sites grandes, e-commerce | Documentação, árvores |
128
- | Crawlee padrão | `enqueueLinks()` | `enqueueLinks({ forefront: true })` |
129
-
130
- ---
131
-
132
- ## robots.txt Parsing
133
-
134
- ### robots-parser 3.0.1
135
-
136
- `robots-parser` é a biblioteca mais completa para parsing de robots.txt. Versão 3.0.1 é compatível com RFC 9309 (a versão atual do padrão).
137
-
138
- **Características RFC 9309:**
139
- - Suporte a `User-agent`, `Allow`, `Disallow`, `Crawl-delay`, `Sitemap`
140
- - Suporte a `*` como curinga no User-agent
141
- - Suporte a `$` como curinga no final de Allow/Disallow
142
- - Suporte a linhas de comment (`#`)
143
-
144
- ```ts
145
- import robotsParser from 'robots-parser';
146
-
147
- const robotsTxt = `
148
- User-agent: *
149
- Disallow: /admin/
150
- Disallow: /private/
151
- Allow: /admin/dashboard
152
- Crawl-delay: 2
153
- Sitemap: https://example.com/sitemap.xml
154
-
155
- User-agent: Googlebot
156
- Allow: /
157
- `;
158
-
159
- const robots = robotsParser('https://example.com/robots.txt', robotsTxt);
160
-
161
- // Verificar se um URL é permitido
162
- const isAllowed = robots.isAllowed('https://example.com/page');
163
- // → true
164
-
165
- const isDisallowed = robots.isAllowed('https://example.com/admin/settings');
166
- // → false
167
-
168
- // Obter crawl-delay
169
- const delay = robots.getCrawlDelay('Googlebot');
170
- // → undefined (não definido para Googlebot)
171
-
172
- // Obter Sitemap
173
- const sitemaps = robots.getSitemaps();
174
- // → ['https://example.com/sitemap.xml']
175
-
176
- // Obter Allowed/Disallow para um user-agent específico
177
- const rules = robots.getDisallowedPaths('*');
178
- // → ['/admin/', '/private/']
179
- ```
180
-
181
- ### Crawlee: RobotsTxtFile
182
-
183
- Crawlee tem suporte built-in a robots.txt via `RobotsTxtFile`. Ele é integrado automaticamente ao crawler, respeitando regras.
184
-
185
- ```ts
186
- import { RobotsTxtFile } from 'crawlee';
187
-
188
- // Crawlee respeita robots.txt automaticamente
189
- const crawler = new PlaywrightCrawler({
190
- // robots.txt é checado antes de cada request
191
- // URLs bloqueadas são ignoradas silenciosamente
192
- });
193
-
194
- // Forçar desabilitação (não recomendado)
195
- const crawler = new PlaywrightCrawler({
196
- // NOTA: Não há opção direta para desabilitar robots.txt check
197
- // Robots.txt é sempre respeitado pelo Crawlee
198
- });
199
- ```
200
-
201
- ### Parsing Manual com robots-parser
202
-
203
- Para controle total, use `robots-parser` diretamente:
204
-
205
- ```ts
206
- import robotsParser from 'robots-parser';
207
- import { gotScraping } from 'got-scraping';
208
-
209
- async function checkRobotsTxt(url: string, userAgent = '*'): Promise<{
210
- allowed: boolean;
211
- crawlDelay: number | null;
212
- sitemaps: string[];
213
- }> {
214
- const parsedUrl = new URL(url);
215
- const robotsUrl = `${parsedUrl.origin}/robots.txt`;
216
-
217
- const response = await gotScraping(robotsUrl);
218
- const robots = robotsParser(robotsUrl, response.body);
219
-
220
- return {
221
- allowed: robots.isAllowed(url, userAgent) ?? true,
222
- crawlDelay: robots.getCrawlDelay(userAgent) ?? null,
223
- sitemaps: robots.getSitemaps() ?? [],
224
- };
225
- }
226
-
227
- // Usar
228
- const result = await checkRobotsTxt('https://example.com/page');
229
- if (!result.allowed) {
230
- console.log('URL bloqueada por robots.txt');
231
- if (result.crawlDelay) {
232
- console.log(`Aguardar ${result.crawlDelay} segundos`);
233
- }
234
- }
235
- ```
236
-
237
- ### Rate Limiting Baseado em Crawl-Delay
238
-
239
- ```ts
240
- function getCrawlDelayMs(robots: ReturnType<typeof robotsParser>, userAgent: string): number {
241
- const delay = robots.getCrawlDelay(userAgent);
242
- if (delay === null || delay === undefined) return 1000; // Default 1s
243
- return delay * 1000;
244
- }
245
-
246
- // Usar no crawler
247
- const crawler = new PlaywrightCrawler({
248
- async requestHandler({ page, enqueueLinks }) {
249
- const robots = robotsParser('https://example.com/robots.txt', robotsContent);
250
- const delayMs = getCrawlDelayMs(robots, '*');
251
-
252
- // Aplicar delay entre requests
253
- await new Promise(resolve => setTimeout(resolve, delayMs));
254
-
255
- // ... processar página
256
- },
257
- });
258
- ```
259
-
260
- ---
261
-
262
- ## Sitemap Parsing
263
-
264
- ### sitemapper 4.1.6
265
-
266
- `sitemapper` é a biblioteca mais rápida para parsing de sitemaps XML. Suporta sitemaps com milhões de URLs.
267
-
268
- **Características:**
269
- - Parsing streaming (não carrega tudo na memória)
270
- - Suporte a sitemap index (sitemaps que referenciam outros sitemaps)
271
- - Tratamento de erros robusto
272
-
273
- ```ts
274
- import { Sitemapper } from 'sitemapper';
275
-
276
- const sitemapper = new Sitemapper({
277
- timeout: 15000,
278
- url: 'https://example.com/sitemap.xml',
279
- });
280
-
281
- const { sites } = await sitemapper.fetch();
282
- console.log(sites);
283
- // → ['https://example.com/', 'https://example.com/page1', ...]
284
- ```
285
-
286
- ### Crawlee RobotsTxtFile.parseUrlsFromSitemaps()
287
-
288
- Crawlee pode extrair URLs de sitemaps referenciados no robots.txt:
289
-
290
- ```ts
291
- import { RobotsTxtFile } from 'crawlee';
292
-
293
- const robotsContent = `
294
- User-agent: *
295
- Disallow: /admin/
296
- Sitemap: https://example.com/sitemap.xml
297
- Sitemap: https://example.com/sitemap-products.xml
298
- `;
299
-
300
- const robots = RobotsTxtFile.parse(robotsContent);
301
- const sitemapUrls = robots.getSitemaps();
302
- // → ['https://example.com/sitemap.xml', 'https://example.com/sitemap-products.xml']
303
-
304
- // Para cada sitemap, usar sitemapper para extrair URLs
305
- import { Sitemapper } from 'sitemapper';
306
-
307
- const allUrls: string[] = [];
308
- for (const sitemapUrl of sitemapUrls) {
309
- const sitemapper = new Sitemapper({ url: sitemapUrl });
310
- const { sites } = await sitemapper.fetch();
311
- allUrls.push(...sites);
312
- }
313
-
314
- console.log(`Encontradas ${allUrls.length} URLs em sitemaps`);
315
- ```
316
-
317
- ### Parsing Combinado: robots.txt + sitemaps
318
-
319
- ```ts
320
- import robotsParser from 'robots-parser';
321
- import { Sitemapper } from 'sitemapper';
322
- import { gotScraping } from 'got-scraping';
323
-
324
- async function discoverUrlsFromSitemaps(
325
- baseUrl: string,
326
- ): Promise<{ urls: string[]; robots: ReturnType<typeof robotsParser> }> {
327
- const parsedUrl = new URL(baseUrl);
328
- const robotsUrl = `${parsedUrl.origin}/robots.txt`;
329
-
330
- // 1. Buscar e parsear robots.txt
331
- const robotsResponse = await gotScraping(robotsUrl);
332
- const robots = robotsParser(robotsUrl, robotsResponse.body);
333
-
334
- // 2. Extrair URLs de sitemaps
335
- const sitemapUrls = robots.getSitemaps() ?? [];
336
- const discoveredUrls: string[] = [];
337
-
338
- for (const sitemapUrl of sitemapUrls) {
339
- try {
340
- const sitemapper = new Sitemapper({
341
- url: sitemapUrl,
342
- timeout: 30000,
343
- });
344
- const { sites } = await sitemapper.fetch();
345
- discoveredUrls.push(...sites);
346
- } catch (error) {
347
- console.error(`Erro ao parse sitemap ${sitemapUrl}:`, error);
348
- }
349
- }
350
-
351
- // 3. Filtrar por robots.txt
352
- const allowedUrls = discoveredUrls.filter(url => robots.isAllowed(url) ?? true);
353
-
354
- return { urls: allowedUrls, robots };
355
- }
356
-
357
- const { urls } = await discoverUrlsFromSitemaps('https://example.com');
358
- console.log(`${urls.length} URLs permitidas por robots.txt`);
359
- ```
360
-
361
- ### Sitemap Index com Muitas URLs
362
-
363
- ```ts
364
- // Para sitemaps muito grandes, usar streaming
365
- import { Sitemapper } from 'sitemapper';
366
-
367
- const sitemapper = new Sitemapper({
368
- url: 'https://example.com/sitemap.xml',
369
- timeout: 60000, // 60s para sitemaps grandes
370
- });
371
-
372
- // Processar em lotes para memória
373
- const { sites } = await sitemapper.fetch();
374
- const batchSize = 1000;
375
-
376
- for (let i = 0; i < sites.length; i += batchSize) {
377
- const batch = sites.slice(i, i + batchSize);
378
- // Processar batch
379
- console.log(`Processando batch ${Math.floor(i / batchSize) + 1}: ${batch.length} URLs`);
380
- }
381
- ```
382
-
383
- ---
384
-
385
- ## URL Frontier com Prioridade
386
-
387
- ### p-queue 9.3.0
388
-
389
- `p-queue` é a fila com prioridade mais popular no Node.js. Permite controle fino de concorrência e prioridade.
390
-
391
- **Características:**
392
- - Prioridade 1-10 (1 = mais alta, 10 = mais baixa)
393
- - Controle de concorrência (limite de workers)
394
- - Intervalos entre requests (rate limiting)
395
- - Timeout por item
396
- - Persistência (pode ser combinada com storage)
397
-
398
- ```ts
399
- import PQueue from 'p-queue';
400
-
401
- const queue = new PQueue({
402
- concurrency: 5, // 5 requests simultâneos
403
- intervalCap: 10, // Máximo 10 requests por intervalo
404
- interval: 1000, // 1 segundo entre intervalos
405
- timeout: 30000, // Timeout de 30s por request
406
- });
407
-
408
- // Prioridade: 1 = mais alta, 10 = mais baixa
409
- queue.add(() => fetch('https://example.com'), { priority: 1 }); // Alta
410
- queue.add(() => fetch('https://example.com/a'), { priority: 5 }); // Média
411
- queue.add(() => fetch('https://example.com/b'), { priority: 10 }); // Baixa
412
- ```
413
-
414
- ### microfrontier
415
-
416
- `microfrontier` é uma alternativa leve para frontiers de URL. Oferece persistência em disco e controle de prioridade.
417
-
418
- ```ts
419
- import { Microfrontier } from 'microfrontier';
420
-
421
- const frontier = new Microfrontier({
422
- storage: './frontier-storage',
423
- maxConcurrent: 5,
424
- });
425
-
426
- // Adicionar URLs com prioridade
427
- frontier.push({ url: 'https://example.com', priority: 1 });
428
- frontier.push({ url: 'https://example.com/a', priority: 5 });
429
-
430
- // Pegar próxima URL
431
- const next = frontier.shift();
432
- ```
433
-
434
- ### Frontier com p-queue para Crawlee
435
-
436
- ```ts
437
- import PQueue from 'p-queue';
438
- import { PlaywrightCrawler } from 'crawlee';
439
-
440
- const queue = new PQueue({ concurrency: 3, intervalCap: 5, interval: 2000 });
441
-
442
- const crawler = new PlaywrightCrawler({
443
- maxConcurrency: 3,
444
- requestHandlerTimeoutSecs: 30,
445
- async requestHandler({ page, enqueueLinks }) {
446
- // Extrair e classificar links
447
- const links = await page.$$eval('a[href]', anchors =>
448
- anchors.map(a => ({
449
- url: a.href,
450
- priority: a.closest('nav') ? 1 : // Navegação = alta
451
- a.closest('article') ? 3 : // Artigo = média
452
- a.closest('footer') ? 8 : // Footer = baixa
453
- 5 // Default
454
- }))
455
- );
456
-
457
- // Adicionar com prioridade
458
- await queue.addAll(
459
- links.map(link => async () => {
460
- await page.goto(link.url);
461
- // Processar...
462
- }),
463
- { priority: link.priority }
464
- );
465
- },
466
- });
467
- ```
468
-
469
- ### Rate Limiting por Domínio
470
-
471
- ```ts
472
- import PQueue from 'p-queue';
473
-
474
- // Filas separadas por domínio
475
- const domainQueues = new Map<string, PQueue>();
476
-
477
- function getQueueForDomain(domain: string): PQueue {
478
- if (!domainQueues.has(domain)) {
479
- domainQueues.set(domain, new PQueue({
480
- concurrency: 2,
481
- intervalCap: 3,
482
- interval: 5000, // 3 requests a cada 5 segundos por domínio
483
- }));
484
- }
485
- return domainQueues.get(domain)!;
486
- }
487
-
488
- // Usar
489
- const domain = new URL(url).hostname;
490
- const queue = getQueueForDomain(domain);
491
- await queue.add(() => fetchAndProcess(url));
492
- ```
493
-
494
- ---
495
-
496
- ## URL Normalization
497
-
498
- ### normalize-url 9.0.0
499
-
500
- `normalize-url` é a biblioteca mais completa para normalização de URLs. Remove tracking params, sorting query strings, e muito mais.
501
-
502
- **Características:**
503
- - Remove `utm_*`, `fbclid`, `gclid` e outros tracking params
504
- - Sorting de query string
505
- - Conversão de protocolo
506
- - Remoção de trailing slashes
507
- - Normalização de host (lowercase)
508
-
509
- ```ts
510
- import normalizeUrl from 'normalize-url';
511
-
512
- // Remover tracking params
513
- normalizeUrl('https://example.com/page?utm_source=google&utm_medium=cpc&id=123');
514
- // → 'https://example.com/page?id=123'
515
-
516
- // Sorting de query
517
- normalizeUrl('https://example.com/page?z=1&a=2&m=3');
518
- // → 'https://example.com/page?a=2&m=3&z=1'
519
-
520
- // Normalização completa
521
- normalizeUrl('https://Example.COM/Page/?id=123#section', {
522
- sortQueryParams: true,
523
- removeTrailingSlash: true,
524
- removeExplicitPort: true,
525
- stripWWW: true,
526
- stripHash: true,
527
- removeDuplicateSlash: true,
528
- });
529
- // → 'https://example.com/Page?id=123'
530
-
531
- // Configuração customizada
532
- normalizeUrl('https://example.com/page', {
533
- protocols: ['https'],
534
- forceHttp: false,
535
- forceHttps: true,
536
- stripAuthentication: true,
537
- stripWWW: true,
538
- removeTrailingSlash: true,
539
- removeSingleDotSlash: true,
540
- sortQueryParams: true,
541
- removeDirectoryIndex: true,
542
- });
543
- ```
544
-
545
- ### Tracking Parameters Comuns para Remoção
546
-
547
- ```ts
548
- const TRACKING_PARAMS = new Set([
549
- // Google Analytics
550
- 'utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',
551
- 'utm_id', 'utm_cid', 'utm_reader', 'utm_name', 'utm_social',
552
- 'utm_social-type', 'utm_internal',
553
- // Google Ads
554
- 'gclid', 'gclsrc', 'dclid', 'gbraid', 'wbraid',
555
- // Facebook
556
- 'fbclid', 'fb_action_ids', 'fb_action_types', 'fb_ref', 'fb_source',
557
- // Microsoft
558
- 'msclkid', 'mc_cid', 'mc_eid',
559
- // Twitter
560
- 'twclid',
561
- // HubSpot
562
- 'hsa_cam', 'hsa_grp', 'hsa_mt', 'hsa_src', 'hsa_ad', 'hsa_acc',
563
- 'hsa_net', 'hsa_ver', 'hsa_la', 'hsa_ol', 'hsa_kw', 'hsa_target',
564
- 'hsa addTarget', 'hsa_src_campaign', 'hsa_src_ad',
565
- // Outros
566
- 'ref', 'source', 'medium', 'campaign', 'content', 'term',
567
- 'spm', 'from', 'share_id',
568
- ]);
569
-
570
- function normalizeForDedup(url: string): string {
571
- const parsed = new URL(url);
572
-
573
- // Remove tracking params
574
- const params = [...parsed.searchParams.entries()]
575
- .filter(([key]) => !TRACKING_PARAMS.has(key.toLowerCase()));
576
-
577
- // Sort params
578
- params.sort((a, b) => a[0].localeCompare(b[0]));
579
-
580
- // Reconstruir URL
581
- parsed.search = params.length > 0
582
- ? new URLSearchParams(params).toString()
583
- : '';
584
-
585
- // Normalizar
586
- return normalizeUrl(parsed.toString(), {
587
- sortQueryParams: true,
588
- removeTrailingSlash: true,
589
- stripWWW: true,
590
- stripHash: true,
591
- });
592
- }
593
-
594
- // Resultados
595
- normalizeForDedup('https://example.com/page?utm_source=google&id=123');
596
- // → 'https://example.com/page?id=123'
597
-
598
- normalizeForDedup('https://www.example.com/page/?utm_campaign=test#section');
599
- // → 'https://example.com/page'
600
- ```
601
-
602
- ### url-normalize (Alternativa)
603
-
604
- ```ts
605
- import { normalize } from 'url-normalize';
606
-
607
- const normalized = normalize('https://example.com/./page/../page?id=123');
608
- // → 'https://example.com/page?id=123'
609
- ```
610
-
611
- ### ufo (Alternativa Leve)
612
-
613
- ```ts
614
- import { normalizeURL, withQuery } from 'ufo';
615
-
616
- const normalized = normalizeURL('https://example.com/page/?id=123');
617
- // → 'https://example.com/page?id=123'
618
- ```
619
-
620
- ### Deduplicação de URLs Normalizadas
621
-
622
- ```ts
623
- import normalizeUrl from 'normalize-url';
624
-
625
- class UrlDeduplicator {
626
- private seen = new Set<string>();
627
-
628
- isUnique(url: string): boolean {
629
- const normalized = normalizeUrl(url, {
630
- sortQueryParams: true,
631
- removeTrailingSlash: true,
632
- stripWWW: true,
633
- stripHash: true,
634
- });
635
-
636
- if (this.seen.has(normalized)) {
637
- return false;
638
- }
639
-
640
- this.seen.add(normalized);
641
- return true;
642
- }
643
-
644
- get size(): number {
645
- return this.seen.size;
646
- }
647
-
648
- clear(): void {
649
- this.seen.clear();
650
- }
651
- }
652
-
653
- // Usar no crawler
654
- const dedup = new UrlDeduplicator();
655
- const urls = [
656
- 'https://example.com/page?utm_source=google',
657
- 'https://www.example.com/page/',
658
- 'https://example.com/page#section',
659
- 'https://example.com/page?id=123',
660
- ];
661
-
662
- const unique = urls.filter(url => dedup.isUnique(url));
663
- // → ['https://example.com/page?utm_source=google'] (primeira única)
664
- ```
665
-
666
- ---
667
-
668
- ## Depth-Limited Crawling
669
-
670
- ### Crawlee maxCrawlDepth
671
-
672
- `maxCrawlDepth` controla a profundidade máxima do crawl. A página inicial tem profundidade 0, links dela têm profundidade 1, e assim por diante.
673
-
674
- ```ts
675
- import { PlaywrightCrawler } from 'crawlee';
676
-
677
- const crawler = new PlaywrightCrawler({
678
- maxCrawlDepth: 3, // Máximo 3 níveis de profundidade
679
- requestHandlerTimeoutSecs: 30,
680
- async requestHandler({ page, enqueueLinks, request }) {
681
- const depth = request.userData?.depth ?? 0;
682
- console.log(`Processando: ${request.url} (profundidade: ${depth})`);
683
-
684
- // Só enfileirar se não atingiu o limite
685
- if (depth < 3) {
686
- await enqueueLinks({
687
- userData: { depth: depth + 1 },
688
- });
689
- }
690
- },
691
- });
692
-
693
- await crawler.run(['https://example.com']);
694
- ```
695
-
696
- ### Controle de Profundidade Manual
697
-
698
- ```ts
699
- import { PlaywrightCrawler } from 'crawlee';
700
-
701
- interface CrawlState {
702
- url: string;
703
- depth: number;
704
- parent: string | null;
705
- }
706
-
707
- const MAX_DEPTH = 3;
708
-
709
- const crawler = new PlaywrightCrawler({
710
- requestHandlerTimeoutSecs: 30,
711
- async requestHandler({ page, enqueueLinks, request }) {
712
- const state: CrawlState = request.userData ?? { url: request.url, depth: 0, parent: null };
713
-
714
- console.log(`${' '.repeat(state.depth)}[${state.depth}] ${request.url}`);
715
-
716
- // Processar página...
717
-
718
- // Enfileirar com controle de profundidade
719
- if (state.depth < MAX_DEPTH) {
720
- const links = await page.$$eval('a[href]', anchors =>
721
- anchors.map(a => a.href)
722
- );
723
-
724
- // Filtrar links internos
725
- const internalLinks = links.filter(link => {
726
- try {
727
- return new URL(link).hostname === new URL(request.url).hostname;
728
- } catch {
729
- return false;
730
- }
731
- });
732
-
733
- // Enfileirar com profundidade incrementada
734
- await enqueueLinks({
735
- userData: internalLinks.map(link => ({
736
- url: link,
737
- depth: state.depth + 1,
738
- parent: request.url,
739
- })),
740
- });
741
- }
742
- },
743
- });
744
-
745
- await crawler.run(['https://example.com']);
746
- ```
747
-
748
- ### Profundidade por Seção
749
-
750
- ```ts
751
- // Profundidade diferente por seção do site
752
- function getMaxDepthForPath(pathname: string): number {
753
- if (pathname.startsWith('/docs')) return 5; // Docs: mais profundo
754
- if (pathname.startsWith('/blog')) return 3; // Blog: médio
755
- if (pathname.startsWith('/products')) return 2; // Produtos: raso
756
- return 4; // Default
757
- }
758
-
759
- const crawler = new PlaywrightCrawler({
760
- async requestHandler({ page, enqueueLinks, request }) {
761
- const url = new URL(request.url);
762
- const maxDepth = getMaxDepthForPath(url.pathname);
763
- const currentDepth = request.userData?.depth ?? 0;
764
-
765
- if (currentDepth < maxDepth) {
766
- await enqueueLinks({
767
- userData: { depth: currentDepth + 1 },
768
- });
769
- }
770
- },
771
- });
772
- ```
773
-
774
- ---
775
-
776
- ## Domain-Specific Crawl Rules
777
-
778
- ### Crawlee EnqueueStrategy
779
-
780
- Crawlee oferece estratégias de enfileiramento por domínio/origem:
781
-
782
- ```ts
783
- import { PlaywrightCrawler, EnqueueStrategy } from 'crawlee';
784
-
785
- const crawler = new PlaywrightCrawler({
786
- async requestHandler({ page, enqueueLinks }) {
787
- // SameHostname: mesmo host (subdomínios diferentes NÃO são incluídos)
788
- await enqueueLinks({ strategy: EnqueueStrategy.SameHostname });
789
- // Exemplo: example.com → example.com OK, sub.example.com NÃO
790
-
791
- // SameDomain: mesmo domínio (subdomínios SÃO incluídos)
792
- await enqueueLinks({ strategy: EnqueueStrategy.SameDomain });
793
- // Exemplo: example.com → sub.example.com OK, other.com NÃO
794
-
795
- // SameOrigin: mesma origem (host + porta)
796
- await enqueueLinks({ strategy: EnqueueStrategy.SameOrigin });
797
- // Exemplo: https://example.com:443 → https://example.com:443 OK
798
-
799
- // All: todos os links (incluindo externos)
800
- await enqueueLinks({ strategy: EnqueueStrategy.All });
801
- // Exemplo: example.com → qualquer site
802
- },
803
- });
804
- ```
805
-
806
- ### Globs e Regexps
807
-
808
- ```ts
809
- const crawler = new PlaywrightCrawler({
810
- async requestHandler({ page, enqueueLinks }) {
811
- // Glob patterns — incluir apenas URLs que correspondem
812
- await enqueueLinks({
813
- globs: [
814
- 'https://example.com/blog/**', // Blog e subpáginas
815
- 'https://example.com/docs/**/api/**', // Documentação API
816
- ],
817
- });
818
-
819
- // Regex patterns — incluir apenas URLs que correspondem
820
- await enqueueLinks({
821
- regexps: [
822
- /https:\/\/example\.com\/products\/\d+/, // Páginas de produto
823
- /https:\/\/example\.com\/categories\/\w+/, // Categorias
824
- ],
825
- });
826
-
827
- // Excluir URLs com patterns
828
- await enqueueLinks({
829
- exclude: [
830
- '**/login', // Páginas de login
831
- '**/signup', // Cadastro
832
- '**/*.pdf', // PDFs
833
- '**/admin/**', // Admin
834
- '**/*?sort=*', // Ordenação
835
- '**/*?page=*', // Paginação
836
- ],
837
- });
838
- },
839
- });
840
- ```
841
-
842
- ### Regras Combinadas
843
-
844
- ```ts
845
- const crawler = new PlaywrightCrawler({
846
- async requestHandler({ page, enqueueLinks }) {
847
- await enqueueLinks({
848
- strategy: EnqueueStrategy.SameDomain,
849
- globs: [
850
- 'https://example.com/**',
851
- ],
852
- exclude: [
853
- '**/login',
854
- '**/signup',
855
- '**/admin/**',
856
- '**/*.pdf',
857
- '**/*.zip',
858
- ],
859
- regexps: [],
860
- userData: { crawledBy: 'main-crawler' },
861
- });
862
- },
863
- });
864
- ```
865
-
866
- ### Filtragem por Tipo de Link
867
-
868
- ```ts
869
- function classifyLink(url: string, text: string): 'high' | 'medium' | 'low' | 'skip' {
870
- const parsed = new URL(url);
871
-
872
- // Pular links indesejados
873
- if (parsed.pathname.match(/\.(pdf|zip|jpg|png|gif|mp4)$/i)) return 'skip';
874
- if (parsed.pathname.includes('/login') || parsed.pathname.includes('/signup')) return 'skip';
875
- if (parsed.search.includes('sort=') || parsed.search.includes('page=')) return 'skip';
876
-
877
- // Links de alta prioridade
878
- if (parsed.pathname.startsWith('/docs')) return 'high';
879
- if (parsed.pathname.startsWith('/api')) return 'high';
880
- if (parsed.pathname.startsWith('/blog')) return 'medium';
881
-
882
- // Links de baixa prioridade
883
- if (parsed.pathname.startsWith('/terms')) return 'low';
884
- if (parsed.pathname.startsWith('/privacy')) return 'low';
885
-
886
- return 'medium';
887
- }
888
-
889
- const crawler = new PlaywrightCrawler({
890
- async requestHandler({ page, enqueueLinks }) {
891
- const links = await page.$$eval('a[href]', anchors =>
892
- anchors.map(a => ({ url: a.href, text: a.textContent?.trim() ?? '' }))
893
- );
894
-
895
- const priorityMap = { high: 1, medium: 5, low: 8, skip: 10 };
896
-
897
- // Filtrar e classificar
898
- const filtered = links
899
- .map(link => ({
900
- ...link,
901
- priority: classifyLink(link.url, link.text),
902
- }))
903
- .filter(link => link.priority !== 'skip');
904
-
905
- // Enfileirar com prioridade
906
- for (const link of filtered) {
907
- await enqueueLinks({
908
- userData: { priority: priorityMap[link.priority] },
909
- });
910
- }
911
- },
912
- });
913
- ```
914
-
915
- ---
916
-
917
- ## Canonical URLs e Redirect Handling
918
-
919
- ### Canonical URLs
920
-
921
- Canonical URLs indicam a URL preferida para uma página. Crawlers devem usar a canonical em vez da URL original para evitar conteúdo duplicado.
922
-
923
- ```ts
924
- import { PlaywrightCrawler } from 'crawlee';
925
-
926
- const crawler = new PlaywrightCrawler({
927
- async requestHandler({ page, enqueueLinks, request }) {
928
- // Extrair canonical URL
929
- const canonical = await page.$eval(
930
- 'link[rel="canonical"]',
931
- el => el.getAttribute('href'),
932
- ).catch(() => null);
933
-
934
- // Se canonical existe e é diferente, usar canonical
935
- if (canonical && canonical !== request.url) {
936
- const canonicalUrl = new URL(canonical, request.url).toString();
937
- console.log(`Canonical: ${request.url} → ${canonicalUrl}`);
938
-
939
- // Enfileirar canonical se ainda não foi visitado
940
- await enqueueLinks({
941
- globs: [canonicalUrl],
942
- });
943
- }
944
-
945
- // Processar normalmente...
946
- },
947
- });
948
- ```
949
-
950
- ### Redirect Handling
951
-
952
- ```ts
953
- import { PlaywrightCrawler } from 'crawlee';
954
-
955
- const crawler = new PlaywrightCrawler({
956
- async requestHandler({ page, enqueueLinks, request }) {
957
- // Capturar redirects durante a navegação
958
- const response = await page.goto(request.url);
959
-
960
- if (response) {
961
- const finalUrl = page.url();
962
- const status = response.status();
963
-
964
- // 301/302 redirects
965
- if ([301, 302, 307, 308].includes(status)) {
966
- console.log(`Redirect ${status}: ${request.url} → ${finalUrl}`);
967
- }
968
-
969
- // URL final pode ter mudado
970
- if (finalUrl !== request.url) {
971
- console.log(`Final URL: ${finalUrl}`);
972
- }
973
- }
974
-
975
- // Extrair canonical
976
- const canonical = await page.$eval(
977
- 'link[rel="canonical"]',
978
- el => el.getAttribute('href'),
979
- ).catch(() => null);
980
-
981
- // Usar canonical se disponível
982
- const effectiveUrl = canonical
983
- ? new URL(canonical, page.url()).toString()
984
- : page.url();
985
-
986
- console.log(`Effective URL: ${effectiveUrl}`);
987
- },
988
- });
989
- ```
990
-
991
- ### Redirect Chain Tracking
992
-
993
- ```ts
994
- import { PlaywrightCrawler } from 'crawlee';
995
-
996
- interface RedirectChain {
997
- original: string;
998
- redirects: Array<{ url: string; status: number; timestamp: number }>;
999
- final: string;
1000
- }
1001
-
1002
- const crawler = new PlaywrightCrawler({
1003
- async requestHandler({ page, request }) {
1004
- const chain: RedirectChain = {
1005
- original: request.url,
1006
- redirects: [],
1007
- final: '',
1008
- };
1009
-
1010
- // Interceptar redirects
1011
- page.on('response', response => {
1012
- const status = response.status();
1013
- if ([301, 302, 307, 308].includes(status)) {
1014
- chain.redirects.push({
1015
- url: response.url(),
1016
- status,
1017
- timestamp: Date.now(),
1018
- });
1019
- }
1020
- });
1021
-
1022
- await page.goto(request.url, { waitUntil: 'networkidle' });
1023
- chain.final = page.url();
1024
-
1025
- if (chain.redirects.length > 0) {
1026
- console.log(`Redirect chain: ${chain.original}`);
1027
- for (const redirect of chain.redirects) {
1028
- console.log(` ${redirect.status} → ${redirect.url}`);
1029
- }
1030
- console.log(` Final: ${chain.final}`);
1031
- }
1032
- },
1033
- });
1034
- ```
1035
-
1036
- ### Canonical + Redirect Combinado
1037
-
1038
- ```ts
1039
- function resolveEffectiveUrl(pageUrl: string, canonicalHref: string | null): string {
1040
- // 1. Se canonical existe, é a fonte de verdade
1041
- if (canonicalHref) {
1042
- try {
1043
- return new URL(canonicalHref, pageUrl).toString();
1044
- } catch {
1045
- // Canonical inválido, usar pageUrl
1046
- }
1047
- }
1048
-
1049
- // 2. Caso contrário, usar a URL da página
1050
- return pageUrl;
1051
- }
1052
-
1053
- const crawler = new PlaywrightCrawler({
1054
- async requestHandler({ page, request }) {
1055
- const canonical = await page.$eval(
1056
- 'link[rel="canonical"]',
1057
- el => el.getAttribute('href'),
1058
- ).catch(() => null);
1059
-
1060
- const effectiveUrl = resolveEffectiveUrl(request.url, canonical);
1061
-
1062
- // Verificar se já processamos esta canonical
1063
- if (effectiveUrl !== request.url) {
1064
- console.log(`Canonical mismatch: ${request.url} → ${effectiveUrl}`);
1065
- }
1066
-
1067
- // Processar com a URL efetiva
1068
- },
1069
- });
1070
- ```
1071
-
1072
- ---
1073
-
1074
- ## Código Completo
1075
-
1076
- ### Exemplo 1: Crawler BFS com robots.txt, Sitemap, e Profundidade
1077
-
1078
- ```ts
1079
- import { PlaywrightCrawler, RobotsTxtFile } from 'crawlee';
1080
- import robotsParser from 'robots-parser';
1081
- import { Sitemapper } from 'sitemapper';
1082
- import { gotScraping } from 'got-scraping';
1083
- import normalizeUrl from 'normalize-url';
1084
-
1085
- interface CrawlConfig {
1086
- startUrls: string[];
1087
- maxDepth: number;
1088
- maxConcurrency: number;
1089
- crawlDelay: number;
1090
- userAgent: string;
1091
- }
1092
-
1093
- async function buildCrawler(config: CrawlConfig) {
1094
- // 1. Descobrir URLs via sitemap
1095
- const sitemapUrls: string[] = [];
1096
- for (const startUrl of config.startUrls) {
1097
- const parsedUrl = new URL(startUrl);
1098
-
1099
- try {
1100
- const robotsResponse = await gotScraping(`${parsedUrl.origin}/robots.txt`);
1101
- const robots = robotsParser(`${parsedUrl.origin}/robots.txt`, robotsResponse.body);
1102
-
1103
- const sitemapEndpoints = robots.getSitemaps() ?? [];
1104
- for (const sitemapUrl of sitemapEndpoints) {
1105
- const sitemapper = new Sitemapper({ url: sitemapUrl, timeout: 30000 });
1106
- const { sites } = await sitemapper.fetch();
1107
- sitemapUrls.push(...sites);
1108
- }
1109
- } catch (error) {
1110
- console.error(`Erro ao descobrir sitemaps para ${parsedUrl.origin}:`, error);
1111
- }
1112
- }
1113
-
1114
- console.log(`Descobertas ${sitemapUrls.length} URLs via sitemaps`);
1115
-
1116
- // 2. Deduplicar URLs normalizadas
1117
- const seen = new Set<string>();
1118
- const uniqueUrls = sitemapUrls.filter(url => {
1119
- const normalized = normalizeUrl(url, {
1120
- sortQueryParams: true,
1121
- stripWWW: true,
1122
- stripHash: true,
1123
- removeTrailingSlash: true,
1124
- });
1125
- if (seen.has(normalized)) return false;
1126
- seen.add(normalized);
1127
- return true;
1128
- });
1129
-
1130
- console.log(`${uniqueUrls.length} URLs únicas após normalização`);
1131
-
1132
- // 3. Criar crawler BFS com controle de profundidade
1133
- const crawler = new PlaywrightCrawler({
1134
- maxConcurrency: config.maxConcurrency,
1135
- requestHandlerTimeoutSecs: 30,
1136
- async requestHandler({ page, enqueueLinks, request }) {
1137
- const depth = request.userData?.depth ?? 0;
1138
- const indent = ' '.repeat(depth);
1139
-
1140
- console.log(`${indent}[Depth ${depth}] ${request.url}`);
1141
-
1142
- // Extrair dados da página
1143
- const title = await page.title();
1144
- const content = await page.content();
1145
-
1146
- // Processar dados...
1147
-
1148
- // Enfileirar links se não atingiu limite de profundidade
1149
- if (depth < config.maxDepth) {
1150
- await enqueueLinks({
1151
- strategy: 'same-domain',
1152
- userData: { depth: depth + 1 },
1153
- });
1154
- }
1155
- },
1156
- });
1157
-
1158
- // 4. Executar
1159
- const seedUrls = uniqueUrls.slice(0, 100); // Limitar URLs iniciais
1160
- await crawler.run(seedUrls);
1161
-
1162
- return {
1163
- totalProcessed: crawler.requestQueue?.handledCount() ?? 0,
1164
- totalEnqueued: crawler.requestQueue?.pendingCount() ?? 0,
1165
- };
1166
- }
1167
-
1168
- // Executar
1169
- const result = await buildCrawler({
1170
- startUrls: ['https://example.com'],
1171
- maxDepth: 3,
1172
- maxConcurrency: 3,
1173
- crawlDelay: 2,
1174
- userAgent: 'MyBot/1.0',
1175
- });
1176
-
1177
- console.log(`Crawl completo: ${result.totalProcessed} processadas, ${result.totalEnqueued} enfileiradas`);
1178
- ```
1179
-
1180
- ### Exemplo 2: Crawler DFS com Prioridade
1181
-
1182
- ```ts
1183
- import { PlaywrightCrawler } from 'crawlee';
1184
- import PQueue from 'p-queue';
1185
-
1186
- const queue = new PQueue({ concurrency: 5, intervalCap: 10, interval: 1000 });
1187
-
1188
- function classifyPriority(url: string): number {
1189
- const parsed = new URL(url);
1190
- if (parsed.pathname.startsWith('/docs')) return 1; // Alta
1191
- if (parsed.pathname.startsWith('/api')) return 2; // Alta
1192
- if (parsed.pathname.startsWith('/blog')) return 4; // Média
1193
- if (parsed.pathname.startsWith('/products')) return 6; // Média-baixa
1194
- return 8; // Baixa
1195
- }
1196
-
1197
- const crawler = new PlaywrightCrawler({
1198
- requestQueue: await (await import('crawlee')).RequestQueue.open('dfs-queue'),
1199
- async requestHandler({ page, enqueueLinks, request }) {
1200
- const depth = request.userData?.depth ?? 0;
1201
-
1202
- // DFS: forefront = true para ir para o início da fila
1203
- await enqueueLinks({
1204
- forefront: true, // DFS!
1205
- userData: { depth: depth + 1 },
1206
- });
1207
- },
1208
- });
1209
-
1210
- // Iniciar com URLs seed
1211
- await crawler.run([
1212
- 'https://example.com/docs',
1213
- 'https://example.com/api',
1214
- ]);
1215
- ```
1216
-
1217
- ### Exemplo 3: Rate Limiting por Domínio com p-queue
1218
-
1219
- ```ts
1220
- import PQueue from 'p-queue';
1221
-
1222
- const domainQueues = new Map<string, PQueue>();
1223
-
1224
- function getDomainQueue(domain: string): PQueue {
1225
- if (!domainQueues.has(domain)) {
1226
- domainQueues.set(domain, new PQueue({
1227
- concurrency: 2,
1228
- intervalCap: 3,
1229
- interval: 5000, // 3 requests a cada 5s por domínio
1230
- }));
1231
- }
1232
- return domainQueues.get(domain)!;
1233
- }
1234
-
1235
- async function crawlWithRateLimit(urls: string[]): Promise<void> {
1236
- const promises = urls.map(async (url) => {
1237
- const domain = new URL(url).hostname;
1238
- const queue = getDomainQueue(domain);
1239
-
1240
- await queue.add(async () => {
1241
- console.log(`Crawling: ${url}`);
1242
- // Simular crawl
1243
- await new Promise(resolve => setTimeout(resolve, 1000));
1244
- console.log(`Concluído: ${url}`);
1245
- });
1246
- });
1247
-
1248
- await Promise.all(promises);
1249
- }
1250
-
1251
- await crawlWithRateLimit([
1252
- 'https://example.com/page1',
1253
- 'https://example.com/page2',
1254
- 'https://other.com/page1',
1255
- 'https://other.com/page2',
1256
- ]);
1257
- ```
1258
-
1259
- ### Exemplo 4: Crawler Completo com Todas as Funcionalidades
1260
-
1261
- ```ts
1262
- import { PlaywrightCrawler, RequestQueue } from 'crawlee';
1263
- import robotsParser from 'robots-parser';
1264
- import { Sitemapper } from 'sitemapper';
1265
- import { gotScraping } from 'got-scraping';
1266
- import normalizeUrl from 'normalize-url';
1267
-
1268
- interface FullCrawlConfig {
1269
- startUrls: string[];
1270
- maxDepth: number;
1271
- maxConcurrency: number;
1272
- crawlDelay: number;
1273
- respectRobotsTxt: boolean;
1274
- useSitemaps: boolean;
1275
- }
1276
-
1277
- class WebCrawler {
1278
- private queue: RequestQueue;
1279
- private robots: Map<string, ReturnType<typeof robotsParser>> = new Map();
1280
- private seen: Set<string> = new Set();
1281
- private config: FullCrawlConfig;
1282
-
1283
- constructor(config: FullCrawlConfig) {
1284
- this.config = config;
1285
- }
1286
-
1287
- async initialize(): Promise<void> {
1288
- this.queue = await RequestQueue.open('full-crawl');
1289
-
1290
- // Descobrir sitemaps se habilitado
1291
- if (this.config.useSitemaps) {
1292
- await this.discoverFromSitemaps();
1293
- }
1294
- }
1295
-
1296
- private async discoverFromSitemaps(): Promise<void> {
1297
- for (const url of this.config.startUrls) {
1298
- const origin = new URL(url).origin;
1299
-
1300
- try {
1301
- // Buscar robots.txt
1302
- const robotsResponse = await gotScraping(`${origin}/robots.txt`);
1303
- const robots = robotsParser(`${origin}/robots.txt`, robotsResponse.body);
1304
- this.robots.set(origin, robots);
1305
-
1306
- // Extrair sitemaps
1307
- const sitemapEndpoints = robots.getSitemaps() ?? [];
1308
- for (const sitemapUrl of sitemapEndpoints) {
1309
- const sitemapper = new Sitemapper({ url: sitemapUrl, timeout: 30000 });
1310
- const { sites } = await sitemapper.fetch();
1311
-
1312
- for (const siteUrl of sites) {
1313
- const normalized = this.normalizeUrl(siteUrl);
1314
- if (!this.seen.has(normalized) && this.isAllowed(siteUrl)) {
1315
- this.seen.add(normalized);
1316
- await this.queue.addRequest({
1317
- url: siteUrl,
1318
- userData: { depth: 0 },
1319
- });
1320
- }
1321
- }
1322
- }
1323
- } catch (error) {
1324
- console.error(`Erro ao processar ${origin}:`, error);
1325
- }
1326
- }
1327
- }
1328
-
1329
- private normalizeUrl(url: string): string {
1330
- return normalizeUrl(url, {
1331
- sortQueryParams: true,
1332
- stripWWW: true,
1333
- stripHash: true,
1334
- removeTrailingSlash: true,
1335
- });
1336
- }
1337
-
1338
- private isAllowed(url: string): boolean {
1339
- if (!this.config.respectRobotsTxt) return true;
1340
-
1341
- const origin = new URL(url).origin;
1342
- const robots = this.robots.get(origin);
1343
- if (!robots) return true;
1344
-
1345
- return robots.isAllowed(url) ?? true;
1346
- }
1347
-
1348
- async crawl(): Promise<{ processed: number; enqueued: number }> {
1349
- const crawler = new PlaywrightCrawler({
1350
- maxConcurrency: this.config.maxConcurrency,
1351
- requestHandlerTimeoutSecs: 30,
1352
- requestQueue: this.queue,
1353
- async requestHandler({ page, enqueueLinks, request }) {
1354
- const depth = request.userData?.depth ?? 0;
1355
- const indent = ' '.repeat(depth);
1356
-
1357
- console.log(`${indent}[${depth}] ${request.url}`);
1358
-
1359
- // Extrair dados...
1360
- const title = await page.title();
1361
- console.log(`${indent} Title: ${title}`);
1362
-
1363
- // Enfileirar links
1364
- if (depth < this.config.maxDepth) {
1365
- const links = await page.$$eval('a[href]', anchors =>
1366
- anchors.map(a => a.href)
1367
- );
1368
-
1369
- for (const link of links) {
1370
- const normalized = this.normalizeUrl(link);
1371
- if (!this.seen.has(normalized) && this.isAllowed(link)) {
1372
- this.seen.add(normalized);
1373
- await this.queue.addRequest({
1374
- url: link,
1375
- userData: { depth: depth + 1 },
1376
- });
1377
- }
1378
- }
1379
- }
1380
- },
1381
- });
1382
-
1383
- await crawler.run(this.config.startUrls);
1384
-
1385
- return {
1386
- processed: this.queue.handledCount(),
1387
- enqueued: this.queue.pendingCount(),
1388
- };
1389
- }
1390
- }
1391
-
1392
- // Executar crawler completo
1393
- const crawler = new WebCrawler({
1394
- startUrls: ['https://example.com'],
1395
- maxDepth: 3,
1396
- maxConcurrency: 3,
1397
- crawlDelay: 2,
1398
- respectRobotsTxt: true,
1399
- useSitemaps: true,
1400
- });
1401
-
1402
- await crawler.initialize();
1403
- const result = await crawler.crawl();
1404
- console.log(`Crawl completo: ${result.processed} processadas`);
1405
- ```
1406
-
1407
- ---
1408
-
1409
- ## Referências
1410
-
1411
- - [Crawlee Documentation](https://crawlee.dev)
1412
- - [robots-parser npm](https://www.npmjs.com/package/robots-parser)
1413
- - [RFC 9309 - Robots Exclusion Protocol](https://www.rfc-editor.org/rfc/rfc9309)
1414
- - [sitemapper npm](https://www.npmjs.com/package/sitemapper)
1415
- - [p-queue npm](https://www.npmjs.com/package/p-queue)
1416
- - [normalize-url npm](https://www.npmjs.com/package/normalize-url)
1417
- - [ufo npm](https://www.npmjs.com/package/ufo)