@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.
- package/Dockerfile +1339 -0
- package/README.md +68 -22
- package/alternatives.ts +1218 -0
- package/biome.json +153 -0
- package/boards.json +1517 -0
- package/compute.ts +3144 -0
- package/cores.json +1801 -0
- package/dist/acquisition.d.ts +359 -0
- package/dist/acquisition.d.ts.map +1 -0
- package/dist/acquisition.js +629 -0
- package/dist/acquisition.js.map +1 -0
- package/dist/alternatives.d.ts +509 -0
- package/dist/alternatives.d.ts.map +1 -0
- package/dist/alternatives.js +951 -0
- package/dist/alternatives.js.map +1 -0
- package/dist/automation.d.ts +426 -0
- package/dist/automation.d.ts.map +1 -0
- package/dist/automation.js +561 -0
- package/dist/automation.js.map +1 -0
- package/dist/browser.d.ts +562 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +1057 -0
- package/dist/browser.js.map +1 -0
- package/dist/capacitor.config.d.ts +13 -0
- package/dist/capacitor.config.d.ts.map +1 -0
- package/dist/capacitor.config.js +26 -0
- package/dist/capacitor.config.js.map +1 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +111 -0
- package/dist/cli.js.map +1 -0
- package/dist/communication.d.ts +192 -0
- package/dist/communication.d.ts.map +1 -0
- package/dist/communication.js +418 -0
- package/dist/communication.js.map +1 -0
- package/dist/compute.d.ts +1161 -0
- package/dist/compute.d.ts.map +1 -0
- package/dist/compute.js +2273 -0
- package/dist/compute.js.map +1 -0
- package/dist/distribution.d.ts +529 -0
- package/dist/distribution.d.ts.map +1 -0
- package/dist/distribution.js +811 -0
- package/dist/distribution.js.map +1 -0
- package/dist/execution.d.ts +530 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +761 -0
- package/dist/execution.js.map +1 -0
- package/dist/format.d.ts +19 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +60 -0
- package/dist/format.js.map +1 -0
- package/dist/foundation.d.ts +176 -0
- package/dist/foundation.d.ts.map +1 -0
- package/dist/foundation.js +309 -0
- package/dist/foundation.js.map +1 -0
- package/dist/index.d.ts +733 -122
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1018 -122
- package/dist/index.js.map +1 -1
- package/dist/integration.d.ts +236 -0
- package/dist/integration.d.ts.map +1 -0
- package/dist/integration.js +236 -0
- package/dist/integration.js.map +1 -0
- package/dist/intelligence.d.ts +94 -0
- package/dist/intelligence.d.ts.map +1 -0
- package/dist/intelligence.js +145 -0
- package/dist/intelligence.js.map +1 -0
- package/dist/isolation.d.ts +129 -0
- package/dist/isolation.d.ts.map +1 -0
- package/dist/isolation.js +96 -0
- package/dist/isolation.js.map +1 -0
- package/dist/media.d.ts +344 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +986 -0
- package/dist/media.js.map +1 -0
- package/dist/modes.d.ts +359 -0
- package/dist/modes.d.ts.map +1 -0
- package/dist/modes.js +134 -0
- package/dist/modes.js.map +1 -0
- package/dist/{library/public.d.ts → operations.d.ts} +15 -1
- package/dist/operations.d.ts.map +1 -0
- package/dist/{library/public.js → operations.js} +18 -7
- package/dist/operations.js.map +1 -0
- package/dist/orchestrator.d.ts +1339 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +4308 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/performance.d.ts +416 -0
- package/dist/performance.d.ts.map +1 -0
- package/dist/performance.js +827 -0
- package/dist/performance.js.map +1 -0
- package/dist/quantum.d.ts +810 -0
- package/dist/quantum.d.ts.map +1 -0
- package/dist/quantum.js +2073 -0
- package/dist/quantum.js.map +1 -0
- package/dist/render.d.ts +381 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +1073 -0
- package/dist/render.js.map +1 -0
- package/dist/scheduler.d.ts +596 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +1259 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/security.d.ts +501 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +1170 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/{server/node.js → server.js} +16 -2
- package/dist/server.js.map +1 -0
- package/dist/tiers.d.ts +1002 -0
- package/dist/tiers.d.ts.map +1 -0
- package/dist/tiers.js +2165 -0
- package/dist/tiers.js.map +1 -0
- package/dist/virtual.d.ts +641 -0
- package/dist/virtual.d.ts.map +1 -0
- package/dist/virtual.js +1285 -0
- package/dist/virtual.js.map +1 -0
- package/dist/virtualcpu.d.ts +316 -0
- package/dist/virtualcpu.d.ts.map +1 -0
- package/dist/virtualcpu.js +1180 -0
- package/dist/virtualcpu.js.map +1 -0
- package/dist/virtualgpu.d.ts +345 -0
- package/dist/virtualgpu.d.ts.map +1 -0
- package/dist/virtualgpu.js +1000 -0
- package/dist/virtualgpu.js.map +1 -0
- package/dist/virtualization.d.ts +607 -0
- package/dist/virtualization.d.ts.map +1 -0
- package/dist/virtualization.js +1187 -0
- package/dist/virtualization.js.map +1 -0
- package/dist/virtualmemory.d.ts +818 -0
- package/dist/virtualmemory.d.ts.map +1 -0
- package/dist/virtualmemory.js +1796 -0
- package/dist/virtualmemory.js.map +1 -0
- package/dist/webscrape.d.ts +720 -0
- package/dist/webscrape.d.ts.map +1 -0
- package/dist/webscrape.js +2697 -0
- package/dist/webscrape.js.map +1 -0
- package/docker.config +769 -0
- package/docs/CONVERSA.txt +1523 -0
- package/docs/alternatives.md +499 -0
- package/docs/architecture-1.8.19.md +76 -0
- package/docs/architecture-1.8.19.mmd +33 -0
- package/docs/architecture-1.8.19.png +0 -0
- package/docs/architecture.md +355 -0
- package/docs/artifactavailability.md +6 -0
- package/docs/brancharchive-2026-08-18.md +18 -0
- package/docs/browser.md +7 -0
- package/docs/consolidation.md +70 -0
- package/docs/e2ugh-engine.md +528 -0
- package/{dist/examples/localjob.js → docs/example-localjob.ts} +3 -3
- package/{dist/examples/publicapi.js → docs/example-publicapi.ts} +2 -2
- package/docs/hardware.md +342 -0
- package/docs/optimization.md +126 -0
- package/docs/performance.md +499 -0
- package/docs/planning.1.8.18.md +94 -0
- package/docs/planning.1.8.19.md +49 -0
- package/docs/releasenotes-1.8.17.md +6 -0
- package/docs/releasenotes-1.8.18.md +32 -0
- package/docs/releasenotes-1.8.19.md +35 -0
- package/docs/research-1.8.18-isolation.md +43 -0
- package/docs/research-1.8.19-virtual-browser.md +27 -0
- package/docs/saddle.archive.1.8.17.tar.gz.gpg +0 -0
- package/docs/security.md +454 -0
- package/docs/todo-1.8.16.md +56 -1
- package/docs/todo-1.8.18.md +164 -0
- package/docs/todo-1.8.19.md +241 -0
- package/docs/viability.md +777 -0
- package/docs/virtualization.md +335 -0
- package/docs/web-duplicatecleanup.md +9 -0
- package/docs/web-ideas.md +106 -0
- package/docs/workflowimprovements-2026-08-19.md +70 -0
- package/gpumonitor.cpp +1543 -0
- package/gpus.json +2408 -0
- package/index.ts +1478 -0
- package/media.ts +1337 -0
- package/mttg.config +1549 -0
- package/orchestrator.ts +5462 -0
- package/package.json +304 -55
- package/passage.config +1331 -0
- package/performance.ts +1049 -0
- package/processors.json +2217 -0
- package/qemu.config +1062 -0
- package/qemubridge.py +1340 -0
- package/quantum.ts +2393 -0
- package/render.ts +1325 -0
- package/scheduler.ts +1600 -0
- package/security.ts +1449 -0
- package/tiers.ts +2871 -0
- package/tsconfig.json +29 -0
- package/virtualcpu.ts +1273 -0
- package/virtualgpu.ts +1181 -0
- package/virtualhardware.c +1011 -0
- package/virtualhardware.json +739 -0
- package/virtualization.ts +1628 -0
- package/virtualizationcore.cpp +4635 -0
- package/virtualmemory.ts +2303 -0
- package/vm.config.json +1910 -0
- package/{extension → web/extension}/manifest.json +1 -1
- package/web/readme.md +382 -0
- package/web/tsconfig.json +25 -0
- package/dist/adapters/forge.d.ts +0 -17
- package/dist/adapters/forge.d.ts.map +0 -1
- package/dist/adapters/forge.js +0 -19
- package/dist/adapters/forge.js.map +0 -1
- package/dist/adapters/forgejo.d.ts +0 -49
- package/dist/adapters/forgejo.d.ts.map +0 -1
- package/dist/adapters/forgejo.js +0 -8
- package/dist/adapters/forgejo.js.map +0 -1
- package/dist/adapters/github.d.ts +0 -12
- package/dist/adapters/github.d.ts.map +0 -1
- package/dist/adapters/github.js +0 -20
- package/dist/adapters/github.js.map +0 -1
- package/dist/adapters/gitlab.d.ts +0 -17
- package/dist/adapters/gitlab.d.ts.map +0 -1
- package/dist/adapters/gitlab.js +0 -10
- package/dist/adapters/gitlab.js.map +0 -1
- package/dist/adapters/huggingface.d.ts +0 -17
- package/dist/adapters/huggingface.d.ts.map +0 -1
- package/dist/adapters/huggingface.js +0 -6
- package/dist/adapters/huggingface.js.map +0 -1
- package/dist/adapters/socket.d.ts +0 -11
- package/dist/adapters/socket.d.ts.map +0 -1
- package/dist/adapters/socket.js +0 -17
- package/dist/adapters/socket.js.map +0 -1
- package/dist/adapters/transport.d.ts +0 -7
- package/dist/adapters/transport.d.ts.map +0 -1
- package/dist/adapters/transport.js +0 -36
- package/dist/adapters/transport.js.map +0 -1
- package/dist/ai/chunk.d.ts +0 -2
- package/dist/ai/chunk.d.ts.map +0 -1
- package/dist/ai/chunk.js +0 -36
- package/dist/ai/chunk.js.map +0 -1
- package/dist/ai/llmstxt.d.ts +0 -6
- package/dist/ai/llmstxt.d.ts.map +0 -1
- package/dist/ai/llmstxt.js +0 -12
- package/dist/ai/llmstxt.js.map +0 -1
- package/dist/ai/provenance.d.ts +0 -22
- package/dist/ai/provenance.d.ts.map +0 -1
- package/dist/ai/provenance.js +0 -25
- package/dist/ai/provenance.js.map +0 -1
- package/dist/ai/rag.d.ts +0 -26
- package/dist/ai/rag.d.ts.map +0 -1
- package/dist/ai/rag.js +0 -22
- package/dist/ai/rag.js.map +0 -1
- package/dist/ai/tokens.d.ts +0 -15
- package/dist/ai/tokens.d.ts.map +0 -1
- package/dist/ai/tokens.js +0 -9
- package/dist/ai/tokens.js.map +0 -1
- package/dist/api/auth.d.ts +0 -16
- package/dist/api/auth.d.ts.map +0 -1
- package/dist/api/auth.js +0 -19
- package/dist/api/auth.js.map +0 -1
- package/dist/api/contracts.d.ts +0 -28
- package/dist/api/contracts.d.ts.map +0 -1
- package/dist/api/contracts.js +0 -14
- package/dist/api/contracts.js.map +0 -1
- package/dist/api/control.d.ts +0 -10
- package/dist/api/control.d.ts.map +0 -1
- package/dist/api/control.js +0 -35
- package/dist/api/control.js.map +0 -1
- package/dist/api/http.d.ts +0 -7
- package/dist/api/http.d.ts.map +0 -1
- package/dist/api/http.js +0 -12
- package/dist/api/http.js.map +0 -1
- package/dist/api/rate.d.ts +0 -28
- package/dist/api/rate.d.ts.map +0 -1
- package/dist/api/rate.js +0 -36
- package/dist/api/rate.js.map +0 -1
- package/dist/api/security.d.ts +0 -12
- package/dist/api/security.d.ts.map +0 -1
- package/dist/api/security.js +0 -56
- package/dist/api/security.js.map +0 -1
- package/dist/api/service.d.ts +0 -5
- package/dist/api/service.d.ts.map +0 -1
- package/dist/api/service.js +0 -70
- package/dist/api/service.js.map +0 -1
- package/dist/apps/registry.d.ts +0 -33
- package/dist/apps/registry.d.ts.map +0 -1
- package/dist/apps/registry.js +0 -24
- package/dist/apps/registry.js.map +0 -1
- package/dist/binary/archive.d.ts +0 -27
- package/dist/binary/archive.d.ts.map +0 -1
- package/dist/binary/archive.js +0 -46
- package/dist/binary/archive.js.map +0 -1
- package/dist/binary/build.d.ts +0 -29
- package/dist/binary/build.d.ts.map +0 -1
- package/dist/binary/build.js +0 -17
- package/dist/binary/build.js.map +0 -1
- package/dist/binary/transform.d.ts +0 -70
- package/dist/binary/transform.d.ts.map +0 -1
- package/dist/binary/transform.js +0 -105
- package/dist/binary/transform.js.map +0 -1
- package/dist/bot/adapter.d.ts +0 -5
- package/dist/bot/adapter.d.ts.map +0 -1
- package/dist/bot/adapter.js +0 -11
- package/dist/bot/adapter.js.map +0 -1
- package/dist/bot/bot.d.ts +0 -28
- package/dist/bot/bot.d.ts.map +0 -1
- package/dist/bot/bot.js +0 -52
- package/dist/bot/bot.js.map +0 -1
- package/dist/bot/commands.d.ts +0 -8
- package/dist/bot/commands.d.ts.map +0 -1
- package/dist/bot/commands.js +0 -19
- package/dist/bot/commands.js.map +0 -1
- package/dist/bot/permissions.d.ts +0 -13
- package/dist/bot/permissions.d.ts.map +0 -1
- package/dist/bot/permissions.js +0 -16
- package/dist/bot/permissions.js.map +0 -1
- package/dist/browser/actions.d.ts +0 -33
- package/dist/browser/actions.d.ts.map +0 -1
- package/dist/browser/actions.js +0 -44
- package/dist/browser/actions.js.map +0 -1
- package/dist/browser/agent.d.ts +0 -21
- package/dist/browser/agent.d.ts.map +0 -1
- package/dist/browser/agent.js +0 -13
- package/dist/browser/agent.js.map +0 -1
- package/dist/browser/context.d.ts +0 -43
- package/dist/browser/context.d.ts.map +0 -1
- package/dist/browser/context.js +0 -54
- package/dist/browser/context.js.map +0 -1
- package/dist/browser/fingerprint.d.ts +0 -4
- package/dist/browser/fingerprint.d.ts.map +0 -1
- package/dist/browser/fingerprint.js +0 -12
- package/dist/browser/fingerprint.js.map +0 -1
- package/dist/browser/index.d.ts +0 -11
- package/dist/browser/index.d.ts.map +0 -1
- package/dist/browser/index.js +0 -11
- package/dist/browser/index.js.map +0 -1
- package/dist/browser/playwright.d.ts +0 -11
- package/dist/browser/playwright.d.ts.map +0 -1
- package/dist/browser/playwright.js +0 -24
- package/dist/browser/playwright.js.map +0 -1
- package/dist/browser/recorder.d.ts +0 -21
- package/dist/browser/recorder.d.ts.map +0 -1
- package/dist/browser/recorder.js +0 -58
- package/dist/browser/recorder.js.map +0 -1
- package/dist/browser/session.d.ts +0 -14
- package/dist/browser/session.d.ts.map +0 -1
- package/dist/browser/session.js +0 -21
- package/dist/browser/session.js.map +0 -1
- package/dist/browser/snapshot.d.ts +0 -69
- package/dist/browser/snapshot.d.ts.map +0 -1
- package/dist/browser/snapshot.js +0 -133
- package/dist/browser/snapshot.js.map +0 -1
- package/dist/captcha/contract.d.ts +0 -35
- package/dist/captcha/contract.d.ts.map +0 -1
- package/dist/captcha/contract.js +0 -17
- package/dist/captcha/contract.js.map +0 -1
- package/dist/captcha/evidence.d.ts +0 -10
- package/dist/captcha/evidence.d.ts.map +0 -1
- package/dist/captcha/evidence.js +0 -9
- package/dist/captcha/evidence.js.map +0 -1
- package/dist/captcha/guard.d.ts +0 -23
- package/dist/captcha/guard.d.ts.map +0 -1
- package/dist/captcha/guard.js +0 -12
- package/dist/captcha/guard.js.map +0 -1
- package/dist/cli/main.d.ts +0 -4
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -46
- package/dist/cli/main.js.map +0 -1
- package/dist/core/errors.d.ts +0 -84
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js +0 -54
- package/dist/core/errors.js.map +0 -1
- package/dist/core/events.d.ts +0 -9
- package/dist/core/events.d.ts.map +0 -1
- package/dist/core/events.js +0 -21
- package/dist/core/events.js.map +0 -1
- package/dist/core/hash.d.ts +0 -10
- package/dist/core/hash.d.ts.map +0 -1
- package/dist/core/hash.js +0 -82
- package/dist/core/hash.js.map +0 -1
- package/dist/core/ids.d.ts +0 -10
- package/dist/core/ids.d.ts.map +0 -1
- package/dist/core/ids.js +0 -15
- package/dist/core/ids.js.map +0 -1
- package/dist/delivery/manifest.d.ts +0 -35
- package/dist/delivery/manifest.d.ts.map +0 -1
- package/dist/delivery/manifest.js +0 -68
- package/dist/delivery/manifest.js.map +0 -1
- package/dist/deploy/index.d.ts +0 -6
- package/dist/deploy/index.d.ts.map +0 -1
- package/dist/deploy/index.js +0 -6
- package/dist/deploy/index.js.map +0 -1
- package/dist/dispatch/resumable.d.ts +0 -102
- package/dist/dispatch/resumable.d.ts.map +0 -1
- package/dist/dispatch/resumable.js +0 -64
- package/dist/dispatch/resumable.js.map +0 -1
- package/dist/dispatch/workflow.d.ts +0 -6
- package/dist/dispatch/workflow.d.ts.map +0 -1
- package/dist/dispatch/workflow.js +0 -37
- package/dist/dispatch/workflow.js.map +0 -1
- package/dist/domain/artifacts.d.ts +0 -12
- package/dist/domain/artifacts.d.ts.map +0 -1
- package/dist/domain/artifacts.js +0 -14
- package/dist/domain/artifacts.js.map +0 -1
- package/dist/domain/jobs.d.ts +0 -12
- package/dist/domain/jobs.d.ts.map +0 -1
- package/dist/domain/jobs.js +0 -20
- package/dist/domain/jobs.js.map +0 -1
- package/dist/domain/providers.d.ts +0 -10
- package/dist/domain/providers.d.ts.map +0 -1
- package/dist/domain/providers.js +0 -8
- package/dist/domain/providers.js.map +0 -1
- package/dist/domain/runtime.d.ts +0 -14
- package/dist/domain/runtime.d.ts.map +0 -1
- package/dist/domain/runtime.js +0 -10
- package/dist/domain/runtime.js.map +0 -1
- package/dist/domain/sessions.d.ts +0 -12
- package/dist/domain/sessions.d.ts.map +0 -1
- package/dist/domain/sessions.js +0 -57
- package/dist/domain/sessions.js.map +0 -1
- package/dist/examples/localjob.d.ts +0 -2
- package/dist/examples/localjob.d.ts.map +0 -1
- package/dist/examples/localjob.js.map +0 -1
- package/dist/examples/publicapi.d.ts +0 -2
- package/dist/examples/publicapi.d.ts.map +0 -1
- package/dist/examples/publicapi.js.map +0 -1
- package/dist/extension/build.d.ts +0 -9
- package/dist/extension/build.d.ts.map +0 -1
- package/dist/extension/build.js +0 -85
- package/dist/extension/build.js.map +0 -1
- package/dist/extension/content.d.ts +0 -6
- package/dist/extension/content.d.ts.map +0 -1
- package/dist/extension/content.js +0 -135
- package/dist/extension/content.js.map +0 -1
- package/dist/extension/index.d.ts +0 -7
- package/dist/extension/index.d.ts.map +0 -1
- package/dist/extension/index.js +0 -7
- package/dist/extension/index.js.map +0 -1
- package/dist/extension/pagebridge.d.ts +0 -6
- package/dist/extension/pagebridge.d.ts.map +0 -1
- package/dist/extension/pagebridge.js +0 -42
- package/dist/extension/pagebridge.js.map +0 -1
- package/dist/extension/permissions.d.ts +0 -26
- package/dist/extension/permissions.d.ts.map +0 -1
- package/dist/extension/permissions.js +0 -28
- package/dist/extension/permissions.js.map +0 -1
- package/dist/extension/popup.d.ts +0 -5
- package/dist/extension/popup.d.ts.map +0 -1
- package/dist/extension/popup.js +0 -26
- package/dist/extension/popup.js.map +0 -1
- package/dist/extension/protocol.d.ts +0 -58
- package/dist/extension/protocol.d.ts.map +0 -1
- package/dist/extension/protocol.js +0 -101
- package/dist/extension/protocol.js.map +0 -1
- package/dist/extension/serviceworker.d.ts +0 -25
- package/dist/extension/serviceworker.d.ts.map +0 -1
- package/dist/extension/serviceworker.js +0 -102
- package/dist/extension/serviceworker.js.map +0 -1
- package/dist/extension/worker.d.ts +0 -28
- package/dist/extension/worker.d.ts.map +0 -1
- package/dist/extension/worker.js +0 -22
- package/dist/extension/worker.js.map +0 -1
- package/dist/format/check.d.ts +0 -8
- package/dist/format/check.d.ts.map +0 -1
- package/dist/format/check.js +0 -38
- package/dist/format/check.js.map +0 -1
- package/dist/library/public.d.ts.map +0 -1
- package/dist/library/public.js.map +0 -1
- package/dist/mcp/browser.d.ts +0 -9
- package/dist/mcp/browser.d.ts.map +0 -1
- package/dist/mcp/browser.js +0 -13
- package/dist/mcp/browser.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -35
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js +0 -40
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/transport.d.ts +0 -7
- package/dist/mcp/transport.d.ts.map +0 -1
- package/dist/mcp/transport.js +0 -17
- package/dist/mcp/transport.js.map +0 -1
- package/dist/memory/bridge.d.ts +0 -14
- package/dist/memory/bridge.d.ts.map +0 -1
- package/dist/memory/bridge.js +0 -16
- package/dist/memory/bridge.js.map +0 -1
- package/dist/memory/engine.d.ts +0 -38
- package/dist/memory/engine.d.ts.map +0 -1
- package/dist/memory/engine.js +0 -109
- package/dist/memory/engine.js.map +0 -1
- package/dist/memory/modes.d.ts +0 -43
- package/dist/memory/modes.d.ts.map +0 -1
- package/dist/memory/modes.js +0 -66
- package/dist/memory/modes.js.map +0 -1
- package/dist/memory/objects.d.ts +0 -21
- package/dist/memory/objects.d.ts.map +0 -1
- package/dist/memory/objects.js +0 -20
- package/dist/memory/objects.js.map +0 -1
- package/dist/memory/planner.d.ts +0 -66
- package/dist/memory/planner.d.ts.map +0 -1
- package/dist/memory/planner.js +0 -108
- package/dist/memory/planner.js.map +0 -1
- package/dist/memory/targets.d.ts +0 -78
- package/dist/memory/targets.d.ts.map +0 -1
- package/dist/memory/targets.js +0 -29
- package/dist/memory/targets.js.map +0 -1
- package/dist/memory/transforms.d.ts +0 -19
- package/dist/memory/transforms.d.ts.map +0 -1
- package/dist/memory/transforms.js +0 -14
- package/dist/memory/transforms.js.map +0 -1
- package/dist/modes/matrix.d.ts +0 -23
- package/dist/modes/matrix.d.ts.map +0 -1
- package/dist/modes/matrix.js +0 -18
- package/dist/modes/matrix.js.map +0 -1
- package/dist/modes/modes.d.ts +0 -33
- package/dist/modes/modes.d.ts.map +0 -1
- package/dist/modes/modes.js +0 -15
- package/dist/modes/modes.js.map +0 -1
- package/dist/modes/resolve.d.ts +0 -96
- package/dist/modes/resolve.d.ts.map +0 -1
- package/dist/modes/resolve.js +0 -48
- package/dist/modes/resolve.js.map +0 -1
- package/dist/observability/metrics.d.ts +0 -14
- package/dist/observability/metrics.d.ts.map +0 -1
- package/dist/observability/metrics.js +0 -18
- package/dist/observability/metrics.js.map +0 -1
- package/dist/packager/manifest.d.ts +0 -66
- package/dist/packager/manifest.d.ts.map +0 -1
- package/dist/packager/manifest.js +0 -94
- package/dist/packager/manifest.js.map +0 -1
- package/dist/packager/publish.d.ts +0 -51
- package/dist/packager/publish.d.ts.map +0 -1
- package/dist/packager/publish.js +0 -18
- package/dist/packager/publish.js.map +0 -1
- package/dist/packager/targetcli.d.ts +0 -7
- package/dist/packager/targetcli.d.ts.map +0 -1
- package/dist/packager/targetcli.js +0 -22
- package/dist/packager/targetcli.js.map +0 -1
- package/dist/persistence/adapter.d.ts +0 -5
- package/dist/persistence/adapter.d.ts.map +0 -1
- package/dist/persistence/adapter.js +0 -11
- package/dist/persistence/adapter.js.map +0 -1
- package/dist/persistence/drizzle.d.ts +0 -2
- package/dist/persistence/drizzle.d.ts.map +0 -1
- package/dist/persistence/drizzle.js +0 -12
- package/dist/persistence/drizzle.js.map +0 -1
- package/dist/persistence/memory.d.ts +0 -2
- package/dist/persistence/memory.d.ts.map +0 -1
- package/dist/persistence/memory.js +0 -27
- package/dist/persistence/memory.js.map +0 -1
- package/dist/persistence/migrations.d.ts +0 -19
- package/dist/persistence/migrations.d.ts.map +0 -1
- package/dist/persistence/migrations.js +0 -13
- package/dist/persistence/migrations.js.map +0 -1
- package/dist/persistence/prisma.d.ts +0 -2
- package/dist/persistence/prisma.d.ts.map +0 -1
- package/dist/persistence/prisma.js +0 -25
- package/dist/persistence/prisma.js.map +0 -1
- package/dist/persistence/schema.d.ts +0 -63
- package/dist/persistence/schema.d.ts.map +0 -1
- package/dist/persistence/schema.js +0 -28
- package/dist/persistence/schema.js.map +0 -1
- package/dist/persistence/sql.d.ts +0 -3
- package/dist/persistence/sql.d.ts.map +0 -1
- package/dist/persistence/sql.js +0 -37
- package/dist/persistence/sql.js.map +0 -1
- package/dist/protocol/blocks.d.ts +0 -10
- package/dist/protocol/blocks.d.ts.map +0 -1
- package/dist/protocol/blocks.js +0 -26
- package/dist/protocol/blocks.js.map +0 -1
- package/dist/protocol/json.d.ts +0 -6
- package/dist/protocol/json.d.ts.map +0 -1
- package/dist/protocol/json.js +0 -6
- package/dist/protocol/json.js.map +0 -1
- package/dist/protocol/ndjson.d.ts +0 -3
- package/dist/protocol/ndjson.d.ts.map +0 -1
- package/dist/protocol/ndjson.js +0 -20
- package/dist/protocol/ndjson.js.map +0 -1
- package/dist/protocol/sse.d.ts +0 -7
- package/dist/protocol/sse.d.ts.map +0 -1
- package/dist/protocol/sse.js +0 -25
- package/dist/protocol/sse.js.map +0 -1
- package/dist/proxy/pool.d.ts +0 -9
- package/dist/proxy/pool.d.ts.map +0 -1
- package/dist/proxy/pool.js +0 -27
- package/dist/proxy/pool.js.map +0 -1
- package/dist/queue/idempotency.d.ts +0 -10
- package/dist/queue/idempotency.d.ts.map +0 -1
- package/dist/queue/idempotency.js +0 -13
- package/dist/queue/idempotency.js.map +0 -1
- package/dist/queue/persistent.d.ts +0 -14
- package/dist/queue/persistent.d.ts.map +0 -1
- package/dist/queue/persistent.js +0 -66
- package/dist/queue/persistent.js.map +0 -1
- package/dist/queue/queue.d.ts +0 -7
- package/dist/queue/queue.d.ts.map +0 -1
- package/dist/queue/queue.js +0 -55
- package/dist/queue/queue.js.map +0 -1
- package/dist/queue/saga.d.ts +0 -5
- package/dist/queue/saga.d.ts.map +0 -1
- package/dist/queue/saga.js +0 -20
- package/dist/queue/saga.js.map +0 -1
- package/dist/release/assets.d.ts +0 -144
- package/dist/release/assets.d.ts.map +0 -1
- package/dist/release/assets.js +0 -157
- package/dist/release/assets.js.map +0 -1
- package/dist/release/evidence.d.ts +0 -92
- package/dist/release/evidence.d.ts.map +0 -1
- package/dist/release/evidence.js +0 -148
- package/dist/release/evidence.js.map +0 -1
- package/dist/release/verify.d.ts +0 -12
- package/dist/release/verify.d.ts.map +0 -1
- package/dist/release/verify.js +0 -112
- package/dist/release/verify.js.map +0 -1
- package/dist/runners/chain.d.ts +0 -125
- package/dist/runners/chain.d.ts.map +0 -1
- package/dist/runners/chain.js +0 -95
- package/dist/runners/chain.js.map +0 -1
- package/dist/runners/health.d.ts +0 -36
- package/dist/runners/health.d.ts.map +0 -1
- package/dist/runners/health.js +0 -26
- package/dist/runners/health.js.map +0 -1
- package/dist/runners/heartbeat.d.ts +0 -23
- package/dist/runners/heartbeat.d.ts.map +0 -1
- package/dist/runners/heartbeat.js +0 -29
- package/dist/runners/heartbeat.js.map +0 -1
- package/dist/runners/inprocess.d.ts +0 -17
- package/dist/runners/inprocess.d.ts.map +0 -1
- package/dist/runners/inprocess.js +0 -20
- package/dist/runners/inprocess.js.map +0 -1
- package/dist/runners/scheduler.d.ts +0 -5
- package/dist/runners/scheduler.d.ts.map +0 -1
- package/dist/runners/scheduler.js +0 -19
- package/dist/runners/scheduler.js.map +0 -1
- package/dist/runtime/abort.d.ts +0 -8
- package/dist/runtime/abort.d.ts.map +0 -1
- package/dist/runtime/abort.js +0 -13
- package/dist/runtime/abort.js.map +0 -1
- package/dist/runtime/compatibility.d.ts +0 -37
- package/dist/runtime/compatibility.d.ts.map +0 -1
- package/dist/runtime/compatibility.js +0 -10
- package/dist/runtime/compatibility.js.map +0 -1
- package/dist/runtime/detect.d.ts +0 -13
- package/dist/runtime/detect.d.ts.map +0 -1
- package/dist/runtime/detect.js +0 -18
- package/dist/runtime/detect.js.map +0 -1
- package/dist/runtime/engine.d.ts +0 -20
- package/dist/runtime/engine.d.ts.map +0 -1
- package/dist/runtime/engine.js +0 -61
- package/dist/runtime/engine.js.map +0 -1
- package/dist/runtime/retry.d.ts +0 -19
- package/dist/runtime/retry.d.ts.map +0 -1
- package/dist/runtime/retry.js +0 -54
- package/dist/runtime/retry.js.map +0 -1
- package/dist/runtime/worker.d.ts +0 -10
- package/dist/runtime/worker.d.ts.map +0 -1
- package/dist/runtime/worker.js +0 -25
- package/dist/runtime/worker.js.map +0 -1
- package/dist/scrape/cache.d.ts +0 -45
- package/dist/scrape/cache.d.ts.map +0 -1
- package/dist/scrape/cache.js +0 -45
- package/dist/scrape/cache.js.map +0 -1
- package/dist/scrape/crawl.d.ts +0 -47
- package/dist/scrape/crawl.d.ts.map +0 -1
- package/dist/scrape/crawl.js +0 -114
- package/dist/scrape/crawl.js.map +0 -1
- package/dist/scrape/extract.d.ts +0 -63
- package/dist/scrape/extract.d.ts.map +0 -1
- package/dist/scrape/extract.js +0 -47
- package/dist/scrape/extract.js.map +0 -1
- package/dist/scrape/normalize.d.ts +0 -52
- package/dist/scrape/normalize.d.ts.map +0 -1
- package/dist/scrape/normalize.js +0 -102
- package/dist/scrape/normalize.js.map +0 -1
- package/dist/scrape/robots.d.ts +0 -37
- package/dist/scrape/robots.d.ts.map +0 -1
- package/dist/scrape/robots.js +0 -71
- package/dist/scrape/robots.js.map +0 -1
- package/dist/scrape/schema.d.ts +0 -23
- package/dist/scrape/schema.d.ts.map +0 -1
- package/dist/scrape/schema.js +0 -92
- package/dist/scrape/schema.js.map +0 -1
- package/dist/scrape/scraper.d.ts +0 -6
- package/dist/scrape/scraper.d.ts.map +0 -1
- package/dist/scrape/scraper.js +0 -46
- package/dist/scrape/scraper.js.map +0 -1
- package/dist/scrape/semantic.d.ts +0 -25
- package/dist/scrape/semantic.d.ts.map +0 -1
- package/dist/scrape/semantic.js +0 -27
- package/dist/scrape/semantic.js.map +0 -1
- package/dist/server/node.d.ts +0 -7
- package/dist/server/node.d.ts.map +0 -1
- package/dist/server/node.js.map +0 -1
- package/dist/sessions/file.d.ts +0 -25
- package/dist/sessions/file.d.ts.map +0 -1
- package/dist/sessions/file.js +0 -13
- package/dist/sessions/file.js.map +0 -1
- package/dist/sessions/replay.d.ts +0 -9
- package/dist/sessions/replay.d.ts.map +0 -1
- package/dist/sessions/replay.js +0 -70
- package/dist/sessions/replay.js.map +0 -1
- package/dist/sessions/store.d.ts +0 -25
- package/dist/sessions/store.d.ts.map +0 -1
- package/dist/sessions/store.js +0 -13
- package/dist/sessions/store.js.map +0 -1
- package/dist/storage/adapter.d.ts +0 -5
- package/dist/storage/adapter.d.ts.map +0 -1
- package/dist/storage/adapter.js +0 -11
- package/dist/storage/adapter.js.map +0 -1
- package/dist/storage/cache.d.ts +0 -23
- package/dist/storage/cache.d.ts.map +0 -1
- package/dist/storage/cache.js +0 -79
- package/dist/storage/cache.js.map +0 -1
- package/dist/storage/checksum.d.ts +0 -3
- package/dist/storage/checksum.d.ts.map +0 -1
- package/dist/storage/checksum.js +0 -19
- package/dist/storage/checksum.js.map +0 -1
- package/dist/storage/chunked.d.ts +0 -21
- package/dist/storage/chunked.d.ts.map +0 -1
- package/dist/storage/chunked.js +0 -67
- package/dist/storage/chunked.js.map +0 -1
- package/dist/storage/content.d.ts +0 -24
- package/dist/storage/content.d.ts.map +0 -1
- package/dist/storage/content.js +0 -44
- package/dist/storage/content.js.map +0 -1
- package/dist/storage/filehosting.d.ts +0 -2
- package/dist/storage/filehosting.d.ts.map +0 -1
- package/dist/storage/filehosting.js +0 -24
- package/dist/storage/filehosting.js.map +0 -1
- package/dist/storage/githubcontents.d.ts +0 -2
- package/dist/storage/githubcontents.d.ts.map +0 -1
- package/dist/storage/githubcontents.js +0 -29
- package/dist/storage/githubcontents.js.map +0 -1
- package/dist/storage/index.d.ts +0 -12
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js +0 -12
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/local.d.ts +0 -2
- package/dist/storage/local.d.ts.map +0 -1
- package/dist/storage/local.js +0 -72
- package/dist/storage/local.js.map +0 -1
- package/dist/storage/memory.d.ts +0 -6
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js +0 -36
- package/dist/storage/memory.js.map +0 -1
- package/dist/storage/pool.d.ts +0 -95
- package/dist/storage/pool.d.ts.map +0 -1
- package/dist/storage/pool.js +0 -202
- package/dist/storage/pool.js.map +0 -1
- package/dist/storage/s3compatible.d.ts +0 -3
- package/dist/storage/s3compatible.d.ts.map +0 -1
- package/dist/storage/s3compatible.js +0 -70
- package/dist/storage/s3compatible.js.map +0 -1
- package/dist/storage/sync.d.ts +0 -47
- package/dist/storage/sync.d.ts.map +0 -1
- package/dist/storage/sync.js +0 -75
- package/dist/storage/sync.js.map +0 -1
- package/dist/surfaces/adapters.d.ts +0 -97
- package/dist/surfaces/adapters.d.ts.map +0 -1
- package/dist/surfaces/adapters.js +0 -50
- package/dist/surfaces/adapters.js.map +0 -1
- package/dist/surfaces/controls.d.ts +0 -18
- package/dist/surfaces/controls.d.ts.map +0 -1
- package/dist/surfaces/controls.js +0 -45
- package/dist/surfaces/controls.js.map +0 -1
- package/dist/surfaces/manifest.d.ts +0 -68
- package/dist/surfaces/manifest.d.ts.map +0 -1
- package/dist/surfaces/manifest.js +0 -42
- package/dist/surfaces/manifest.js.map +0 -1
- package/dist/surfaces/n8n.d.ts +0 -25
- package/dist/surfaces/n8n.d.ts.map +0 -1
- package/dist/surfaces/n8n.js +0 -31
- package/dist/surfaces/n8n.js.map +0 -1
- package/dist/surfaces/operations.d.ts +0 -32
- package/dist/surfaces/operations.d.ts.map +0 -1
- package/dist/surfaces/operations.js +0 -53
- package/dist/surfaces/operations.js.map +0 -1
- package/dist/surfaces/requirements.d.ts +0 -29
- package/dist/surfaces/requirements.d.ts.map +0 -1
- package/dist/surfaces/requirements.js +0 -50
- package/dist/surfaces/requirements.js.map +0 -1
- package/dist/surfaces/targets.d.ts +0 -196
- package/dist/surfaces/targets.d.ts.map +0 -1
- package/dist/surfaces/targets.js +0 -27
- package/dist/surfaces/targets.js.map +0 -1
- package/dist/webhook/delivery.d.ts +0 -18
- package/dist/webhook/delivery.d.ts.map +0 -1
- package/dist/webhook/delivery.js +0 -36
- package/dist/webhook/delivery.js.map +0 -1
- package/dist/webhook/receiver.d.ts +0 -26
- package/dist/webhook/receiver.d.ts.map +0 -1
- package/dist/webhook/receiver.js +0 -24
- package/dist/webhook/receiver.js.map +0 -1
- package/dist/webhook/signature.d.ts +0 -3
- package/dist/webhook/signature.d.ts.map +0 -1
- package/dist/webhook/signature.js +0 -7
- package/dist/webhook/signature.js.map +0 -1
- package/dist/workflow/manifest.d.ts +0 -22
- package/dist/workflow/manifest.d.ts.map +0 -1
- package/dist/workflow/manifest.js +0 -21
- package/dist/workflow/manifest.js.map +0 -1
- package/dist/workflow/registry.d.ts +0 -7
- package/dist/workflow/registry.d.ts.map +0 -1
- package/dist/workflow/registry.js +0 -18
- package/dist/workflow/registry.js.map +0 -1
- package/dist/workflow/templates.d.ts +0 -6
- package/dist/workflow/templates.d.ts.map +0 -1
- package/dist/workflow/templates.js +0 -18
- package/dist/workflow/templates.js.map +0 -1
- package/dist/workflow/triggers.d.ts +0 -64
- package/dist/workflow/triggers.d.ts.map +0 -1
- package/dist/workflow/triggers.js +0 -99
- package/dist/workflow/triggers.js.map +0 -1
- package/docs/logs/.gitkeep +0 -0
- package/docs/plans/00.index.md +0 -50
- package/docs/plans/01.architecture.md +0 -86
- package/docs/plans/02.research.computer.use.md +0 -58
- package/docs/plans/03.research.captcha.bypass.md +0 -68
- package/docs/plans/04.research.sandbox.ai.md +0 -52
- package/docs/plans/05.capture.platform.md +0 -57
- package/docs/plans/06.dependencies.md +0 -97
- package/docs/plans/07.captcha.test.page.md +0 -41
- package/docs/plans/08.production.infra.md +0 -70
- package/docs/plans/09.database.schema.md +0 -121
- package/docs/plans/10.cloudinary.storage.md +0 -57
- package/docs/plans/11.movement.logs.json.md +0 -72
- package/docs/plans/12.research.atlas.agent.browser.md +0 -79
- package/docs/plans/13.research.anti.detection.md +0 -898
- package/docs/plans/14.research.proxy.md +0 -1495
- package/docs/plans/15.research.retry.rate.limit.md +0 -1958
- package/docs/plans/16.research.crawling.md +0 -1417
- package/docs/plans/17.research.caching.md +0 -1610
- package/docs/plans/18.research.content.extraction.md +0 -1952
- package/docs/plans/19.research.errors.events.md +0 -1523
- package/docs/plans/20.research.zod.validation.md +0 -1350
- package/docs/plans/21.research.batch.concurrency.md +0 -1888
- package/docs/plans/22.research.universal.runtime.md +0 -944
- package/docs/plans/23.research.ai.integration.md +0 -1465
- package/docs/plans/24.research.memory.persistence.md +0 -1979
- package/docs/plans/25.research.server.api.md +0 -342
- package/docs/plans/26.research.compilation.md +0 -249
- package/docs/plans/27.research.html.parsing.md +0 -251
- package/docs/plans/28.action.plan.md +0 -50
- package/docs/plans/29.api.reference.md +0 -174
- package/docs/plans/30.architecture.plan.md +0 -94
- package/docs/plans/31.auditoria.dados.md +0 -163
- package/docs/plans/32.bots.automacao.computacional.md +0 -214
- package/docs/plans/33.bots.codigo.revisao.md +0 -220
- package/docs/plans/34.bots.seguranca.cicd.md +0 -366
- package/docs/plans/35.comparativo.concorrencia.md +0 -464
- package/docs/plans/36.computational.memory.md +0 -340
- package/docs/plans/37.deploystrategy.md +0 -394
- package/docs/plans/38.flow.md +0 -155
- package/docs/plans/39.multi.platform.bot.md +0 -252
- package/docs/plans/40.npm.publish.md +0 -250
- package/docs/plans/41.o.que.falta.md +0 -407
- package/docs/plans/42.pesquisa.concorrencia.md +0 -721
- package/docs/plans/43.plan.universal.architecture.md +0 -496
- package/docs/plans/44.reference.md +0 -100
- package/docs/plans/45.robotarchitecture.md +0 -237
- package/docs/plans/46.scdnintegration.md +0 -284
- package/docs/plans/47.multiforge.readme.md +0 -129
- package/docs/plans/48.theory.v4.repo.os.md +0 -152
- package/docs/plans/49.third.party.infra.md +0 -12
- package/docs/plans/50.file.as.compute.md +0 -39
- package/docs/plans/51.architecture.virtual.processor.md +0 -80
- package/docs/plans/52.manifesto.v8.md +0 -11
- package/docs/plans/58.cdn.list.md +0 -23
- package/docs/plans/59.sql.frameworks.md +0 -33
- package/docs/plans/60.sql.thirdparty.md +0 -26
- package/docs/plans/61.objective.multiforge.md +0 -63
- package/docs/plans/62.huggingface.upload.md +0 -26
- package/docs/plans/63.kaggle.upload.md +0 -24
- package/docs/plans/64.npm.storage.md +0 -30
- package/docs/plans/65.rclone.terabox.md +0 -32
- package/docs/plans/66.buckets.and.models.todo.md +0 -14
- package/docs/plans/67.database.todo.md +0 -13
- package/docs/plans/68.deploy.packages.todo.md +0 -12
- package/docs/plans/69.report.human.operator.md +0 -133
- package/docs/plans/70.report.brain2qwerty.ems.md +0 -135
- package/docs/plans/71.report.hd.infinito.vram.md +0 -155
- package/docs/plans/72.plan.hd.infinito.node.md +0 -146
- package/docs/plans/73.plan.scifi.repos.md +0 -125
- package/docs/plans/74.000.manifesto.v8.flat.2..md +0 -11
- package/docs/plans/README.md +0 -489
- package/docs/plans/aggregate_platforms.mjs +0 -146
- package/docs/plans/examplesession.json +0 -36
- package/docs/plans/missing-facts.md +0 -192
- package/docs/plans/models.md +0 -64
- package/docs/plans/organize.cjs +0 -270
- package/docs/plans/platforms.md +0 -2887
- package/docs/plans/sites.md +0 -31322
- package/docs/sources/farm.py +0 -117
- package/docs/sources/html/saddle1.html +0 -132
- package/docs/sources/html/saddle2.html +0 -157
- package/docs/sources/html/saddle3.html +0 -119
- package/docs/sources/html/saddle4.html +0 -144
- package/docs/sources/html/saddle5.html +0 -72
- package/docs/sources/html/saddle6.html +0 -171
- package/docs/sources/html/saddle7.html +0 -236
- package/docs/sources/saddle.ts +0 -74
- package/docs/sources/schema.prisma +0 -88
- package/docs/sources/script.sh +0 -64
- package/docs/sources/workflows.yml +0 -458
- package/docs/talks1/_body.txt +0 -14
- package/docs/talks1/_index.md +0 -15
- package/docs/talks1/_screenshot.png +0 -0
- package/docs/talks1/assistant-01.md +0 -5
- package/docs/talks1/assistant-02.md +0 -5
- package/docs/talks1/assistant-03.md +0 -531
- package/docs/talks1/assistant-04.md +0 -26
- package/docs/talks1/assistant-05.md +0 -774
- package/docs/talks1/assistant-06.md +0 -1718
- package/docs/talks1/scrape-share.cjs +0 -185
- package/docs/talks1/scrape-share.ts +0 -183
- package/docs/talks1/user-01.md +0 -3
- package/docs/talks1/user-02.md +0 -3
- package/docs/talks1/user-03.md +0 -88
- package/docs/talks1/user-04.md +0 -3
- package/docs/talks1/user-05.md +0 -3
- package/docs/talks1/user-06.md +0 -88
- package/docs/talks1/user-07.md +0 -88
- package/docs/talks2/_body.txt +0 -14
- package/docs/talks2/_index.md +0 -16
- package/docs/talks2/_screenshot.png +0 -0
- package/docs/talks2/assistant-01.md +0 -5
- package/docs/talks2/assistant-02.md +0 -5
- package/docs/talks2/assistant-03.md +0 -424
- package/docs/talks2/assistant-04.md +0 -598
- package/docs/talks2/assistant-05.md +0 -1280
- package/docs/talks2/assistant-06.md +0 -1227
- package/docs/talks2/assistant-07.md +0 -1252
- package/docs/talks2/user-01.md +0 -3
- package/docs/talks2/user-02.md +0 -3
- package/docs/talks2/user-03.md +0 -88
- package/docs/talks2/user-04.md +0 -88
- package/docs/talks2/user-05.md +0 -88
- package/docs/talks2/user-06.md +0 -88
- package/docs/talks2/user-07.md +0 -3
- package/docs/talks3/_body.txt +0 -467
- package/docs/talks3/_index.md +0 -10
- package/docs/talks3/_screenshot.png +0 -0
- package/docs/talks3/assistant-01.md +0 -417
- package/docs/talks3/assistant-02.md +0 -417
- package/docs/talks3/assistant-03.md +0 -29
- package/docs/talks3/assistant-04.md +0 -727
- package/docs/talks3/user-01.md +0 -88
- package/docs/talks3/user-02.md +0 -88
- package/docs/talks3/user-03.md +0 -3
- package/docs/talks3/user-04.md +0 -3
- package/docs/talks4/_body.txt +0 -14
- package/docs/talks4/_index.md +0 -12
- package/docs/talks4/_screenshot.png +0 -0
- package/docs/talks4/assistant-01.md +0 -5
- package/docs/talks4/assistant-02.md +0 -5
- package/docs/talks4/assistant-03.md +0 -35
- package/docs/talks4/assistant-04.md +0 -512
- package/docs/talks4/assistant-05.md +0 -599
- package/docs/talks4/user-01.md +0 -3
- package/docs/talks4/user-02.md +0 -3
- package/docs/talks4/user-03.md +0 -88
- package/docs/talks4/user-04.md +0 -88
- package/docs/talks4/user-05.md +0 -7
- package/docs/talks5/_body.txt +0 -14
- package/docs/talks5/_index.md +0 -13
- package/docs/talks5/_screenshot.png +0 -0
- package/docs/talks5/assistant-01.md +0 -5
- package/docs/talks5/assistant-02.md +0 -5
- package/docs/talks5/assistant-03.md +0 -690
- package/docs/talks5/assistant-04.md +0 -758
- package/docs/talks5/assistant-05.md +0 -974
- package/docs/talks5/user-01.md +0 -3
- package/docs/talks5/user-02.md +0 -3
- package/docs/talks5/user-03.md +0 -105
- package/docs/talks5/user-04.md +0 -105
- package/docs/talks5/user-05.md +0 -63
- package/docs/talks5/user-06.md +0 -105
- package/docs/talks6/_body.txt +0 -14
- package/docs/talks6/_index.md +0 -9
- package/docs/talks6/_screenshot.png +0 -0
- package/docs/talks6/assistant-01.md +0 -5
- package/docs/talks6/assistant-02.md +0 -5
- package/docs/talks6/assistant-03.md +0 -1499
- package/docs/talks6/user-01.md +0 -3
- package/docs/talks6/user-02.md +0 -3
- package/docs/talks6/user-03.md +0 -88
- package/docs/talks6/user-04.md +0 -88
- package/docs/talks7/_body.txt +0 -14
- package/docs/talks7/_index.md +0 -10
- package/docs/talks7/_screenshot.png +0 -0
- package/docs/talks7/assistant-01.md +0 -5
- package/docs/talks7/assistant-02.md +0 -5
- package/docs/talks7/assistant-03.md +0 -523
- package/docs/talks7/assistant-04.md +0 -617
- package/docs/talks7/user-01.md +0 -3
- package/docs/talks7/user-02.md +0 -3
- package/docs/talks7/user-03.md +0 -105
- package/docs/talks7/user-04.md +0 -67
- package/docs/talks8/conversa1.txt +0 -1322
- package/docs/talks8/conversa2.txt +0 -237
- 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
- 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
- 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
- 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
- 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
- package/docs/talks9/README (2).md +0 -489
- package/docs/talks9/README.md +0 -198
- 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
- package/docs/talks9/conversa.txt +0 -544
- package/docs/talks9/other (2).md +0 -39
- package/docs/talks9/other.md +0 -57
- package/docs/talks9/outro.txt +0 -24
- /package/{extension/README.md → docs/extension.md} +0 -0
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* acquisition.ts — scraping, crawling, proxy selection and captcha-policy
|
|
3
|
+
* contracts of the engine generation.
|
|
4
|
+
*
|
|
5
|
+
* This file is the v2.0.0 grand-merge consolidation of the engine
|
|
6
|
+
* acquisition surface (the captcha domain and the eight engine-generation
|
|
7
|
+
* scrape modules: robots, cache, normalize, extract, schema, semantic,
|
|
8
|
+
* crawl, scraper) into the single root-level domain file of the e2ugh
|
|
9
|
+
* family standard: ordinal sections, JSDoc on every block, imports hoisted
|
|
10
|
+
* and deduplicated, intra-domain imports dissolved. The whole file stays
|
|
11
|
+
* free of npm dependencies (node built-ins only) so the public barrel and
|
|
12
|
+
* the virtual-hardware runtime load it without node_modules — the legacy
|
|
13
|
+
* webscrape toolkit generation lives in webscrape.ts.
|
|
14
|
+
*/
|
|
15
|
+
import { sha256 } from "./foundation.js";
|
|
16
|
+
import { transport } from "./integration.js";
|
|
17
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
18
|
+
/* Section 1: captcha/contract.ts — captcha contracts separate detection and evidence from any solver provider. */
|
|
19
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
20
|
+
/**
|
|
21
|
+
* captcha contracts separate detection and evidence from any solver provider.
|
|
22
|
+
*/
|
|
23
|
+
export const captchatypes = Object.freeze(["hcaptcha", "turnstile", "recaptcha", "unknown"]);
|
|
24
|
+
export function captchacontract(options = {}) {
|
|
25
|
+
const detect = options.detect ?? (() => ({ kind: "unknown", detected: false }));
|
|
26
|
+
const solve = options.solve;
|
|
27
|
+
return {
|
|
28
|
+
async detect(context) { const result = await detect(context); return { kind: captchatypes.includes(result.kind) ? result.kind : "unknown", detected: Boolean(result.detected), sitekey: result.sitekey, evidenceurl: result.evidenceurl }; },
|
|
29
|
+
async request(context) { return { status: "reviewrequired", kind: context.kind ?? "unknown", message: "captcha requires explicit human or external solver review", context }; },
|
|
30
|
+
async solve(context) { if (typeof solve !== "function")
|
|
31
|
+
return { status: "unavailable", reason: "no external solver configured" }; const result = await solve(context); return { status: result?.passed ? "passed" : "failed", passed: Boolean(result?.passed), solver: result?.solver ?? "external", token: result?.token, evidenceurl: result?.evidenceurl }; },
|
|
32
|
+
assert(result) { if (!result?.passed)
|
|
33
|
+
throw new Error("captcha assertion failed"); return result; }
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
37
|
+
/* Section 2: captcha/guard.ts — captcha guard blocks silent automation and records a review event for audit. */
|
|
38
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
39
|
+
/**
|
|
40
|
+
* captcha guard blocks silent automation and records a review event for audit.
|
|
41
|
+
*/
|
|
42
|
+
export function captchaguard(options = {}) {
|
|
43
|
+
const events = [];
|
|
44
|
+
return {
|
|
45
|
+
async check(context) { const result = await options.contract.detect(context); if (!result.detected)
|
|
46
|
+
return { allowed: true, result }; const event = { type: "captcha.detected", at: Date.now(), kind: result.kind, sitekey: result.sitekey }; events.push(event); return { allowed: false, result, event, action: "reviewrequired" }; },
|
|
47
|
+
events() { return events.map((event) => ({ ...event })); }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
51
|
+
/* Section 3: captcha/evidence.ts — captcha evidence stores references and hashes, never raw secrets or tokens by default. */
|
|
52
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
53
|
+
/**
|
|
54
|
+
* captcha evidence stores references and hashes, never raw secrets or tokens by default.
|
|
55
|
+
*/
|
|
56
|
+
export function evidence(options = {}) {
|
|
57
|
+
const payload = options.data instanceof Uint8Array ? options.data : options.data ? new TextEncoder().encode(String(options.data)) : null;
|
|
58
|
+
return { kind: options.kind ?? "unknown", passed: Boolean(options.passed), solver: options.solver ?? "manual", evidenceurl: options.evidenceurl, sha256: payload ? sha256(payload) : options.sha256, createdat: options.createdat ?? Date.now(), metadata: { ...(options.metadata ?? {}) } };
|
|
59
|
+
}
|
|
60
|
+
const cache = new Map();
|
|
61
|
+
const cachettl = 24 * 60 * 60 * 1000;
|
|
62
|
+
/** Parses robots text into both historical directives and active groups. */
|
|
63
|
+
export function robotsrules(text = "") { const directives = []; const groups = []; const sitemaps = []; let directive = null; let group = null; for (const raw of text.split(/\r?\n/)) {
|
|
64
|
+
const line = raw.split("#", 1)[0].trim();
|
|
65
|
+
if (!line)
|
|
66
|
+
continue;
|
|
67
|
+
const separator = line.indexOf(":");
|
|
68
|
+
if (separator < 0)
|
|
69
|
+
continue;
|
|
70
|
+
const key = line.slice(0, separator).trim().toLowerCase();
|
|
71
|
+
const value = line.slice(separator + 1).trim();
|
|
72
|
+
if (key === "user-agent") {
|
|
73
|
+
directive = { userAgent: value, allow: [], disallow: [] };
|
|
74
|
+
directives.push(directive);
|
|
75
|
+
group = { agents: [value.toLowerCase()], allow: [], disallow: [], sitemaps: [] };
|
|
76
|
+
groups.push(group);
|
|
77
|
+
}
|
|
78
|
+
else if (key === "allow" && value) {
|
|
79
|
+
directive?.allow.push(value);
|
|
80
|
+
group?.allow.push(value);
|
|
81
|
+
}
|
|
82
|
+
else if (key === "disallow" && value) {
|
|
83
|
+
directive?.disallow.push(value);
|
|
84
|
+
group?.disallow.push(value);
|
|
85
|
+
}
|
|
86
|
+
else if (key === "crawl-delay" && Number.isFinite(Number(value))) {
|
|
87
|
+
const delay = Number(value);
|
|
88
|
+
if (directive)
|
|
89
|
+
directive.crawlDelay = delay;
|
|
90
|
+
if (group)
|
|
91
|
+
group.delay = delay;
|
|
92
|
+
}
|
|
93
|
+
else if (key === "sitemap" && value) {
|
|
94
|
+
sitemaps.push(value);
|
|
95
|
+
if (group)
|
|
96
|
+
group.sitemaps.push(value);
|
|
97
|
+
}
|
|
98
|
+
} return { directives, groups, sitemaps, crawlDelay: directives.find((value) => value.crawlDelay !== undefined)?.crawlDelay }; }
|
|
99
|
+
/** Fetches and caches a site's robots policy without failing the caller's scrape. */
|
|
100
|
+
export async function fetchRobotsTxt(siteUrl, options = {}) { const base = siteUrl.replace(/\/$/, ""); const robotsUrl = `${base}/robots.txt`; const cached = cache.get(robotsUrl); if (cached && Date.now() - cached.fetchedAt < cachettl)
|
|
101
|
+
return cached.robots; try {
|
|
102
|
+
const response = await fetch(robotsUrl, { headers: { "User-Agent": options.userAgent ?? "Saddle/2.0.0" }, signal: AbortSignal.timeout(options.timeout ?? 5000) });
|
|
103
|
+
const robots = response.ok ? robotsrules(await response.text()) : robotsrules();
|
|
104
|
+
cache.set(robotsUrl, { robots, fetchedAt: Date.now() });
|
|
105
|
+
return robots;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
const robots = robotsrules();
|
|
109
|
+
cache.set(robotsUrl, { robots, fetchedAt: Date.now() });
|
|
110
|
+
return robots;
|
|
111
|
+
} }
|
|
112
|
+
/** Checks whether a URL is allowed for a selected agent. */
|
|
113
|
+
export function isAllowed(url, robots, userAgent = "*") { try {
|
|
114
|
+
const path = new URL(url).pathname;
|
|
115
|
+
const rules = robots.directives.filter((value) => matchagent(value.userAgent, userAgent));
|
|
116
|
+
return !rules.some((value) => value.disallow.some((pattern) => pattern && path.startsWith(pattern) && !value.allow.some((allowed) => allowed.length >= pattern.length && path.startsWith(allowed))));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return true;
|
|
120
|
+
} }
|
|
121
|
+
/** Returns the selected agent's crawl delay. */
|
|
122
|
+
export function getCrawlDelay(robots, userAgent = "*") { return robots.directives.find((value) => matchagent(value.userAgent, userAgent))?.crawlDelay ?? robots.crawlDelay; }
|
|
123
|
+
export function getSitemaps(robots) { return [...robots.sitemaps]; }
|
|
124
|
+
export function robotsallowed(rules, target, agent = "*") { return isAllowed(target, rules, agent); }
|
|
125
|
+
export function robotsdelay(rules, agent = "*") { return getCrawlDelay(rules, agent) ?? 0; }
|
|
126
|
+
function matchagent(pattern, userAgent) { const normalized = pattern.toLowerCase(); const candidate = userAgent.toLowerCase(); return normalized === "*" || candidate.includes(normalized.replaceAll("*", "")); }
|
|
127
|
+
const defaultconfig = { maxSize: 1000, defaultTtlMs: 300000, checkPeriodMs: 60000 };
|
|
128
|
+
/** Provides a bounded typed cache facade for historical scrape callers. */
|
|
129
|
+
export class WebScrapeCache {
|
|
130
|
+
store = new Map();
|
|
131
|
+
config;
|
|
132
|
+
constructor(config = {}) { this.config = { ...defaultconfig, ...config }; }
|
|
133
|
+
get(key) { const entry = this.store.get(key); if (!entry)
|
|
134
|
+
return undefined; if (entry.expires && Date.now() > entry.expires) {
|
|
135
|
+
this.store.delete(key);
|
|
136
|
+
return undefined;
|
|
137
|
+
} return entry.value; }
|
|
138
|
+
set(key, value, ttlMs) { if (this.store.size >= this.config.maxSize && !this.store.has(key))
|
|
139
|
+
this.store.delete(this.store.keys().next().value); this.store.set(key, { value, timestamp: Date.now(), expires: ttlMs ? Date.now() + ttlMs : Date.now() + this.config.defaultTtlMs }); }
|
|
140
|
+
has(key) { return this.get(key) !== undefined; }
|
|
141
|
+
delete(key) { return this.store.delete(key); }
|
|
142
|
+
clear() { this.store.clear(); }
|
|
143
|
+
getOrSet(key, factory, ttlMs) { const cached = this.get(key); if (cached !== undefined)
|
|
144
|
+
return Promise.resolve(cached); return factory().then((value) => { this.set(key, value, ttlMs); return value; }); }
|
|
145
|
+
size() { return this.store.size; }
|
|
146
|
+
keys() { return [...this.store.keys()]; }
|
|
147
|
+
}
|
|
148
|
+
/** Creates the historical typed cache facade. */
|
|
149
|
+
export function createCache(config) { return new WebScrapeCache(config); }
|
|
150
|
+
/** Creates the active stale-aware fetch cache contract. */
|
|
151
|
+
export function ttlcache(options = {}) {
|
|
152
|
+
const values = new Map();
|
|
153
|
+
const ttl = options.ttl ?? 300000;
|
|
154
|
+
return {
|
|
155
|
+
get(key) { const item = values.get(key); if (!item)
|
|
156
|
+
return null; const now = Date.now(); if (now > item.expires) {
|
|
157
|
+
if (now > item.stale)
|
|
158
|
+
values.delete(key);
|
|
159
|
+
return options.stale ? item.value : null;
|
|
160
|
+
} return item.value; },
|
|
161
|
+
set(key, value, valueoptions = {}) { const now = Date.now(); values.set(key, { value, timestamp: now, expires: now + (valueoptions.ttl ?? ttl), stale: now + (valueoptions.stale ?? ttl * 2) }); return value; },
|
|
162
|
+
delete(key) { values.delete(key); },
|
|
163
|
+
clear() { values.clear(); },
|
|
164
|
+
size() { return values.size; }
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
168
|
+
/* Section 6: scrape/normalize.ts — content normalization classifies bounded response bytes without owning a parser, transport or storage backend. */
|
|
169
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
170
|
+
/**
|
|
171
|
+
* content normalization classifies bounded response bytes without owning a parser, transport or storage backend.
|
|
172
|
+
*/
|
|
173
|
+
const extensions = Object.freeze({
|
|
174
|
+
".json": "application/json",
|
|
175
|
+
".map": "application/json",
|
|
176
|
+
".xml": "application/xml",
|
|
177
|
+
".rss": "application/rss+xml",
|
|
178
|
+
".atom": "application/atom+xml",
|
|
179
|
+
".md": "text/markdown",
|
|
180
|
+
".markdown": "text/markdown",
|
|
181
|
+
".html": "text/html",
|
|
182
|
+
".htm": "text/html",
|
|
183
|
+
".txt": "text/plain",
|
|
184
|
+
".csv": "text/csv"
|
|
185
|
+
});
|
|
186
|
+
/** Detects a normalized media type from a header, URL suffix or caller fallback. */
|
|
187
|
+
export function detectcontenttype(header, url, fallback = "application/octet-stream") {
|
|
188
|
+
const value = String(header ?? "").split(";", 1)[0].trim().toLowerCase();
|
|
189
|
+
if (value)
|
|
190
|
+
return value;
|
|
191
|
+
try {
|
|
192
|
+
const pathname = new URL(url).pathname.toLowerCase();
|
|
193
|
+
const suffix = Object.keys(extensions).find((extension) => pathname.endsWith(extension));
|
|
194
|
+
if (suffix)
|
|
195
|
+
return extensions[suffix];
|
|
196
|
+
}
|
|
197
|
+
catch { /* invalid or absent URLs remain caller-owned metadata */ }
|
|
198
|
+
return String(fallback).toLowerCase();
|
|
199
|
+
}
|
|
200
|
+
/** Normalizes bounded input bytes into a serializable text, JSON or binary result. */
|
|
201
|
+
export function normalizeresult(input, options = {}) {
|
|
202
|
+
const contenttype = detectcontenttype(options.contenttype, options.url, options.defaultcontenttype ?? "application/octet-stream");
|
|
203
|
+
const bytes = tobytes(input);
|
|
204
|
+
const maxbytes = boundedlimit(options.maxbytes, 2_000_000);
|
|
205
|
+
if (bytes.byteLength > maxbytes)
|
|
206
|
+
throw normalizationerror("CONTENT_TOO_LARGE", `content exceeds ${maxbytes} bytes`);
|
|
207
|
+
const kind = contentkind(contenttype);
|
|
208
|
+
if (kind === "binary")
|
|
209
|
+
return { contenttype, kind, size: bytes.byteLength, bytes };
|
|
210
|
+
const text = new TextDecoder(options.charset ?? "utf-8", { fatal: false }).decode(bytes).replaceAll("\r\n", "\n");
|
|
211
|
+
if (text.length > boundedlimit(options.maxtext, maxbytes))
|
|
212
|
+
throw normalizationerror("TEXT_TOO_LARGE", "decoded content exceeds the configured text limit");
|
|
213
|
+
if (kind === "json") {
|
|
214
|
+
try {
|
|
215
|
+
return { contenttype, kind, size: bytes.byteLength, content: text, data: JSON.parse(text) };
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
throw normalizationerror("INVALID_JSON", `invalid JSON content: ${error.message}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return { contenttype, kind, size: bytes.byteLength, content: text };
|
|
222
|
+
}
|
|
223
|
+
/** Reads a caller-provided response body after checking declared and actual size limits. */
|
|
224
|
+
export async function normalizeresponse(response, options = {}) {
|
|
225
|
+
if (!response || typeof response !== "object")
|
|
226
|
+
throw new TypeError("response is required");
|
|
227
|
+
const headers = response.headers;
|
|
228
|
+
const header = typeof headers?.get === "function" ? headers.get("content-type") : headers?.["content-type"];
|
|
229
|
+
const declared = Number(typeof headers?.get === "function" ? headers.get("content-length") : headers?.["content-length"]);
|
|
230
|
+
const maxbytes = boundedlimit(options.maxbytes, 2_000_000);
|
|
231
|
+
if (Number.isFinite(declared) && declared > maxbytes)
|
|
232
|
+
throw normalizationerror("CONTENT_TOO_LARGE", `content exceeds ${maxbytes} bytes`);
|
|
233
|
+
const body = typeof response.arrayBuffer === "function" ? await response.arrayBuffer() : await response.text();
|
|
234
|
+
return normalizeresult(body, { ...options, contenttype: header ?? options.contenttype, url: options.url ?? response.url });
|
|
235
|
+
}
|
|
236
|
+
function contentkind(contenttype) {
|
|
237
|
+
if (contenttype === "application/json" || contenttype.endsWith("+json"))
|
|
238
|
+
return "json";
|
|
239
|
+
if (contenttype === "text/html" || contenttype === "application/xhtml+xml")
|
|
240
|
+
return "html";
|
|
241
|
+
if (contenttype === "application/xml" || contenttype === "text/xml" || contenttype.endsWith("+xml"))
|
|
242
|
+
return "xml";
|
|
243
|
+
if (contenttype === "text/markdown")
|
|
244
|
+
return "markdown";
|
|
245
|
+
if (contenttype.startsWith("text/"))
|
|
246
|
+
return "text";
|
|
247
|
+
return "binary";
|
|
248
|
+
}
|
|
249
|
+
function tobytes(input) {
|
|
250
|
+
if (typeof input === "string")
|
|
251
|
+
return new TextEncoder().encode(input);
|
|
252
|
+
if (input instanceof Uint8Array)
|
|
253
|
+
return input;
|
|
254
|
+
if (input instanceof ArrayBuffer)
|
|
255
|
+
return new Uint8Array(input);
|
|
256
|
+
if (ArrayBuffer.isView(input))
|
|
257
|
+
return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
258
|
+
throw new TypeError("content must be a string, ArrayBuffer or typed array");
|
|
259
|
+
}
|
|
260
|
+
function boundedlimit(value, fallback) {
|
|
261
|
+
const limit = Number(value ?? fallback);
|
|
262
|
+
if (!Number.isSafeInteger(limit) || limit < 1)
|
|
263
|
+
throw new TypeError("content limit must be a positive safe integer");
|
|
264
|
+
return limit;
|
|
265
|
+
}
|
|
266
|
+
function normalizationerror(code, message) {
|
|
267
|
+
const error = new Error(message);
|
|
268
|
+
error.code = code;
|
|
269
|
+
return error;
|
|
270
|
+
}
|
|
271
|
+
/** Extracts the compact active scrape result without a DOM dependency. */
|
|
272
|
+
export function extracthtml(html, url) { const title = match(html, /<title\b[^<>]*>([\s\S]*?)<\/title\s*>/i); const description = match(html, /<meta\b[^<>]+name=["']description["'][^<>]+content=["']([^"']*)["']/i) ?? match(html, /<meta\b[^<>]+content=["']([^"']*)["'][^<>]+name=["']description["']/i); const links = [...html.matchAll(/<a\b[^<>]+href=["']([^"']+)["'][^<>]*>/gi)].map((item) => resolveurl(item[1], url)).filter((value) => Boolean(value)); const text = htmltotext(html); return { url, title: decode(title ?? ""), description: decode(description ?? ""), text, links: [...new Set(links)] }; }
|
|
273
|
+
/** Extracts structured content for historical TypeScript callers. */
|
|
274
|
+
export async function extractContent(html, options = {}) {
|
|
275
|
+
let source = html;
|
|
276
|
+
for (const selector of options.removeSelectors ?? [])
|
|
277
|
+
source = removeSelector(source, selector);
|
|
278
|
+
const metadata = extractmetadata(source);
|
|
279
|
+
const text = options.readable ? readabletext(source) : htmltotext(source);
|
|
280
|
+
const content = options.maxLength ? text.slice(0, options.maxLength) : text;
|
|
281
|
+
return { content, text, links: options.preserveLinks === false ? [] : extractlinks(source), images: options.preserveImages === false ? [] : extractimages(source), tables: options.preserveTables === false ? [] : extracttables(source), metadata, jsonLd: extractjsonld(source) };
|
|
282
|
+
}
|
|
283
|
+
/** Extracts readable page text from a document string. */
|
|
284
|
+
export async function extractReadable(html) { return (await extractContent(html, { readable: true })).content; }
|
|
285
|
+
function match(value, expression) { return value.match(expression)?.[1]?.trim(); }
|
|
286
|
+
/** Single-pass XML/HTML entity decode: the pattern never re-examines its own output, so a double-escaped `&lt;` decodes once to the literal text `<` and never again to `<`. */
|
|
287
|
+
const ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', "#39": "'" };
|
|
288
|
+
function decode(value) { return value.replace(/&(amp|lt|gt|quot|#39);/g, (whole, entity) => ENTITIES[entity] ?? whole); }
|
|
289
|
+
/** Linear single-pass script/style block removal: case-insensitive, tolerates `</script >` closing whitespace, and drops any unterminated block so no `<script` fragment can survive. One scan, no regex backtracking. */
|
|
290
|
+
function stripblocks(html, ...tags) {
|
|
291
|
+
const open = new RegExp(`<(${tags.join("|")})\\b[^<>]*>`, "i");
|
|
292
|
+
let out = "";
|
|
293
|
+
let cursor = 0;
|
|
294
|
+
let match;
|
|
295
|
+
while ((match = open.exec(html.slice(cursor))) !== null) {
|
|
296
|
+
const start = cursor + match.index;
|
|
297
|
+
out += html.slice(cursor, start);
|
|
298
|
+
const closeTag = `</${match[1].toLowerCase()}`;
|
|
299
|
+
const close = html.toLowerCase().indexOf(closeTag, start + match[0].length);
|
|
300
|
+
if (close < 0)
|
|
301
|
+
return out; /* unterminated block: the rest is dropped */
|
|
302
|
+
const gt = html.indexOf(">", close);
|
|
303
|
+
cursor = gt < 0 ? html.length : gt + 1;
|
|
304
|
+
}
|
|
305
|
+
return out + html.slice(cursor);
|
|
306
|
+
}
|
|
307
|
+
function resolveurl(value, base) { try {
|
|
308
|
+
const parsed = new URL(value, base);
|
|
309
|
+
return parsed.pathname === "/" && !parsed.search && !parsed.hash ? `${parsed.protocol}//${parsed.host}` : parsed.href;
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
return null;
|
|
313
|
+
} }
|
|
314
|
+
function htmltotext(html) { return decode(stripblocks(html, "script", "style").replace(/<br\s*\/?>/gi, "\n").replace(/<[^<>]+>/g, " ").replace(/\s+/g, " ").trim()); }
|
|
315
|
+
/** Extracts readable text from the first article main or body section through linear index scans instead of nested dot-star patterns. */
|
|
316
|
+
function readabletext(html) {
|
|
317
|
+
const lower = html.toLowerCase();
|
|
318
|
+
for (const tag of ["article", "main", "body"]) {
|
|
319
|
+
const open = lower.indexOf(`<${tag}`);
|
|
320
|
+
if (open >= 0) {
|
|
321
|
+
const close = lower.indexOf(`</${tag}`, open);
|
|
322
|
+
const segment = close > open ? html.slice(open, close) : html.slice(open);
|
|
323
|
+
if (segment)
|
|
324
|
+
return htmltotext(segment);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return htmltotext(html);
|
|
328
|
+
}
|
|
329
|
+
function extractmetadata(html) { return { title: match(html, /<title\b[^<>]*>([\s\S]*?)<\/title\s*>/i) ?? match(html, /<meta\b[^<>]+property=["']og:title["'][^<>]+content=["']([^"']*)["']/i) ?? "", description: matchmeta(html, "description") ?? matchmeta(html, "og:description"), favicon: match(html, /<link\b[^<>]+rel=["'](?:icon|shortcut icon)["'][^<>]+href=["']([^"']*)["']/i), language: match(html, /<html\b[^<>]+lang=["']([^"']*)["']/i), author: matchmeta(html, "author"), ogImage: matchmeta(html, "og:image"), ogType: matchmeta(html, "og:type"), keywords: matchmeta(html, "keywords")?.split(",").map((value) => value.trim()) }; }
|
|
330
|
+
function matchmeta(html, name) { return match(html, new RegExp(`<meta\\b[^<>]+(?:name|property)=["']${name}["'][^<>]+content=["']([^"']*)["']`, "i")) ?? match(html, new RegExp(`<meta\\b[^<>]+content=["']([^"']*)["'][^<>]+(?:name|property)=["']${name}["']`, "i")); }
|
|
331
|
+
function extractlinks(html) { return [...html.matchAll(/<a\b[^<>]+href=["']([^"']+)["'][^<>]*>([\s\S]*?)<\/a\s*>/gi)].map((item) => ({ href: resolveurl(item[1]) ?? item[1], text: htmltotext(item[2]).slice(0, 200), isInternal: false, isExternal: true })); }
|
|
332
|
+
function extractimages(html) { return [...html.matchAll(/<img\b[^<>]+src=["']([^"']+)["'][^<>]*>/gi)].map((item) => ({ src: item[1], alt: match(item[0], /alt=["']([^"']*)["']/i) ?? "", width: numberattribute(item[0], "width"), height: numberattribute(item[0], "height") })); }
|
|
333
|
+
function numberattribute(value, name) { const parsed = Number(match(value, new RegExp(`${name}=["'](\\d+)["']`, "i"))); return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined; }
|
|
334
|
+
function extracttables(html) { return [...html.matchAll(/<table\b[^<>]*>[\s\S]*?<\/table\s*>/gi)].map((table) => { const source = table[0]; const body = source.match(/<tbody\b[^<>]*>[\s\S]*?<\/tbody\s*>/i)?.[0] ?? source; return { headers: [...source.matchAll(/<th\b[^<>]*>([\s\S]*?)<\/th\s*>/gi)].map((item) => htmltotext(item[1])), rows: [...body.matchAll(/<tr\b[^<>]*>([\s\S]*?)<\/tr\s*>/gi)].map((row) => [...row[1].matchAll(/<td\b[^<>]*>([\s\S]*?)<\/td\s*>/gi)].map((item) => htmltotext(item[1]))).filter((row) => row.length) }; }); }
|
|
335
|
+
function extractjsonld(html) { const values = []; for (const item of html.matchAll(/<script\b[^<>]+type=["']application\/ld\+json["'][^<>]*>([\s\S]*?)<\/script\s*>/gi))
|
|
336
|
+
try {
|
|
337
|
+
values.push(JSON.parse(item[1]));
|
|
338
|
+
}
|
|
339
|
+
catch { /* malformed structured data remains non fatal */ } return values; }
|
|
340
|
+
function removeSelector(html, selector) { const tag = selector.match(/^\s*([a-z][a-z0-9]*)\s*$/i)?.[1]; if (tag)
|
|
341
|
+
return html.replace(new RegExp(`<${tag}[^>]*>[\\s\\S]*?<\/${tag}>`, "gi"), ""); const className = selector.match(/^\.([a-z0-9_-]+)$/i)?.[1]; return className ? html.replace(new RegExp(`<([a-z][a-z0-9]*)[^>]*class=["'][^"']*\\b${className}\\b[^"']*["'][^>]*>[\\s\\S]*?<\\/\\1>`, "gi"), "") : html; }
|
|
342
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
343
|
+
/* Section 8: scrape/schema.ts — schema extraction accepts safe field descriptors and never evaluates source strings. */
|
|
344
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
345
|
+
/**
|
|
346
|
+
* schema extraction accepts safe field descriptors and never evaluates source strings.
|
|
347
|
+
*/
|
|
348
|
+
export function extractwithschema(html, schema = {}, url) {
|
|
349
|
+
const result = {};
|
|
350
|
+
for (const [name, descriptor] of Object.entries(schema))
|
|
351
|
+
result[name] = extractfield(html, descriptor, url);
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
/** Extracts schema fields with bounded payload and field-level source provenance. */
|
|
355
|
+
export function extractstructured(html, schema = {}, options = {}) {
|
|
356
|
+
if (typeof html !== "string")
|
|
357
|
+
throw new TypeError("structured extraction requires html text");
|
|
358
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema))
|
|
359
|
+
throw new TypeError("structured extraction requires a schema object");
|
|
360
|
+
if (options.parser !== undefined && typeof options.parser !== "function")
|
|
361
|
+
throw new TypeError("structured extraction parser must be a function");
|
|
362
|
+
const sourceurl = String(options.url ?? "");
|
|
363
|
+
const extractedat = String(options.extractedat ?? new Date(Number(options.now ?? Date.now())).toISOString());
|
|
364
|
+
const maxbytes = normalizebound(options.maxbytes ?? 65536, "maxbytes");
|
|
365
|
+
const parser = options.parser ?? ((input) => extractwithschema(input.html, input.schema, input.url));
|
|
366
|
+
const values = parser({ html, schema, url: sourceurl });
|
|
367
|
+
if (!values || typeof values !== "object" || Array.isArray(values))
|
|
368
|
+
throw new TypeError("structured extraction parser must return an object");
|
|
369
|
+
const bounded = boundpayload(values, maxbytes);
|
|
370
|
+
const provenance = Object.fromEntries(Object.entries(schema).map(([name, descriptor]) => [name, {
|
|
371
|
+
sourceurl,
|
|
372
|
+
selector: descriptorselector(descriptor),
|
|
373
|
+
extractedat,
|
|
374
|
+
truncated: bounded.truncated.includes(name)
|
|
375
|
+
}]));
|
|
376
|
+
return { version: 1, sourceurl, extractedat, values: bounded.values, provenance, bytes: bounded.bytes, maxbytes, truncated: bounded.truncated };
|
|
377
|
+
}
|
|
378
|
+
function extractfield(html, descriptor, url) {
|
|
379
|
+
if (typeof descriptor === "function")
|
|
380
|
+
return descriptor({ html, url });
|
|
381
|
+
if (typeof descriptor === "string")
|
|
382
|
+
return textfromselector(html, descriptor);
|
|
383
|
+
if (!descriptor || typeof descriptor.selector !== "string")
|
|
384
|
+
throw new TypeError("schema field requires selector or function");
|
|
385
|
+
if (descriptor.selector === "title")
|
|
386
|
+
return html.match(/<title[^>]*>([\s\S]*?)<\/title>/i)?.[1]?.trim() ?? null;
|
|
387
|
+
const escaped = descriptor.selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
388
|
+
const attribute = descriptor.attribute;
|
|
389
|
+
const pattern = attribute ? new RegExp(`<[^>]+${escaped}[^>]*${attribute}=["']([^"']+)["'][^>]*>`, "i") : new RegExp(`<${escaped}[^>]*>([\\s\\S]*?)<\\/${escaped}>`, "i");
|
|
390
|
+
return pattern.exec(html)?.[1]?.replace(/<[^<>]+>/g, " ").replace(/\s+/g, " ").trim() ?? null;
|
|
391
|
+
}
|
|
392
|
+
function textfromselector(html, selector) { return extractfield(html, { selector }); }
|
|
393
|
+
function descriptorselector(descriptor) { return typeof descriptor === "string" ? descriptor : typeof descriptor === "function" ? "function" : String(descriptor?.selector ?? "unknown"); }
|
|
394
|
+
function normalizebound(value, name) { const normalized = Number(value); if (!Number.isSafeInteger(normalized) || normalized <= 0)
|
|
395
|
+
throw new RangeError(`${name} must be a positive safe integer`); return normalized; }
|
|
396
|
+
function boundpayload(values, maxbytes) {
|
|
397
|
+
const bounded = {};
|
|
398
|
+
const truncated = [];
|
|
399
|
+
for (const [name, value] of Object.entries(values)) {
|
|
400
|
+
const candidate = JSON.stringify({ ...bounded, [name]: value });
|
|
401
|
+
if (byteLength(candidate) <= maxbytes) {
|
|
402
|
+
bounded[name] = value;
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (typeof value === "string") {
|
|
406
|
+
const clipped = clipstring(value, (trial) => byteLength(JSON.stringify({ ...bounded, [name]: trial })) <= maxbytes);
|
|
407
|
+
bounded[name] = clipped;
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
bounded[name] = null;
|
|
411
|
+
}
|
|
412
|
+
truncated.push(name);
|
|
413
|
+
}
|
|
414
|
+
const bytes = byteLength(JSON.stringify(bounded));
|
|
415
|
+
if (bytes > maxbytes)
|
|
416
|
+
throw new RangeError("structured extraction payload budget is too small");
|
|
417
|
+
return { values: bounded, bytes, truncated };
|
|
418
|
+
}
|
|
419
|
+
function clipstring(value, fits) {
|
|
420
|
+
let low = 0;
|
|
421
|
+
let high = value.length;
|
|
422
|
+
let result = "";
|
|
423
|
+
while (low <= high) {
|
|
424
|
+
const middle = Math.floor((low + high) / 2);
|
|
425
|
+
const candidate = value.slice(0, middle);
|
|
426
|
+
if (fits(candidate)) {
|
|
427
|
+
result = candidate;
|
|
428
|
+
low = middle + 1;
|
|
429
|
+
}
|
|
430
|
+
else
|
|
431
|
+
high = middle - 1;
|
|
432
|
+
}
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
function byteLength(value) { return new TextEncoder().encode(String(value)).byteLength; }
|
|
436
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
437
|
+
/* Section 9: scrape/semantic.ts — semantic extraction exposes bounded headings, landmarks, controls and links without evaluating page code. */
|
|
438
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
439
|
+
/**
|
|
440
|
+
* semantic extraction exposes bounded headings, landmarks, controls and links without evaluating page code.
|
|
441
|
+
*/
|
|
442
|
+
/** Extracts semantic page facts from HTML using safe built-in parsing heuristics. */
|
|
443
|
+
export function extractsemantic(html, url) {
|
|
444
|
+
const source = String(html ?? "");
|
|
445
|
+
const headings = [...source.matchAll(/<h([1-6])\b[^>]*>([\s\S]*?)<\/h\1>/gi)].slice(0, 100).map((match) => ({ level: Number(match[1]), text: clean(match[2]) })).filter((item) => item.text);
|
|
446
|
+
const landmarks = [...source.matchAll(/<(main|nav|header|footer|aside|section|article)\b([^>]*)>/gi)].slice(0, 100).map((match) => ({ role: match[1].toLowerCase(), label: attribute(match[2], "aria-label") ?? attribute(match[2], "id") ?? "" }));
|
|
447
|
+
const controls = controlmatches(source).slice(0, 200).map((control, index) => ({ ref: `e${index + 1}`, role: attribute(control.attrs, "role") ?? control.tag, name: attribute(control.attrs, "aria-label") ?? attribute(control.attrs, "placeholder") ?? clean(control.content), type: attribute(control.attrs, "type") }));
|
|
448
|
+
const links = [...source.matchAll(/<a\b([^<>]*)href=["']([^"']+)["'][^<>]*>([\s\S]*?)<\/a\s*>/gi)].slice(0, 500).map((match) => ({ url: resolveurlhelper(match[2], url), text: clean(match[3]), rel: attribute(match[1], "rel") })).filter((link) => link.url);
|
|
449
|
+
return { url, title: clean(source.match(/<title\b[^<>]*>([\s\S]*?)<\/title\s*>/i)?.[1] ?? ""), headings, landmarks, controls, links: dedupe(links, (item) => item.url), semantictext: clean(stripblocks(source, "script", "style").replace(/<[^<>]+>/g, " ")).slice(0, 100000) };
|
|
450
|
+
}
|
|
451
|
+
/** Strips remaining tags, collapses whitespace and decodes entities exactly once in a single pass. */
|
|
452
|
+
function clean(value) { return String(value ?? "").replace(/<[^<>]+>/g, " ").replace(/\s+/g, " ").replace(/&(amp|lt|gt|quot|#39);/g, (whole, entity) => ENTITIES[entity] ?? whole).trim(); }
|
|
453
|
+
/** Collects paired and standalone control elements in document order through hardened linear patterns so inputs without closing tags stay extractable. */
|
|
454
|
+
function controlmatches(source) {
|
|
455
|
+
const paired = [...source.matchAll(/<(button|input|textarea|select|a)\b([^<>]*)>([\s\S]*?)<\/\1\s*>/gi)].map((match) => ({ index: match.index ?? 0, tag: match[1].toLowerCase(), attrs: match[2], content: match[3] }));
|
|
456
|
+
const pairedstarts = new Set(paired.map((item) => item.index));
|
|
457
|
+
const standalone = [...source.matchAll(/<input\b([^<>]*)>/gi)].filter((match) => !pairedstarts.has(match.index ?? 0)).map((match) => ({ index: match.index ?? 0, tag: "input", attrs: match[1], content: "" }));
|
|
458
|
+
return [...paired, ...standalone].sort((left, right) => left.index - right.index);
|
|
459
|
+
}
|
|
460
|
+
function attribute(value, name) { return value.match(new RegExp(`${name}=["']([^"']*)["']`, "i"))?.[1] ?? null; }
|
|
461
|
+
function resolveurlhelper(value, base) { try {
|
|
462
|
+
return new URL(value, base).href;
|
|
463
|
+
}
|
|
464
|
+
catch {
|
|
465
|
+
return null;
|
|
466
|
+
} }
|
|
467
|
+
function dedupe(values, key) { const seen = new Set(); return values.filter((value) => { const item = key(value); if (seen.has(item))
|
|
468
|
+
return false; seen.add(item); return true; }); }
|
|
469
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
470
|
+
/* Section 10: scrape/crawl.ts — scrape crawl context owns URL normalization traversal frontier and durable crawl state. */
|
|
471
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
472
|
+
/**
|
|
473
|
+
* scrape crawl context owns URL normalization traversal frontier and durable crawl state.
|
|
474
|
+
*
|
|
475
|
+
* The context keeps single page acquisition injectable while grouping the correlated
|
|
476
|
+
* crawl responsibilities that previously lived in four separate top level files.
|
|
477
|
+
*/
|
|
478
|
+
/** Removes fragments and tracking parameters before crawl deduplication. */
|
|
479
|
+
export function normalizeurl(value) {
|
|
480
|
+
const url = new URL(value);
|
|
481
|
+
url.hash = "";
|
|
482
|
+
for (const key of [...url.searchParams.keys()])
|
|
483
|
+
if (/^(utm_|fbclid$|msclkid$|gclid$|gclsrc$|dclid$|gbraid$|wbraid$|twclid$|campaign$|content$|term$|source$|medium$|ref$|share_id$)/i.test(key))
|
|
484
|
+
url.searchParams.delete(key);
|
|
485
|
+
if (url.pathname.length > 1)
|
|
486
|
+
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
487
|
+
return url.href;
|
|
488
|
+
}
|
|
489
|
+
/** Compares two crawl targets by origin. */
|
|
490
|
+
export function sameorigin(left, right) { return new URL(left).origin === new URL(right).origin; }
|
|
491
|
+
/** Creates a bounded priority frontier for crawler and queue adapters. */
|
|
492
|
+
export function crawlfrontier(options = {}) {
|
|
493
|
+
const maxpages = Number(options.maxpages ?? 20);
|
|
494
|
+
const maxperdomain = Number(options.maxperdomain ?? maxpages);
|
|
495
|
+
const queue = [];
|
|
496
|
+
const seen = new Set();
|
|
497
|
+
const completed = new Set();
|
|
498
|
+
const domains = new Map();
|
|
499
|
+
/** Adds a URL once while respecting the global page budget. */
|
|
500
|
+
function add(input = {}) {
|
|
501
|
+
const url = String(input.url ?? "");
|
|
502
|
+
if (!url || seen.has(url) || seen.size >= maxpages)
|
|
503
|
+
return false;
|
|
504
|
+
seen.add(url);
|
|
505
|
+
queue.push({ url, depth: Number(input.depth ?? 0), priority: Number(input.priority ?? 0), discoveredat: Number(input.discoveredat ?? Date.now()) });
|
|
506
|
+
queue.sort((left, right) => right.priority - left.priority || left.discoveredat - right.discoveredat);
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
/** Removes the next URL that still fits its per-domain budget. */
|
|
510
|
+
function next() {
|
|
511
|
+
while (queue.length) {
|
|
512
|
+
const item = queue.shift();
|
|
513
|
+
const domain = new URL(item.url).hostname;
|
|
514
|
+
if ((domains.get(domain) ?? 0) >= maxperdomain)
|
|
515
|
+
continue;
|
|
516
|
+
domains.set(domain, (domains.get(domain) ?? 0) + 1);
|
|
517
|
+
return { ...item };
|
|
518
|
+
}
|
|
519
|
+
return null;
|
|
520
|
+
}
|
|
521
|
+
/** Records a completed URL for diagnostics and persistence-friendly state. */
|
|
522
|
+
function complete(url) { completed.add(String(url)); }
|
|
523
|
+
/** Returns stable frontier diagnostics without exposing mutable collections. */
|
|
524
|
+
function state() { return { maxpages, maxperdomain, queued: queue.length, discovered: seen.size, completed: completed.size, domains: Object.fromEntries(domains) }; }
|
|
525
|
+
return { add, next, complete, state, list() { return queue.map((item) => ({ ...item })); } };
|
|
526
|
+
}
|
|
527
|
+
/** Creates a durable crawl queue around a caller-owned store. */
|
|
528
|
+
export function persistentqueue(options = {}) {
|
|
529
|
+
const store = options.store;
|
|
530
|
+
const values = [];
|
|
531
|
+
const seen = new Set();
|
|
532
|
+
/** Restores unfinished crawl records from the injected store. */
|
|
533
|
+
async function restore() { if (typeof store?.list !== "function")
|
|
534
|
+
return; for (const item of await store.list())
|
|
535
|
+
if (!seen.has(item.url) && item.status !== "done") {
|
|
536
|
+
seen.add(item.url);
|
|
537
|
+
values.push(item);
|
|
538
|
+
} }
|
|
539
|
+
/** Adds a crawl record and persists it when the store supports writes. */
|
|
540
|
+
async function add(item) { if (!item?.url || seen.has(item.url))
|
|
541
|
+
return false; const value = { url: item.url, depth: item.depth ?? 0, status: "queued", createdat: Date.now(), metadata: item.metadata ?? {} }; seen.add(value.url); values.push(value); if (typeof store?.save === "function")
|
|
542
|
+
await store.save(value); return true; }
|
|
543
|
+
/** Claims the next queued crawl record. */
|
|
544
|
+
async function next() { const item = values.find((value) => value.status === "queued"); if (!item)
|
|
545
|
+
return null; item.status = "running"; if (typeof store?.update === "function")
|
|
546
|
+
await store.update(item.url, item); return item; }
|
|
547
|
+
/** Completes a crawl record and persists the resulting status. */
|
|
548
|
+
async function complete(url, patch = {}) { const item = values.find((value) => value.url === url); if (!item)
|
|
549
|
+
return null; Object.assign(item, patch, { status: patch.status ?? "done", processedat: Date.now() }); if (typeof store?.update === "function")
|
|
550
|
+
await store.update(url, item); return item; }
|
|
551
|
+
return { restore, add, next, complete, list() { return values.map((value) => ({ ...value })); } };
|
|
552
|
+
}
|
|
553
|
+
/** Runs bounded breadth first traversal through the injected single page scrape contract. */
|
|
554
|
+
export async function crawl(start, options = {}) {
|
|
555
|
+
const maxdepth = options.maxdepth ?? 1;
|
|
556
|
+
const maxpages = options.maxpages ?? 20;
|
|
557
|
+
const sameDomain = options.samedomain ?? true;
|
|
558
|
+
const frontier = crawlfrontier({ maxpages, maxperdomain: options.maxperdomain ?? maxpages });
|
|
559
|
+
frontier.add({ url: normalizeurl(start), depth: 0, priority: options.startpriority ?? 0 });
|
|
560
|
+
const results = [];
|
|
561
|
+
while (frontier.state().queued && results.length < maxpages) {
|
|
562
|
+
const current = frontier.next();
|
|
563
|
+
if (!current || current.depth > maxdepth)
|
|
564
|
+
continue;
|
|
565
|
+
const result = await options.scrape(current.url);
|
|
566
|
+
results.push({ ...result, depth: current.depth });
|
|
567
|
+
frontier.complete(current.url);
|
|
568
|
+
if (current.depth >= maxdepth)
|
|
569
|
+
continue;
|
|
570
|
+
for (const link of result.links ?? []) {
|
|
571
|
+
let url;
|
|
572
|
+
try {
|
|
573
|
+
url = normalizeurl(link);
|
|
574
|
+
}
|
|
575
|
+
catch {
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
if (sameDomain && !sameorigin(start, url))
|
|
579
|
+
continue;
|
|
580
|
+
frontier.add({ url, depth: current.depth + 1, priority: Number(options.priority?.(url, result) ?? 0) });
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return { results, stats: { ...frontier.state(), completed: results.length, maxdepth, maxpages } };
|
|
584
|
+
}
|
|
585
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
586
|
+
/* Section 11: scrape/scraper.ts — scraper composes robots policy cache transport and extraction without browser assumptions. */
|
|
587
|
+
/* ════════════════════════════════════════════════════════════════════ */
|
|
588
|
+
/**
|
|
589
|
+
* scraper composes robots policy cache transport and extraction without browser assumptions.
|
|
590
|
+
*/
|
|
591
|
+
export function scraper(options = {}) {
|
|
592
|
+
const client = options.transport ?? transport({ fetcher: options.fetcher, timeout: options.timeout, attempts: options.attempts });
|
|
593
|
+
const cache = options.cache ?? ttlcache(options.cacheoptions);
|
|
594
|
+
const agent = options.agent ?? "*";
|
|
595
|
+
const policies = new Map();
|
|
596
|
+
return {
|
|
597
|
+
async robots(origin) {
|
|
598
|
+
if (policies.has(origin))
|
|
599
|
+
return policies.get(origin);
|
|
600
|
+
const url = new URL("/robots.txt", origin).href;
|
|
601
|
+
const response = await client.request(url);
|
|
602
|
+
const rules = robotsrules(response.ok ? await response.text() : "");
|
|
603
|
+
policies.set(origin, rules);
|
|
604
|
+
return rules;
|
|
605
|
+
},
|
|
606
|
+
async scrape(url) {
|
|
607
|
+
const target = new URL(url);
|
|
608
|
+
if (!["http:", "https:"].includes(target.protocol))
|
|
609
|
+
throw new TypeError("scraper accepts http and https only");
|
|
610
|
+
const rules = await this.robots(target.origin);
|
|
611
|
+
if (!robotsallowed(rules, target.href, agent))
|
|
612
|
+
throw new Error("robots policy disallows target");
|
|
613
|
+
const cached = cache.get(target.href);
|
|
614
|
+
if (cached)
|
|
615
|
+
return cached;
|
|
616
|
+
const wait = robotsdelay(rules, agent);
|
|
617
|
+
if (wait)
|
|
618
|
+
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
|
|
619
|
+
const response = await client.request(target.href, { headers: options.headers });
|
|
620
|
+
if (!response.ok)
|
|
621
|
+
throw new Error(`scrape request failed with ${response.status}`);
|
|
622
|
+
const result = extracthtml(await response.text(), target.href);
|
|
623
|
+
cache.set(target.href, result, { ttl: options.ttl });
|
|
624
|
+
return result;
|
|
625
|
+
},
|
|
626
|
+
cache
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
//# sourceMappingURL=acquisition.js.map
|