@detiq/crawler 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +49 -0
- package/README.md +11 -0
- package/dist/accessibility-auditor.d.ts +29 -0
- package/dist/accessibility-auditor.js +57 -0
- package/dist/accessibility-auditor.js.map +7 -0
- package/dist/ai-login.d.ts +32 -0
- package/dist/ai-login.js +177 -0
- package/dist/ai-login.js.map +7 -0
- package/dist/auth-token-rotator.d.ts +47 -0
- package/dist/auth-token-rotator.js +58 -0
- package/dist/auth-token-rotator.js.map +7 -0
- package/dist/auth.d.ts +20 -0
- package/dist/auth.js +329 -0
- package/dist/auth.js.map +7 -0
- package/dist/browser-extension.d.ts +37 -0
- package/dist/browser-extension.js +113 -0
- package/dist/browser-extension.js.map +7 -0
- package/dist/captcha-solver.d.ts +16 -0
- package/dist/captcha-solver.js +105 -0
- package/dist/captcha-solver.js.map +7 -0
- package/dist/color-contrast.d.ts +30 -0
- package/dist/color-contrast.js +78 -0
- package/dist/color-contrast.js.map +7 -0
- package/dist/content-chunker.d.ts +18 -0
- package/dist/content-chunker.js +152 -0
- package/dist/content-chunker.js.map +7 -0
- package/dist/content-dedup.d.ts +23 -0
- package/dist/content-dedup.js +60 -0
- package/dist/content-dedup.js.map +7 -0
- package/dist/cookie-consent.d.ts +25 -0
- package/dist/cookie-consent.js +78 -0
- package/dist/cookie-consent.js.map +7 -0
- package/dist/cookie-jar.d.ts +20 -0
- package/dist/cookie-jar.js +61 -0
- package/dist/cookie-jar.js.map +7 -0
- package/dist/crawler.d.ts +179 -0
- package/dist/crawler.js +3672 -0
- package/dist/crawler.js.map +7 -0
- package/dist/custom-js-injector.d.ts +42 -0
- package/dist/custom-js-injector.js +50 -0
- package/dist/custom-js-injector.js.map +7 -0
- package/dist/dark-mode-capture.d.ts +23 -0
- package/dist/dark-mode-capture.js +75 -0
- package/dist/dark-mode-capture.js.map +7 -0
- package/dist/dead-link-detector.d.ts +37 -0
- package/dist/dead-link-detector.js +50 -0
- package/dist/dead-link-detector.js.map +7 -0
- package/dist/element-hash.d.ts +9 -0
- package/dist/element-hash.js +9 -0
- package/dist/element-hash.js.map +7 -0
- package/dist/email-otp.d.ts +42 -0
- package/dist/email-otp.js +177 -0
- package/dist/email-otp.js.map +7 -0
- package/dist/engine-router.d.ts +47 -0
- package/dist/engine-router.js +94 -0
- package/dist/engine-router.js.map +7 -0
- package/dist/export/bulk-export.d.ts +26 -0
- package/dist/export/bulk-export.js +76 -0
- package/dist/export/bulk-export.js.map +7 -0
- package/dist/export/vector-export.d.ts +76 -0
- package/dist/export/vector-export.js +85 -0
- package/dist/export/vector-export.js.map +7 -0
- package/dist/extractors/advanced.d.ts +54 -0
- package/dist/extractors/advanced.js +245 -0
- package/dist/extractors/advanced.js.map +7 -0
- package/dist/extractors/artifact-envelope.d.ts +63 -0
- package/dist/extractors/artifact-envelope.js +63 -0
- package/dist/extractors/artifact-envelope.js.map +7 -0
- package/dist/failure-analysis-agent.d.ts +16 -0
- package/dist/failure-analysis-agent.js +40 -0
- package/dist/failure-analysis-agent.js.map +7 -0
- package/dist/feature-flag-detector.d.ts +30 -0
- package/dist/feature-flag-detector.js +55 -0
- package/dist/feature-flag-detector.js.map +7 -0
- package/dist/form-detector.d.ts +34 -0
- package/dist/form-detector.js +58 -0
- package/dist/form-detector.js.map +7 -0
- package/dist/frontier.d.ts +32 -0
- package/dist/frontier.js +83 -0
- package/dist/frontier.js.map +7 -0
- package/dist/gap-pass.d.ts +35 -0
- package/dist/gap-pass.js +81 -0
- package/dist/gap-pass.js.map +7 -0
- package/dist/graphql-detector.d.ts +39 -0
- package/dist/graphql-detector.js +86 -0
- package/dist/graphql-detector.js.map +7 -0
- package/dist/http-engine.d.ts +80 -0
- package/dist/http-engine.js +304 -0
- package/dist/http-engine.js.map +7 -0
- package/dist/incremental-diff.d.ts +59 -0
- package/dist/incremental-diff.js +61 -0
- package/dist/incremental-diff.js.map +7 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +7 -0
- package/dist/input-fuzzer.d.ts +30 -0
- package/dist/input-fuzzer.js +105 -0
- package/dist/input-fuzzer.js.map +7 -0
- package/dist/interactive-probe.d.ts +104 -0
- package/dist/interactive-probe.js +442 -0
- package/dist/interactive-probe.js.map +7 -0
- package/dist/job-queue.d.ts +171 -0
- package/dist/job-queue.js +2256 -0
- package/dist/job-queue.js.map +7 -0
- package/dist/js-coverage.d.ts +29 -0
- package/dist/js-coverage.js +56 -0
- package/dist/js-coverage.js.map +7 -0
- package/dist/js-router-detector.d.ts +17 -0
- package/dist/js-router-detector.js +90 -0
- package/dist/js-router-detector.js.map +7 -0
- package/dist/language-detector.d.ts +22 -0
- package/dist/language-detector.js +57 -0
- package/dist/language-detector.js.map +7 -0
- package/dist/link-classifier.d.ts +23 -0
- package/dist/link-classifier.js +40 -0
- package/dist/link-classifier.js.map +7 -0
- package/dist/live-view.d.ts +36 -0
- package/dist/live-view.js +100 -0
- package/dist/live-view.js.map +7 -0
- package/dist/logger.d.ts +2 -0
- package/dist/logger.js +10 -0
- package/dist/logger.js.map +7 -0
- package/dist/markdown-extract.d.ts +8 -0
- package/dist/markdown-extract.js +54 -0
- package/dist/markdown-extract.js.map +7 -0
- package/dist/native-crawler.d.ts +69 -0
- package/dist/native-crawler.js +839 -0
- package/dist/native-crawler.js.map +7 -0
- package/dist/network-observer.d.ts +49 -0
- package/dist/network-observer.js +149 -0
- package/dist/network-observer.js.map +7 -0
- package/dist/network-throttle.d.ts +25 -0
- package/dist/network-throttle.js +34 -0
- package/dist/network-throttle.js.map +7 -0
- package/dist/openapi-generator.d.ts +49 -0
- package/dist/openapi-generator.js +89 -0
- package/dist/openapi-generator.js.map +7 -0
- package/dist/pdf-extractor.d.ts +28 -0
- package/dist/pdf-extractor.js +81 -0
- package/dist/pdf-extractor.js.map +7 -0
- package/dist/performance-metrics.d.ts +53 -0
- package/dist/performance-metrics.js +83 -0
- package/dist/performance-metrics.js.map +7 -0
- package/dist/phash.d.ts +38 -0
- package/dist/phash.js +115 -0
- package/dist/phash.js.map +7 -0
- package/dist/pii-scrubber.d.ts +21 -0
- package/dist/pii-scrubber.js +75 -0
- package/dist/pii-scrubber.js.map +7 -0
- package/dist/playwright-recorder.d.ts +39 -0
- package/dist/playwright-recorder.js +123 -0
- package/dist/playwright-recorder.js.map +7 -0
- package/dist/policies/crawl-safety.d.ts +9 -0
- package/dist/policies/crawl-safety.js +37 -0
- package/dist/policies/crawl-safety.js.map +7 -0
- package/dist/profiles/domain-profile.d.ts +19 -0
- package/dist/profiles/domain-profile.js +140 -0
- package/dist/profiles/domain-profile.js.map +7 -0
- package/dist/proxy.d.ts +50 -0
- package/dist/proxy.js +165 -0
- package/dist/proxy.js.map +7 -0
- package/dist/rate-limiter.d.ts +31 -0
- package/dist/rate-limiter.js +64 -0
- package/dist/rate-limiter.js.map +7 -0
- package/dist/redirect-tracker.d.ts +37 -0
- package/dist/redirect-tracker.js +65 -0
- package/dist/redirect-tracker.js.map +7 -0
- package/dist/redis-frontier.d.ts +48 -0
- package/dist/redis-frontier.js +126 -0
- package/dist/redis-frontier.js.map +7 -0
- package/dist/redis-queue.d.ts +48 -0
- package/dist/redis-queue.js +165 -0
- package/dist/redis-queue.js.map +7 -0
- package/dist/response-cache.d.ts +38 -0
- package/dist/response-cache.js +140 -0
- package/dist/response-cache.js.map +7 -0
- package/dist/responsive-detector.d.ts +29 -0
- package/dist/responsive-detector.js +46 -0
- package/dist/responsive-detector.js.map +7 -0
- package/dist/retry-policy.d.ts +20 -0
- package/dist/retry-policy.js +54 -0
- package/dist/retry-policy.js.map +7 -0
- package/dist/robots-txt.d.ts +9 -0
- package/dist/robots-txt.js +77 -0
- package/dist/robots-txt.js.map +7 -0
- package/dist/screen-reader.d.ts +16 -0
- package/dist/screen-reader.js +46 -0
- package/dist/screen-reader.js.map +7 -0
- package/dist/screenshot-masker.d.ts +28 -0
- package/dist/screenshot-masker.js +62 -0
- package/dist/screenshot-masker.js.map +7 -0
- package/dist/seo-checker.d.ts +33 -0
- package/dist/seo-checker.js +91 -0
- package/dist/seo-checker.js.map +7 -0
- package/dist/session-capture.d.ts +35 -0
- package/dist/session-capture.js +267 -0
- package/dist/session-capture.js.map +7 -0
- package/dist/session-export.d.ts +49 -0
- package/dist/session-export.js +117 -0
- package/dist/session-export.js.map +7 -0
- package/dist/sitemap-writer.d.ts +21 -0
- package/dist/sitemap-writer.js +47 -0
- package/dist/sitemap-writer.js.map +7 -0
- package/dist/sitemap.d.ts +51 -0
- package/dist/sitemap.js +152 -0
- package/dist/sitemap.js.map +7 -0
- package/dist/skyvern.d.ts +56 -0
- package/dist/skyvern.js +129 -0
- package/dist/skyvern.js.map +7 -0
- package/dist/sqs-queue.d.ts +2 -0
- package/dist/sqs-queue.js +47 -0
- package/dist/sqs-queue.js.map +7 -0
- package/dist/sso-token.d.ts +29 -0
- package/dist/sso-token.js +76 -0
- package/dist/sso-token.js.map +7 -0
- package/dist/stealth/human-behavior.d.ts +20 -0
- package/dist/stealth/human-behavior.js +168 -0
- package/dist/stealth/human-behavior.js.map +7 -0
- package/dist/telemetry.d.ts +34 -0
- package/dist/telemetry.js +77 -0
- package/dist/telemetry.js.map +7 -0
- package/dist/test-executor.d.ts +67 -0
- package/dist/test-executor.js +311 -0
- package/dist/test-executor.js.map +7 -0
- package/dist/tls-fingerprint.d.ts +50 -0
- package/dist/tls-fingerprint.js +81 -0
- package/dist/tls-fingerprint.js.map +7 -0
- package/dist/url-pattern-completer.d.ts +28 -0
- package/dist/url-pattern-completer.js +87 -0
- package/dist/url-pattern-completer.js.map +7 -0
- package/dist/visual-diff-verdict.d.ts +40 -0
- package/dist/visual-diff-verdict.js +25 -0
- package/dist/visual-diff-verdict.js.map +7 -0
- package/dist/webhook-notifier.d.ts +30 -0
- package/dist/webhook-notifier.js +76 -0
- package/dist/webhook-notifier.js.map +7 -0
- package/dist/websocket-detector.d.ts +24 -0
- package/dist/websocket-detector.js +60 -0
- package/dist/websocket-detector.js.map +7 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +33 -0
- package/dist/worker.js.map +7 -0
- package/package.json +45 -0
- package/src/accessibility-auditor.ts +102 -0
- package/src/ai-login.ts +218 -0
- package/src/auth-token-rotator.ts +89 -0
- package/src/auth.ts +396 -0
- package/src/browser-extension.ts +186 -0
- package/src/captcha-solver.ts +143 -0
- package/src/color-contrast.ts +116 -0
- package/src/content-chunker.ts +170 -0
- package/src/content-dedup.ts +99 -0
- package/src/cookie-consent.ts +106 -0
- package/src/cookie-jar.ts +91 -0
- package/src/crawler.ts +4305 -0
- package/src/custom-js-injector.ts +93 -0
- package/src/dark-mode-capture.ts +110 -0
- package/src/dead-link-detector.ts +76 -0
- package/src/element-hash.ts +16 -0
- package/src/email-otp.ts +252 -0
- package/src/engine-router.ts +141 -0
- package/src/export/bulk-export.ts +85 -0
- package/src/export/vector-export.ts +160 -0
- package/src/extractors/advanced.ts +283 -0
- package/src/extractors/artifact-envelope.ts +111 -0
- package/src/failure-analysis-agent.ts +49 -0
- package/src/feature-flag-detector.ts +97 -0
- package/src/form-detector.ts +103 -0
- package/src/frontier.test.ts +64 -0
- package/src/frontier.ts +112 -0
- package/src/gap-pass.ts +122 -0
- package/src/graphql-detector.ts +129 -0
- package/src/http-engine.ts +433 -0
- package/src/incremental-diff.ts +121 -0
- package/src/index.ts +35 -0
- package/src/input-fuzzer.ts +129 -0
- package/src/interactive-probe.ts +623 -0
- package/src/job-queue.test.ts +120 -0
- package/src/job-queue.ts +2701 -0
- package/src/js-coverage.ts +87 -0
- package/src/js-router-detector.ts +112 -0
- package/src/language-detector.ts +82 -0
- package/src/link-classifier.ts +65 -0
- package/src/live-view.ts +141 -0
- package/src/logger.ts +9 -0
- package/src/markdown-extract.test.ts +73 -0
- package/src/markdown-extract.ts +76 -0
- package/src/native-crawler.ts +1106 -0
- package/src/network-observer.ts +204 -0
- package/src/network-throttle.ts +69 -0
- package/src/openapi-generator.ts +135 -0
- package/src/pdf-extractor.ts +123 -0
- package/src/performance-metrics.ts +134 -0
- package/src/phash.ts +151 -0
- package/src/pii-scrubber.ts +99 -0
- package/src/playwright-recorder.ts +170 -0
- package/src/policies/crawl-safety.ts +46 -0
- package/src/profiles/domain-profile.ts +167 -0
- package/src/proxy.ts +238 -0
- package/src/rate-limiter.ts +87 -0
- package/src/redirect-tracker.ts +97 -0
- package/src/redis-frontier.ts +143 -0
- package/src/redis-queue.ts +208 -0
- package/src/response-cache.ts +150 -0
- package/src/responsive-detector.ts +92 -0
- package/src/retry-policy.ts +87 -0
- package/src/robots-txt.ts +96 -0
- package/src/screen-reader.ts +89 -0
- package/src/screenshot-masker.ts +98 -0
- package/src/seo-checker.ts +134 -0
- package/src/session-capture.ts +325 -0
- package/src/session-export.test.ts +75 -0
- package/src/session-export.ts +172 -0
- package/src/sitemap-writer.ts +65 -0
- package/src/sitemap.test.ts +131 -0
- package/src/sitemap.ts +224 -0
- package/src/skyvern.ts +199 -0
- package/src/sqs-queue.ts +49 -0
- package/src/sso-token.ts +120 -0
- package/src/stealth/human-behavior.ts +191 -0
- package/src/telemetry.ts +122 -0
- package/src/test-executor.test.ts +72 -0
- package/src/test-executor.ts +424 -0
- package/src/tls-fingerprint.ts +111 -0
- package/src/url-pattern-completer.ts +114 -0
- package/src/visual-diff-verdict.test.ts +80 -0
- package/src/visual-diff-verdict.ts +57 -0
- package/src/webhook-notifier.ts +109 -0
- package/src/websocket-detector.ts +83 -0
- package/src/worker.ts +48 -0
- package/tsconfig.json +13 -0
- package/types/accessibility-auditor.d.ts +29 -0
- package/types/ai-login.d.ts +32 -0
- package/types/auth-token-rotator.d.ts +47 -0
- package/types/auth.d.ts +20 -0
- package/types/browser-extension.d.ts +37 -0
- package/types/bull-worker.d.ts +6 -0
- package/types/captcha-solver.d.ts +16 -0
- package/types/color-contrast.d.ts +30 -0
- package/types/content-chunker.d.ts +18 -0
- package/types/content-dedup.d.ts +23 -0
- package/types/cookie-consent.d.ts +25 -0
- package/types/cookie-jar.d.ts +20 -0
- package/types/crawler.d.ts +179 -0
- package/types/custom-js-injector.d.ts +42 -0
- package/types/dark-mode-capture.d.ts +23 -0
- package/types/dead-link-detector.d.ts +37 -0
- package/types/element-hash.d.ts +9 -0
- package/types/email-otp.d.ts +42 -0
- package/types/engine-router.d.ts +47 -0
- package/types/export/bulk-export.d.ts +26 -0
- package/types/export/vector-export.d.ts +76 -0
- package/types/extractors/advanced.d.ts +54 -0
- package/types/extractors/artifact-envelope.d.ts +63 -0
- package/types/failure-analysis-agent.d.ts +16 -0
- package/types/feature-flag-detector.d.ts +30 -0
- package/types/form-detector.d.ts +34 -0
- package/types/frontier.d.ts +32 -0
- package/types/gap-pass.d.ts +35 -0
- package/types/graphql-detector.d.ts +39 -0
- package/types/http-engine.d.ts +80 -0
- package/types/incremental-diff.d.ts +59 -0
- package/types/index.d.ts +35 -0
- package/types/input-fuzzer.d.ts +30 -0
- package/types/interactive-probe.d.ts +104 -0
- package/types/job-queue.d.ts +171 -0
- package/types/js-coverage.d.ts +29 -0
- package/types/js-router-detector.d.ts +17 -0
- package/types/language-detector.d.ts +22 -0
- package/types/link-classifier.d.ts +23 -0
- package/types/live-view.d.ts +36 -0
- package/types/logger.d.ts +2 -0
- package/types/markdown-extract.d.ts +8 -0
- package/types/native-crawler.d.ts +69 -0
- package/types/network-observer.d.ts +49 -0
- package/types/network-throttle.d.ts +25 -0
- package/types/openapi-generator.d.ts +49 -0
- package/types/pdf-extractor.d.ts +28 -0
- package/types/performance-metrics.d.ts +53 -0
- package/types/phash.d.ts +38 -0
- package/types/pii-scrubber.d.ts +21 -0
- package/types/playwright-recorder.d.ts +39 -0
- package/types/policies/crawl-safety.d.ts +9 -0
- package/types/profiles/domain-profile.d.ts +19 -0
- package/types/proxy.d.ts +50 -0
- package/types/rate-limiter.d.ts +31 -0
- package/types/redirect-tracker.d.ts +37 -0
- package/types/redis-frontier.d.ts +48 -0
- package/types/redis-queue.d.ts +48 -0
- package/types/response-cache.d.ts +38 -0
- package/types/responsive-detector.d.ts +29 -0
- package/types/retry-policy.d.ts +20 -0
- package/types/robots-txt.d.ts +9 -0
- package/types/screen-reader.d.ts +16 -0
- package/types/screenshot-masker.d.ts +28 -0
- package/types/seo-checker.d.ts +33 -0
- package/types/session-capture.d.ts +38 -0
- package/types/session-export.d.ts +49 -0
- package/types/sitemap-writer.d.ts +21 -0
- package/types/sitemap.d.ts +51 -0
- package/types/skyvern.d.ts +56 -0
- package/types/sqs-queue.d.ts +2 -0
- package/types/sso-token.d.ts +29 -0
- package/types/stealth/human-behavior.d.ts +20 -0
- package/types/telemetry.d.ts +34 -0
- package/types/test-executor.d.ts +67 -0
- package/types/tls-fingerprint.d.ts +50 -0
- package/types/url-pattern-completer.d.ts +28 -0
- package/types/visual-diff-verdict.d.ts +40 -0
- package/types/webhook-notifier.d.ts +30 -0
- package/types/websocket-detector.d.ts +24 -0
- package/types/worker.d.ts +1 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const CONSENT_SELECTORS = [
|
|
2
|
+
// Cookiebot
|
|
3
|
+
"#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll",
|
|
4
|
+
"#CybotCookiebotDialogBodyButtonAccept",
|
|
5
|
+
// OneTrust
|
|
6
|
+
"#onetrust-accept-btn-handler",
|
|
7
|
+
".ot-sdk-accept-btn",
|
|
8
|
+
// TrustArc
|
|
9
|
+
'.truste_popframe [title*="Accept"]',
|
|
10
|
+
"#truste-consent-button",
|
|
11
|
+
// Usercentrics
|
|
12
|
+
'[data-testid="uc-accept-all-button"]',
|
|
13
|
+
// Generic high-confidence
|
|
14
|
+
'[id*="accept"][id*="cookie"]',
|
|
15
|
+
'[class*="accept"][class*="cookie"]',
|
|
16
|
+
'[class*="cookie"][class*="accept"]',
|
|
17
|
+
// GDPR Cookie Compliance
|
|
18
|
+
".gdpr-cookie-notice-accept",
|
|
19
|
+
// Quantcast
|
|
20
|
+
".qc-cmp2-summary-buttons button:first-child"
|
|
21
|
+
];
|
|
22
|
+
const ACCEPT_TEXT_PATTERNS = [
|
|
23
|
+
/^accept all$/i,
|
|
24
|
+
/^accept all cookies$/i,
|
|
25
|
+
/^allow all$/i,
|
|
26
|
+
/^i accept$/i,
|
|
27
|
+
/^agree$/i,
|
|
28
|
+
/^ok$/i,
|
|
29
|
+
/^got it$/i,
|
|
30
|
+
/^allow cookies$/i
|
|
31
|
+
];
|
|
32
|
+
async function acceptCookieConsent(page, opts = {}) {
|
|
33
|
+
const { waitMs = 1500 } = opts;
|
|
34
|
+
await page.waitForTimeout(waitMs).catch(() => {
|
|
35
|
+
});
|
|
36
|
+
for (const selector of CONSENT_SELECTORS) {
|
|
37
|
+
try {
|
|
38
|
+
const el = await page.$(selector);
|
|
39
|
+
if (el && await el.isVisible()) {
|
|
40
|
+
await el.click({ timeout: 2e3 });
|
|
41
|
+
await page.waitForTimeout(500);
|
|
42
|
+
return { found: true, clicked: true, method: `selector: ${selector}` };
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const buttons = await page.$$('button, [role="button"], a[class*="cookie"]');
|
|
49
|
+
for (const btn of buttons) {
|
|
50
|
+
const text = (await btn.textContent() ?? "").trim();
|
|
51
|
+
if (ACCEPT_TEXT_PATTERNS.some((re) => re.test(text))) {
|
|
52
|
+
if (await btn.isVisible()) {
|
|
53
|
+
await btn.click({ timeout: 2e3 });
|
|
54
|
+
await page.waitForTimeout(500);
|
|
55
|
+
return { found: true, clicked: true, method: `text: "${text}"` };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} catch {
|
|
60
|
+
}
|
|
61
|
+
return { found: false, clicked: false };
|
|
62
|
+
}
|
|
63
|
+
async function isConsentBannerVisible(page) {
|
|
64
|
+
try {
|
|
65
|
+
for (const sel of CONSENT_SELECTORS.slice(0, 5)) {
|
|
66
|
+
const el = await page.$(sel);
|
|
67
|
+
if (el && await el.isVisible()) return true;
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
acceptCookieConsent,
|
|
76
|
+
isConsentBannerVisible
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=cookie-consent.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cookie-consent.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Cookie consent auto-acceptor.\n *\n * Detects and clicks \"Accept\" on common cookie consent banners before the\n * crawler proceeds. Without this, many EU sites show a consent wall that\n * blocks content or shows a different layout, making crawl results unreliable.\n *\n * Supports: Cookiebot, OneTrust, TrustArc, Usercentrics, GDPR Cookie Compliance,\n * generic \"Accept All\" / \"Accept Cookies\" buttons.\n *\n * Strategy: try known selectors first, then fall back to text-based button search.\n * Non-blocking \u2014 if no banner is found or click fails, crawl proceeds normally.\n */\n\nimport type { Page } from 'playwright';\n\nexport interface ConsentResult {\n found: boolean;\n clicked: boolean;\n method?: string; // which selector/strategy matched\n error?: string;\n}\n\n// Known consent platform selectors\nconst CONSENT_SELECTORS = [\n // Cookiebot\n '#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll',\n '#CybotCookiebotDialogBodyButtonAccept',\n // OneTrust\n '#onetrust-accept-btn-handler',\n '.ot-sdk-accept-btn',\n // TrustArc\n '.truste_popframe [title*=\"Accept\"]',\n '#truste-consent-button',\n // Usercentrics\n '[data-testid=\"uc-accept-all-button\"]',\n // Generic high-confidence\n '[id*=\"accept\"][id*=\"cookie\"]',\n '[class*=\"accept\"][class*=\"cookie\"]',\n '[class*=\"cookie\"][class*=\"accept\"]',\n // GDPR Cookie Compliance\n '.gdpr-cookie-notice-accept',\n // Quantcast\n '.qc-cmp2-summary-buttons button:first-child',\n];\n\n// Fallback: button text matching\nconst ACCEPT_TEXT_PATTERNS = [\n /^accept all$/i,\n /^accept all cookies$/i,\n /^allow all$/i,\n /^i accept$/i,\n /^agree$/i,\n /^ok$/i,\n /^got it$/i,\n /^allow cookies$/i,\n];\n\nexport async function acceptCookieConsent(page: Page, opts: { waitMs?: number } = {}): Promise<ConsentResult> {\n const { waitMs = 1_500 } = opts;\n\n // Wait briefly for consent banners to appear\n await page.waitForTimeout(waitMs).catch(() => {});\n\n // Try known selectors first\n for (const selector of CONSENT_SELECTORS) {\n try {\n const el = await page.$(selector);\n if (el && await el.isVisible()) {\n await el.click({ timeout: 2_000 });\n await page.waitForTimeout(500);\n return { found: true, clicked: true, method: `selector: ${selector}` };\n }\n } catch { /* try next */ }\n }\n\n // Fallback: find buttons with accept-like text\n try {\n const buttons = await page.$$('button, [role=\"button\"], a[class*=\"cookie\"]');\n for (const btn of buttons) {\n const text = ((await btn.textContent()) ?? '').trim();\n if (ACCEPT_TEXT_PATTERNS.some(re => re.test(text))) {\n if (await btn.isVisible()) {\n await btn.click({ timeout: 2_000 });\n await page.waitForTimeout(500);\n return { found: true, clicked: true, method: `text: \"${text}\"` };\n }\n }\n }\n } catch { /* non-fatal */ }\n\n return { found: false, clicked: false };\n}\n\n/** Check if a consent banner is still visible after attempted dismissal */\nexport async function isConsentBannerVisible(page: Page): Promise<boolean> {\n try {\n for (const sel of CONSENT_SELECTORS.slice(0, 5)) {\n const el = await page.$(sel);\n if (el && await el.isVisible()) return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAwBA,MAAM,oBAAoB;AAAA;AAAA,EAExB;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAGA,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB,MAAY,OAA4B,CAAC,GAA2B;AAC5G,QAAM,EAAE,SAAS,KAAM,IAAI;AAG3B,QAAM,KAAK,eAAe,MAAM,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AAGhD,aAAW,YAAY,mBAAmB;AACxC,QAAI;AACF,YAAM,KAAK,MAAM,KAAK,EAAE,QAAQ;AAChC,UAAI,MAAM,MAAM,GAAG,UAAU,GAAG;AAC9B,cAAM,GAAG,MAAM,EAAE,SAAS,IAAM,CAAC;AACjC,cAAM,KAAK,eAAe,GAAG;AAC7B,eAAO,EAAE,OAAO,MAAM,SAAS,MAAM,QAAQ,aAAa,QAAQ,GAAG;AAAA,MACvE;AAAA,IACF,QAAQ;AAAA,IAAiB;AAAA,EAC3B;AAGA,MAAI;AACF,UAAM,UAAU,MAAM,KAAK,GAAG,6CAA6C;AAC3E,eAAW,OAAO,SAAS;AACzB,YAAM,QAAS,MAAM,IAAI,YAAY,KAAM,IAAI,KAAK;AACpD,UAAI,qBAAqB,KAAK,QAAM,GAAG,KAAK,IAAI,CAAC,GAAG;AAClD,YAAI,MAAM,IAAI,UAAU,GAAG;AACzB,gBAAM,IAAI,MAAM,EAAE,SAAS,IAAM,CAAC;AAClC,gBAAM,KAAK,eAAe,GAAG;AAC7B,iBAAO,EAAE,OAAO,MAAM,SAAS,MAAM,QAAQ,UAAU,IAAI,IAAI;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAAkB;AAE1B,SAAO,EAAE,OAAO,OAAO,SAAS,MAAM;AACxC;AAGA,eAAsB,uBAAuB,MAA8B;AACzE,MAAI;AACF,eAAW,OAAO,kBAAkB,MAAM,GAAG,CAAC,GAAG;AAC/C,YAAM,KAAK,MAAM,KAAK,EAAE,GAAG;AAC3B,UAAI,MAAM,MAAM,GAAG,UAAU,EAAG,QAAO;AAAA,IACzC;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie jar — persist and restore Playwright storageState cookies between
|
|
3
|
+
* crawl segments and restarts. Enables continuous auth across session boundaries
|
|
4
|
+
* (e.g. segment 1 logs in, segment 2–N inherit the session without re-login).
|
|
5
|
+
*
|
|
6
|
+
* Storage: JSON file per project in the crawl cache dir.
|
|
7
|
+
* Format: Playwright's storageState shape (cookies + origins).
|
|
8
|
+
*/
|
|
9
|
+
export interface CookieJarEntry {
|
|
10
|
+
projectId: string;
|
|
11
|
+
tenantId: string;
|
|
12
|
+
storageState: string;
|
|
13
|
+
savedAt: string;
|
|
14
|
+
domain: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function saveCookieJar(cacheDir: string, projectId: string, tenantId: string, storageState: string, domain: string): Promise<void>;
|
|
17
|
+
export declare function loadCookieJar(cacheDir: string, projectId: string, maxAgeMs?: number): Promise<string | null>;
|
|
18
|
+
export declare function clearCookieJar(cacheDir: string, projectId: string): Promise<void>;
|
|
19
|
+
/** Merge two storageState JSON strings — second takes priority for same-domain cookies. */
|
|
20
|
+
export declare function mergeStorageStates(base: string, overlay: string): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
function jarPath(cacheDir, projectId) {
|
|
4
|
+
return path.join(cacheDir, `cookie-jar-${projectId}.json`);
|
|
5
|
+
}
|
|
6
|
+
async function saveCookieJar(cacheDir, projectId, tenantId, storageState, domain) {
|
|
7
|
+
await fs.mkdir(cacheDir, { recursive: true });
|
|
8
|
+
const entry = {
|
|
9
|
+
projectId,
|
|
10
|
+
tenantId,
|
|
11
|
+
storageState,
|
|
12
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13
|
+
domain
|
|
14
|
+
};
|
|
15
|
+
await fs.writeFile(jarPath(cacheDir, projectId), JSON.stringify(entry, null, 2), "utf8");
|
|
16
|
+
}
|
|
17
|
+
async function loadCookieJar(cacheDir, projectId, maxAgeMs = 8 * 60 * 60 * 1e3) {
|
|
18
|
+
try {
|
|
19
|
+
const raw = await fs.readFile(jarPath(cacheDir, projectId), "utf8");
|
|
20
|
+
const entry = JSON.parse(raw);
|
|
21
|
+
const age = Date.now() - new Date(entry.savedAt).getTime();
|
|
22
|
+
if (age > maxAgeMs) return null;
|
|
23
|
+
return entry.storageState;
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function clearCookieJar(cacheDir, projectId) {
|
|
29
|
+
try {
|
|
30
|
+
await fs.unlink(jarPath(cacheDir, projectId));
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function mergeStorageStates(base, overlay) {
|
|
35
|
+
try {
|
|
36
|
+
const a = JSON.parse(base);
|
|
37
|
+
const b = JSON.parse(overlay);
|
|
38
|
+
const cookies = [...a.cookies ?? []];
|
|
39
|
+
for (const ck of b.cookies ?? []) {
|
|
40
|
+
const idx = cookies.findIndex(
|
|
41
|
+
(c) => c.name === ck.name && c.domain === ck.domain && c.path === ck.path
|
|
42
|
+
);
|
|
43
|
+
if (idx >= 0) cookies[idx] = ck;
|
|
44
|
+
else cookies.push(ck);
|
|
45
|
+
}
|
|
46
|
+
const originsMap = /* @__PURE__ */ new Map();
|
|
47
|
+
for (const o of [...a.origins ?? [], ...b.origins ?? []]) {
|
|
48
|
+
originsMap.set(o.origin, o);
|
|
49
|
+
}
|
|
50
|
+
return JSON.stringify({ cookies, origins: [...originsMap.values()] });
|
|
51
|
+
} catch {
|
|
52
|
+
return overlay || base;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export {
|
|
56
|
+
clearCookieJar,
|
|
57
|
+
loadCookieJar,
|
|
58
|
+
mergeStorageStates,
|
|
59
|
+
saveCookieJar
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=cookie-jar.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cookie-jar.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Cookie jar \u2014 persist and restore Playwright storageState cookies between\n * crawl segments and restarts. Enables continuous auth across session boundaries\n * (e.g. segment 1 logs in, segment 2\u2013N inherit the session without re-login).\n *\n * Storage: JSON file per project in the crawl cache dir.\n * Format: Playwright's storageState shape (cookies + origins).\n */\n\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nexport interface CookieJarEntry {\n projectId: string;\n tenantId: string;\n storageState: string; // JSON-stringified Playwright StorageState\n savedAt: string; // ISO timestamp\n domain: string; // hostname for quick lookup\n}\n\nfunction jarPath(cacheDir: string, projectId: string): string {\n return path.join(cacheDir, `cookie-jar-${projectId}.json`);\n}\n\nexport async function saveCookieJar(\n cacheDir: string,\n projectId: string,\n tenantId: string,\n storageState: string,\n domain: string,\n): Promise<void> {\n await fs.mkdir(cacheDir, { recursive: true });\n const entry: CookieJarEntry = {\n projectId,\n tenantId,\n storageState,\n savedAt: new Date().toISOString(),\n domain,\n };\n await fs.writeFile(jarPath(cacheDir, projectId), JSON.stringify(entry, null, 2), 'utf8');\n}\n\nexport async function loadCookieJar(\n cacheDir: string,\n projectId: string,\n maxAgeMs = 8 * 60 * 60 * 1000, // 8 hours\n): Promise<string | null> {\n try {\n const raw = await fs.readFile(jarPath(cacheDir, projectId), 'utf8');\n const entry: CookieJarEntry = JSON.parse(raw);\n const age = Date.now() - new Date(entry.savedAt).getTime();\n if (age > maxAgeMs) return null; // expired\n return entry.storageState;\n } catch {\n return null;\n }\n}\n\nexport async function clearCookieJar(cacheDir: string, projectId: string): Promise<void> {\n try {\n await fs.unlink(jarPath(cacheDir, projectId));\n } catch { /* already gone */ }\n}\n\n/** Merge two storageState JSON strings \u2014 second takes priority for same-domain cookies. */\nexport function mergeStorageStates(base: string, overlay: string): string {\n try {\n const a = JSON.parse(base);\n const b = JSON.parse(overlay);\n\n // Cookies: overlay replaces same-name+domain+path cookies from base\n const cookies = [...(a.cookies ?? [])];\n for (const ck of (b.cookies ?? [])) {\n const idx = cookies.findIndex(\n (c: any) => c.name === ck.name && c.domain === ck.domain && c.path === ck.path,\n );\n if (idx >= 0) cookies[idx] = ck;\n else cookies.push(ck);\n }\n\n // Origins: merge origins, overlay wins on same-origin\n const originsMap = new Map<string, any>();\n for (const o of [...(a.origins ?? []), ...(b.origins ?? [])]) {\n originsMap.set(o.origin, o);\n }\n\n return JSON.stringify({ cookies, origins: [...originsMap.values()] });\n } catch {\n return overlay || base;\n }\n}\n"],
|
|
5
|
+
"mappings": "AASA,YAAY,QAAQ;AACpB,YAAY,UAAU;AAUtB,SAAS,QAAQ,UAAkB,WAA2B;AAC5D,SAAO,KAAK,KAAK,UAAU,cAAc,SAAS,OAAO;AAC3D;AAEA,eAAsB,cACpB,UACA,WACA,UACA,cACA,QACe;AACf,QAAM,GAAG,MAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AAC5C,QAAM,QAAwB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,IAChC;AAAA,EACF;AACA,QAAM,GAAG,UAAU,QAAQ,UAAU,SAAS,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,MAAM;AACzF;AAEA,eAAsB,cACpB,UACA,WACA,WAAW,IAAI,KAAK,KAAK,KACD;AACxB,MAAI;AACF,UAAM,MAAM,MAAM,GAAG,SAAS,QAAQ,UAAU,SAAS,GAAG,MAAM;AAClE,UAAM,QAAwB,KAAK,MAAM,GAAG;AAC5C,UAAM,MAAM,KAAK,IAAI,IAAI,IAAI,KAAK,MAAM,OAAO,EAAE,QAAQ;AACzD,QAAI,MAAM,SAAU,QAAO;AAC3B,WAAO,MAAM;AAAA,EACf,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,eAAe,UAAkB,WAAkC;AACvF,MAAI;AACF,UAAM,GAAG,OAAO,QAAQ,UAAU,SAAS,CAAC;AAAA,EAC9C,QAAQ;AAAA,EAAqB;AAC/B;AAGO,SAAS,mBAAmB,MAAc,SAAyB;AACxE,MAAI;AACF,UAAM,IAAI,KAAK,MAAM,IAAI;AACzB,UAAM,IAAI,KAAK,MAAM,OAAO;AAG5B,UAAM,UAAU,CAAC,GAAI,EAAE,WAAW,CAAC,CAAE;AACrC,eAAW,MAAO,EAAE,WAAW,CAAC,GAAI;AAClC,YAAM,MAAM,QAAQ;AAAA,QAClB,CAAC,MAAW,EAAE,SAAS,GAAG,QAAQ,EAAE,WAAW,GAAG,UAAU,EAAE,SAAS,GAAG;AAAA,MAC5E;AACA,UAAI,OAAO,EAAG,SAAQ,GAAG,IAAI;AAAA,UACxB,SAAQ,KAAK,EAAE;AAAA,IACtB;AAGA,UAAM,aAAa,oBAAI,IAAiB;AACxC,eAAW,KAAK,CAAC,GAAI,EAAE,WAAW,CAAC,GAAI,GAAI,EAAE,WAAW,CAAC,CAAE,GAAG;AAC5D,iBAAW,IAAI,EAAE,QAAQ,CAAC;AAAA,IAC5B;AAEA,WAAO,KAAK,UAAU,EAAE,SAAS,SAAS,CAAC,GAAG,WAAW,OAAO,CAAC,EAAE,CAAC;AAAA,EACtE,QAAQ;AACN,WAAO,WAAW;AAAA,EACpB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZeTa-AI Crawler — Stagehand hybrid architecture
|
|
3
|
+
*
|
|
4
|
+
* Three-layer stack:
|
|
5
|
+
* Layer 1 — Playwright (deterministic): navigation, screenshots, DOM fallbacks
|
|
6
|
+
* Layer 2 — Stagehand act/extract (AI): login, element understanding, smart link discovery
|
|
7
|
+
* Layer 3 — Skyvern (vision): fallback for CAPTCHAs, legacy apps, visual-only flows
|
|
8
|
+
*
|
|
9
|
+
* enableCaching: true → repeat crawls of the same site cost ~zero AI tokens after first run.
|
|
10
|
+
*/
|
|
11
|
+
import type { Credentials } from './auth.js';
|
|
12
|
+
import { type SkyvernConfig } from './skyvern.js';
|
|
13
|
+
import { type TraversalStrategy } from './frontier.js';
|
|
14
|
+
import { type ApiEndpointObservationInput } from './network-observer.js';
|
|
15
|
+
import type { ProxyTierConfig } from './proxy.js';
|
|
16
|
+
interface PerformanceMetric {
|
|
17
|
+
url: string;
|
|
18
|
+
screenName: string;
|
|
19
|
+
lcp?: number;
|
|
20
|
+
fcp?: number;
|
|
21
|
+
ttfb?: number;
|
|
22
|
+
cls?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Lightweight pre-crawl link discovery: loads the app URL in a headless (proxy-aware) browser
|
|
26
|
+
* and returns same-site `<a href>` links. Complements sitemap discovery for SPA/app sites that
|
|
27
|
+
* have no sitemap.xml. Best-effort — returns [] on any failure (bot wall, timeout, etc.).
|
|
28
|
+
* chromium.launch({ proxy }) handles proxy 407 auth itself (same client), so no CDP handler needed.
|
|
29
|
+
*/
|
|
30
|
+
export declare function discoverLinksViaBrowser(appUrl: string, opts?: {
|
|
31
|
+
proxyUrl?: string;
|
|
32
|
+
maxLinks?: number;
|
|
33
|
+
}): Promise<string[]>;
|
|
34
|
+
export declare function crawlProject(opts: {
|
|
35
|
+
tenantId: string;
|
|
36
|
+
projectId: string;
|
|
37
|
+
appUrl: string;
|
|
38
|
+
credentials?: Credentials;
|
|
39
|
+
/** Playwright storageState JSON string — if present, session is restored and AI login is skipped. */
|
|
40
|
+
storageState?: string;
|
|
41
|
+
screenshotDir?: string;
|
|
42
|
+
/** When true, run a fast URL-only discovery crawl — skips screenshots, DB saves, and AI element extraction. Returns discoveredUrls in the result object. */
|
|
43
|
+
discoveryMode?: boolean;
|
|
44
|
+
maxScreens?: number;
|
|
45
|
+
/** Seed URLs added to the initial crawl queue — link discovery still runs from each page. */
|
|
46
|
+
startUrls?: string[];
|
|
47
|
+
/** When provided, crawl ONLY these exact URLs (no link-following, no full screen clear). Used for selected-screen recrawl. */
|
|
48
|
+
selectiveUrls?: string[];
|
|
49
|
+
/** When true, run the interactive probe after static crawl to capture real validation errors, toasts, and modals. */
|
|
50
|
+
interactive?: boolean;
|
|
51
|
+
/** Optional abort signal — abort() cancels the crawl between page navigations. */
|
|
52
|
+
abortSignal?: AbortSignal;
|
|
53
|
+
/** Platform job ID — stored on screens so we can diff which were found in each crawl. */
|
|
54
|
+
jobId?: string;
|
|
55
|
+
/** Device profiles to capture screenshots for after the main DESKTOP crawl.
|
|
56
|
+
* Values: 'MOBILE_PORTRAIT' | 'TABLET'
|
|
57
|
+
* The main crawl always runs as DESKTOP. Extra profiles trigger a screenshot-only pass.
|
|
58
|
+
*/
|
|
59
|
+
deviceProfiles?: string[];
|
|
60
|
+
/** HTTP Basic Auth credentials — injected as Authorization header on same-origin requests. */
|
|
61
|
+
httpBasicUsername?: string;
|
|
62
|
+
httpBasicPassword?: string;
|
|
63
|
+
/** Bearer/API token — injected as a request header and into localStorage. Skips AI login. */
|
|
64
|
+
authToken?: string;
|
|
65
|
+
/** Header name for authToken (default: 'Authorization'). */
|
|
66
|
+
authTokenHeader?: string;
|
|
67
|
+
/** Prefix for authToken value (default: 'Bearer '). */
|
|
68
|
+
authTokenPrefix?: string;
|
|
69
|
+
/** CAPTCHA solving API key (2captcha or CapSolver). */
|
|
70
|
+
captchaSolverApiKey?: string;
|
|
71
|
+
/** CAPTCHA solving service provider (default: '2captcha'). */
|
|
72
|
+
captchaSolverProvider?: '2captcha' | 'capsolver';
|
|
73
|
+
/**
|
|
74
|
+
* Path to a Chrome user data directory for profile inheritance.
|
|
75
|
+
* When set, the crawler exports the existing session from this profile and injects it,
|
|
76
|
+
* so the agent is already logged in. Works for local/self-hosted deployments only.
|
|
77
|
+
* Ignored on cloud/Docker (headless env cannot open another Chrome instance safely).
|
|
78
|
+
*/
|
|
79
|
+
chromeProfilePath?: string;
|
|
80
|
+
/** MailSlurp API key for email OTP auto-retrieval (GAP 5). */
|
|
81
|
+
mailslurpApiKey?: string;
|
|
82
|
+
/** MailSlurp inbox ID to poll for OTP emails (GAP 5). */
|
|
83
|
+
mailslurpInboxId?: string;
|
|
84
|
+
/** SSO provider for ROPC token flow — 'okta' | 'azure_ad' | 'generic_oidc' (GAP 18). */
|
|
85
|
+
ssoProvider?: string;
|
|
86
|
+
/** SSO domain or Azure tenant ID (GAP 18). */
|
|
87
|
+
ssoDomain?: string;
|
|
88
|
+
/** SSO OAuth2 client ID (GAP 18). */
|
|
89
|
+
ssoClientId?: string;
|
|
90
|
+
/** SSO OAuth2 client secret (GAP 18). */
|
|
91
|
+
ssoClientSecret?: string;
|
|
92
|
+
/** SSO scopes (space-separated, default: 'openid profile') (GAP 18). */
|
|
93
|
+
ssoScope?: string;
|
|
94
|
+
/** HTTP/HTTPS/SOCKS5 proxy URL — e.g. 'http://user:pass@proxy.example.com:8080' or 'socks5://proxy:1080'.
|
|
95
|
+
* Useful for sites that block datacenter IPs (Akamai, Cloudflare Bot Manager). */
|
|
96
|
+
proxyUrl?: string;
|
|
97
|
+
/** Tiered proxy configuration for automatic per-domain escalation (free → datacenter → residential → premium). */
|
|
98
|
+
proxyTiers?: ProxyTierConfig[];
|
|
99
|
+
/** Use Camoufox (Firefox) as a cookie bootstrapper before the main Chromium crawl.
|
|
100
|
+
* Camoufox visits the URL first to solve Cloudflare JS challenges and extract session
|
|
101
|
+
* cookies, which are then injected into the Chromium crawl as storageState.
|
|
102
|
+
* Enable via Project Settings → Crawl Config → useFirefox: true. */
|
|
103
|
+
useFirefox?: boolean;
|
|
104
|
+
/** Natural language login instructions for Stagehand AI login. E.g. "Click Sign In in the nav, fill email, click Continue". */
|
|
105
|
+
loginInstructions?: string;
|
|
106
|
+
/** Skyvern vision fallback config from workspace settings (overrides SKYVERN_API_URL/KEY env vars). */
|
|
107
|
+
skyvernConfig?: SkyvernConfig;
|
|
108
|
+
/**
|
|
109
|
+
* Max screens to crawl per segment (default 50).
|
|
110
|
+
* After this limit the crawl pauses and remaining URLs are saved so the
|
|
111
|
+
* next job can continue. Total crawl is unlimited — just runs in multiple jobs.
|
|
112
|
+
*/
|
|
113
|
+
segmentSize?: number;
|
|
114
|
+
/** URLs still queued from a previous segment — injected by the job-queue auto-continuation. */
|
|
115
|
+
resumeUrls?: string[];
|
|
116
|
+
/** Segment number (1-based) — used for progress display only. */
|
|
117
|
+
segmentIndex?: number;
|
|
118
|
+
/** Seed the crawl queue from the project's sitemap.xml, in addition to link-following. */
|
|
119
|
+
useSitemap?: boolean;
|
|
120
|
+
/** Explicit sitemap URL override — defaults to `${origin}/sitemap.xml` when useSitemap is set. */
|
|
121
|
+
sitemapUrl?: string;
|
|
122
|
+
/** Crawl queue traversal order. Default BFS — unchanged behavior from before this option existed. */
|
|
123
|
+
traversalStrategy?: TraversalStrategy;
|
|
124
|
+
/** BEST_FIRST only: URLs containing any of these (case-insensitive) are prioritized. */
|
|
125
|
+
bestFirstKeywords?: string[];
|
|
126
|
+
/** When true, skip URLs disallowed by the site's robots.txt. Default false. */
|
|
127
|
+
respectRobotsTxt?: boolean;
|
|
128
|
+
/** When true, dynamically slow crawl speed when server response latency is high (Scrapy-style AutoThrottle). Default false. */
|
|
129
|
+
autoThrottle?: boolean;
|
|
130
|
+
/** Regex pattern — only crawl URLs whose path+query match this pattern. */
|
|
131
|
+
urlFilter?: string;
|
|
132
|
+
/** Already-captured URLs from a previous failed job — pre-seeded into visited map so they're never re-crawled. */
|
|
133
|
+
skipUrls?: string[];
|
|
134
|
+
/** DOM hashes collected in a prior segment — prevents re-screenshotting structurally identical pages across segments. */
|
|
135
|
+
knownDomHashes?: string[];
|
|
136
|
+
/** Called every 10 successful screen captures with current visited URLs and remaining queue — used for checkpoint persistence. */
|
|
137
|
+
onCheckpoint?: (visitedUrls: string[], pendingQueue: string[]) => Promise<void>;
|
|
138
|
+
/** Discovery mode only: called after each page with the current set of discovered original URLs — enables streaming partial results to callers. */
|
|
139
|
+
onUrlsDiscovered?: (urls: string[]) => Promise<void>;
|
|
140
|
+
}, onProgress?: (pct: number, step: string) => Promise<void>): Promise<{
|
|
141
|
+
discoveredUrls: string[];
|
|
142
|
+
screensFound: number;
|
|
143
|
+
screensErrored: number;
|
|
144
|
+
screensSkippedToNextSegment: number;
|
|
145
|
+
isPartial: boolean;
|
|
146
|
+
discovered: never[];
|
|
147
|
+
apiEndpoints: never[];
|
|
148
|
+
performanceMetrics: never[];
|
|
149
|
+
pendingUrls: never[];
|
|
150
|
+
segmentIndex: number;
|
|
151
|
+
hasMoreSegments: boolean;
|
|
152
|
+
domHashes: string[];
|
|
153
|
+
} | {
|
|
154
|
+
screensFound: number;
|
|
155
|
+
screensErrored: number;
|
|
156
|
+
screensSkippedToNextSegment: number;
|
|
157
|
+
isPartial: boolean;
|
|
158
|
+
discovered: {
|
|
159
|
+
url: string;
|
|
160
|
+
screenId?: string;
|
|
161
|
+
elements?: number;
|
|
162
|
+
elementFacts?: Array<{
|
|
163
|
+
meaning: string;
|
|
164
|
+
role: string;
|
|
165
|
+
expectedData?: string;
|
|
166
|
+
}>;
|
|
167
|
+
screenshotPath?: string;
|
|
168
|
+
version?: number;
|
|
169
|
+
error?: string;
|
|
170
|
+
}[];
|
|
171
|
+
apiEndpoints: ApiEndpointObservationInput[];
|
|
172
|
+
performanceMetrics: PerformanceMetric[];
|
|
173
|
+
pendingUrls: string[];
|
|
174
|
+
segmentIndex: number;
|
|
175
|
+
hasMoreSegments: boolean;
|
|
176
|
+
domHashes: string[];
|
|
177
|
+
discoveredUrls?: undefined;
|
|
178
|
+
}>;
|
|
179
|
+
export {};
|