@iflow-mcp/jakeliume-webpeel 0.22.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/LICENSE +15 -0
- package/README.md +313 -0
- package/dist/cache.d.ts +30 -0
- package/dist/cache.js +139 -0
- package/dist/cli/commands/auth.d.ts +5 -0
- package/dist/cli/commands/auth.js +411 -0
- package/dist/cli/commands/doctor.d.ts +37 -0
- package/dist/cli/commands/doctor.js +371 -0
- package/dist/cli/commands/fetch.d.ts +6 -0
- package/dist/cli/commands/fetch.js +1345 -0
- package/dist/cli/commands/guide.d.ts +2 -0
- package/dist/cli/commands/guide.js +183 -0
- package/dist/cli/commands/interact.d.ts +5 -0
- package/dist/cli/commands/interact.js +840 -0
- package/dist/cli/commands/jobs.d.ts +5 -0
- package/dist/cli/commands/jobs.js +997 -0
- package/dist/cli/commands/monitor.d.ts +12 -0
- package/dist/cli/commands/monitor.js +197 -0
- package/dist/cli/commands/observe.d.ts +12 -0
- package/dist/cli/commands/observe.js +158 -0
- package/dist/cli/commands/screenshot.d.ts +5 -0
- package/dist/cli/commands/screenshot.js +282 -0
- package/dist/cli/commands/search.d.ts +5 -0
- package/dist/cli/commands/search.js +1021 -0
- package/dist/cli/commands/setup.d.ts +13 -0
- package/dist/cli/commands/setup.js +244 -0
- package/dist/cli/commands/skill.d.ts +15 -0
- package/dist/cli/commands/skill.js +195 -0
- package/dist/cli/utils.d.ts +84 -0
- package/dist/cli/utils.js +806 -0
- package/dist/cli-auth.d.ts +75 -0
- package/dist/cli-auth.js +369 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.js +99 -0
- package/dist/core/actions.d.ts +69 -0
- package/dist/core/actions.js +495 -0
- package/dist/core/agent.d.ts +98 -0
- package/dist/core/agent.js +558 -0
- package/dist/core/answer.d.ts +42 -0
- package/dist/core/answer.js +395 -0
- package/dist/core/application-tracker.d.ts +84 -0
- package/dist/core/application-tracker.js +184 -0
- package/dist/core/apply.d.ts +162 -0
- package/dist/core/apply.js +816 -0
- package/dist/core/auth-detection.d.ts +35 -0
- package/dist/core/auth-detection.js +358 -0
- package/dist/core/auto-extract.d.ts +82 -0
- package/dist/core/auto-extract.js +604 -0
- package/dist/core/auto-interact.d.ts +23 -0
- package/dist/core/auto-interact.js +246 -0
- package/dist/core/bm25-filter.d.ts +66 -0
- package/dist/core/bm25-filter.js +288 -0
- package/dist/core/branding.d.ts +54 -0
- package/dist/core/branding.js +234 -0
- package/dist/core/browser-fetch.d.ts +323 -0
- package/dist/core/browser-fetch.js +1600 -0
- package/dist/core/browser-pool.d.ts +91 -0
- package/dist/core/browser-pool.js +550 -0
- package/dist/core/budget.d.ts +42 -0
- package/dist/core/budget.js +324 -0
- package/dist/core/business-intel.d.ts +47 -0
- package/dist/core/business-intel.js +279 -0
- package/dist/core/cache.d.ts +13 -0
- package/dist/core/cache.js +121 -0
- package/dist/core/cf-worker-proxy.d.ts +32 -0
- package/dist/core/cf-worker-proxy.js +87 -0
- package/dist/core/challenge-detection.d.ts +26 -0
- package/dist/core/challenge-detection.js +468 -0
- package/dist/core/change-tracking.d.ts +75 -0
- package/dist/core/change-tracking.js +276 -0
- package/dist/core/chunker.d.ts +46 -0
- package/dist/core/chunker.js +249 -0
- package/dist/core/chunking.d.ts +42 -0
- package/dist/core/chunking.js +181 -0
- package/dist/core/circuit-breaker.d.ts +44 -0
- package/dist/core/circuit-breaker.js +85 -0
- package/dist/core/content-pruner.d.ts +47 -0
- package/dist/core/content-pruner.js +425 -0
- package/dist/core/cookie-cache.d.ts +60 -0
- package/dist/core/cookie-cache.js +163 -0
- package/dist/core/crawl-checkpoint.d.ts +54 -0
- package/dist/core/crawl-checkpoint.js +104 -0
- package/dist/core/crawler.d.ts +84 -0
- package/dist/core/crawler.js +349 -0
- package/dist/core/cross-verify.d.ts +27 -0
- package/dist/core/cross-verify.js +93 -0
- package/dist/core/deep-fetch.d.ts +74 -0
- package/dist/core/deep-fetch.js +405 -0
- package/dist/core/deep-research.d.ts +141 -0
- package/dist/core/deep-research.js +972 -0
- package/dist/core/design-analysis.d.ts +70 -0
- package/dist/core/design-analysis.js +490 -0
- package/dist/core/design-compare.d.ts +38 -0
- package/dist/core/design-compare.js +264 -0
- package/dist/core/diff.d.ts +61 -0
- package/dist/core/diff.js +289 -0
- package/dist/core/dns-cache.d.ts +20 -0
- package/dist/core/dns-cache.js +198 -0
- package/dist/core/documents.d.ts +23 -0
- package/dist/core/documents.js +123 -0
- package/dist/core/domain-memory.d.ts +66 -0
- package/dist/core/domain-memory.js +163 -0
- package/dist/core/domain-verify.d.ts +40 -0
- package/dist/core/domain-verify.js +379 -0
- package/dist/core/engine-ranker.d.ts +112 -0
- package/dist/core/engine-ranker.js +395 -0
- package/dist/core/extract-inline.d.ts +38 -0
- package/dist/core/extract-inline.js +215 -0
- package/dist/core/extract-listings.d.ts +38 -0
- package/dist/core/extract-listings.js +461 -0
- package/dist/core/extract.d.ts +9 -0
- package/dist/core/extract.js +139 -0
- package/dist/core/fetch-cache.d.ts +57 -0
- package/dist/core/fetch-cache.js +95 -0
- package/dist/core/fetcher.d.ts +13 -0
- package/dist/core/fetcher.js +12 -0
- package/dist/core/google-cache.d.ts +29 -0
- package/dist/core/google-cache.js +180 -0
- package/dist/core/google-serp-parser.d.ts +82 -0
- package/dist/core/google-serp-parser.js +287 -0
- package/dist/core/hotel-search.d.ts +122 -0
- package/dist/core/hotel-search.js +382 -0
- package/dist/core/http-fetch.d.ts +72 -0
- package/dist/core/http-fetch.js +820 -0
- package/dist/core/human.d.ts +175 -0
- package/dist/core/human.js +680 -0
- package/dist/core/image-caption.d.ts +44 -0
- package/dist/core/image-caption.js +271 -0
- package/dist/core/jobs.d.ts +75 -0
- package/dist/core/jobs.js +634 -0
- package/dist/core/json-ld.d.ts +15 -0
- package/dist/core/json-ld.js +617 -0
- package/dist/core/language-detect.d.ts +18 -0
- package/dist/core/language-detect.js +135 -0
- package/dist/core/links.d.ts +10 -0
- package/dist/core/links.js +44 -0
- package/dist/core/llm-extract.d.ts +71 -0
- package/dist/core/llm-extract.js +507 -0
- package/dist/core/llm-provider.d.ts +100 -0
- package/dist/core/llm-provider.js +702 -0
- package/dist/core/local-search.d.ts +60 -0
- package/dist/core/local-search.js +308 -0
- package/dist/core/logger.d.ts +28 -0
- package/dist/core/logger.js +104 -0
- package/dist/core/map.d.ts +33 -0
- package/dist/core/map.js +127 -0
- package/dist/core/markdown.d.ts +92 -0
- package/dist/core/markdown.js +809 -0
- package/dist/core/metadata.d.ts +34 -0
- package/dist/core/metadata.js +422 -0
- package/dist/core/observe.d.ts +113 -0
- package/dist/core/observe.js +395 -0
- package/dist/core/ocr.d.ts +12 -0
- package/dist/core/ocr.js +33 -0
- package/dist/core/paginate.d.ts +31 -0
- package/dist/core/paginate.js +106 -0
- package/dist/core/pdf.d.ts +8 -0
- package/dist/core/pdf.js +25 -0
- package/dist/core/peel-tls.d.ts +25 -0
- package/dist/core/peel-tls.js +220 -0
- package/dist/core/pipeline.d.ts +132 -0
- package/dist/core/pipeline.js +1666 -0
- package/dist/core/profiles.d.ts +61 -0
- package/dist/core/profiles.js +350 -0
- package/dist/core/prompt-guard.d.ts +30 -0
- package/dist/core/prompt-guard.js +119 -0
- package/dist/core/proxy-config.d.ts +90 -0
- package/dist/core/proxy-config.js +172 -0
- package/dist/core/quick-answer.d.ts +53 -0
- package/dist/core/quick-answer.js +833 -0
- package/dist/core/rate-governor.d.ts +80 -0
- package/dist/core/rate-governor.js +238 -0
- package/dist/core/readability.d.ts +57 -0
- package/dist/core/readability.js +533 -0
- package/dist/core/research.d.ts +66 -0
- package/dist/core/research.js +270 -0
- package/dist/core/retry.d.ts +60 -0
- package/dist/core/retry.js +119 -0
- package/dist/core/safe-browsing.d.ts +30 -0
- package/dist/core/safe-browsing.js +206 -0
- package/dist/core/schema-extraction.d.ts +66 -0
- package/dist/core/schema-extraction.js +352 -0
- package/dist/core/schema-postprocess.d.ts +32 -0
- package/dist/core/schema-postprocess.js +469 -0
- package/dist/core/schema-templates.d.ts +19 -0
- package/dist/core/schema-templates.js +143 -0
- package/dist/core/screenshot.d.ts +224 -0
- package/dist/core/screenshot.js +207 -0
- package/dist/core/search-engines.d.ts +25 -0
- package/dist/core/search-engines.js +182 -0
- package/dist/core/search-provider.d.ts +243 -0
- package/dist/core/search-provider.js +1629 -0
- package/dist/core/searxng-provider.d.ts +35 -0
- package/dist/core/searxng-provider.js +105 -0
- package/dist/core/selective-evidence.d.ts +151 -0
- package/dist/core/selective-evidence.js +389 -0
- package/dist/core/site-search.d.ts +44 -0
- package/dist/core/site-search.js +252 -0
- package/dist/core/sitemap.d.ts +23 -0
- package/dist/core/sitemap.js +105 -0
- package/dist/core/source-credibility.d.ts +29 -0
- package/dist/core/source-credibility.js +584 -0
- package/dist/core/source-scoring.d.ts +166 -0
- package/dist/core/source-scoring.js +396 -0
- package/dist/core/stemmer.d.ts +38 -0
- package/dist/core/stemmer.js +509 -0
- package/dist/core/strategies.d.ts +104 -0
- package/dist/core/strategies.js +1044 -0
- package/dist/core/strategy-hooks.d.ts +145 -0
- package/dist/core/strategy-hooks.js +74 -0
- package/dist/core/structured-extract.d.ts +43 -0
- package/dist/core/structured-extract.js +550 -0
- package/dist/core/summarize.d.ts +17 -0
- package/dist/core/summarize.js +78 -0
- package/dist/core/synonyms.d.ts +42 -0
- package/dist/core/synonyms.js +184 -0
- package/dist/core/system-monitor.d.ts +61 -0
- package/dist/core/system-monitor.js +133 -0
- package/dist/core/table-format.d.ts +30 -0
- package/dist/core/table-format.js +146 -0
- package/dist/core/threat-feeds.d.ts +23 -0
- package/dist/core/threat-feeds.js +104 -0
- package/dist/core/timing.d.ts +21 -0
- package/dist/core/timing.js +33 -0
- package/dist/core/transcript-export.d.ts +47 -0
- package/dist/core/transcript-export.js +107 -0
- package/dist/core/user-agents.d.ts +82 -0
- package/dist/core/user-agents.js +239 -0
- package/dist/core/vertical-search.d.ts +54 -0
- package/dist/core/vertical-search.js +158 -0
- package/dist/core/watch-manager.d.ts +175 -0
- package/dist/core/watch-manager.js +416 -0
- package/dist/core/watch.d.ts +101 -0
- package/dist/core/watch.js +389 -0
- package/dist/core/youtube.d.ts +130 -0
- package/dist/core/youtube.js +1175 -0
- package/dist/ee/challenge-re-export.d.ts +1 -0
- package/dist/ee/challenge-re-export.js +1 -0
- package/dist/ee/challenge-solver.d.ts +72 -0
- package/dist/ee/challenge-solver.js +720 -0
- package/dist/ee/domain-extractors.d.ts +8 -0
- package/dist/ee/domain-extractors.js +8 -0
- package/dist/ee/domain-intel.d.ts +16 -0
- package/dist/ee/domain-intel.js +133 -0
- package/dist/ee/extractors/allrecipes.d.ts +2 -0
- package/dist/ee/extractors/allrecipes.js +120 -0
- package/dist/ee/extractors/amazon.d.ts +2 -0
- package/dist/ee/extractors/amazon.js +78 -0
- package/dist/ee/extractors/arxiv.d.ts +2 -0
- package/dist/ee/extractors/arxiv.js +137 -0
- package/dist/ee/extractors/bestbuy.d.ts +2 -0
- package/dist/ee/extractors/bestbuy.js +78 -0
- package/dist/ee/extractors/carscom.d.ts +2 -0
- package/dist/ee/extractors/carscom.js +121 -0
- package/dist/ee/extractors/coingecko.d.ts +2 -0
- package/dist/ee/extractors/coingecko.js +134 -0
- package/dist/ee/extractors/craigslist.d.ts +2 -0
- package/dist/ee/extractors/craigslist.js +92 -0
- package/dist/ee/extractors/devto.d.ts +2 -0
- package/dist/ee/extractors/devto.js +135 -0
- package/dist/ee/extractors/ebay.d.ts +2 -0
- package/dist/ee/extractors/ebay.js +90 -0
- package/dist/ee/extractors/espn.d.ts +2 -0
- package/dist/ee/extractors/espn.js +260 -0
- package/dist/ee/extractors/etsy.d.ts +2 -0
- package/dist/ee/extractors/etsy.js +52 -0
- package/dist/ee/extractors/facebook.d.ts +2 -0
- package/dist/ee/extractors/facebook.js +46 -0
- package/dist/ee/extractors/github.d.ts +2 -0
- package/dist/ee/extractors/github.js +196 -0
- package/dist/ee/extractors/google-flights.d.ts +2 -0
- package/dist/ee/extractors/google-flights.js +176 -0
- package/dist/ee/extractors/hackernews.d.ts +2 -0
- package/dist/ee/extractors/hackernews.js +147 -0
- package/dist/ee/extractors/imdb.d.ts +2 -0
- package/dist/ee/extractors/imdb.js +172 -0
- package/dist/ee/extractors/index.d.ts +26 -0
- package/dist/ee/extractors/index.js +247 -0
- package/dist/ee/extractors/instagram.d.ts +2 -0
- package/dist/ee/extractors/instagram.js +102 -0
- package/dist/ee/extractors/kalshi.d.ts +2 -0
- package/dist/ee/extractors/kalshi.js +121 -0
- package/dist/ee/extractors/kayak-cars.d.ts +2 -0
- package/dist/ee/extractors/kayak-cars.js +270 -0
- package/dist/ee/extractors/linkedin.d.ts +2 -0
- package/dist/ee/extractors/linkedin.js +113 -0
- package/dist/ee/extractors/medium.d.ts +2 -0
- package/dist/ee/extractors/medium.js +130 -0
- package/dist/ee/extractors/news.d.ts +4 -0
- package/dist/ee/extractors/news.js +173 -0
- package/dist/ee/extractors/npm.d.ts +2 -0
- package/dist/ee/extractors/npm.js +86 -0
- package/dist/ee/extractors/pdf.d.ts +2 -0
- package/dist/ee/extractors/pdf.js +108 -0
- package/dist/ee/extractors/pinterest.d.ts +2 -0
- package/dist/ee/extractors/pinterest.js +34 -0
- package/dist/ee/extractors/polymarket.d.ts +2 -0
- package/dist/ee/extractors/polymarket.js +358 -0
- package/dist/ee/extractors/producthunt.d.ts +2 -0
- package/dist/ee/extractors/producthunt.js +88 -0
- package/dist/ee/extractors/pubmed.d.ts +2 -0
- package/dist/ee/extractors/pubmed.js +162 -0
- package/dist/ee/extractors/pypi.d.ts +2 -0
- package/dist/ee/extractors/pypi.js +80 -0
- package/dist/ee/extractors/reddit.d.ts +2 -0
- package/dist/ee/extractors/reddit.js +438 -0
- package/dist/ee/extractors/redfin.d.ts +2 -0
- package/dist/ee/extractors/redfin.js +156 -0
- package/dist/ee/extractors/semanticscholar.d.ts +2 -0
- package/dist/ee/extractors/semanticscholar.js +131 -0
- package/dist/ee/extractors/shared.d.ts +12 -0
- package/dist/ee/extractors/shared.js +76 -0
- package/dist/ee/extractors/soundcloud.d.ts +2 -0
- package/dist/ee/extractors/soundcloud.js +34 -0
- package/dist/ee/extractors/sportsbetting.d.ts +2 -0
- package/dist/ee/extractors/sportsbetting.js +37 -0
- package/dist/ee/extractors/spotify.d.ts +2 -0
- package/dist/ee/extractors/spotify.js +34 -0
- package/dist/ee/extractors/stackoverflow.d.ts +2 -0
- package/dist/ee/extractors/stackoverflow.js +61 -0
- package/dist/ee/extractors/substack.d.ts +2 -0
- package/dist/ee/extractors/substack.js +115 -0
- package/dist/ee/extractors/substackroot.d.ts +2 -0
- package/dist/ee/extractors/substackroot.js +46 -0
- package/dist/ee/extractors/tiktok.d.ts +2 -0
- package/dist/ee/extractors/tiktok.js +29 -0
- package/dist/ee/extractors/tradingview.d.ts +2 -0
- package/dist/ee/extractors/tradingview.js +182 -0
- package/dist/ee/extractors/twitch.d.ts +2 -0
- package/dist/ee/extractors/twitch.js +36 -0
- package/dist/ee/extractors/twitter.d.ts +2 -0
- package/dist/ee/extractors/twitter.js +327 -0
- package/dist/ee/extractors/types.d.ts +14 -0
- package/dist/ee/extractors/types.js +1 -0
- package/dist/ee/extractors/walmart.d.ts +2 -0
- package/dist/ee/extractors/walmart.js +50 -0
- package/dist/ee/extractors/weather.d.ts +2 -0
- package/dist/ee/extractors/weather.js +133 -0
- package/dist/ee/extractors/wikipedia.d.ts +4 -0
- package/dist/ee/extractors/wikipedia.js +235 -0
- package/dist/ee/extractors/yelp.d.ts +2 -0
- package/dist/ee/extractors/yelp.js +216 -0
- package/dist/ee/extractors/youtube.d.ts +2 -0
- package/dist/ee/extractors/youtube.js +189 -0
- package/dist/ee/extractors/zillow.d.ts +54 -0
- package/dist/ee/extractors/zillow.js +247 -0
- package/dist/ee/extractors-re-export.d.ts +1 -0
- package/dist/ee/extractors-re-export.js +1 -0
- package/dist/ee/premium-hooks.d.ts +20 -0
- package/dist/ee/premium-hooks.js +50 -0
- package/dist/ee/spa-detection.d.ts +2 -0
- package/dist/ee/spa-detection.js +2 -0
- package/dist/ee/stability.d.ts +4 -0
- package/dist/ee/stability.js +29 -0
- package/dist/ee/swr-cache.d.ts +14 -0
- package/dist/ee/swr-cache.js +34 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +291 -0
- package/dist/integrations/index.d.ts +2 -0
- package/dist/integrations/index.js +2 -0
- package/dist/integrations/langchain.d.ts +64 -0
- package/dist/integrations/langchain.js +115 -0
- package/dist/integrations/llamaindex.d.ts +50 -0
- package/dist/integrations/llamaindex.js +91 -0
- 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 +395 -0
- package/dist/mcp/handlers/extract.d.ts +7 -0
- package/dist/mcp/handlers/extract.js +135 -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 +63 -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 +40 -0
- package/dist/mcp/handlers/monitor.d.ts +5 -0
- package/dist/mcp/handlers/monitor.js +41 -0
- package/dist/mcp/handlers/observe.d.ts +8 -0
- package/dist/mcp/handlers/observe.js +37 -0
- package/dist/mcp/handlers/read.d.ts +6 -0
- package/dist/mcp/handlers/read.js +78 -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 +7 -0
- package/dist/mcp/server.js +108 -0
- package/dist/mcp/smart-router.d.ts +23 -0
- package/dist/mcp/smart-router.js +178 -0
- package/dist/server/app.d.ts +14 -0
- package/dist/server/app.js +632 -0
- package/dist/server/auth-store.d.ts +28 -0
- package/dist/server/auth-store.js +88 -0
- package/dist/server/bull-queues.d.ts +60 -0
- package/dist/server/bull-queues.js +90 -0
- package/dist/server/email-service.d.ts +55 -0
- package/dist/server/email-service.js +291 -0
- package/dist/server/job-queue.d.ts +100 -0
- package/dist/server/job-queue.js +145 -0
- package/dist/server/logger.d.ts +10 -0
- package/dist/server/logger.js +37 -0
- package/dist/server/middleware/audit-log.d.ts +14 -0
- package/dist/server/middleware/audit-log.js +73 -0
- package/dist/server/middleware/auth.d.ts +35 -0
- package/dist/server/middleware/auth.js +225 -0
- package/dist/server/middleware/rate-limit.d.ts +50 -0
- package/dist/server/middleware/rate-limit.js +270 -0
- package/dist/server/middleware/scope-guard.d.ts +25 -0
- package/dist/server/middleware/scope-guard.js +45 -0
- package/dist/server/middleware/url-validator.d.ts +15 -0
- package/dist/server/middleware/url-validator.js +201 -0
- package/dist/server/openapi.yaml +6418 -0
- package/dist/server/pg-auth-store.d.ts +146 -0
- package/dist/server/pg-auth-store.js +576 -0
- package/dist/server/pg-job-queue.d.ts +59 -0
- package/dist/server/pg-job-queue.js +375 -0
- package/dist/server/routes/activity.d.ts +6 -0
- package/dist/server/routes/activity.js +79 -0
- package/dist/server/routes/admin-active.d.ts +7 -0
- package/dist/server/routes/admin-active.js +120 -0
- package/dist/server/routes/admin-stats.d.ts +7 -0
- package/dist/server/routes/admin-stats.js +176 -0
- package/dist/server/routes/agent.d.ts +24 -0
- package/dist/server/routes/agent.js +480 -0
- package/dist/server/routes/answer.d.ts +5 -0
- package/dist/server/routes/answer.js +125 -0
- package/dist/server/routes/ask.d.ts +28 -0
- package/dist/server/routes/ask.js +295 -0
- package/dist/server/routes/batch.d.ts +6 -0
- package/dist/server/routes/batch.js +493 -0
- package/dist/server/routes/cache-warm.d.ts +25 -0
- package/dist/server/routes/cache-warm.js +212 -0
- package/dist/server/routes/cli-usage.d.ts +6 -0
- package/dist/server/routes/cli-usage.js +127 -0
- package/dist/server/routes/compat.d.ts +23 -0
- package/dist/server/routes/compat.js +652 -0
- package/dist/server/routes/crawl.d.ts +13 -0
- package/dist/server/routes/crawl.js +287 -0
- package/dist/server/routes/deep-fetch.d.ts +8 -0
- package/dist/server/routes/deep-fetch.js +57 -0
- package/dist/server/routes/deep-research.d.ts +11 -0
- package/dist/server/routes/deep-research.js +232 -0
- package/dist/server/routes/demo.d.ts +24 -0
- package/dist/server/routes/demo.js +517 -0
- package/dist/server/routes/do.d.ts +8 -0
- package/dist/server/routes/do.js +72 -0
- package/dist/server/routes/extract.d.ts +14 -0
- package/dist/server/routes/extract.js +325 -0
- package/dist/server/routes/feed.d.ts +15 -0
- package/dist/server/routes/feed.js +311 -0
- package/dist/server/routes/fetch-queue.d.ts +13 -0
- package/dist/server/routes/fetch-queue.js +357 -0
- package/dist/server/routes/fetch.d.ts +7 -0
- package/dist/server/routes/fetch.js +1274 -0
- package/dist/server/routes/go.d.ts +14 -0
- package/dist/server/routes/go.js +81 -0
- package/dist/server/routes/health.d.ts +11 -0
- package/dist/server/routes/health.js +141 -0
- package/dist/server/routes/jobs.d.ts +7 -0
- package/dist/server/routes/jobs.js +574 -0
- package/dist/server/routes/map.d.ts +11 -0
- package/dist/server/routes/map.js +116 -0
- package/dist/server/routes/mcp.d.ts +14 -0
- package/dist/server/routes/mcp.js +197 -0
- package/dist/server/routes/metrics.d.ts +37 -0
- package/dist/server/routes/metrics.js +149 -0
- package/dist/server/routes/oauth.d.ts +9 -0
- package/dist/server/routes/oauth.js +396 -0
- package/dist/server/routes/playground.d.ts +17 -0
- package/dist/server/routes/playground.js +283 -0
- package/dist/server/routes/reader.d.ts +18 -0
- package/dist/server/routes/reader.js +192 -0
- package/dist/server/routes/research.d.ts +14 -0
- package/dist/server/routes/research.js +482 -0
- package/dist/server/routes/screenshot.d.ts +22 -0
- package/dist/server/routes/screenshot.js +820 -0
- package/dist/server/routes/search.d.ts +6 -0
- package/dist/server/routes/search.js +874 -0
- package/dist/server/routes/session.d.ts +17 -0
- package/dist/server/routes/session.js +548 -0
- package/dist/server/routes/share.d.ts +18 -0
- package/dist/server/routes/share.js +462 -0
- package/dist/server/routes/smart-search/handlers/cars.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/cars.js +102 -0
- package/dist/server/routes/smart-search/handlers/flights.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/flights.js +72 -0
- package/dist/server/routes/smart-search/handlers/general.d.ts +13 -0
- package/dist/server/routes/smart-search/handlers/general.js +717 -0
- package/dist/server/routes/smart-search/handlers/hotels.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/hotels.js +88 -0
- package/dist/server/routes/smart-search/handlers/products.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/products.js +1309 -0
- package/dist/server/routes/smart-search/handlers/rental.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/rental.js +154 -0
- package/dist/server/routes/smart-search/handlers/restaurants.d.ts +2 -0
- package/dist/server/routes/smart-search/handlers/restaurants.js +225 -0
- package/dist/server/routes/smart-search/handlers/transit-verdict.d.ts +41 -0
- package/dist/server/routes/smart-search/handlers/transit-verdict.js +224 -0
- package/dist/server/routes/smart-search/index.d.ts +19 -0
- package/dist/server/routes/smart-search/index.js +546 -0
- package/dist/server/routes/smart-search/intent.d.ts +3 -0
- package/dist/server/routes/smart-search/intent.js +264 -0
- package/dist/server/routes/smart-search/llm.d.ts +16 -0
- package/dist/server/routes/smart-search/llm.js +70 -0
- package/dist/server/routes/smart-search/sources/reddit.d.ts +18 -0
- package/dist/server/routes/smart-search/sources/reddit.js +34 -0
- package/dist/server/routes/smart-search/sources/yelp.d.ts +25 -0
- package/dist/server/routes/smart-search/sources/yelp.js +171 -0
- package/dist/server/routes/smart-search/sources/youtube.d.ts +8 -0
- package/dist/server/routes/smart-search/sources/youtube.js +9 -0
- package/dist/server/routes/smart-search/types.d.ts +81 -0
- package/dist/server/routes/smart-search/types.js +1 -0
- package/dist/server/routes/smart-search/utils.d.ts +20 -0
- package/dist/server/routes/smart-search/utils.js +146 -0
- package/dist/server/routes/stats.d.ts +6 -0
- package/dist/server/routes/stats.js +71 -0
- package/dist/server/routes/stripe.d.ts +15 -0
- package/dist/server/routes/stripe.js +296 -0
- package/dist/server/routes/transcript-export.d.ts +10 -0
- package/dist/server/routes/transcript-export.js +178 -0
- package/dist/server/routes/usage.d.ts +9 -0
- package/dist/server/routes/usage.js +279 -0
- package/dist/server/routes/users.d.ts +8 -0
- package/dist/server/routes/users.js +1867 -0
- package/dist/server/routes/watch.d.ts +15 -0
- package/dist/server/routes/watch.js +309 -0
- package/dist/server/routes/webhooks.d.ts +26 -0
- package/dist/server/routes/webhooks.js +170 -0
- package/dist/server/routes/youtube.d.ts +6 -0
- package/dist/server/routes/youtube.js +130 -0
- package/dist/server/sentry.d.ts +14 -0
- package/dist/server/sentry.js +104 -0
- package/dist/server/types.d.ts +15 -0
- package/dist/server/types.js +7 -0
- package/dist/server/utils/response.d.ts +44 -0
- package/dist/server/utils/response.js +69 -0
- package/dist/server/utils/sse.d.ts +22 -0
- package/dist/server/utils/sse.js +38 -0
- package/dist/types.d.ts +552 -0
- package/dist/types.js +39 -0
- package/llms.txt +105 -0
- package/package.json +189 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page actions executor for browser automation
|
|
3
|
+
*
|
|
4
|
+
* This is WebPeel's "Actions API" — click/scroll/type/wait before extracting.
|
|
5
|
+
*
|
|
6
|
+
* Timeouts:
|
|
7
|
+
* - Default per action: 5s
|
|
8
|
+
* - Max total across all actions: 30s
|
|
9
|
+
*/
|
|
10
|
+
import { TimeoutError, WebPeelError } from '../types.js';
|
|
11
|
+
export const DEFAULT_ACTION_TIMEOUT_MS = 5_000;
|
|
12
|
+
export const MAX_TOTAL_ACTIONS_MS = 30_000;
|
|
13
|
+
function sleep(ms) {
|
|
14
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
15
|
+
}
|
|
16
|
+
async function withTimeout(promise, ms, message) {
|
|
17
|
+
if (!Number.isFinite(ms) || ms <= 0) {
|
|
18
|
+
throw new TimeoutError(message);
|
|
19
|
+
}
|
|
20
|
+
return Promise.race([
|
|
21
|
+
promise,
|
|
22
|
+
new Promise((_, reject) => setTimeout(() => reject(new TimeoutError(message)), ms)),
|
|
23
|
+
]);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Normalize a raw actions array to WebPeel's internal PageAction shape.
|
|
27
|
+
* Accepts Firecrawl-style fields (milliseconds, text, direction/amount).
|
|
28
|
+
*/
|
|
29
|
+
export function normalizeActions(input) {
|
|
30
|
+
if (!input)
|
|
31
|
+
return undefined;
|
|
32
|
+
if (!Array.isArray(input))
|
|
33
|
+
throw new WebPeelError('Invalid actions: must be an array');
|
|
34
|
+
return input.map((raw) => {
|
|
35
|
+
if (!raw || typeof raw !== 'object')
|
|
36
|
+
throw new WebPeelError('Invalid action: must be an object');
|
|
37
|
+
if (typeof raw.type !== 'string')
|
|
38
|
+
throw new WebPeelError('Invalid action: missing type');
|
|
39
|
+
const type = raw.type;
|
|
40
|
+
// Common aliases
|
|
41
|
+
const selector = typeof raw.selector === 'string' ? raw.selector : undefined;
|
|
42
|
+
const timeout = typeof raw.timeout === 'number' ? raw.timeout : undefined;
|
|
43
|
+
switch (type) {
|
|
44
|
+
case 'wait': {
|
|
45
|
+
const ms = typeof raw.milliseconds === 'number'
|
|
46
|
+
? raw.milliseconds
|
|
47
|
+
: typeof raw.ms === 'number'
|
|
48
|
+
? raw.ms
|
|
49
|
+
: typeof raw.value === 'number'
|
|
50
|
+
? raw.value
|
|
51
|
+
: undefined;
|
|
52
|
+
return {
|
|
53
|
+
type: 'wait',
|
|
54
|
+
ms: ms ?? 1000,
|
|
55
|
+
timeout,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
case 'click':
|
|
59
|
+
return { type: 'click', selector, timeout };
|
|
60
|
+
case 'type':
|
|
61
|
+
case 'fill': {
|
|
62
|
+
const value = typeof raw.value === 'string' ? raw.value
|
|
63
|
+
: typeof raw.text === 'string' ? raw.text
|
|
64
|
+
: undefined;
|
|
65
|
+
return { type, selector, value, timeout };
|
|
66
|
+
}
|
|
67
|
+
case 'select': {
|
|
68
|
+
const value = typeof raw.value === 'string' ? raw.value : undefined;
|
|
69
|
+
return { type: 'select', selector, value, timeout };
|
|
70
|
+
}
|
|
71
|
+
case 'press': {
|
|
72
|
+
const key = typeof raw.key === 'string' ? raw.key : (typeof raw.value === 'string' ? raw.value : undefined);
|
|
73
|
+
return { type: 'press', key, timeout };
|
|
74
|
+
}
|
|
75
|
+
case 'hover':
|
|
76
|
+
return { type: 'hover', selector, timeout };
|
|
77
|
+
case 'waitForSelector':
|
|
78
|
+
return { type: 'waitForSelector', selector, timeout };
|
|
79
|
+
case 'scroll': {
|
|
80
|
+
const direction = typeof raw.direction === 'string' ? raw.direction : undefined;
|
|
81
|
+
const amount = typeof raw.amount === 'number' ? raw.amount : undefined;
|
|
82
|
+
// Legacy/internal: to can be top|bottom|number|{x,y}
|
|
83
|
+
let to;
|
|
84
|
+
if (raw.to === 'top' || raw.to === 'bottom' || typeof raw.to === 'number') {
|
|
85
|
+
to = raw.to;
|
|
86
|
+
}
|
|
87
|
+
else if (typeof raw.to === 'object' && raw.to !== null && 'x' in raw.to && 'y' in raw.to) {
|
|
88
|
+
to = { x: raw.to.x, y: raw.to.y };
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
to = undefined;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
type: 'scroll',
|
|
95
|
+
direction: (direction === 'up' || direction === 'down' || direction === 'left' || direction === 'right') ? direction : undefined,
|
|
96
|
+
amount,
|
|
97
|
+
to,
|
|
98
|
+
timeout,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case 'screenshot':
|
|
102
|
+
return { type: 'screenshot', timeout };
|
|
103
|
+
default:
|
|
104
|
+
// Allow forward compatibility — but still pass through known fields.
|
|
105
|
+
return { ...raw };
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check if an error message indicates the execution context was destroyed.
|
|
111
|
+
* This happens on SPAs (like Polymarket) when scrolling triggers navigation.
|
|
112
|
+
*/
|
|
113
|
+
function isContextDestroyedError(err) {
|
|
114
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
115
|
+
return (msg.includes('Execution context was destroyed') ||
|
|
116
|
+
msg.includes('Target closed') ||
|
|
117
|
+
msg.includes('frame was detached') ||
|
|
118
|
+
msg.includes('Session closed'));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Detect the most likely scrollable container on the page.
|
|
122
|
+
* Returns a CSS selector string for the container, or null if only window scrolling is needed.
|
|
123
|
+
*
|
|
124
|
+
* Looks for elements with overflow-y: auto|scroll whose scrollHeight > clientHeight,
|
|
125
|
+
* preferring the largest such element. Used by autoScroll and scrollThrough.
|
|
126
|
+
*/
|
|
127
|
+
export async function detectScrollContainer(page) {
|
|
128
|
+
try {
|
|
129
|
+
return await page.evaluate(() => {
|
|
130
|
+
const candidates = [];
|
|
131
|
+
const elements = document.querySelectorAll('*');
|
|
132
|
+
for (const el of Array.from(elements)) {
|
|
133
|
+
// Skip body/html (that's the default window scroll)
|
|
134
|
+
if (el === document.body || el === document.documentElement)
|
|
135
|
+
continue;
|
|
136
|
+
const style = window.getComputedStyle(el);
|
|
137
|
+
const overflowY = style.overflowY;
|
|
138
|
+
if (overflowY !== 'auto' && overflowY !== 'scroll')
|
|
139
|
+
continue;
|
|
140
|
+
const scrollable = el.scrollHeight - el.clientHeight;
|
|
141
|
+
if (scrollable < 100)
|
|
142
|
+
continue; // Must have meaningful scrollable space
|
|
143
|
+
// Build a reasonable selector
|
|
144
|
+
let selector = el.tagName.toLowerCase();
|
|
145
|
+
if (el.id) {
|
|
146
|
+
selector = `#${CSS.escape(el.id)}`;
|
|
147
|
+
}
|
|
148
|
+
else if (el.className && typeof el.className === 'string') {
|
|
149
|
+
const cls = el.className.trim().split(/\s+/)[0];
|
|
150
|
+
if (cls)
|
|
151
|
+
selector = `${el.tagName.toLowerCase()}.${CSS.escape(cls)}`;
|
|
152
|
+
}
|
|
153
|
+
candidates.push({ selector, scrollable });
|
|
154
|
+
}
|
|
155
|
+
if (candidates.length === 0)
|
|
156
|
+
return null;
|
|
157
|
+
// Sort by most scrollable content and return the best candidate
|
|
158
|
+
candidates.sort((a, b) => b.scrollable - a.scrollable);
|
|
159
|
+
return candidates[0].selector;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Context may be gone — safe to ignore
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Intelligently scroll the page to load all lazy/infinite-scroll content.
|
|
169
|
+
*
|
|
170
|
+
* Improvements over the basic version:
|
|
171
|
+
* 1. Detects virtual/inner scroll containers (Polymarket, React virtualized lists)
|
|
172
|
+
* 2. Uses MutationObserver to detect DOM additions (not just height changes)
|
|
173
|
+
* 3. Gracefully handles execution context destruction (SPA navigation)
|
|
174
|
+
* 4. Stability requires BOTH no height change AND no DOM mutations
|
|
175
|
+
*
|
|
176
|
+
* Stops when:
|
|
177
|
+
* - Height is stable AND no DOM mutations for 2 consecutive checks
|
|
178
|
+
* - maxScrolls limit is reached
|
|
179
|
+
* - Total timeout is exceeded
|
|
180
|
+
* - Execution context is destroyed (SPA navigation)
|
|
181
|
+
*/
|
|
182
|
+
export async function autoScroll(page, options = {}) {
|
|
183
|
+
const { maxScrolls = 20, scrollDelay = 1000, timeout = 30_000, waitForSelector, } = options;
|
|
184
|
+
const startTime = Date.now();
|
|
185
|
+
let scrollCount = 0;
|
|
186
|
+
let stableCount = 0;
|
|
187
|
+
const stableThreshold = 2;
|
|
188
|
+
let totalMutations = 0;
|
|
189
|
+
let scrollContainerFound = false;
|
|
190
|
+
// ── Step 1: Detect the actual scrollable container ─────────────────────────
|
|
191
|
+
// Use || null to normalize undefined (returned by test mocks) to null.
|
|
192
|
+
const containerSelector = (await detectScrollContainer(page)) || null;
|
|
193
|
+
scrollContainerFound = containerSelector !== null;
|
|
194
|
+
// ── Step 2: Get initial height (body or container) ─────────────────────────
|
|
195
|
+
const getHeight = async () => {
|
|
196
|
+
try {
|
|
197
|
+
if (containerSelector) {
|
|
198
|
+
const h = await page.evaluate((sel) => {
|
|
199
|
+
const el = document.querySelector(sel);
|
|
200
|
+
return el ? el.scrollHeight : document.body.scrollHeight;
|
|
201
|
+
}, containerSelector);
|
|
202
|
+
return h || 0;
|
|
203
|
+
}
|
|
204
|
+
// Use string form for backward compatibility with test mocks
|
|
205
|
+
return (await page.evaluate('document.body.scrollHeight')) || 0;
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
if (isContextDestroyedError(err))
|
|
209
|
+
return -1; // Sentinel: context gone
|
|
210
|
+
throw err;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
// ── Step 3: Set up MutationObserver inside the page ─────────────────────────
|
|
214
|
+
// We store a mutation count in window.__wpMutationCount so we can poll it.
|
|
215
|
+
const setupObserver = async () => {
|
|
216
|
+
try {
|
|
217
|
+
await page.evaluate(() => {
|
|
218
|
+
window.__wpMutationCount = 0;
|
|
219
|
+
const observer = new MutationObserver((mutations) => {
|
|
220
|
+
window.__wpMutationCount += mutations.reduce((sum, m) => sum + m.addedNodes.length, 0);
|
|
221
|
+
});
|
|
222
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
223
|
+
window.__wpMutationObserver = observer;
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// If we can't set up the observer, we'll fall back to height-only detection
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
const getMutationCount = async () => {
|
|
231
|
+
try {
|
|
232
|
+
const count = await page.evaluate(() => window.__wpMutationCount ?? 0);
|
|
233
|
+
return typeof count === 'number' ? count : 0;
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return 0;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
const resetMutationCount = async () => {
|
|
240
|
+
try {
|
|
241
|
+
await page.evaluate(() => { window.__wpMutationCount = 0; });
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// Ignore
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
// ── Step 4: Perform the scroll function ────────────────────────────────────
|
|
248
|
+
const scrollToBottom = async () => {
|
|
249
|
+
try {
|
|
250
|
+
if (containerSelector) {
|
|
251
|
+
await page.evaluate((sel) => {
|
|
252
|
+
const el = document.querySelector(sel);
|
|
253
|
+
if (el) {
|
|
254
|
+
el.scrollTop = el.scrollHeight;
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
window.scrollTo(0, document.body.scrollHeight);
|
|
258
|
+
}
|
|
259
|
+
}, containerSelector);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
// Use string form for backward compatibility with test mocks
|
|
263
|
+
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
if (!isContextDestroyedError(err))
|
|
268
|
+
throw err;
|
|
269
|
+
// Context destroyed — will be caught in main loop
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
// ── Main loop ──────────────────────────────────────────────────────────────
|
|
273
|
+
await setupObserver();
|
|
274
|
+
await resetMutationCount();
|
|
275
|
+
const initialHeight = await getHeight();
|
|
276
|
+
if (initialHeight === -1) {
|
|
277
|
+
// Context was already destroyed before we started
|
|
278
|
+
return { scrollCount: 0, finalHeight: 0, contentGrew: false, scrollContainerFound, mutationsDetected: 0 };
|
|
279
|
+
}
|
|
280
|
+
let lastHeight = initialHeight;
|
|
281
|
+
let finalHeight = initialHeight;
|
|
282
|
+
let lastMutationCount = 0;
|
|
283
|
+
while (scrollCount < maxScrolls) {
|
|
284
|
+
// Check timeout
|
|
285
|
+
if (Date.now() - startTime >= timeout) {
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
// Scroll to bottom (with error recovery)
|
|
289
|
+
try {
|
|
290
|
+
await scrollToBottom();
|
|
291
|
+
}
|
|
292
|
+
catch (err) {
|
|
293
|
+
if (isContextDestroyedError(err)) {
|
|
294
|
+
// SPA navigation destroyed the context — stop gracefully
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
throw err;
|
|
298
|
+
}
|
|
299
|
+
scrollCount++;
|
|
300
|
+
// Wait for new content
|
|
301
|
+
const remainingTime = timeout - (Date.now() - startTime);
|
|
302
|
+
const waitMs = Math.min(scrollDelay, Math.max(remainingTime, 0));
|
|
303
|
+
if (waitMs > 0) {
|
|
304
|
+
await sleep(waitMs);
|
|
305
|
+
}
|
|
306
|
+
// Optionally wait for a specific selector
|
|
307
|
+
if (waitForSelector) {
|
|
308
|
+
const selectorTimeout = Math.max(0, timeout - (Date.now() - startTime));
|
|
309
|
+
if (selectorTimeout > 0) {
|
|
310
|
+
await page.waitForSelector(waitForSelector, { timeout: selectorTimeout }).catch(() => { });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Check height (with error recovery)
|
|
314
|
+
let currentHeight;
|
|
315
|
+
try {
|
|
316
|
+
currentHeight = await getHeight();
|
|
317
|
+
if (currentHeight === -1)
|
|
318
|
+
break; // Context destroyed
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
if (isContextDestroyedError(err))
|
|
322
|
+
break;
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
finalHeight = currentHeight;
|
|
326
|
+
// Check mutation count
|
|
327
|
+
const currentMutations = await getMutationCount();
|
|
328
|
+
const mutationsSinceLastCheck = currentMutations - lastMutationCount;
|
|
329
|
+
totalMutations += mutationsSinceLastCheck;
|
|
330
|
+
// Stability check: stable = no height growth AND no new DOM mutations
|
|
331
|
+
const heightStable = currentHeight <= lastHeight;
|
|
332
|
+
const mutationsStable = mutationsSinceLastCheck === 0;
|
|
333
|
+
if (heightStable && mutationsStable) {
|
|
334
|
+
stableCount++;
|
|
335
|
+
if (stableCount >= stableThreshold) {
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
stableCount = 0;
|
|
341
|
+
if (!heightStable)
|
|
342
|
+
lastHeight = currentHeight;
|
|
343
|
+
lastMutationCount = currentMutations;
|
|
344
|
+
await resetMutationCount();
|
|
345
|
+
lastMutationCount = 0;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
scrollCount,
|
|
350
|
+
finalHeight,
|
|
351
|
+
contentGrew: finalHeight > initialHeight,
|
|
352
|
+
scrollContainerFound,
|
|
353
|
+
mutationsDetected: totalMutations,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
export async function executeActions(page, actions, screenshotOptions) {
|
|
357
|
+
let lastScreenshot;
|
|
358
|
+
const screenshotType = screenshotOptions?.type || 'png';
|
|
359
|
+
const screenshotFullPage = screenshotOptions?.fullPage ?? true;
|
|
360
|
+
const screenshotQuality = screenshotOptions?.quality;
|
|
361
|
+
const start = Date.now();
|
|
362
|
+
const deadline = start + MAX_TOTAL_ACTIONS_MS;
|
|
363
|
+
// Normalize once to handle Firecrawl-style aliases even if caller didn't.
|
|
364
|
+
const normalized = normalizeActions(actions) ?? [];
|
|
365
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
366
|
+
const action = normalized[i];
|
|
367
|
+
const remainingTotal = deadline - Date.now();
|
|
368
|
+
if (remainingTotal <= 0) {
|
|
369
|
+
throw new TimeoutError(`Actions timed out after ${MAX_TOTAL_ACTIONS_MS}ms`);
|
|
370
|
+
}
|
|
371
|
+
const perActionTimeout = Math.min(typeof action.timeout === 'number' && action.timeout > 0 ? action.timeout : DEFAULT_ACTION_TIMEOUT_MS, remainingTotal);
|
|
372
|
+
const label = `Action ${i + 1}/${normalized.length} (${action.type})`;
|
|
373
|
+
switch (action.type) {
|
|
374
|
+
case 'wait': {
|
|
375
|
+
const ms = (typeof action.ms === 'number' ? action.ms : undefined)
|
|
376
|
+
?? (typeof action.milliseconds === 'number' ? action.milliseconds : undefined)
|
|
377
|
+
?? 1000;
|
|
378
|
+
const waitMs = Math.min(Math.max(ms, 0), remainingTotal);
|
|
379
|
+
await withTimeout(page.waitForTimeout(waitMs), waitMs + 50, `${label} timed out`);
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
382
|
+
case 'click': {
|
|
383
|
+
if (!action.selector)
|
|
384
|
+
throw new WebPeelError('click action requires selector');
|
|
385
|
+
await withTimeout(page.click(action.selector, { timeout: perActionTimeout }), perActionTimeout + 50, `${label} timed out`);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
case 'scroll': {
|
|
389
|
+
const dir = action.direction;
|
|
390
|
+
const amount = typeof action.amount === 'number' ? action.amount : undefined;
|
|
391
|
+
const scrollPromise = (async () => {
|
|
392
|
+
// Relative scroll (Firecrawl-style)
|
|
393
|
+
if (dir && amount !== undefined) {
|
|
394
|
+
const a = Math.max(0, amount);
|
|
395
|
+
let dx = 0;
|
|
396
|
+
let dy = 0;
|
|
397
|
+
if (dir === 'down')
|
|
398
|
+
dy = a;
|
|
399
|
+
if (dir === 'up')
|
|
400
|
+
dy = -a;
|
|
401
|
+
if (dir === 'right')
|
|
402
|
+
dx = a;
|
|
403
|
+
if (dir === 'left')
|
|
404
|
+
dx = -a;
|
|
405
|
+
await page.evaluate(`window.scrollBy(${dx}, ${dy})`);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
// Legacy absolute scroll target
|
|
409
|
+
if (action.to === 'bottom') {
|
|
410
|
+
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (action.to === 'top') {
|
|
414
|
+
await page.evaluate('window.scrollTo(0, 0)');
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (typeof action.to === 'number') {
|
|
418
|
+
await page.evaluate(`window.scrollTo(0, ${action.to})`);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (typeof action.to === 'object' && action.to !== null && 'x' in action.to && 'y' in action.to) {
|
|
422
|
+
await page.evaluate(`window.scrollTo(${action.to.x}, ${action.to.y})`);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
// Default: scroll to bottom
|
|
426
|
+
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
|
|
427
|
+
})();
|
|
428
|
+
await withTimeout(scrollPromise, perActionTimeout + 50, `${label} timed out`);
|
|
429
|
+
break;
|
|
430
|
+
}
|
|
431
|
+
case 'type': {
|
|
432
|
+
if (!action.selector)
|
|
433
|
+
throw new WebPeelError('type action requires selector');
|
|
434
|
+
const value = action.value ?? action.text;
|
|
435
|
+
if (!value)
|
|
436
|
+
throw new WebPeelError('type action requires text');
|
|
437
|
+
await withTimeout(page.type(action.selector, value, { timeout: perActionTimeout }), perActionTimeout + 50, `${label} timed out`);
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
case 'fill': {
|
|
441
|
+
if (!action.selector)
|
|
442
|
+
throw new WebPeelError('fill action requires selector');
|
|
443
|
+
const value = action.value ?? action.text;
|
|
444
|
+
if (!value)
|
|
445
|
+
throw new WebPeelError('fill action requires value');
|
|
446
|
+
await withTimeout(page.fill(action.selector, value, { timeout: perActionTimeout }), perActionTimeout + 50, `${label} timed out`);
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
case 'select': {
|
|
450
|
+
if (!action.selector)
|
|
451
|
+
throw new WebPeelError('select action requires selector');
|
|
452
|
+
if (!action.value)
|
|
453
|
+
throw new WebPeelError('select action requires value');
|
|
454
|
+
await withTimeout(page.selectOption(action.selector, action.value, { timeout: perActionTimeout }), perActionTimeout + 50, `${label} timed out`);
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
case 'press': {
|
|
458
|
+
const key = action.key;
|
|
459
|
+
if (!key)
|
|
460
|
+
throw new WebPeelError('press action requires key');
|
|
461
|
+
await withTimeout(page.keyboard.press(key), perActionTimeout + 50, `${label} timed out`);
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
case 'hover': {
|
|
465
|
+
if (!action.selector)
|
|
466
|
+
throw new WebPeelError('hover action requires selector');
|
|
467
|
+
await withTimeout(page.hover(action.selector, { timeout: perActionTimeout }), perActionTimeout + 50, `${label} timed out`);
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
case 'waitForSelector': {
|
|
471
|
+
if (!action.selector)
|
|
472
|
+
throw new WebPeelError('waitForSelector action requires selector');
|
|
473
|
+
await withTimeout(page.waitForSelector(action.selector, { timeout: perActionTimeout }), perActionTimeout + 50, `${label} timed out`);
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
case 'screenshot': {
|
|
477
|
+
lastScreenshot = await withTimeout(page.screenshot({
|
|
478
|
+
fullPage: screenshotFullPage,
|
|
479
|
+
type: screenshotType,
|
|
480
|
+
...(screenshotType === 'jpeg' && typeof screenshotQuality === 'number'
|
|
481
|
+
? { quality: screenshotQuality }
|
|
482
|
+
: {}),
|
|
483
|
+
}), perActionTimeout + 50, `${label} timed out`);
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
default: {
|
|
487
|
+
// This should not happen due to our type union, but keep a safe fallback.
|
|
488
|
+
throw new WebPeelError(`Unknown action type: ${action.type}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
// Small yield to avoid starving the event loop in tight action sequences
|
|
492
|
+
await sleep(0);
|
|
493
|
+
}
|
|
494
|
+
return lastScreenshot;
|
|
495
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autonomous web research agent
|
|
3
|
+
* Searches the web, fetches pages, and extracts structured data based on natural language prompts
|
|
4
|
+
*
|
|
5
|
+
* Supports:
|
|
6
|
+
* - depth: "basic" (1 search, top 3) vs "thorough" (multi-step, up to 3 searches, top 10)
|
|
7
|
+
* - maxSources: control how many sources to include (default 5, max 20)
|
|
8
|
+
* - topic: "general" | "news" | "technical" | "academic" — adjusts queries & prioritization
|
|
9
|
+
* - outputSchema: JSON Schema for structured output with validation
|
|
10
|
+
* - streaming callbacks for SSE support
|
|
11
|
+
*/
|
|
12
|
+
export type AgentDepth = 'basic' | 'thorough';
|
|
13
|
+
export type AgentTopic = 'general' | 'news' | 'technical' | 'academic';
|
|
14
|
+
export interface AgentOptions {
|
|
15
|
+
/** Natural language description of what data to extract */
|
|
16
|
+
prompt: string;
|
|
17
|
+
/** Optional URLs to start from */
|
|
18
|
+
urls?: string[];
|
|
19
|
+
/** JSON schema for structured output (legacy — prefer outputSchema) */
|
|
20
|
+
schema?: Record<string, any>;
|
|
21
|
+
/** JSON Schema for structured output with validation */
|
|
22
|
+
outputSchema?: Record<string, any>;
|
|
23
|
+
/** LLM API key (BYOK - bring your own key) */
|
|
24
|
+
llmApiKey: string;
|
|
25
|
+
/** LLM API base URL (default: OpenAI) */
|
|
26
|
+
llmApiBase?: string;
|
|
27
|
+
/** LLM model (default: gpt-4o-mini) */
|
|
28
|
+
llmModel?: string;
|
|
29
|
+
/** Max pages to visit (default: 10) — legacy param */
|
|
30
|
+
maxPages?: number;
|
|
31
|
+
/** Max sources to include (default 5, max 20) */
|
|
32
|
+
maxSources?: number;
|
|
33
|
+
/** Research depth: "basic" or "thorough" */
|
|
34
|
+
depth?: AgentDepth;
|
|
35
|
+
/** Topic filter */
|
|
36
|
+
topic?: AgentTopic;
|
|
37
|
+
/** Max credits/cost to spend */
|
|
38
|
+
maxCredits?: number;
|
|
39
|
+
/** Progress callback (legacy — still supported) */
|
|
40
|
+
onProgress?: (progress: AgentProgress) => void;
|
|
41
|
+
/** Streaming event callback for SSE */
|
|
42
|
+
onEvent?: (event: AgentStreamEvent) => void;
|
|
43
|
+
}
|
|
44
|
+
export interface AgentProgress {
|
|
45
|
+
status: 'searching' | 'visiting' | 'extracting' | 'done';
|
|
46
|
+
currentUrl?: string;
|
|
47
|
+
pagesVisited: number;
|
|
48
|
+
message: string;
|
|
49
|
+
}
|
|
50
|
+
export interface AgentResult {
|
|
51
|
+
success: boolean;
|
|
52
|
+
data: any;
|
|
53
|
+
/** The synthesised answer (text). Only present when no outputSchema. */
|
|
54
|
+
answer?: string;
|
|
55
|
+
sources: string[];
|
|
56
|
+
sourcesDetailed?: Array<{
|
|
57
|
+
url: string;
|
|
58
|
+
title: string;
|
|
59
|
+
}>;
|
|
60
|
+
pagesVisited: number;
|
|
61
|
+
creditsUsed: number;
|
|
62
|
+
tokensUsed?: {
|
|
63
|
+
input: number;
|
|
64
|
+
output: number;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Events emitted during streaming */
|
|
68
|
+
export type AgentStreamEvent = {
|
|
69
|
+
type: 'step';
|
|
70
|
+
action: 'searching';
|
|
71
|
+
query: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: 'step';
|
|
74
|
+
action: 'fetching';
|
|
75
|
+
url: string;
|
|
76
|
+
} | {
|
|
77
|
+
type: 'step';
|
|
78
|
+
action: 'analyzing';
|
|
79
|
+
summary: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: 'chunk';
|
|
82
|
+
text: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: 'done';
|
|
85
|
+
answer: string;
|
|
86
|
+
sources: Array<{
|
|
87
|
+
url: string;
|
|
88
|
+
title: string;
|
|
89
|
+
}>;
|
|
90
|
+
tokensUsed: {
|
|
91
|
+
input: number;
|
|
92
|
+
output: number;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Run autonomous web research agent
|
|
97
|
+
*/
|
|
98
|
+
export declare function runAgent(options: AgentOptions): Promise<AgentResult>;
|