webpeel 0.19.4 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cache.d.ts +0 -1
- package/dist/cache.js +0 -1
- package/dist/cli/commands/auth.d.ts +5 -0
- package/dist/cli/commands/auth.js +476 -0
- package/dist/cli/commands/fetch.d.ts +6 -0
- package/dist/cli/commands/fetch.js +1015 -0
- package/dist/cli/commands/interact.d.ts +5 -0
- package/dist/cli/commands/interact.js +839 -0
- package/dist/cli/commands/jobs.d.ts +5 -0
- package/dist/cli/commands/jobs.js +997 -0
- package/dist/cli/commands/screenshot.d.ts +5 -0
- package/dist/cli/commands/screenshot.js +273 -0
- package/dist/cli/commands/search.d.ts +5 -0
- package/dist/cli/commands/search.js +524 -0
- package/dist/cli/utils.d.ts +84 -0
- package/dist/cli/utils.js +686 -0
- package/dist/cli-auth.d.ts +0 -1
- package/dist/cli-auth.js +0 -1
- package/dist/cli.d.ts +7 -6
- package/dist/cli.js +35 -4698
- package/dist/core/actions.d.ts +0 -1
- package/dist/core/actions.js +0 -1
- package/dist/core/agent.d.ts +0 -1
- package/dist/core/agent.js +9 -12
- package/dist/core/answer.d.ts +0 -1
- package/dist/core/answer.js +0 -1
- package/dist/core/application-tracker.d.ts +0 -1
- package/dist/core/application-tracker.js +0 -1
- package/dist/core/apply.d.ts +0 -1
- package/dist/core/apply.js +0 -1
- package/dist/core/auto-extract.d.ts +0 -1
- package/dist/core/auto-extract.js +0 -1
- package/dist/core/auto-interact.d.ts +0 -1
- package/dist/core/auto-interact.js +0 -1
- package/dist/core/bm25-filter.d.ts +0 -1
- package/dist/core/bm25-filter.js +0 -1
- package/dist/core/branding.d.ts +0 -1
- package/dist/core/branding.js +0 -1
- package/dist/core/browser-fetch.d.ts +0 -1
- package/dist/core/browser-fetch.js +17 -10
- package/dist/core/browser-pool.d.ts +0 -1
- package/dist/core/browser-pool.js +0 -1
- package/dist/core/budget.d.ts +0 -1
- package/dist/core/budget.js +0 -1
- package/dist/core/cache.d.ts +0 -1
- package/dist/core/cache.js +0 -1
- package/dist/core/cf-worker-proxy.d.ts +0 -1
- package/dist/core/cf-worker-proxy.js +0 -1
- package/dist/core/challenge-detection.d.ts +0 -1
- package/dist/core/challenge-detection.js +0 -1
- package/dist/core/change-tracking.d.ts +0 -1
- package/dist/core/change-tracking.js +0 -1
- package/dist/core/chunker.d.ts +0 -1
- package/dist/core/chunker.js +0 -1
- package/dist/core/chunking.d.ts +0 -1
- package/dist/core/chunking.js +0 -1
- package/dist/core/cloak-fetch.d.ts +0 -1
- package/dist/core/cloak-fetch.js +0 -1
- package/dist/core/content-pruner.d.ts +0 -1
- package/dist/core/content-pruner.js +0 -1
- package/dist/core/crawl-checkpoint.d.ts +0 -1
- package/dist/core/crawl-checkpoint.js +0 -1
- package/dist/core/crawler.d.ts +0 -1
- package/dist/core/crawler.js +6 -5
- package/dist/core/cycle-fetch.d.ts +0 -1
- package/dist/core/cycle-fetch.js +0 -1
- package/dist/core/deep-fetch.d.ts +0 -1
- package/dist/core/deep-fetch.js +0 -1
- package/dist/core/design-analysis.d.ts +0 -1
- package/dist/core/design-analysis.js +0 -1
- package/dist/core/design-compare.d.ts +0 -1
- package/dist/core/design-compare.js +0 -1
- package/dist/core/diff.d.ts +0 -1
- package/dist/core/diff.js +0 -1
- package/dist/core/dns-cache.d.ts +0 -1
- package/dist/core/dns-cache.js +0 -1
- package/dist/core/documents.d.ts +0 -1
- package/dist/core/documents.js +0 -1
- package/dist/core/domain-extractors.d.ts +0 -1
- package/dist/core/domain-extractors.js +0 -1
- package/dist/core/extract-inline.d.ts +0 -1
- package/dist/core/extract-inline.js +0 -1
- package/dist/core/extract-listings.d.ts +0 -1
- package/dist/core/extract-listings.js +0 -1
- package/dist/core/extract.d.ts +0 -1
- package/dist/core/extract.js +0 -1
- package/dist/core/fetcher.d.ts +0 -1
- package/dist/core/fetcher.js +0 -1
- package/dist/core/google-cache.d.ts +0 -1
- package/dist/core/google-cache.js +0 -1
- package/dist/core/hotel-search.d.ts +0 -1
- package/dist/core/hotel-search.js +0 -1
- package/dist/core/http-fetch.d.ts +0 -1
- package/dist/core/http-fetch.js +5 -7
- package/dist/core/human.d.ts +0 -1
- package/dist/core/human.js +0 -1
- package/dist/core/jobs.d.ts +0 -1
- package/dist/core/jobs.js +0 -1
- package/dist/core/json-ld.d.ts +0 -1
- package/dist/core/json-ld.js +0 -1
- package/dist/core/llm-extract.d.ts +0 -1
- package/dist/core/llm-extract.js +0 -1
- package/dist/core/logger.d.ts +17 -0
- package/dist/core/logger.js +44 -0
- package/dist/core/map.d.ts +0 -1
- package/dist/core/map.js +0 -1
- package/dist/core/markdown.d.ts +0 -1
- package/dist/core/markdown.js +0 -1
- package/dist/core/metadata.d.ts +0 -1
- package/dist/core/metadata.js +0 -1
- package/dist/core/paginate.d.ts +0 -1
- package/dist/core/paginate.js +0 -1
- package/dist/core/pdf.d.ts +0 -1
- package/dist/core/pdf.js +0 -1
- package/dist/core/peel-tls.d.ts +0 -1
- package/dist/core/peel-tls.js +0 -1
- package/dist/core/pipeline.d.ts +0 -1
- package/dist/core/pipeline.js +22 -25
- package/dist/core/profiles.d.ts +0 -1
- package/dist/core/profiles.js +0 -1
- package/dist/core/quick-answer.d.ts +0 -1
- package/dist/core/quick-answer.js +0 -1
- package/dist/core/rate-governor.d.ts +0 -1
- package/dist/core/rate-governor.js +0 -1
- package/dist/core/readability.d.ts +0 -1
- package/dist/core/readability.js +0 -1
- package/dist/core/research.d.ts +0 -1
- package/dist/core/research.js +0 -1
- package/dist/core/schema-extraction.d.ts +0 -1
- package/dist/core/schema-extraction.js +0 -1
- package/dist/core/schema-postprocess.d.ts +0 -1
- package/dist/core/schema-postprocess.js +0 -1
- package/dist/core/schema-templates.d.ts +0 -1
- package/dist/core/schema-templates.js +0 -1
- package/dist/core/screenshot.d.ts +0 -1
- package/dist/core/screenshot.js +0 -1
- package/dist/core/search-fallback.d.ts +0 -1
- package/dist/core/search-fallback.js +0 -1
- package/dist/core/search-provider.d.ts +0 -1
- package/dist/core/search-provider.js +18 -21
- package/dist/core/site-search.d.ts +0 -1
- package/dist/core/site-search.js +0 -1
- package/dist/core/sitemap.d.ts +0 -1
- package/dist/core/sitemap.js +0 -1
- package/dist/core/stealth-patches.d.ts +0 -1
- package/dist/core/stealth-patches.js +0 -1
- package/dist/core/stemmer.d.ts +0 -1
- package/dist/core/stemmer.js +0 -1
- package/dist/core/strategies.d.ts +6 -1
- package/dist/core/strategies.js +29 -41
- package/dist/core/strategy-hooks.d.ts +0 -1
- package/dist/core/strategy-hooks.js +0 -1
- package/dist/core/summarize.d.ts +0 -1
- package/dist/core/summarize.js +0 -1
- package/dist/core/synonyms.d.ts +0 -1
- package/dist/core/synonyms.js +0 -1
- package/dist/core/table-format.d.ts +0 -1
- package/dist/core/table-format.js +0 -1
- package/dist/core/timing.d.ts +0 -1
- package/dist/core/timing.js +0 -1
- package/dist/core/user-agents.d.ts +0 -1
- package/dist/core/user-agents.js +0 -1
- package/dist/core/watch-manager.d.ts +0 -1
- package/dist/core/watch-manager.js +0 -1
- package/dist/core/watch.d.ts +0 -1
- package/dist/core/watch.js +0 -1
- package/dist/core/youtube.d.ts +0 -1
- package/dist/core/youtube.js +0 -1
- package/dist/index.d.ts +8 -3
- package/dist/index.js +27 -3
- package/dist/integrations/index.d.ts +0 -1
- package/dist/integrations/index.js +0 -1
- package/dist/integrations/langchain.d.ts +0 -1
- package/dist/integrations/langchain.js +0 -1
- package/dist/integrations/llamaindex.d.ts +0 -1
- package/dist/integrations/llamaindex.js +0 -1
- package/dist/mcp/handlers/act.d.ts +5 -0
- package/dist/mcp/handlers/act.js +34 -0
- package/dist/mcp/handlers/definitions.d.ts +6 -0
- package/dist/mcp/handlers/definitions.js +266 -0
- package/dist/mcp/handlers/extract.d.ts +6 -0
- package/dist/mcp/handlers/extract.js +102 -0
- package/dist/mcp/handlers/fetch.d.ts +6 -0
- package/dist/mcp/handlers/fetch.js +98 -0
- package/dist/mcp/handlers/find.d.ts +5 -0
- package/dist/mcp/handlers/find.js +137 -0
- package/dist/mcp/handlers/index.d.ts +13 -0
- package/dist/mcp/handlers/index.js +61 -0
- package/dist/mcp/handlers/legacy.d.ts +25 -0
- package/dist/mcp/handlers/legacy.js +450 -0
- package/dist/mcp/handlers/meta.d.ts +6 -0
- package/dist/mcp/handlers/meta.js +31 -0
- package/dist/mcp/handlers/monitor.d.ts +5 -0
- package/dist/mcp/handlers/monitor.js +41 -0
- package/dist/mcp/handlers/read.d.ts +6 -0
- package/dist/mcp/handlers/read.js +63 -0
- package/dist/mcp/handlers/see.d.ts +5 -0
- package/dist/mcp/handlers/see.js +75 -0
- package/dist/mcp/handlers/types.d.ts +29 -0
- package/dist/mcp/handlers/types.js +28 -0
- package/dist/mcp/server.d.ts +3 -4
- package/dist/mcp/server.js +35 -1101
- package/dist/mcp/smart-router.d.ts +0 -1
- package/dist/mcp/smart-router.js +3 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.js +0 -1
- package/package.json +3 -13
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js.map +0 -1
- package/dist/cli-auth.d.ts.map +0 -1
- package/dist/cli-auth.js.map +0 -1
- package/dist/cli.bundle.cjs +0 -159248
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/core/actions.d.ts.map +0 -1
- package/dist/core/actions.js.map +0 -1
- package/dist/core/agent.d.ts.map +0 -1
- package/dist/core/agent.js.map +0 -1
- package/dist/core/answer.d.ts.map +0 -1
- package/dist/core/answer.js.map +0 -1
- package/dist/core/application-tracker.d.ts.map +0 -1
- package/dist/core/application-tracker.js.map +0 -1
- package/dist/core/apply.d.ts.map +0 -1
- package/dist/core/apply.js.map +0 -1
- package/dist/core/auto-extract.d.ts.map +0 -1
- package/dist/core/auto-extract.js.map +0 -1
- package/dist/core/auto-interact.d.ts.map +0 -1
- package/dist/core/auto-interact.js.map +0 -1
- package/dist/core/bm25-filter.d.ts.map +0 -1
- package/dist/core/bm25-filter.js.map +0 -1
- package/dist/core/branding.d.ts.map +0 -1
- package/dist/core/branding.js.map +0 -1
- package/dist/core/browser-fetch.d.ts.map +0 -1
- package/dist/core/browser-fetch.js.map +0 -1
- package/dist/core/browser-pool.d.ts.map +0 -1
- package/dist/core/browser-pool.js.map +0 -1
- package/dist/core/budget.d.ts.map +0 -1
- package/dist/core/budget.js.map +0 -1
- package/dist/core/cache.d.ts.map +0 -1
- package/dist/core/cache.js.map +0 -1
- package/dist/core/cf-worker-proxy.d.ts.map +0 -1
- package/dist/core/cf-worker-proxy.js.map +0 -1
- package/dist/core/challenge-detection.d.ts.map +0 -1
- package/dist/core/challenge-detection.js.map +0 -1
- package/dist/core/change-tracking.d.ts.map +0 -1
- package/dist/core/change-tracking.js.map +0 -1
- package/dist/core/chunker.d.ts.map +0 -1
- package/dist/core/chunker.js.map +0 -1
- package/dist/core/chunking.d.ts.map +0 -1
- package/dist/core/chunking.js.map +0 -1
- package/dist/core/cloak-fetch.d.ts.map +0 -1
- package/dist/core/cloak-fetch.js.map +0 -1
- package/dist/core/content-pruner.d.ts.map +0 -1
- package/dist/core/content-pruner.js.map +0 -1
- package/dist/core/crawl-checkpoint.d.ts.map +0 -1
- package/dist/core/crawl-checkpoint.js.map +0 -1
- package/dist/core/crawler.d.ts.map +0 -1
- package/dist/core/crawler.js.map +0 -1
- package/dist/core/cycle-fetch.d.ts.map +0 -1
- package/dist/core/cycle-fetch.js.map +0 -1
- package/dist/core/deep-fetch.d.ts.map +0 -1
- package/dist/core/deep-fetch.js.map +0 -1
- package/dist/core/design-analysis.d.ts.map +0 -1
- package/dist/core/design-analysis.js.map +0 -1
- package/dist/core/design-compare.d.ts.map +0 -1
- package/dist/core/design-compare.js.map +0 -1
- package/dist/core/diff.d.ts.map +0 -1
- package/dist/core/diff.js.map +0 -1
- package/dist/core/dns-cache.d.ts.map +0 -1
- package/dist/core/dns-cache.js.map +0 -1
- package/dist/core/documents.d.ts.map +0 -1
- package/dist/core/documents.js.map +0 -1
- package/dist/core/domain-extractors.d.ts.map +0 -1
- package/dist/core/domain-extractors.js.map +0 -1
- package/dist/core/extract-inline.d.ts.map +0 -1
- package/dist/core/extract-inline.js.map +0 -1
- package/dist/core/extract-listings.d.ts.map +0 -1
- package/dist/core/extract-listings.js.map +0 -1
- package/dist/core/extract.d.ts.map +0 -1
- package/dist/core/extract.js.map +0 -1
- package/dist/core/fetcher.d.ts.map +0 -1
- package/dist/core/fetcher.js.map +0 -1
- package/dist/core/google-cache.d.ts.map +0 -1
- package/dist/core/google-cache.js.map +0 -1
- package/dist/core/hotel-search.d.ts.map +0 -1
- package/dist/core/hotel-search.js.map +0 -1
- package/dist/core/http-fetch.d.ts.map +0 -1
- package/dist/core/http-fetch.js.map +0 -1
- package/dist/core/human.d.ts.map +0 -1
- package/dist/core/human.js.map +0 -1
- package/dist/core/jobs.d.ts.map +0 -1
- package/dist/core/jobs.js.map +0 -1
- package/dist/core/json-ld.d.ts.map +0 -1
- package/dist/core/json-ld.js.map +0 -1
- package/dist/core/llm-extract.d.ts.map +0 -1
- package/dist/core/llm-extract.js.map +0 -1
- package/dist/core/map.d.ts.map +0 -1
- package/dist/core/map.js.map +0 -1
- package/dist/core/markdown.d.ts.map +0 -1
- package/dist/core/markdown.js.map +0 -1
- package/dist/core/metadata.d.ts.map +0 -1
- package/dist/core/metadata.js.map +0 -1
- package/dist/core/paginate.d.ts.map +0 -1
- package/dist/core/paginate.js.map +0 -1
- package/dist/core/pdf.d.ts.map +0 -1
- package/dist/core/pdf.js.map +0 -1
- package/dist/core/peel-tls.d.ts.map +0 -1
- package/dist/core/peel-tls.js.map +0 -1
- package/dist/core/pipeline.d.ts.map +0 -1
- package/dist/core/pipeline.js.map +0 -1
- package/dist/core/profiles.d.ts.map +0 -1
- package/dist/core/profiles.js.map +0 -1
- package/dist/core/quick-answer.d.ts.map +0 -1
- package/dist/core/quick-answer.js.map +0 -1
- package/dist/core/rate-governor.d.ts.map +0 -1
- package/dist/core/rate-governor.js.map +0 -1
- package/dist/core/readability.d.ts.map +0 -1
- package/dist/core/readability.js.map +0 -1
- package/dist/core/research.d.ts.map +0 -1
- package/dist/core/research.js.map +0 -1
- package/dist/core/schema-extraction.d.ts.map +0 -1
- package/dist/core/schema-extraction.js.map +0 -1
- package/dist/core/schema-postprocess.d.ts.map +0 -1
- package/dist/core/schema-postprocess.js.map +0 -1
- package/dist/core/schema-templates.d.ts.map +0 -1
- package/dist/core/schema-templates.js.map +0 -1
- package/dist/core/screenshot.d.ts.map +0 -1
- package/dist/core/screenshot.js.map +0 -1
- package/dist/core/search-fallback.d.ts.map +0 -1
- package/dist/core/search-fallback.js.map +0 -1
- package/dist/core/search-provider.d.ts.map +0 -1
- package/dist/core/search-provider.js.map +0 -1
- package/dist/core/site-search.d.ts.map +0 -1
- package/dist/core/site-search.js.map +0 -1
- package/dist/core/sitemap.d.ts.map +0 -1
- package/dist/core/sitemap.js.map +0 -1
- package/dist/core/stealth-patches.d.ts.map +0 -1
- package/dist/core/stealth-patches.js.map +0 -1
- package/dist/core/stemmer.d.ts.map +0 -1
- package/dist/core/stemmer.js.map +0 -1
- package/dist/core/strategies.d.ts.map +0 -1
- package/dist/core/strategies.js.map +0 -1
- package/dist/core/strategy-hooks.d.ts.map +0 -1
- package/dist/core/strategy-hooks.js.map +0 -1
- package/dist/core/summarize.d.ts.map +0 -1
- package/dist/core/summarize.js.map +0 -1
- package/dist/core/synonyms.d.ts.map +0 -1
- package/dist/core/synonyms.js.map +0 -1
- package/dist/core/table-format.d.ts.map +0 -1
- package/dist/core/table-format.js.map +0 -1
- package/dist/core/timing.d.ts.map +0 -1
- package/dist/core/timing.js.map +0 -1
- package/dist/core/user-agents.d.ts.map +0 -1
- package/dist/core/user-agents.js.map +0 -1
- package/dist/core/watch-manager.d.ts.map +0 -1
- package/dist/core/watch-manager.js.map +0 -1
- package/dist/core/watch.d.ts.map +0 -1
- package/dist/core/watch.js.map +0 -1
- package/dist/core/youtube.d.ts.map +0 -1
- package/dist/core/youtube.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integrations/index.d.ts.map +0 -1
- package/dist/integrations/index.js.map +0 -1
- package/dist/integrations/langchain.d.ts.map +0 -1
- package/dist/integrations/langchain.js.map +0 -1
- package/dist/integrations/llamaindex.d.ts.map +0 -1
- package/dist/integrations/llamaindex.js.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/smart-router.d.ts.map +0 -1
- package/dist/mcp/smart-router.js.map +0 -1
- package/dist/server/app.d.ts +0 -15
- package/dist/server/app.d.ts.map +0 -1
- package/dist/server/app.js +0 -350
- package/dist/server/app.js.map +0 -1
- package/dist/server/auth-store.d.ts +0 -28
- package/dist/server/auth-store.d.ts.map +0 -1
- package/dist/server/auth-store.js +0 -89
- package/dist/server/auth-store.js.map +0 -1
- package/dist/server/email-service.d.ts +0 -22
- package/dist/server/email-service.d.ts.map +0 -1
- package/dist/server/email-service.js +0 -80
- package/dist/server/email-service.js.map +0 -1
- package/dist/server/job-queue.d.ts +0 -93
- package/dist/server/job-queue.d.ts.map +0 -1
- package/dist/server/job-queue.js +0 -146
- package/dist/server/job-queue.js.map +0 -1
- package/dist/server/logger.d.ts +0 -11
- package/dist/server/logger.d.ts.map +0 -1
- package/dist/server/logger.js +0 -38
- package/dist/server/logger.js.map +0 -1
- package/dist/server/middleware/auth.d.ts +0 -29
- package/dist/server/middleware/auth.d.ts.map +0 -1
- package/dist/server/middleware/auth.js +0 -222
- package/dist/server/middleware/auth.js.map +0 -1
- package/dist/server/middleware/rate-limit.d.ts +0 -25
- package/dist/server/middleware/rate-limit.d.ts.map +0 -1
- package/dist/server/middleware/rate-limit.js +0 -168
- package/dist/server/middleware/rate-limit.js.map +0 -1
- package/dist/server/middleware/url-validator.d.ts +0 -16
- package/dist/server/middleware/url-validator.d.ts.map +0 -1
- package/dist/server/middleware/url-validator.js +0 -187
- package/dist/server/middleware/url-validator.js.map +0 -1
- package/dist/server/openapi.yaml +0 -4944
- package/dist/server/pg-auth-store.d.ts +0 -133
- package/dist/server/pg-auth-store.d.ts.map +0 -1
- package/dist/server/pg-auth-store.js +0 -473
- package/dist/server/pg-auth-store.js.map +0 -1
- package/dist/server/pg-job-queue.d.ts +0 -60
- package/dist/server/pg-job-queue.d.ts.map +0 -1
- package/dist/server/pg-job-queue.js +0 -365
- package/dist/server/pg-job-queue.js.map +0 -1
- package/dist/server/premium/domain-intel.d.ts +0 -17
- package/dist/server/premium/domain-intel.d.ts.map +0 -1
- package/dist/server/premium/domain-intel.js +0 -134
- package/dist/server/premium/domain-intel.js.map +0 -1
- package/dist/server/premium/index.d.ts +0 -18
- package/dist/server/premium/index.d.ts.map +0 -1
- package/dist/server/premium/index.js +0 -36
- package/dist/server/premium/index.js.map +0 -1
- package/dist/server/premium/swr-cache.d.ts +0 -15
- package/dist/server/premium/swr-cache.d.ts.map +0 -1
- package/dist/server/premium/swr-cache.js +0 -35
- package/dist/server/premium/swr-cache.js.map +0 -1
- package/dist/server/routes/activity.d.ts +0 -7
- package/dist/server/routes/activity.d.ts.map +0 -1
- package/dist/server/routes/activity.js +0 -68
- package/dist/server/routes/activity.js.map +0 -1
- package/dist/server/routes/agent.d.ts +0 -16
- package/dist/server/routes/agent.d.ts.map +0 -1
- package/dist/server/routes/agent.js +0 -247
- package/dist/server/routes/agent.js.map +0 -1
- package/dist/server/routes/answer.d.ts +0 -6
- package/dist/server/routes/answer.d.ts.map +0 -1
- package/dist/server/routes/answer.js +0 -133
- package/dist/server/routes/answer.js.map +0 -1
- package/dist/server/routes/ask.d.ts +0 -23
- package/dist/server/routes/ask.d.ts.map +0 -1
- package/dist/server/routes/ask.js +0 -119
- package/dist/server/routes/ask.js.map +0 -1
- package/dist/server/routes/batch.d.ts +0 -7
- package/dist/server/routes/batch.d.ts.map +0 -1
- package/dist/server/routes/batch.js +0 -412
- package/dist/server/routes/batch.js.map +0 -1
- package/dist/server/routes/cli-usage.d.ts +0 -7
- package/dist/server/routes/cli-usage.d.ts.map +0 -1
- package/dist/server/routes/cli-usage.js +0 -121
- package/dist/server/routes/cli-usage.js.map +0 -1
- package/dist/server/routes/compat.d.ts +0 -24
- package/dist/server/routes/compat.d.ts.map +0 -1
- package/dist/server/routes/compat.js +0 -653
- package/dist/server/routes/compat.js.map +0 -1
- package/dist/server/routes/deep-fetch.d.ts +0 -9
- package/dist/server/routes/deep-fetch.d.ts.map +0 -1
- package/dist/server/routes/deep-fetch.js +0 -50
- package/dist/server/routes/deep-fetch.js.map +0 -1
- package/dist/server/routes/demo.d.ts +0 -25
- package/dist/server/routes/demo.d.ts.map +0 -1
- package/dist/server/routes/demo.js +0 -434
- package/dist/server/routes/demo.js.map +0 -1
- package/dist/server/routes/extract.d.ts +0 -9
- package/dist/server/routes/extract.d.ts.map +0 -1
- package/dist/server/routes/extract.js +0 -150
- package/dist/server/routes/extract.js.map +0 -1
- package/dist/server/routes/fetch.d.ts +0 -8
- package/dist/server/routes/fetch.d.ts.map +0 -1
- package/dist/server/routes/fetch.js +0 -988
- package/dist/server/routes/fetch.js.map +0 -1
- package/dist/server/routes/health.d.ts +0 -8
- package/dist/server/routes/health.d.ts.map +0 -1
- package/dist/server/routes/health.js +0 -20
- package/dist/server/routes/health.js.map +0 -1
- package/dist/server/routes/jobs.d.ts +0 -8
- package/dist/server/routes/jobs.d.ts.map +0 -1
- package/dist/server/routes/jobs.js +0 -487
- package/dist/server/routes/jobs.js.map +0 -1
- package/dist/server/routes/mcp.d.ts +0 -18
- package/dist/server/routes/mcp.d.ts.map +0 -1
- package/dist/server/routes/mcp.js +0 -1260
- package/dist/server/routes/mcp.js.map +0 -1
- package/dist/server/routes/oauth.d.ts +0 -10
- package/dist/server/routes/oauth.d.ts.map +0 -1
- package/dist/server/routes/oauth.js +0 -334
- package/dist/server/routes/oauth.js.map +0 -1
- package/dist/server/routes/quick-answer.d.ts +0 -9
- package/dist/server/routes/quick-answer.d.ts.map +0 -1
- package/dist/server/routes/quick-answer.js +0 -93
- package/dist/server/routes/quick-answer.js.map +0 -1
- package/dist/server/routes/screenshot.d.ts +0 -23
- package/dist/server/routes/screenshot.d.ts.map +0 -1
- package/dist/server/routes/screenshot.js +0 -819
- package/dist/server/routes/screenshot.js.map +0 -1
- package/dist/server/routes/search.d.ts +0 -7
- package/dist/server/routes/search.d.ts.map +0 -1
- package/dist/server/routes/search.js +0 -312
- package/dist/server/routes/search.js.map +0 -1
- package/dist/server/routes/session.d.ts +0 -16
- package/dist/server/routes/session.d.ts.map +0 -1
- package/dist/server/routes/session.js +0 -278
- package/dist/server/routes/session.js.map +0 -1
- package/dist/server/routes/stats.d.ts +0 -7
- package/dist/server/routes/stats.d.ts.map +0 -1
- package/dist/server/routes/stats.js +0 -65
- package/dist/server/routes/stats.js.map +0 -1
- package/dist/server/routes/stripe.d.ts +0 -16
- package/dist/server/routes/stripe.d.ts.map +0 -1
- package/dist/server/routes/stripe.js +0 -283
- package/dist/server/routes/stripe.js.map +0 -1
- package/dist/server/routes/users.d.ts +0 -9
- package/dist/server/routes/users.d.ts.map +0 -1
- package/dist/server/routes/users.js +0 -1211
- package/dist/server/routes/users.js.map +0 -1
- package/dist/server/routes/watch.d.ts +0 -16
- package/dist/server/routes/watch.d.ts.map +0 -1
- package/dist/server/routes/watch.js +0 -257
- package/dist/server/routes/watch.js.map +0 -1
- package/dist/server/routes/webhooks.d.ts +0 -16
- package/dist/server/routes/webhooks.d.ts.map +0 -1
- package/dist/server/routes/webhooks.js +0 -74
- package/dist/server/routes/webhooks.js.map +0 -1
- package/dist/server/routes/youtube.d.ts +0 -7
- package/dist/server/routes/youtube.d.ts.map +0 -1
- package/dist/server/routes/youtube.js +0 -93
- package/dist/server/routes/youtube.js.map +0 -1
- package/dist/server/sentry.d.ts +0 -14
- package/dist/server/sentry.d.ts.map +0 -1
- package/dist/server/sentry.js +0 -39
- package/dist/server/sentry.js.map +0 -1
- package/dist/server/types.d.ts +0 -16
- package/dist/server/types.d.ts.map +0 -1
- package/dist/server/types.js +0 -8
- package/dist/server/types.js.map +0 -1
- package/dist/server/utils/response.d.ts +0 -45
- package/dist/server/utils/response.d.ts.map +0 -1
- package/dist/server/utils/response.js +0 -70
- package/dist/server/utils/response.js.map +0 -1
- package/dist/server/utils/sse.d.ts +0 -23
- package/dist/server/utils/sse.d.ts.map +0 -1
- package/dist/server/utils/sse.js +0 -39
- package/dist/server/utils/sse.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search commands: search, sites, batch, crawl, map
|
|
3
|
+
*/
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
import { peel, peelBatch, cleanup } from '../../index.js';
|
|
7
|
+
import { checkUsage, showUsageFooter, loadConfig } from '../../cli-auth.js';
|
|
8
|
+
import { writeStdout, formatListingsCsv } from '../utils.js';
|
|
9
|
+
export function registerSearchCommands(program) {
|
|
10
|
+
// ── search command ────────────────────────────────────────────────────────
|
|
11
|
+
program
|
|
12
|
+
.command('search <query>')
|
|
13
|
+
.description('Search the web (DuckDuckGo by default, or use --site for site-specific search)')
|
|
14
|
+
.option('-n, --count <n>', 'Number of results (1-10)', '5')
|
|
15
|
+
.option('--top <n>', 'Limit results (alias for --count)')
|
|
16
|
+
.option('--provider <provider>', 'Search provider: duckduckgo (default) or brave')
|
|
17
|
+
.option('--search-api-key <key>', 'API key for the search provider (or env WEBPEEL_BRAVE_API_KEY)')
|
|
18
|
+
.option('--site <site>', 'Search a specific site (e.g. ebay, amazon, github). Run "webpeel sites" for full list.')
|
|
19
|
+
.option('--json', 'Output as JSON')
|
|
20
|
+
.option('--urls-only', 'Output only URLs, one per line (pipe-friendly)')
|
|
21
|
+
.option('--table', 'Output site-search results as a formatted table (requires --site)')
|
|
22
|
+
.option('--csv', 'Output site-search results as CSV (requires --site)')
|
|
23
|
+
.option('--budget <n>', 'Token budget for site-search result content', parseInt)
|
|
24
|
+
.option('-s, --silent', 'Silent mode')
|
|
25
|
+
.option('--proxy <url>', 'Proxy URL for requests (http://host:port, socks5://user:pass@host:port)')
|
|
26
|
+
.option('--agent', 'Agent mode: sets --json, --silent, and --budget 4000 (override with --budget N)')
|
|
27
|
+
.action(async (query, options) => {
|
|
28
|
+
// --agent sets sensible defaults for AI agents; explicit flags override
|
|
29
|
+
if (options.agent) {
|
|
30
|
+
if (!options.json)
|
|
31
|
+
options.json = true;
|
|
32
|
+
if (!options.silent)
|
|
33
|
+
options.silent = true;
|
|
34
|
+
if (options.budget === undefined)
|
|
35
|
+
options.budget = 4000;
|
|
36
|
+
}
|
|
37
|
+
const isJson = options.json;
|
|
38
|
+
const isSilent = options.silent;
|
|
39
|
+
// --top overrides --count when both are provided
|
|
40
|
+
const count = parseInt(options.top ?? options.count) || 5;
|
|
41
|
+
// Check usage quota
|
|
42
|
+
const usageCheck = await checkUsage();
|
|
43
|
+
if (!usageCheck.allowed) {
|
|
44
|
+
console.error(usageCheck.message);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
// ── --site: site-specific structured search ───────────────────────────
|
|
48
|
+
if (options.site) {
|
|
49
|
+
const spinner = isSilent ? null : ora(`Searching ${options.site}...`).start();
|
|
50
|
+
try {
|
|
51
|
+
const { buildSiteSearchUrl } = await import('../../core/site-search.js');
|
|
52
|
+
const siteResult = buildSiteSearchUrl(options.site, query);
|
|
53
|
+
// Fetch the raw HTML (needed for listing extraction)
|
|
54
|
+
const htmlResult = await peel(siteResult.url, {
|
|
55
|
+
format: 'html',
|
|
56
|
+
timeout: 30000,
|
|
57
|
+
proxy: options.proxy,
|
|
58
|
+
});
|
|
59
|
+
if (spinner) {
|
|
60
|
+
spinner.succeed(`Fetched ${siteResult.site} in ${htmlResult.elapsed}ms`);
|
|
61
|
+
}
|
|
62
|
+
// Extract listings from the HTML
|
|
63
|
+
const { extractListings } = await import('../../core/extract-listings.js');
|
|
64
|
+
let listings = extractListings(htmlResult.content, siteResult.url);
|
|
65
|
+
// Apply budget if requested
|
|
66
|
+
if (options.budget && options.budget > 0 && listings.length > 0) {
|
|
67
|
+
const { budgetListings } = await import('../../core/budget.js');
|
|
68
|
+
const { maxItems } = budgetListings(listings.length, options.budget);
|
|
69
|
+
listings = listings.slice(0, maxItems);
|
|
70
|
+
}
|
|
71
|
+
// Show usage footer
|
|
72
|
+
if (usageCheck.usageInfo && !isSilent) {
|
|
73
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, false);
|
|
74
|
+
}
|
|
75
|
+
// Output
|
|
76
|
+
if (options.csv) {
|
|
77
|
+
const rows = listings.map(item => {
|
|
78
|
+
const row = {};
|
|
79
|
+
for (const [k, v] of Object.entries(item)) {
|
|
80
|
+
if (v !== undefined)
|
|
81
|
+
row[k] = v;
|
|
82
|
+
}
|
|
83
|
+
return row;
|
|
84
|
+
});
|
|
85
|
+
await writeStdout(formatListingsCsv(rows));
|
|
86
|
+
}
|
|
87
|
+
else if (options.table) {
|
|
88
|
+
const { formatTable } = await import('../../core/table-format.js');
|
|
89
|
+
const rows = listings.map(item => {
|
|
90
|
+
const row = {};
|
|
91
|
+
for (const [k, v] of Object.entries(item)) {
|
|
92
|
+
if (v !== undefined)
|
|
93
|
+
row[k] = v;
|
|
94
|
+
}
|
|
95
|
+
return row;
|
|
96
|
+
});
|
|
97
|
+
await writeStdout(formatTable(rows) + '\n');
|
|
98
|
+
}
|
|
99
|
+
else if (isJson) {
|
|
100
|
+
const envelope = {
|
|
101
|
+
site: siteResult.site,
|
|
102
|
+
query: siteResult.query,
|
|
103
|
+
url: siteResult.url,
|
|
104
|
+
count: listings.length,
|
|
105
|
+
items: listings,
|
|
106
|
+
elapsed: htmlResult.elapsed,
|
|
107
|
+
};
|
|
108
|
+
await writeStdout(JSON.stringify(envelope, null, 2) + '\n');
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
if (listings.length === 0) {
|
|
112
|
+
await writeStdout('No listings found.\n');
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
await writeStdout(`Found ${listings.length} listings on ${siteResult.site}:\n\n`);
|
|
116
|
+
for (const [i, item] of listings.entries()) {
|
|
117
|
+
const pricePart = item.price ? ` — ${item.price}` : '';
|
|
118
|
+
process.stdout.write(`${i + 1}. ${item.title}${pricePart}\n`);
|
|
119
|
+
if (item.link)
|
|
120
|
+
process.stdout.write(` ${item.link}\n`);
|
|
121
|
+
process.stdout.write('\n');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
await cleanup();
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (spinner)
|
|
130
|
+
spinner.fail('Site search failed');
|
|
131
|
+
if (error instanceof Error) {
|
|
132
|
+
console.error(`\nError: ${error.message}`);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
console.error('\nError: Unknown error occurred');
|
|
136
|
+
}
|
|
137
|
+
await cleanup();
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const spinner = isSilent ? null : ora('Searching...').start();
|
|
142
|
+
try {
|
|
143
|
+
// Route search through the WebPeel API when a key is configured
|
|
144
|
+
const searchCfg = loadConfig();
|
|
145
|
+
const searchApiKey = searchCfg.apiKey || process.env.WEBPEEL_API_KEY;
|
|
146
|
+
const searchApiUrl = process.env.WEBPEEL_API_URL || 'https://api.webpeel.dev';
|
|
147
|
+
if (!searchApiKey) {
|
|
148
|
+
if (spinner)
|
|
149
|
+
spinner.fail('Authentication required');
|
|
150
|
+
console.error('No API key configured. Run: webpeel auth <your-key>');
|
|
151
|
+
console.error('Get a free key at: https://app.webpeel.dev/keys');
|
|
152
|
+
process.exit(2);
|
|
153
|
+
}
|
|
154
|
+
const searchParams = new URLSearchParams({ q: query });
|
|
155
|
+
searchParams.set('limit', String(Math.min(Math.max(count, 1), 10)));
|
|
156
|
+
if (options.budget)
|
|
157
|
+
searchParams.set('budget', String(options.budget));
|
|
158
|
+
const searchRes = await fetch(`${searchApiUrl}/v1/search?${searchParams}`, {
|
|
159
|
+
headers: { Authorization: `Bearer ${searchApiKey}` },
|
|
160
|
+
signal: AbortSignal.timeout(30000),
|
|
161
|
+
});
|
|
162
|
+
if (searchRes.status === 401) {
|
|
163
|
+
if (spinner)
|
|
164
|
+
spinner.fail('Authentication failed');
|
|
165
|
+
console.error('API key invalid or expired. Run: webpeel auth <new-key>');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
if (searchRes.status === 429) {
|
|
169
|
+
if (spinner)
|
|
170
|
+
spinner.fail('Rate limited');
|
|
171
|
+
console.error('Rate limit exceeded. Check your plan at https://app.webpeel.dev/billing');
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
if (!searchRes.ok) {
|
|
175
|
+
const body = await searchRes.text().catch(() => '');
|
|
176
|
+
throw new Error(`Search API error ${searchRes.status}: ${body.slice(0, 200)}`);
|
|
177
|
+
}
|
|
178
|
+
const searchData = await searchRes.json();
|
|
179
|
+
// API returns { success: true, data: { web: [...] } } or { results: [...] }
|
|
180
|
+
let results = searchData.data?.web || searchData.data?.results || searchData.results || [];
|
|
181
|
+
if (spinner) {
|
|
182
|
+
spinner.succeed(`Found ${results.length} results`);
|
|
183
|
+
}
|
|
184
|
+
// Show usage footer for free/anonymous users
|
|
185
|
+
if (usageCheck.usageInfo && !isSilent) {
|
|
186
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, false);
|
|
187
|
+
}
|
|
188
|
+
if (options.urlsOnly) {
|
|
189
|
+
// Pipe-friendly: one URL per line
|
|
190
|
+
for (const result of results) {
|
|
191
|
+
await writeStdout(result.url + '\n');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (isJson) {
|
|
195
|
+
const jsonStr = JSON.stringify({ query, results, count: results.length }, null, 2);
|
|
196
|
+
await writeStdout(jsonStr + '\n');
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
for (const result of results) {
|
|
200
|
+
console.log(`\n${result.title}`);
|
|
201
|
+
console.log(result.url);
|
|
202
|
+
console.log(result.snippet);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
process.exit(0);
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
if (spinner) {
|
|
209
|
+
spinner.fail('Search failed');
|
|
210
|
+
}
|
|
211
|
+
if (error instanceof Error) {
|
|
212
|
+
console.error(`\nError: ${error.message}`);
|
|
213
|
+
const msg = error.message.toLowerCase();
|
|
214
|
+
if (msg.includes('brave') && msg.includes('api key')) {
|
|
215
|
+
console.error('\n💡 Hint: Set your Brave API key: webpeel config set braveApiKey YOUR_KEY');
|
|
216
|
+
console.error(' Or use free DuckDuckGo search (default, no key needed).');
|
|
217
|
+
}
|
|
218
|
+
else if (msg.includes('timeout') || msg.includes('timed out')) {
|
|
219
|
+
console.error('\n💡 Hint: Search timed out. Try a more specific query or try again.');
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
console.error('\nError: Unknown error occurred');
|
|
224
|
+
}
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
// ── sites command — list all supported site templates ────────────────────
|
|
229
|
+
program
|
|
230
|
+
.command('sites')
|
|
231
|
+
.description('List all sites supported by "webpeel search --site <site>"')
|
|
232
|
+
.option('--json', 'Output as JSON')
|
|
233
|
+
.option('--category <cat>', 'Filter by category (shopping, social, tech, jobs, general, real-estate, food)')
|
|
234
|
+
.action(async (options) => {
|
|
235
|
+
const { listSites } = await import('../../core/site-search.js');
|
|
236
|
+
let sites = listSites();
|
|
237
|
+
if (options.category) {
|
|
238
|
+
sites = sites.filter(s => s.category === options.category);
|
|
239
|
+
}
|
|
240
|
+
if (options.json) {
|
|
241
|
+
await writeStdout(JSON.stringify(sites, null, 2) + '\n');
|
|
242
|
+
process.exit(0);
|
|
243
|
+
}
|
|
244
|
+
// Group by category for pretty output
|
|
245
|
+
const byCategory = new Map();
|
|
246
|
+
for (const site of sites) {
|
|
247
|
+
if (!byCategory.has(site.category))
|
|
248
|
+
byCategory.set(site.category, []);
|
|
249
|
+
byCategory.get(site.category).push(site);
|
|
250
|
+
}
|
|
251
|
+
const categoryOrder = ['shopping', 'general', 'social', 'tech', 'jobs', 'real-estate', 'food'];
|
|
252
|
+
const sortedCategories = categoryOrder.filter(c => byCategory.has(c));
|
|
253
|
+
console.log('\nWebPeel Site-Aware Search — supported sites\n');
|
|
254
|
+
console.log('Usage: webpeel search --site <id> "<query>"\n');
|
|
255
|
+
for (const cat of sortedCategories) {
|
|
256
|
+
const catSites = byCategory.get(cat);
|
|
257
|
+
const label = cat.charAt(0).toUpperCase() + cat.slice(1);
|
|
258
|
+
console.log(` ${label}:`);
|
|
259
|
+
for (const s of catSites) {
|
|
260
|
+
console.log(` ${s.id.padEnd(16)} ${s.name}`);
|
|
261
|
+
}
|
|
262
|
+
console.log('');
|
|
263
|
+
}
|
|
264
|
+
process.exit(0);
|
|
265
|
+
});
|
|
266
|
+
// ── batch command ─────────────────────────────────────────────────────────
|
|
267
|
+
program
|
|
268
|
+
.command('batch [file]')
|
|
269
|
+
.description('Fetch multiple URLs from file or stdin pipe')
|
|
270
|
+
.option('-c, --concurrency <n>', 'Max concurrent fetches (default: 3)', '3')
|
|
271
|
+
.option('-o, --output <dir>', 'Output directory (one file per URL)')
|
|
272
|
+
.option('--json', 'Output as JSON array')
|
|
273
|
+
.option('-s, --silent', 'Silent mode')
|
|
274
|
+
.option('-r, --render', 'Use headless browser')
|
|
275
|
+
.option('--selector <css>', 'CSS selector to extract')
|
|
276
|
+
.action(async (file, options) => {
|
|
277
|
+
const isJson = options.json;
|
|
278
|
+
const isSilent = options.silent;
|
|
279
|
+
const shouldRender = options.render;
|
|
280
|
+
const selector = options.selector;
|
|
281
|
+
// Check usage quota
|
|
282
|
+
const usageCheck = await checkUsage();
|
|
283
|
+
if (!usageCheck.allowed) {
|
|
284
|
+
console.error(usageCheck.message);
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
const spinner = isSilent ? null : ora('Loading URLs...').start();
|
|
288
|
+
try {
|
|
289
|
+
// Read URLs from file or stdin
|
|
290
|
+
let urls;
|
|
291
|
+
if (file) {
|
|
292
|
+
// Read from file
|
|
293
|
+
try {
|
|
294
|
+
const content = readFileSync(file, 'utf-8');
|
|
295
|
+
urls = content.split('\n')
|
|
296
|
+
.map(line => line.trim())
|
|
297
|
+
.filter(line => line && !line.startsWith('#'));
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
throw new Error(`Failed to read file: ${file}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else if (!process.stdin.isTTY) {
|
|
304
|
+
// Read from stdin pipe
|
|
305
|
+
const chunks = [];
|
|
306
|
+
for await (const chunk of process.stdin) {
|
|
307
|
+
chunks.push(chunk);
|
|
308
|
+
}
|
|
309
|
+
const content = Buffer.concat(chunks).toString('utf-8');
|
|
310
|
+
urls = content.split('\n')
|
|
311
|
+
.map(line => line.trim())
|
|
312
|
+
.filter(line => line && !line.startsWith('#'));
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
throw new Error('Provide a file path or pipe URLs via stdin.\n Example: cat urls.txt | webpeel batch');
|
|
316
|
+
}
|
|
317
|
+
if (urls.length === 0) {
|
|
318
|
+
throw new Error('No URLs found in file');
|
|
319
|
+
}
|
|
320
|
+
if (spinner) {
|
|
321
|
+
spinner.text = `Fetching ${urls.length} URLs (concurrency: ${options.concurrency})...`;
|
|
322
|
+
}
|
|
323
|
+
// Batch fetch
|
|
324
|
+
const results = await peelBatch(urls, {
|
|
325
|
+
concurrency: parseInt(options.concurrency) || 3,
|
|
326
|
+
render: shouldRender,
|
|
327
|
+
selector: selector,
|
|
328
|
+
});
|
|
329
|
+
if (spinner) {
|
|
330
|
+
const successCount = results.filter(r => 'content' in r).length;
|
|
331
|
+
spinner.succeed(`Completed: ${successCount}/${urls.length} successful`);
|
|
332
|
+
}
|
|
333
|
+
// Show usage footer for free/anonymous users
|
|
334
|
+
if (usageCheck.usageInfo && !isSilent) {
|
|
335
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, false);
|
|
336
|
+
}
|
|
337
|
+
// Output results
|
|
338
|
+
if (isJson) {
|
|
339
|
+
const jsonStr = JSON.stringify(results, null, 2);
|
|
340
|
+
await new Promise((resolve, reject) => {
|
|
341
|
+
process.stdout.write(jsonStr + '\n', (err) => {
|
|
342
|
+
if (err)
|
|
343
|
+
reject(err);
|
|
344
|
+
else
|
|
345
|
+
resolve();
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
else if (options.output) {
|
|
350
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
351
|
+
const { join } = await import('path');
|
|
352
|
+
// Create output directory
|
|
353
|
+
mkdirSync(options.output, { recursive: true });
|
|
354
|
+
results.forEach((result, i) => {
|
|
355
|
+
const urlObj = new URL(urls[i]);
|
|
356
|
+
const filename = `${i + 1}_${urlObj.hostname.replace(/[^a-z0-9]/gi, '_')}.md`;
|
|
357
|
+
const filepath = join(options.output, filename);
|
|
358
|
+
if ('content' in result) {
|
|
359
|
+
writeFileSync(filepath, result.content);
|
|
360
|
+
}
|
|
361
|
+
else {
|
|
362
|
+
writeFileSync(filepath, `Error: ${result.error}`);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
if (!isSilent) {
|
|
366
|
+
console.log(`\nResults saved to: ${options.output}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
// Print results to stdout
|
|
371
|
+
results.forEach((result, i) => {
|
|
372
|
+
console.log(`\n=== ${urls[i]} ===\n`);
|
|
373
|
+
if ('content' in result) {
|
|
374
|
+
console.log(result.content.slice(0, 500) + '...');
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
console.log(`Error: ${result.error}`);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
await cleanup();
|
|
382
|
+
process.exit(0);
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
if (spinner) {
|
|
386
|
+
spinner.fail('Batch fetch failed');
|
|
387
|
+
}
|
|
388
|
+
if (error instanceof Error) {
|
|
389
|
+
console.error(`\nError: ${error.message}`);
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
console.error('\nError: Unknown error occurred');
|
|
393
|
+
}
|
|
394
|
+
await cleanup();
|
|
395
|
+
process.exit(1);
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
// ── crawl command ─────────────────────────────────────────────────────────
|
|
399
|
+
program
|
|
400
|
+
.command('crawl <url>')
|
|
401
|
+
.description('Crawl a website starting from a URL')
|
|
402
|
+
.option('--max-pages <number>', 'Maximum number of pages to crawl (default: 10, max: 100)', (v) => parseInt(v, 10), 10)
|
|
403
|
+
.option('--max-depth <number>', 'Maximum depth to crawl (default: 2, max: 5)', (v) => parseInt(v, 10), 2)
|
|
404
|
+
.option('--allowed-domains <domains...>', 'Only crawl these domains (default: same as starting URL)')
|
|
405
|
+
.option('--exclude <patterns...>', 'Exclude URLs matching these regex patterns')
|
|
406
|
+
.option('--ignore-robots', 'Ignore robots.txt (default: respect robots.txt)')
|
|
407
|
+
.option('--rate-limit <ms>', 'Rate limit between requests in ms (default: 1000)', (v) => parseInt(v, 10), 1000)
|
|
408
|
+
.option('-r, --render', 'Use headless browser for all pages')
|
|
409
|
+
.option('--stealth', 'Use stealth mode for all pages')
|
|
410
|
+
.option('-s, --silent', 'Silent mode (no spinner)')
|
|
411
|
+
.option('--json', 'Output as JSON')
|
|
412
|
+
.option('--resume', 'Resume an interrupted crawl from its last checkpoint')
|
|
413
|
+
.action(async (url, options) => {
|
|
414
|
+
// Check usage quota
|
|
415
|
+
const usageCheck = await checkUsage();
|
|
416
|
+
if (!usageCheck.allowed) {
|
|
417
|
+
console.error(usageCheck.message);
|
|
418
|
+
process.exit(1);
|
|
419
|
+
}
|
|
420
|
+
const { crawl } = await import('../../core/crawler.js');
|
|
421
|
+
const spinner = options.silent ? null : ora('Crawling...').start();
|
|
422
|
+
try {
|
|
423
|
+
const results = await crawl(url, {
|
|
424
|
+
maxPages: options.maxPages,
|
|
425
|
+
maxDepth: options.maxDepth,
|
|
426
|
+
allowedDomains: options.allowedDomains,
|
|
427
|
+
excludePatterns: options.exclude,
|
|
428
|
+
respectRobotsTxt: !options.ignoreRobots,
|
|
429
|
+
rateLimitMs: options.rateLimit,
|
|
430
|
+
render: options.render || false,
|
|
431
|
+
stealth: options.stealth || false,
|
|
432
|
+
resume: options.resume || false,
|
|
433
|
+
});
|
|
434
|
+
if (spinner) {
|
|
435
|
+
spinner.succeed(`Crawled ${results.length} pages`);
|
|
436
|
+
}
|
|
437
|
+
// Show usage footer for free/anonymous users
|
|
438
|
+
if (usageCheck.usageInfo && !options.silent) {
|
|
439
|
+
showUsageFooter(usageCheck.usageInfo, usageCheck.isAnonymous || false, options.stealth || false);
|
|
440
|
+
}
|
|
441
|
+
if (options.json) {
|
|
442
|
+
console.log(JSON.stringify({ pages: results, count: results.length }, null, 2));
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
results.forEach((result, i) => {
|
|
446
|
+
console.log(`\n${'='.repeat(60)}`);
|
|
447
|
+
console.log(`[${i + 1}/${results.length}] ${result.title}`);
|
|
448
|
+
console.log(`URL: ${result.url}`);
|
|
449
|
+
console.log(`Depth: ${result.depth}${result.parent ? ` (from: ${result.parent})` : ''}`);
|
|
450
|
+
console.log(`Links found: ${result.links.length}`);
|
|
451
|
+
console.log(`Elapsed: ${result.elapsed}ms`);
|
|
452
|
+
if (result.error) {
|
|
453
|
+
console.log(`ERROR: ${result.error}`);
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
console.log(`\n${result.markdown.slice(0, 500)}${result.markdown.length > 500 ? '...' : ''}`);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
await cleanup();
|
|
461
|
+
process.exit(0);
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
if (spinner) {
|
|
465
|
+
spinner.fail('Crawl failed');
|
|
466
|
+
}
|
|
467
|
+
if (error instanceof Error) {
|
|
468
|
+
console.error(`\nError: ${error.message}`);
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
console.error('\nError: Unknown error occurred');
|
|
472
|
+
}
|
|
473
|
+
await cleanup();
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
// ── map command ───────────────────────────────────────────────────────────
|
|
478
|
+
program
|
|
479
|
+
.command('map <url>')
|
|
480
|
+
.description('Discover all URLs on a domain (sitemap + crawl)')
|
|
481
|
+
.option('--no-sitemap', 'Skip sitemap.xml discovery')
|
|
482
|
+
.option('--no-crawl', 'Skip homepage crawl')
|
|
483
|
+
.option('--max <n>', 'Maximum URLs to discover (default: 5000)', (v) => parseInt(v, 10), 5000)
|
|
484
|
+
.option('--include <patterns...>', 'Include only URLs matching these regex patterns')
|
|
485
|
+
.option('--exclude <patterns...>', 'Exclude URLs matching these regex patterns')
|
|
486
|
+
.option('--json', 'Output as JSON')
|
|
487
|
+
.option('-s, --silent', 'Silent mode')
|
|
488
|
+
.action(async (url, options) => {
|
|
489
|
+
const { mapDomain } = await import('../../core/map.js');
|
|
490
|
+
const spinner = options.silent ? null : ora('Discovering URLs...').start();
|
|
491
|
+
try {
|
|
492
|
+
const result = await mapDomain(url, {
|
|
493
|
+
useSitemap: options.sitemap !== false,
|
|
494
|
+
crawlHomepage: options.crawl !== false,
|
|
495
|
+
maxUrls: options.max,
|
|
496
|
+
includePatterns: options.include,
|
|
497
|
+
excludePatterns: options.exclude,
|
|
498
|
+
});
|
|
499
|
+
if (spinner)
|
|
500
|
+
spinner.succeed(`Found ${result.total} URLs in ${result.elapsed}ms`);
|
|
501
|
+
if (options.json) {
|
|
502
|
+
console.log(JSON.stringify(result, null, 2));
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
for (const u of result.urls) {
|
|
506
|
+
console.log(u);
|
|
507
|
+
}
|
|
508
|
+
if (!options.silent) {
|
|
509
|
+
console.error(`\nTotal: ${result.total} URLs`);
|
|
510
|
+
if (result.sitemapUrls.length > 0) {
|
|
511
|
+
console.error(`Sitemaps used: ${result.sitemapUrls.join(', ')}`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
process.exit(0);
|
|
516
|
+
}
|
|
517
|
+
catch (error) {
|
|
518
|
+
if (spinner)
|
|
519
|
+
spinner.fail('URL discovery failed');
|
|
520
|
+
console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
521
|
+
process.exit(1);
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI utilities — config, API client, output formatting, helpers.
|
|
3
|
+
* Imported by all command modules.
|
|
4
|
+
*/
|
|
5
|
+
import type { PeelResult, PeelEnvelope, PageAction, PeelOptions } from '../types.js';
|
|
6
|
+
export declare const cliVersion: string;
|
|
7
|
+
export declare const VERB_ALIASES: Set<string>;
|
|
8
|
+
export declare function checkForUpdates(): Promise<void>;
|
|
9
|
+
export declare const NO_COLOR: boolean;
|
|
10
|
+
export declare const bold: (s: string) => string;
|
|
11
|
+
export declare const dim: (s: string) => string;
|
|
12
|
+
export declare const cyan: (s: string) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Parse action strings into PageAction array
|
|
15
|
+
* Formats:
|
|
16
|
+
* click:.selector — click an element
|
|
17
|
+
* type:.selector=text — type text into an input
|
|
18
|
+
* fill:.selector=text — fill an input (replaces existing value)
|
|
19
|
+
* scroll:down:500 — scroll direction + amount
|
|
20
|
+
* scroll:bottom — scroll to bottom (legacy)
|
|
21
|
+
* scroll:top — scroll to top (legacy)
|
|
22
|
+
* wait:2000 — wait N ms
|
|
23
|
+
* press:Enter — press a keyboard key
|
|
24
|
+
* hover:.selector — hover over an element
|
|
25
|
+
* waitFor:.selector — wait for a selector to appear
|
|
26
|
+
* select:.selector=value — select dropdown option
|
|
27
|
+
* screenshot — take a screenshot
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseActions(actionStrings: string[]): PageAction[];
|
|
30
|
+
/**
|
|
31
|
+
* Format an error with actionable suggestions based on error type
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatError(error: Error, _url: string, options: any): string;
|
|
34
|
+
/**
|
|
35
|
+
* Routes ALL fetch requests through the WebPeel API.
|
|
36
|
+
* CLI is a pure API client — no local Playwright.
|
|
37
|
+
*/
|
|
38
|
+
export declare function fetchViaApi(url: string, options: PeelOptions, apiKey: string, apiUrl: string): Promise<any>;
|
|
39
|
+
/**
|
|
40
|
+
* Reconstruct the standard Commander help layout for --help-all and subcommands.
|
|
41
|
+
* This mirrors Commander's own default formatHelp() so subcommand help keeps working.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildCommanderHelp(cmd: any, helper: any): string;
|
|
44
|
+
/**
|
|
45
|
+
* Condensed, Anthropic-style help for the root command (default --help).
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildCondensedHelp(): string;
|
|
48
|
+
/**
|
|
49
|
+
* Format a past Date relative to now (e.g. "2h ago", "5m ago").
|
|
50
|
+
*/
|
|
51
|
+
export declare function formatRelativeTime(past: Date): string;
|
|
52
|
+
export declare function classifyErrorCode(error: unknown): string;
|
|
53
|
+
export interface OutputExtra {
|
|
54
|
+
/** Was this result served from the local cache? */
|
|
55
|
+
cached?: boolean;
|
|
56
|
+
/** Structured listings data (from --extract-all) */
|
|
57
|
+
structured?: Record<string, unknown>[];
|
|
58
|
+
/** Was content distilled/truncated to fit a budget? */
|
|
59
|
+
truncated?: boolean;
|
|
60
|
+
/** Total items available before budget limiting (listings only) */
|
|
61
|
+
totalAvailable?: number;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build a unified PeelEnvelope from a PeelResult.
|
|
65
|
+
*
|
|
66
|
+
* All existing PeelResult fields are spread first (backward compatibility),
|
|
67
|
+
* then canonical envelope fields override/extend them.
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildEnvelope(result: PeelResult, extra: OutputExtra): PeelEnvelope & Record<string, unknown>;
|
|
70
|
+
export declare function outputResult(result: PeelResult, options: any, extra?: OutputExtra): Promise<void>;
|
|
71
|
+
export declare function writeStdout(data: string): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Convert an array of listing items to CSV.
|
|
74
|
+
*/
|
|
75
|
+
export declare function formatListingsCsv(items: Array<Record<string, string | undefined>>): string;
|
|
76
|
+
/**
|
|
77
|
+
* Normalise the result of --extract (which may be a flat object or contain
|
|
78
|
+
* arrays) into an array of row objects suitable for CSV / table rendering.
|
|
79
|
+
*/
|
|
80
|
+
export declare function normaliseExtractedToRows(extracted: Record<string, any>): Array<Record<string, string | undefined>>;
|
|
81
|
+
/** Helper function to extract colors from content */
|
|
82
|
+
export declare function extractColors(content: string): string[];
|
|
83
|
+
/** Helper function to extract font information */
|
|
84
|
+
export declare function extractFonts(content: string): string[];
|