@taodigital/crawler 0.0.0-stage → 1.2.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/Dockerfile +82 -0
- package/README.md +10 -2
- 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/accessibility-tree-crawler.d.ts +44 -0
- package/dist/accessibility-tree-crawler.js +156 -0
- package/dist/accessibility-tree-crawler.js.map +7 -0
- package/dist/advanced-ui-probes.d.ts +47 -0
- package/dist/advanced-ui-probes.js +310 -0
- package/dist/advanced-ui-probes.js.map +7 -0
- package/dist/ai-login.d.ts +32 -0
- package/dist/ai-login.js +250 -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 +348 -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/crawl-session-manager.d.ts +44 -0
- package/dist/crawl-session-manager.js +145 -0
- package/dist/crawl-session-manager.js.map +7 -0
- package/dist/crawler.d.ts +233 -0
- package/dist/crawler.js +6239 -0
- package/dist/crawler.js.map +7 -0
- package/dist/crud-interaction.d.ts +31 -0
- package/dist/crud-interaction.js +264 -0
- package/dist/crud-interaction.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/dropdown-enumerator.d.ts +20 -0
- package/dist/dropdown-enumerator.js +230 -0
- package/dist/dropdown-enumerator.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 +64 -0
- package/dist/extractors/advanced.js +265 -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/extractors/branding-extractor.d.ts +46 -0
- package/dist/extractors/branding-extractor.js +104 -0
- package/dist/extractors/branding-extractor.js.map +7 -0
- package/dist/extractors/summary-extractor.d.ts +10 -0
- package/dist/extractors/summary-extractor.js +36 -0
- package/dist/extractors/summary-extractor.js.map +7 -0
- package/dist/failure-analysis-agent.d.ts +16 -0
- package/dist/failure-analysis-agent.js +42 -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/filter-pagination-crawler.d.ts +52 -0
- package/dist/filter-pagination-crawler.js +299 -0
- package/dist/filter-pagination-crawler.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 +40 -0
- package/dist/frontier.js +103 -0
- package/dist/frontier.js.map +7 -0
- package/dist/gap-pass.d.ts +36 -0
- package/dist/gap-pass.js +115 -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 +318 -0
- package/dist/http-engine.js.map +7 -0
- package/dist/incremental-diff.d.ts +116 -0
- package/dist/incremental-diff.js +137 -0
- package/dist/incremental-diff.js.map +7 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.js +83 -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 +144 -0
- package/dist/interactive-probe.js +865 -0
- package/dist/interactive-probe.js.map +7 -0
- package/dist/job-queue.d.ts +297 -0
- package/dist/job-queue.js +3812 -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 +105 -0
- package/dist/live-view.js.map +7 -0
- package/dist/locator-extractor.d.ts +46 -0
- package/dist/locator-extractor.js +220 -0
- package/dist/locator-extractor.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/multi-context-handler.d.ts +55 -0
- package/dist/multi-context-handler.js +182 -0
- package/dist/multi-context-handler.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/nested-window-crawler.d.ts +41 -0
- package/dist/nested-window-crawler.js +172 -0
- package/dist/nested-window-crawler.js.map +7 -0
- package/dist/network-action-correlator.d.ts +47 -0
- package/dist/network-action-correlator.js +209 -0
- package/dist/network-action-correlator.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-collector.d.ts +50 -0
- package/dist/performance-metrics-collector.js +155 -0
- package/dist/performance-metrics-collector.js.map +7 -0
- package/dist/performance-metrics.d.ts +52 -0
- package/dist/performance-metrics.js +83 -0
- package/dist/performance-metrics.js.map +7 -0
- package/dist/phash.d.ts +50 -0
- package/dist/phash.js +136 -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 +41 -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 +160 -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 +15 -0
- package/dist/screen-reader.js +48 -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/service-worker-interceptor.d.ts +36 -0
- package/dist/service-worker-interceptor.js +136 -0
- package/dist/service-worker-interceptor.js.map +7 -0
- package/dist/session-capture.d.ts +39 -0
- package/dist/session-capture.js +274 -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/shadow-dom-crawler.d.ts +35 -0
- package/dist/shadow-dom-crawler.js +132 -0
- package/dist/shadow-dom-crawler.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 +160 -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 +13 -0
- package/dist/sqs-queue.js +115 -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/state-graph.d.ts +59 -0
- package/dist/state-graph.js +193 -0
- package/dist/state-graph.js.map +7 -0
- package/dist/stealth/human-behavior.d.ts +20 -0
- package/dist/stealth/human-behavior.js +202 -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 +81 -0
- package/dist/test-executor.js +443 -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 +122 -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 +27 -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 +49 -4
- package/src/accessibility-auditor.ts +102 -0
- package/src/accessibility-tree-crawler.ts +246 -0
- package/src/advanced-ui-probes.ts +470 -0
- package/src/ai-login.ts +298 -0
- package/src/auth-token-rotator.ts +89 -0
- package/src/auth.ts +418 -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/crawl-session-manager.ts +231 -0
- package/src/crawler.ts +7123 -0
- package/src/crawler.ts.rej +12 -0
- package/src/crud-interaction.ts +386 -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/dropdown-enumerator.ts +312 -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 +309 -0
- package/src/extractors/artifact-envelope.ts +111 -0
- package/src/extractors/branding-extractor.ts +159 -0
- package/src/extractors/summary-extractor.ts +49 -0
- package/src/failure-analysis-agent.ts +51 -0
- package/src/feature-flag-detector.ts +97 -0
- package/src/filter-pagination-crawler.ts +500 -0
- package/src/form-detector.ts +103 -0
- package/src/frontier.test.ts +64 -0
- package/src/frontier.ts +144 -0
- package/src/gap-pass.ts +165 -0
- package/src/graphql-detector.ts +129 -0
- package/src/http-engine.ts +453 -0
- package/src/incremental-diff.ts +259 -0
- package/src/index.ts +52 -0
- package/src/input-fuzzer.ts +129 -0
- package/src/interactive-probe.ts +1136 -0
- package/src/job-queue.test.ts +187 -0
- package/src/job-queue.ts +4504 -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 +146 -0
- package/src/locator-extractor.ts +309 -0
- package/src/logger.ts +9 -0
- package/src/markdown-extract.test.ts +73 -0
- package/src/markdown-extract.ts +76 -0
- package/src/multi-context-handler.ts +296 -0
- package/src/native-crawler.ts +1108 -0
- package/src/nested-window-crawler.ts +310 -0
- package/src/network-action-correlator.ts +320 -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-collector.ts +243 -0
- package/src/performance-metrics.ts +134 -0
- package/src/phash.ts +184 -0
- package/src/pii-scrubber.ts +99 -0
- package/src/playwright-recorder.ts +170 -0
- package/src/policies/crawl-safety.ts +52 -0
- package/src/profiles/domain-profile.ts +190 -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 +98 -0
- package/src/screenshot-masker.ts +98 -0
- package/src/seo-checker.ts +134 -0
- package/src/service-worker-interceptor.ts +185 -0
- package/src/session-capture.ts +335 -0
- package/src/session-export.test.ts +75 -0
- package/src/session-export.ts +172 -0
- package/src/shadow-dom-crawler.ts +198 -0
- package/src/sitemap-writer.ts +65 -0
- package/src/sitemap.test.ts +127 -0
- package/src/sitemap.ts +233 -0
- package/src/skyvern.ts +199 -0
- package/src/sqs-queue.ts +129 -0
- package/src/sso-token.ts +120 -0
- package/src/state-graph.ts +280 -0
- package/src/stealth/human-behavior.ts +227 -0
- package/src/telemetry.ts +122 -0
- package/src/test-executor.test.ts +72 -0
- package/src/test-executor.ts +578 -0
- package/src/tls-fingerprint.ts +111 -0
- package/src/url-pattern-completer.ts +161 -0
- package/src/vendor.d.ts +20 -0
- package/src/visual-diff-verdict.test.ts +80 -0
- package/src/visual-diff-verdict.ts +59 -0
- package/src/webhook-notifier.ts +109 -0
- package/src/websocket-detector.ts +83 -0
- package/src/worker.ts +50 -0
- package/tsconfig.json +13 -0
- package/types/accessibility-auditor.d.ts +29 -0
- package/types/accessibility-tree-crawler.d.ts +44 -0
- package/types/advanced-ui-probes.d.ts +47 -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/crawl-session-manager.d.ts +44 -0
- package/types/crawler.d.ts +233 -0
- package/types/crud-interaction.d.ts +31 -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/dropdown-enumerator.d.ts +20 -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 +64 -0
- package/types/extractors/artifact-envelope.d.ts +63 -0
- package/types/extractors/branding-extractor.d.ts +46 -0
- package/types/extractors/summary-extractor.d.ts +10 -0
- package/types/failure-analysis-agent.d.ts +16 -0
- package/types/feature-flag-detector.d.ts +30 -0
- package/types/filter-pagination-crawler.d.ts +52 -0
- package/types/form-detector.d.ts +34 -0
- package/types/frontier.d.ts +40 -0
- package/types/gap-pass.d.ts +36 -0
- package/types/graphql-detector.d.ts +39 -0
- package/types/http-engine.d.ts +80 -0
- package/types/incremental-diff.d.ts +116 -0
- package/types/index.d.ts +52 -0
- package/types/input-fuzzer.d.ts +30 -0
- package/types/interactive-probe.d.ts +144 -0
- package/types/job-queue.d.ts +308 -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/locator-extractor.d.ts +46 -0
- package/types/logger.d.ts +2 -0
- package/types/markdown-extract.d.ts +8 -0
- package/types/multi-context-handler.d.ts +55 -0
- package/types/native-crawler.d.ts +69 -0
- package/types/nested-window-crawler.d.ts +41 -0
- package/types/network-action-correlator.d.ts +47 -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-collector.d.ts +50 -0
- package/types/performance-metrics.d.ts +52 -0
- package/types/phash.d.ts +50 -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 +15 -0
- package/types/screenshot-masker.d.ts +28 -0
- package/types/seo-checker.d.ts +33 -0
- package/types/service-worker-interceptor.d.ts +36 -0
- package/types/session-capture.d.ts +39 -0
- package/types/session-export.d.ts +49 -0
- package/types/shadow-dom-crawler.d.ts +35 -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 +13 -0
- package/types/sso-token.d.ts +29 -0
- package/types/state-graph.d.ts +59 -0
- package/types/stealth/human-behavior.d.ts +20 -0
- package/types/telemetry.d.ts +34 -0
- package/types/test-executor.d.ts +84 -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,137 @@
|
|
|
1
|
+
function hashContent(text) {
|
|
2
|
+
let h1 = 5381;
|
|
3
|
+
let h2 = 52711;
|
|
4
|
+
for (let i = 0; i < text.length; i++) {
|
|
5
|
+
const c = text.charCodeAt(i);
|
|
6
|
+
h1 = (Math.imul(h1, 33) ^ c) >>> 0;
|
|
7
|
+
h2 = (Math.imul(h2, 31) ^ c) >>> 0;
|
|
8
|
+
}
|
|
9
|
+
return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
|
|
10
|
+
}
|
|
11
|
+
function normalizeText(text) {
|
|
12
|
+
return text.split("\n").map((l) => l.trim()).filter((l) => l.length > 0).join("\n");
|
|
13
|
+
}
|
|
14
|
+
function computeContentHash(url, markdownText) {
|
|
15
|
+
const normalized = normalizeText(markdownText);
|
|
16
|
+
return {
|
|
17
|
+
url,
|
|
18
|
+
hash: hashContent(normalized),
|
|
19
|
+
textLength: normalized.length,
|
|
20
|
+
computedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function diffContent(url, currentMarkdown, priorHashes) {
|
|
24
|
+
const current = computeContentHash(url, currentMarkdown);
|
|
25
|
+
const prior = priorHashes.get(url);
|
|
26
|
+
if (!prior) {
|
|
27
|
+
return { url, changed: true, currentHash: current.hash, reason: "new" };
|
|
28
|
+
}
|
|
29
|
+
if (prior === current.hash) {
|
|
30
|
+
return { url, changed: false, previousHash: prior, currentHash: current.hash, reason: "unchanged" };
|
|
31
|
+
}
|
|
32
|
+
return { url, changed: true, previousHash: prior, currentHash: current.hash, reason: "changed" };
|
|
33
|
+
}
|
|
34
|
+
function buildPriorHashMap(screenRecords) {
|
|
35
|
+
const map = /* @__PURE__ */ new Map();
|
|
36
|
+
for (const s of screenRecords) {
|
|
37
|
+
if (s.url && s.elementHash) map.set(s.url, s.elementHash);
|
|
38
|
+
}
|
|
39
|
+
return map;
|
|
40
|
+
}
|
|
41
|
+
function partitionByChange(urls, priorHashes) {
|
|
42
|
+
const toProcess = [];
|
|
43
|
+
const toSkip = [];
|
|
44
|
+
for (const url of urls) {
|
|
45
|
+
if (priorHashes.has(url)) {
|
|
46
|
+
toProcess.push(url);
|
|
47
|
+
} else {
|
|
48
|
+
toProcess.push(url);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { toProcess, toSkip };
|
|
52
|
+
}
|
|
53
|
+
function computeTextDiffs(previous, current) {
|
|
54
|
+
const prevLines = previous.split("\n");
|
|
55
|
+
const currLines = current.split("\n");
|
|
56
|
+
const changes = [];
|
|
57
|
+
const prevSet = new Set(prevLines);
|
|
58
|
+
const currSet = new Set(currLines);
|
|
59
|
+
let lineNum = 0;
|
|
60
|
+
for (const line of prevLines) {
|
|
61
|
+
if (!currSet.has(line)) {
|
|
62
|
+
changes.push({ type: "removed", line: lineNum, content: line });
|
|
63
|
+
}
|
|
64
|
+
lineNum++;
|
|
65
|
+
}
|
|
66
|
+
lineNum = 0;
|
|
67
|
+
for (const line of currLines) {
|
|
68
|
+
if (!prevSet.has(line)) {
|
|
69
|
+
changes.push({ type: "added", line: lineNum, content: line });
|
|
70
|
+
}
|
|
71
|
+
lineNum++;
|
|
72
|
+
}
|
|
73
|
+
return changes;
|
|
74
|
+
}
|
|
75
|
+
function computeSetDiffs(previous, current) {
|
|
76
|
+
const prevSet = new Set(previous);
|
|
77
|
+
const currSet = new Set(current);
|
|
78
|
+
return {
|
|
79
|
+
added: current.filter((u) => !prevSet.has(u)),
|
|
80
|
+
removed: previous.filter((u) => !currSet.has(u))
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function flattenJson(obj, prefix = "") {
|
|
84
|
+
if (typeof obj !== "object" || obj === null) {
|
|
85
|
+
return { [prefix]: obj };
|
|
86
|
+
}
|
|
87
|
+
const result = {};
|
|
88
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
89
|
+
const path = prefix ? `${prefix}.${k}` : k;
|
|
90
|
+
if (typeof v === "object" && v !== null && !Array.isArray(v)) {
|
|
91
|
+
Object.assign(result, flattenJson(v, path));
|
|
92
|
+
} else {
|
|
93
|
+
result[path] = v;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
function computeJsonDiffs(previous, current) {
|
|
99
|
+
const prevFlat = flattenJson(previous);
|
|
100
|
+
const currFlat = flattenJson(current);
|
|
101
|
+
const allKeys = /* @__PURE__ */ new Set([...Object.keys(prevFlat), ...Object.keys(currFlat)]);
|
|
102
|
+
const changes = [];
|
|
103
|
+
for (const path of allKeys) {
|
|
104
|
+
const oldVal = prevFlat[path];
|
|
105
|
+
const newVal = currFlat[path];
|
|
106
|
+
if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
|
107
|
+
changes.push({ path, old: oldVal, new: newVal });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return changes;
|
|
111
|
+
}
|
|
112
|
+
function countMonitorDiffs(diffs) {
|
|
113
|
+
let count = 0;
|
|
114
|
+
if (diffs.markdown) count += diffs.markdown.length;
|
|
115
|
+
if (diffs.html) count += diffs.html.length;
|
|
116
|
+
if (diffs.json) count += diffs.json.length;
|
|
117
|
+
if (diffs.summary) count += diffs.summary.length;
|
|
118
|
+
if (diffs.links) count += diffs.links.added.length + diffs.links.removed.length;
|
|
119
|
+
if (diffs.images) count += diffs.images.added.length + diffs.images.removed.length;
|
|
120
|
+
if (diffs.branding) count += diffs.branding.length;
|
|
121
|
+
if (diffs.screenshot) count += diffs.screenshot.changed > 0 ? 1 : 0;
|
|
122
|
+
return count;
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
buildPriorHashMap,
|
|
126
|
+
computeContentHash,
|
|
127
|
+
computeJsonDiffs,
|
|
128
|
+
computeSetDiffs,
|
|
129
|
+
computeTextDiffs,
|
|
130
|
+
countMonitorDiffs,
|
|
131
|
+
diffContent,
|
|
132
|
+
flattenJson,
|
|
133
|
+
hashContent,
|
|
134
|
+
normalizeText,
|
|
135
|
+
partitionByChange
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=incremental-diff.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/incremental-diff.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Incremental crawl diff \u2014 compute stable content hashes and skip unchanged screens.\n *\n * Each crawled page gets a content fingerprint (murmurhash-free, pure JS).\n * On the next crawl of the same project, pages with the same fingerprint are\n * marked SKIPPED instead of re-processed, drastically reducing crawl time and\n * LLM token spend for sites with mostly-static content.\n *\n * Design: \"same content hash\" means the meaningful text hasn't changed.\n * Layout/CSS/JS changes that don't affect visible text are ignored intentionally.\n */\n\nexport interface ContentHash {\n url: string;\n hash: string;\n textLength: number;\n computedAt: string; // ISO timestamp\n}\n\nexport interface DiffResult {\n url: string;\n changed: boolean;\n previousHash?: string;\n currentHash: string;\n reason: 'new' | 'changed' | 'unchanged';\n}\n\n/**\n * Compute a stable 64-bit-ish hash from text content.\n * djb2 variant \u2014 fast, no deps, collision-resistant enough for content fingerprinting.\n */\nexport function hashContent(text: string): string {\n let h1 = 5381;\n let h2 = 52711;\n for (let i = 0; i < text.length; i++) {\n const c = text.charCodeAt(i);\n h1 = (Math.imul(h1, 33) ^ c) >>> 0;\n h2 = (Math.imul(h2, 31) ^ c) >>> 0;\n }\n return (h1 >>> 0).toString(16).padStart(8, '0') + (h2 >>> 0).toString(16).padStart(8, '0');\n}\n\n/**\n * Normalize text before hashing \u2014 strips whitespace-only lines, trims each line,\n * collapses runs of blank lines. Makes hash stable across minor formatting changes.\n */\nexport function normalizeText(text: string): string {\n return text\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l.length > 0)\n .join('\\n');\n}\n\nexport function computeContentHash(url: string, markdownText: string): ContentHash {\n const normalized = normalizeText(markdownText);\n return {\n url,\n hash: hashContent(normalized),\n textLength: normalized.length,\n computedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Compare a page's current content against prior hashes.\n * Returns { changed: false } for unchanged pages \u2014 caller should skip re-processing.\n */\nexport function diffContent(\n url: string,\n currentMarkdown: string,\n priorHashes: Map<string, string>, // url \u2192 hash\n): DiffResult {\n const current = computeContentHash(url, currentMarkdown);\n const prior = priorHashes.get(url);\n\n if (!prior) {\n return { url, changed: true, currentHash: current.hash, reason: 'new' };\n }\n if (prior === current.hash) {\n return { url, changed: false, previousHash: prior, currentHash: current.hash, reason: 'unchanged' };\n }\n return { url, changed: true, previousHash: prior, currentHash: current.hash, reason: 'changed' };\n}\n\n/**\n * Build a hash map from prior screen records (from DB query result).\n * screenRecords: Array<{ url: string; elementHash?: string | null }>\n */\nexport function buildPriorHashMap(screenRecords: Array<{ url: string; elementHash?: string | null }>): Map<string, string> {\n const map = new Map<string, string>();\n for (const s of screenRecords) {\n if (s.url && s.elementHash) map.set(s.url, s.elementHash);\n }\n return map;\n}\n\n/**\n * Filter a batch of discovered URLs against prior hashes.\n * Returns { toProcess, toSkip } \u2014 caller enqueues toProcess, logs toSkip count.\n *\n * Note: filtering at URL level only works if the prior crawl already visited the URL.\n * For new URLs, they're always in toProcess.\n */\nexport function partitionByChange(\n urls: string[],\n priorHashes: Map<string, string>,\n): { toProcess: string[]; toSkip: string[] } {\n const toProcess: string[] = [];\n const toSkip: string[] = [];\n for (const url of urls) {\n if (priorHashes.has(url)) {\n // Can't know if changed without fetching \u2014 still needs fetch, but hash after fetch\n // will determine skip. Include all \u2014 hash check happens post-fetch.\n toProcess.push(url);\n } else {\n toProcess.push(url);\n }\n }\n return { toProcess, toSkip };\n}\n\n// \u2500\u2500\u2500 Typed monitor diffs (GAP-01) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A single line-level change in text content (markdown, html, summary). */\nexport interface TextChange {\n type: 'added' | 'removed';\n line: number;\n content: string;\n}\n\n/** A change to a specific JSON path between two scraped JSON objects. */\nexport interface JsonChange {\n path: string;\n old: unknown;\n new: unknown;\n}\n\n/** Set-based change for collections like links or images. */\nexport interface SetChange {\n added: string[];\n removed: string[];\n}\n\n/** Screenshot pixel-level change. changed is percentage (0-100). */\nexport interface ImageChange {\n size: number;\n changed: number;\n mask?: string; // base64 diff mask\n}\n\n/** All possible diffs for a single monitor tick. */\nexport interface MonitorDiffs {\n markdown?: TextChange[];\n html?: TextChange[];\n json?: JsonChange[];\n summary?: TextChange[];\n links?: SetChange;\n images?: SetChange;\n branding?: JsonChange[];\n screenshot?: ImageChange;\n}\n\n/**\n * Compute line-level text diffs between two strings.\n * Returns TextChange[] showing exactly which lines were added or removed.\n * No external dependencies \u2014 pure JS Myers-inspired algorithm.\n */\nexport function computeTextDiffs(previous: string, current: string): TextChange[] {\n const prevLines = previous.split('\\n');\n const currLines = current.split('\\n');\n const changes: TextChange[] = [];\n\n const prevSet = new Set(prevLines);\n const currSet = new Set(currLines);\n\n let lineNum = 0;\n for (const line of prevLines) {\n if (!currSet.has(line)) {\n changes.push({ type: 'removed', line: lineNum, content: line });\n }\n lineNum++;\n }\n lineNum = 0;\n for (const line of currLines) {\n if (!prevSet.has(line)) {\n changes.push({ type: 'added', line: lineNum, content: line });\n }\n lineNum++;\n }\n\n return changes;\n}\n\n/**\n * Compute set-based diffs for URL collections (links, images).\n */\nexport function computeSetDiffs(previous: string[], current: string[]): SetChange {\n const prevSet = new Set(previous);\n const currSet = new Set(current);\n return {\n added: current.filter(u => !prevSet.has(u)),\n removed: previous.filter(u => !currSet.has(u)),\n };\n}\n\n/**\n * Flatten a JSON object into dot-notation path/value pairs.\n * Used to compute JsonChange[] between two JSON extraction results.\n */\nexport function flattenJson(obj: unknown, prefix = ''): Record<string, unknown> {\n if (typeof obj !== 'object' || obj === null) {\n return { [prefix]: obj };\n }\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj as Record<string, unknown>)) {\n const path = prefix ? `${prefix}.${k}` : k;\n if (typeof v === 'object' && v !== null && !Array.isArray(v)) {\n Object.assign(result, flattenJson(v, path));\n } else {\n result[path] = v;\n }\n }\n return result;\n}\n\n/**\n * Compute JSON path-level diffs between two extraction results.\n */\nexport function computeJsonDiffs(previous: unknown, current: unknown): JsonChange[] {\n const prevFlat = flattenJson(previous);\n const currFlat = flattenJson(current);\n const allKeys = new Set([...Object.keys(prevFlat), ...Object.keys(currFlat)]);\n const changes: JsonChange[] = [];\n for (const path of allKeys) {\n const oldVal = prevFlat[path];\n const newVal = currFlat[path];\n if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n changes.push({ path, old: oldVal, new: newVal });\n }\n }\n return changes;\n}\n\n/**\n * Count total number of changes across all diff types.\n */\nexport function countMonitorDiffs(diffs: MonitorDiffs): number {\n let count = 0;\n if (diffs.markdown) count += diffs.markdown.length;\n if (diffs.html) count += diffs.html.length;\n if (diffs.json) count += diffs.json.length;\n if (diffs.summary) count += diffs.summary.length;\n if (diffs.links) count += diffs.links.added.length + diffs.links.removed.length;\n if (diffs.images) count += diffs.images.added.length + diffs.images.removed.length;\n if (diffs.branding) count += diffs.branding.length;\n if (diffs.screenshot) count += diffs.screenshot.changed > 0 ? 1 : 0;\n return count;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export * from './crawler.js';
|
|
2
|
+
export * from './visual-diff-verdict.js';
|
|
3
|
+
export * from './auth.js';
|
|
4
|
+
export * from './screen-reader.js';
|
|
5
|
+
export * from './job-queue.js';
|
|
6
|
+
export { startSqsWorker, getDlqStats, redriveFromDlq } from './sqs-queue.js';
|
|
7
|
+
export * from './session-capture.js';
|
|
8
|
+
export * from './session-export.js';
|
|
9
|
+
export * from './test-executor.js';
|
|
10
|
+
export { startLiveView, getFrame, liveViewNavigate, completeLiveView, closeLiveView, sendInput } from './live-view.js';
|
|
11
|
+
export { waitForEmailOTP, getInboxEmail } from './email-otp.js';
|
|
12
|
+
export { getSsoToken, getSsoClientCredentialsToken } from './sso-token.js';
|
|
13
|
+
export type { SsoConfig, SsoProvider } from './sso-token.js';
|
|
14
|
+
export * from './engine-router.js';
|
|
15
|
+
export * from './profiles/domain-profile.js';
|
|
16
|
+
export * from './policies/crawl-safety.js';
|
|
17
|
+
export * from './extractors/artifact-envelope.js';
|
|
18
|
+
export * from './network-observer.js';
|
|
19
|
+
export { createChromeTlsAgent, probeTlsFingerprint, chromeTlsAgent, CHROME_TLS_HEADERS } from './tls-fingerprint.js';
|
|
20
|
+
export type { TlsFingerprintOptions } from './tls-fingerprint.js';
|
|
21
|
+
export { prepareExtensionProfile, adBlockerProfile } from './browser-extension.js';
|
|
22
|
+
export type { ExtensionSource, ExtensionProfile } from './browser-extension.js';
|
|
23
|
+
export { createRedisQueue, maybeCreateRedisQueue, isRedisQueueEnabled } from './redis-queue.js';
|
|
24
|
+
export type { RedisQueueJob, RedisQueueClient } from './redis-queue.js';
|
|
25
|
+
export { discoverProjectUrls, discoverSitemapUrls } from './sitemap.js';
|
|
26
|
+
export type { UrlCandidate } from './sitemap.js';
|
|
27
|
+
export { httpCrawl } from './http-engine.js';
|
|
28
|
+
export { extractMarkdown } from './markdown-extract.js';
|
|
29
|
+
export type { ExtractedMarkdown } from './markdown-extract.js';
|
|
30
|
+
export type { HttpScreen, HttpCrawlOpts, HttpCrawlResult, HttpOutputFormat } from './http-engine.js';
|
|
31
|
+
export { TieredProxyManager } from './proxy.js';
|
|
32
|
+
export type { ProxyTier, ProxyTierConfig } from './proxy.js';
|
|
33
|
+
export { RedisCrawlFrontier, isRedisFrontierEnabled } from './redis-frontier.js';
|
|
34
|
+
export { startSpan, endSpan, withSpan, increment, flushMetrics } from './telemetry.js';
|
|
35
|
+
export type { Span, FinishedSpan } from './telemetry.js';
|
|
36
|
+
export { analyzeFailure } from './failure-analysis-agent.js';
|
|
37
|
+
export type { FailureContext } from './failure-analysis-agent.js';
|
|
38
|
+
export { elementToPlaywrightLocator, elementsToPlaywrightLocators, formatLocatorsForPrompt, detectAuthWallLocators } from './locator-extractor.js';
|
|
39
|
+
export type { PlaywrightLocator } from './locator-extractor.js';
|
|
40
|
+
export * from './dropdown-enumerator.js';
|
|
41
|
+
export * from './crud-interaction.js';
|
|
42
|
+
export * from './filter-pagination-crawler.js';
|
|
43
|
+
export * from './multi-context-handler.js';
|
|
44
|
+
export * from './advanced-ui-probes.js';
|
|
45
|
+
export * from './state-graph.js';
|
|
46
|
+
export * from './nested-window-crawler.js';
|
|
47
|
+
export * from './shadow-dom-crawler.js';
|
|
48
|
+
export * from './network-action-correlator.js';
|
|
49
|
+
export * from './crawl-session-manager.js';
|
|
50
|
+
export * from './accessibility-tree-crawler.js';
|
|
51
|
+
export * from './performance-metrics.js';
|
|
52
|
+
export * from './service-worker-interceptor.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export * from "./crawler.js";
|
|
2
|
+
export * from "./visual-diff-verdict.js";
|
|
3
|
+
export * from "./auth.js";
|
|
4
|
+
export * from "./screen-reader.js";
|
|
5
|
+
export * from "./job-queue.js";
|
|
6
|
+
import { startSqsWorker, getDlqStats, redriveFromDlq } from "./sqs-queue.js";
|
|
7
|
+
export * from "./session-capture.js";
|
|
8
|
+
export * from "./session-export.js";
|
|
9
|
+
export * from "./test-executor.js";
|
|
10
|
+
import { startLiveView, getFrame, liveViewNavigate, completeLiveView, closeLiveView, sendInput } from "./live-view.js";
|
|
11
|
+
import { waitForEmailOTP, getInboxEmail } from "./email-otp.js";
|
|
12
|
+
import { getSsoToken, getSsoClientCredentialsToken } from "./sso-token.js";
|
|
13
|
+
export * from "./engine-router.js";
|
|
14
|
+
export * from "./profiles/domain-profile.js";
|
|
15
|
+
export * from "./policies/crawl-safety.js";
|
|
16
|
+
export * from "./extractors/artifact-envelope.js";
|
|
17
|
+
export * from "./network-observer.js";
|
|
18
|
+
import { createChromeTlsAgent, probeTlsFingerprint, chromeTlsAgent, CHROME_TLS_HEADERS } from "./tls-fingerprint.js";
|
|
19
|
+
import { prepareExtensionProfile, adBlockerProfile } from "./browser-extension.js";
|
|
20
|
+
import { createRedisQueue, maybeCreateRedisQueue, isRedisQueueEnabled } from "./redis-queue.js";
|
|
21
|
+
import { discoverProjectUrls, discoverSitemapUrls } from "./sitemap.js";
|
|
22
|
+
import { httpCrawl } from "./http-engine.js";
|
|
23
|
+
import { extractMarkdown } from "./markdown-extract.js";
|
|
24
|
+
import { TieredProxyManager } from "./proxy.js";
|
|
25
|
+
import { RedisCrawlFrontier, isRedisFrontierEnabled } from "./redis-frontier.js";
|
|
26
|
+
import { startSpan, endSpan, withSpan, increment, flushMetrics } from "./telemetry.js";
|
|
27
|
+
import { analyzeFailure } from "./failure-analysis-agent.js";
|
|
28
|
+
import { elementToPlaywrightLocator, elementsToPlaywrightLocators, formatLocatorsForPrompt, detectAuthWallLocators } from "./locator-extractor.js";
|
|
29
|
+
export * from "./dropdown-enumerator.js";
|
|
30
|
+
export * from "./crud-interaction.js";
|
|
31
|
+
export * from "./filter-pagination-crawler.js";
|
|
32
|
+
export * from "./multi-context-handler.js";
|
|
33
|
+
export * from "./advanced-ui-probes.js";
|
|
34
|
+
export * from "./state-graph.js";
|
|
35
|
+
export * from "./nested-window-crawler.js";
|
|
36
|
+
export * from "./shadow-dom-crawler.js";
|
|
37
|
+
export * from "./network-action-correlator.js";
|
|
38
|
+
export * from "./crawl-session-manager.js";
|
|
39
|
+
export * from "./accessibility-tree-crawler.js";
|
|
40
|
+
export * from "./performance-metrics.js";
|
|
41
|
+
export * from "./service-worker-interceptor.js";
|
|
42
|
+
export {
|
|
43
|
+
CHROME_TLS_HEADERS,
|
|
44
|
+
RedisCrawlFrontier,
|
|
45
|
+
TieredProxyManager,
|
|
46
|
+
adBlockerProfile,
|
|
47
|
+
analyzeFailure,
|
|
48
|
+
chromeTlsAgent,
|
|
49
|
+
closeLiveView,
|
|
50
|
+
completeLiveView,
|
|
51
|
+
createChromeTlsAgent,
|
|
52
|
+
createRedisQueue,
|
|
53
|
+
detectAuthWallLocators,
|
|
54
|
+
discoverProjectUrls,
|
|
55
|
+
discoverSitemapUrls,
|
|
56
|
+
elementToPlaywrightLocator,
|
|
57
|
+
elementsToPlaywrightLocators,
|
|
58
|
+
endSpan,
|
|
59
|
+
extractMarkdown,
|
|
60
|
+
flushMetrics,
|
|
61
|
+
formatLocatorsForPrompt,
|
|
62
|
+
getDlqStats,
|
|
63
|
+
getFrame,
|
|
64
|
+
getInboxEmail,
|
|
65
|
+
getSsoClientCredentialsToken,
|
|
66
|
+
getSsoToken,
|
|
67
|
+
httpCrawl,
|
|
68
|
+
increment,
|
|
69
|
+
isRedisFrontierEnabled,
|
|
70
|
+
isRedisQueueEnabled,
|
|
71
|
+
liveViewNavigate,
|
|
72
|
+
maybeCreateRedisQueue,
|
|
73
|
+
prepareExtensionProfile,
|
|
74
|
+
probeTlsFingerprint,
|
|
75
|
+
redriveFromDlq,
|
|
76
|
+
sendInput,
|
|
77
|
+
startLiveView,
|
|
78
|
+
startSpan,
|
|
79
|
+
startSqsWorker,
|
|
80
|
+
waitForEmailOTP,
|
|
81
|
+
withSpan
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["export * from './crawler.js';\nexport * from './visual-diff-verdict.js';\nexport * from './auth.js';\nexport * from './screen-reader.js';\nexport * from './job-queue.js';\nexport { startSqsWorker, getDlqStats, redriveFromDlq } from './sqs-queue.js';\nexport * from './session-capture.js';\nexport * from './session-export.js';\nexport * from './test-executor.js';\nexport { startLiveView, getFrame, liveViewNavigate, completeLiveView, closeLiveView, sendInput } from './live-view.js';\nexport { waitForEmailOTP, getInboxEmail } from './email-otp.js';\nexport { getSsoToken, getSsoClientCredentialsToken } from './sso-token.js';\nexport type { SsoConfig, SsoProvider } from './sso-token.js';\nexport * from './engine-router.js';\nexport * from './profiles/domain-profile.js';\nexport * from './policies/crawl-safety.js';\nexport * from './extractors/artifact-envelope.js';\nexport * from './network-observer.js';\nexport { createChromeTlsAgent, probeTlsFingerprint, chromeTlsAgent, CHROME_TLS_HEADERS } from './tls-fingerprint.js';\nexport type { TlsFingerprintOptions } from './tls-fingerprint.js';\nexport { prepareExtensionProfile, adBlockerProfile } from './browser-extension.js';\nexport type { ExtensionSource, ExtensionProfile } from './browser-extension.js';\nexport { createRedisQueue, maybeCreateRedisQueue, isRedisQueueEnabled } from './redis-queue.js';\nexport type { RedisQueueJob, RedisQueueClient } from './redis-queue.js';\nexport { discoverProjectUrls, discoverSitemapUrls } from './sitemap.js';\nexport type { UrlCandidate } from './sitemap.js';\nexport { httpCrawl } from './http-engine.js';\nexport { extractMarkdown } from './markdown-extract.js';\nexport type { ExtractedMarkdown } from './markdown-extract.js';\nexport type { HttpScreen, HttpCrawlOpts, HttpCrawlResult, HttpOutputFormat } from './http-engine.js';\nexport { TieredProxyManager } from './proxy.js';\nexport type { ProxyTier, ProxyTierConfig } from './proxy.js';\nexport { RedisCrawlFrontier, isRedisFrontierEnabled } from './redis-frontier.js';\nexport { startSpan, endSpan, withSpan, increment, flushMetrics } from './telemetry.js';\nexport type { Span, FinishedSpan } from './telemetry.js';\nexport { analyzeFailure } from './failure-analysis-agent.js';\nexport type { FailureContext } from './failure-analysis-agent.js';\nexport { elementToPlaywrightLocator, elementsToPlaywrightLocators, formatLocatorsForPrompt, detectAuthWallLocators } from './locator-extractor.js';\nexport type { PlaywrightLocator } from './locator-extractor.js';\nexport * from './dropdown-enumerator.js';\nexport * from './crud-interaction.js';\nexport * from './filter-pagination-crawler.js';\nexport * from './multi-context-handler.js';\nexport * from './advanced-ui-probes.js';\nexport * from './state-graph.js';\nexport * from './nested-window-crawler.js';\nexport * from './shadow-dom-crawler.js';\nexport * from './network-action-correlator.js';\nexport * from './crawl-session-manager.js';\nexport * from './accessibility-tree-crawler.js';\nexport * from './performance-metrics.js';\nexport * from './service-worker-interceptor.js';\n"],
|
|
5
|
+
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,gBAAgB,aAAa,sBAAsB;AAC5D,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,eAAe,UAAU,kBAAkB,kBAAkB,eAAe,iBAAiB;AACtG,SAAS,iBAAiB,qBAAqB;AAC/C,SAAS,aAAa,oCAAoC;AAE1D,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,sBAAsB,qBAAqB,gBAAgB,0BAA0B;AAE9F,SAAS,yBAAyB,wBAAwB;AAE1D,SAAS,kBAAkB,uBAAuB,2BAA2B;AAE7E,SAAS,qBAAqB,2BAA2B;AAEzD,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;AAGhC,SAAS,0BAA0B;AAEnC,SAAS,oBAAoB,8BAA8B;AAC3D,SAAS,WAAW,SAAS,UAAU,WAAW,oBAAoB;AAEtE,SAAS,sBAAsB;AAE/B,SAAS,4BAA4B,8BAA8B,yBAAyB,8BAA8B;AAE1H,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input fuzzer — generate test data for form fields.
|
|
3
|
+
*
|
|
4
|
+
* For each field type, produces a set of test values covering:
|
|
5
|
+
* - Happy path (valid, normal input)
|
|
6
|
+
* - Boundary (min/max length, min/max value)
|
|
7
|
+
* - Edge cases (empty, very long, special chars, SQL injection probe, XSS probe)
|
|
8
|
+
* - Type-invalid (wrong type for the field)
|
|
9
|
+
*
|
|
10
|
+
* This feeds ZeTa's test generator to automatically create form validation tests.
|
|
11
|
+
* Values are safe probes (NOT actual exploits) — they test whether the app
|
|
12
|
+
* properly rejects/accepts boundary inputs.
|
|
13
|
+
*/
|
|
14
|
+
import type { FormField } from './form-detector.js';
|
|
15
|
+
export type InputCase = {
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
expectedValid: boolean;
|
|
19
|
+
category: 'happy' | 'boundary' | 'edge' | 'invalid';
|
|
20
|
+
};
|
|
21
|
+
export declare function generateFieldCases(field: FormField): InputCase[];
|
|
22
|
+
export interface FuzzedForm {
|
|
23
|
+
formIndex: number;
|
|
24
|
+
purpose: string;
|
|
25
|
+
fieldCases: Array<{
|
|
26
|
+
field: FormField;
|
|
27
|
+
cases: InputCase[];
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
export declare function fuzzForm(form: import('./form-detector.js').DetectedForm): FuzzedForm;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const LOREM = "Lorem ipsum dolor sit amet consectetur adipiscing elit";
|
|
2
|
+
function generateEmailCases() {
|
|
3
|
+
return [
|
|
4
|
+
{ label: "valid email", value: "test@example.com", expectedValid: true, category: "happy" },
|
|
5
|
+
{ label: "email with plus", value: "test+tag@example.com", expectedValid: true, category: "happy" },
|
|
6
|
+
{ label: "missing @", value: "notanemail.com", expectedValid: false, category: "invalid" },
|
|
7
|
+
{ label: "missing domain", value: "test@", expectedValid: false, category: "invalid" },
|
|
8
|
+
{ label: "empty", value: "", expectedValid: false, category: "edge" },
|
|
9
|
+
{ label: "very long email", value: "a".repeat(100) + "@example.com", expectedValid: false, category: "boundary" },
|
|
10
|
+
{ label: "special chars", value: "test<script>@example.com", expectedValid: false, category: "edge" }
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
function generatePasswordCases(minLength, maxLength) {
|
|
14
|
+
const min = minLength ?? 8;
|
|
15
|
+
const max = maxLength ?? 128;
|
|
16
|
+
return [
|
|
17
|
+
{ label: "valid password", value: "ValidP@ss1", expectedValid: true, category: "happy" },
|
|
18
|
+
{ label: "minimum length", value: "A".repeat(min), expectedValid: true, category: "boundary" },
|
|
19
|
+
{ label: "below minimum", value: "A".repeat(Math.max(1, min - 1)), expectedValid: false, category: "boundary" },
|
|
20
|
+
{ label: "max length", value: "Aa1!".repeat(Math.ceil(max / 4)).slice(0, max), expectedValid: true, category: "boundary" },
|
|
21
|
+
{ label: "empty", value: "", expectedValid: false, category: "edge" },
|
|
22
|
+
{ label: "spaces only", value: " ", expectedValid: false, category: "edge" }
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
function generateTextCases(minLength, maxLength, required) {
|
|
26
|
+
const cases = [
|
|
27
|
+
{ label: "typical text", value: "Test Input Value", expectedValid: true, category: "happy" },
|
|
28
|
+
{ label: "single char", value: "A", expectedValid: !minLength || minLength <= 1, category: "boundary" },
|
|
29
|
+
{ label: "empty", value: "", expectedValid: !required, category: "edge" },
|
|
30
|
+
{ label: "spaces only", value: " ", expectedValid: !required, category: "edge" },
|
|
31
|
+
{ label: "very long text", value: LOREM.repeat(20), expectedValid: !maxLength || maxLength > LOREM.length * 20, category: "boundary" },
|
|
32
|
+
{ label: "unicode", value: "\u65E5\u672C\u8A9E\u30C6\u30B9\u30C8 \xDCn\xEFc\xF6d\xE9 Emojitest \u{1F389}", expectedValid: true, category: "edge" },
|
|
33
|
+
{ label: "HTML special chars", value: "<script>alert(1)</script>", expectedValid: true, category: "edge" },
|
|
34
|
+
{ label: "SQL probe", value: "' OR '1'='1", expectedValid: true, category: "edge" }
|
|
35
|
+
];
|
|
36
|
+
if (minLength) cases.push({ label: `below min (${minLength})`, value: "x".repeat(Math.max(0, minLength - 1)), expectedValid: false, category: "boundary" });
|
|
37
|
+
if (maxLength) cases.push({ label: `above max (${maxLength})`, value: "x".repeat(maxLength + 1), expectedValid: false, category: "boundary" });
|
|
38
|
+
return cases;
|
|
39
|
+
}
|
|
40
|
+
function generateNumberCases(min, max) {
|
|
41
|
+
const minN = min !== void 0 ? parseFloat(min) : void 0;
|
|
42
|
+
const maxN = max !== void 0 ? parseFloat(max) : void 0;
|
|
43
|
+
return [
|
|
44
|
+
{ label: "valid number", value: "42", expectedValid: true, category: "happy" },
|
|
45
|
+
{ label: "zero", value: "0", expectedValid: minN === void 0 || minN <= 0, category: "boundary" },
|
|
46
|
+
{ label: "negative", value: "-1", expectedValid: minN === void 0 || minN < 0, category: "boundary" },
|
|
47
|
+
{ label: "decimal", value: "3.14", expectedValid: true, category: "happy" },
|
|
48
|
+
{ label: "text as number", value: "notanumber", expectedValid: false, category: "invalid" },
|
|
49
|
+
{ label: "empty", value: "", expectedValid: false, category: "edge" },
|
|
50
|
+
...minN !== void 0 ? [{ label: `below min (${min})`, value: String(minN - 1), expectedValid: false, category: "boundary" }] : [],
|
|
51
|
+
...maxN !== void 0 ? [{ label: `above max (${max})`, value: String(maxN + 1), expectedValid: false, category: "boundary" }] : []
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
function generateSelectCases(options) {
|
|
55
|
+
if (!options?.length) return [{ label: "first option", value: "", expectedValid: true, category: "happy" }];
|
|
56
|
+
return [
|
|
57
|
+
{ label: `first option (${options[0]})`, value: options[0], expectedValid: true, category: "happy" },
|
|
58
|
+
{ label: "invalid option", value: "__INVALID_OPTION__", expectedValid: false, category: "invalid" },
|
|
59
|
+
{ label: "empty selection", value: "", expectedValid: false, category: "edge" },
|
|
60
|
+
...options.length > 1 ? [{ label: `last option (${options[options.length - 1]})`, value: options[options.length - 1], expectedValid: true, category: "happy" }] : []
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
function generateFieldCases(field) {
|
|
64
|
+
switch (field.type) {
|
|
65
|
+
case "email":
|
|
66
|
+
return generateEmailCases();
|
|
67
|
+
case "password":
|
|
68
|
+
return generatePasswordCases(field.minLength, field.maxLength);
|
|
69
|
+
case "number":
|
|
70
|
+
return generateNumberCases(field.min, field.max);
|
|
71
|
+
case "select":
|
|
72
|
+
return generateSelectCases(field.options);
|
|
73
|
+
case "checkbox":
|
|
74
|
+
return [
|
|
75
|
+
{ label: "checked", value: "true", expectedValid: true, category: "happy" },
|
|
76
|
+
{ label: "unchecked", value: "false", expectedValid: !field.required, category: field.required ? "invalid" : "happy" }
|
|
77
|
+
];
|
|
78
|
+
case "date":
|
|
79
|
+
return [
|
|
80
|
+
{ label: "valid date", value: "2026-01-15", expectedValid: true, category: "happy" },
|
|
81
|
+
{ label: "invalid date", value: "9999-99-99", expectedValid: false, category: "invalid" },
|
|
82
|
+
{ label: "empty", value: "", expectedValid: !field.required, category: "edge" }
|
|
83
|
+
];
|
|
84
|
+
case "url":
|
|
85
|
+
return [
|
|
86
|
+
{ label: "valid URL", value: "https://example.com", expectedValid: true, category: "happy" },
|
|
87
|
+
{ label: "missing protocol", value: "example.com", expectedValid: false, category: "invalid" },
|
|
88
|
+
{ label: "empty", value: "", expectedValid: !field.required, category: "edge" }
|
|
89
|
+
];
|
|
90
|
+
default:
|
|
91
|
+
return generateTextCases(field.minLength, field.maxLength, field.required);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function fuzzForm(form) {
|
|
95
|
+
return {
|
|
96
|
+
formIndex: form.index,
|
|
97
|
+
purpose: form.purpose,
|
|
98
|
+
fieldCases: form.fields.map((field) => ({ field, cases: generateFieldCases(field) }))
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
fuzzForm,
|
|
103
|
+
generateFieldCases
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=input-fuzzer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/input-fuzzer.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Input fuzzer \u2014 generate test data for form fields.\n *\n * For each field type, produces a set of test values covering:\n * - Happy path (valid, normal input)\n * - Boundary (min/max length, min/max value)\n * - Edge cases (empty, very long, special chars, SQL injection probe, XSS probe)\n * - Type-invalid (wrong type for the field)\n *\n * This feeds ZeTa's test generator to automatically create form validation tests.\n * Values are safe probes (NOT actual exploits) \u2014 they test whether the app\n * properly rejects/accepts boundary inputs.\n */\n\nimport type { FormField } from './form-detector.js';\n\nexport type InputCase = {\n label: string; // human-readable test case name\n value: string;\n expectedValid: boolean; // true if input should be accepted\n category: 'happy' | 'boundary' | 'edge' | 'invalid';\n};\n\nconst LOREM = 'Lorem ipsum dolor sit amet consectetur adipiscing elit';\n\nfunction generateEmailCases(): InputCase[] {\n return [\n { label: 'valid email', value: 'test@example.com', expectedValid: true, category: 'happy' },\n { label: 'email with plus', value: 'test+tag@example.com', expectedValid: true, category: 'happy' },\n { label: 'missing @', value: 'notanemail.com', expectedValid: false, category: 'invalid' },\n { label: 'missing domain', value: 'test@', expectedValid: false, category: 'invalid' },\n { label: 'empty', value: '', expectedValid: false, category: 'edge' },\n { label: 'very long email', value: 'a'.repeat(100) + '@example.com', expectedValid: false, category: 'boundary' },\n { label: 'special chars', value: 'test<script>@example.com', expectedValid: false, category: 'edge' },\n ];\n}\n\nfunction generatePasswordCases(minLength?: number, maxLength?: number): InputCase[] {\n const min = minLength ?? 8;\n const max = maxLength ?? 128;\n return [\n { label: 'valid password', value: 'ValidP@ss1', expectedValid: true, category: 'happy' },\n { label: 'minimum length', value: 'A'.repeat(min), expectedValid: true, category: 'boundary' },\n { label: 'below minimum', value: 'A'.repeat(Math.max(1, min - 1)), expectedValid: false, category: 'boundary' },\n { label: 'max length', value: 'Aa1!'.repeat(Math.ceil(max / 4)).slice(0, max), expectedValid: true, category: 'boundary' },\n { label: 'empty', value: '', expectedValid: false, category: 'edge' },\n { label: 'spaces only', value: ' ', expectedValid: false, category: 'edge' },\n ];\n}\n\nfunction generateTextCases(minLength?: number, maxLength?: number, required?: boolean): InputCase[] {\n const cases: InputCase[] = [\n { label: 'typical text', value: 'Test Input Value', expectedValid: true, category: 'happy' },\n { label: 'single char', value: 'A', expectedValid: !minLength || minLength <= 1, category: 'boundary' },\n { label: 'empty', value: '', expectedValid: !required, category: 'edge' },\n { label: 'spaces only', value: ' ', expectedValid: !required, category: 'edge' },\n { label: 'very long text', value: LOREM.repeat(20), expectedValid: !maxLength || maxLength > LOREM.length * 20, category: 'boundary' },\n { label: 'unicode', value: '\u65E5\u672C\u8A9E\u30C6\u30B9\u30C8 \u00DCn\u00EFc\u00F6d\u00E9 Emojitest \uD83C\uDF89', expectedValid: true, category: 'edge' },\n { label: 'HTML special chars', value: '<script>alert(1)</script>', expectedValid: true, category: 'edge' },\n { label: 'SQL probe', value: \"' OR '1'='1\", expectedValid: true, category: 'edge' },\n ];\n if (minLength) cases.push({ label: `below min (${minLength})`, value: 'x'.repeat(Math.max(0, minLength - 1)), expectedValid: false, category: 'boundary' });\n if (maxLength) cases.push({ label: `above max (${maxLength})`, value: 'x'.repeat(maxLength + 1), expectedValid: false, category: 'boundary' });\n return cases;\n}\n\nfunction generateNumberCases(min?: string, max?: string): InputCase[] {\n const minN = min !== undefined ? parseFloat(min) : undefined;\n const maxN = max !== undefined ? parseFloat(max) : undefined;\n return [\n { label: 'valid number', value: '42', expectedValid: true, category: 'happy' },\n { label: 'zero', value: '0', expectedValid: minN === undefined || minN <= 0, category: 'boundary' },\n { label: 'negative', value: '-1', expectedValid: minN === undefined || minN < 0, category: 'boundary' },\n { label: 'decimal', value: '3.14', expectedValid: true, category: 'happy' },\n { label: 'text as number', value: 'notanumber', expectedValid: false, category: 'invalid' },\n { label: 'empty', value: '', expectedValid: false, category: 'edge' },\n ...(minN !== undefined ? [{ label: `below min (${min})`, value: String(minN - 1), expectedValid: false, category: 'boundary' as const }] : []),\n ...(maxN !== undefined ? [{ label: `above max (${max})`, value: String(maxN + 1), expectedValid: false, category: 'boundary' as const }] : []),\n ];\n}\n\nfunction generateSelectCases(options?: string[]): InputCase[] {\n if (!options?.length) return [{ label: 'first option', value: '', expectedValid: true, category: 'happy' }];\n return [\n { label: `first option (${options[0]})`, value: options[0], expectedValid: true, category: 'happy' },\n { label: 'invalid option', value: '__INVALID_OPTION__', expectedValid: false, category: 'invalid' },\n { label: 'empty selection', value: '', expectedValid: false, category: 'edge' },\n ...(options.length > 1 ? [{ label: `last option (${options[options.length - 1]})`, value: options[options.length - 1], expectedValid: true, category: 'happy' as const }] : []),\n ];\n}\n\nexport function generateFieldCases(field: FormField): InputCase[] {\n switch (field.type) {\n case 'email': return generateEmailCases();\n case 'password': return generatePasswordCases(field.minLength, field.maxLength);\n case 'number': return generateNumberCases(field.min, field.max);\n case 'select': return generateSelectCases(field.options);\n case 'checkbox': return [\n { label: 'checked', value: 'true', expectedValid: true, category: 'happy' },\n { label: 'unchecked', value: 'false', expectedValid: !field.required, category: field.required ? 'invalid' : 'happy' },\n ];\n case 'date': return [\n { label: 'valid date', value: '2026-01-15', expectedValid: true, category: 'happy' },\n { label: 'invalid date', value: '9999-99-99', expectedValid: false, category: 'invalid' },\n { label: 'empty', value: '', expectedValid: !field.required, category: 'edge' },\n ];\n case 'url': return [\n { label: 'valid URL', value: 'https://example.com', expectedValid: true, category: 'happy' },\n { label: 'missing protocol', value: 'example.com', expectedValid: false, category: 'invalid' },\n { label: 'empty', value: '', expectedValid: !field.required, category: 'edge' },\n ];\n default:\n return generateTextCases(field.minLength, field.maxLength, field.required);\n }\n}\n\nexport interface FuzzedForm {\n formIndex: number;\n purpose: string;\n fieldCases: Array<{ field: FormField; cases: InputCase[] }>;\n}\n\nexport function fuzzForm(form: import('./form-detector.js').DetectedForm): FuzzedForm {\n return {\n formIndex: form.index,\n purpose: form.purpose,\n fieldCases: form.fields.map(field => ({ field, cases: generateFieldCases(field) })),\n };\n}\n"],
|
|
5
|
+
"mappings": "AAuBA,MAAM,QAAQ;AAEd,SAAS,qBAAkC;AACzC,SAAO;AAAA,IACL,EAAE,OAAO,eAAe,OAAO,oBAAoB,eAAe,MAAM,UAAU,QAAQ;AAAA,IAC1F,EAAE,OAAO,mBAAmB,OAAO,wBAAwB,eAAe,MAAM,UAAU,QAAQ;AAAA,IAClG,EAAE,OAAO,aAAa,OAAO,kBAAkB,eAAe,OAAO,UAAU,UAAU;AAAA,IACzF,EAAE,OAAO,kBAAkB,OAAO,SAAS,eAAe,OAAO,UAAU,UAAU;AAAA,IACrF,EAAE,OAAO,SAAS,OAAO,IAAI,eAAe,OAAO,UAAU,OAAO;AAAA,IACpE,EAAE,OAAO,mBAAmB,OAAO,IAAI,OAAO,GAAG,IAAI,gBAAgB,eAAe,OAAO,UAAU,WAAW;AAAA,IAChH,EAAE,OAAO,iBAAiB,OAAO,4BAA4B,eAAe,OAAO,UAAU,OAAO;AAAA,EACtG;AACF;AAEA,SAAS,sBAAsB,WAAoB,WAAiC;AAClF,QAAM,MAAM,aAAa;AACzB,QAAM,MAAM,aAAa;AACzB,SAAO;AAAA,IACL,EAAE,OAAO,kBAAkB,OAAO,cAAc,eAAe,MAAM,UAAU,QAAQ;AAAA,IACvF,EAAE,OAAO,kBAAkB,OAAO,IAAI,OAAO,GAAG,GAAG,eAAe,MAAM,UAAU,WAAW;AAAA,IAC7F,EAAE,OAAO,iBAAiB,OAAO,IAAI,OAAO,KAAK,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,eAAe,OAAO,UAAU,WAAW;AAAA,IAC9G,EAAE,OAAO,cAAc,OAAO,OAAO,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,eAAe,MAAM,UAAU,WAAW;AAAA,IACzH,EAAE,OAAO,SAAS,OAAO,IAAI,eAAe,OAAO,UAAU,OAAO;AAAA,IACpE,EAAE,OAAO,eAAe,OAAO,YAAY,eAAe,OAAO,UAAU,OAAO;AAAA,EACpF;AACF;AAEA,SAAS,kBAAkB,WAAoB,WAAoB,UAAiC;AAClG,QAAM,QAAqB;AAAA,IACzB,EAAE,OAAO,gBAAgB,OAAO,oBAAoB,eAAe,MAAM,UAAU,QAAQ;AAAA,IAC3F,EAAE,OAAO,eAAe,OAAO,KAAK,eAAe,CAAC,aAAa,aAAa,GAAG,UAAU,WAAW;AAAA,IACtG,EAAE,OAAO,SAAS,OAAO,IAAI,eAAe,CAAC,UAAU,UAAU,OAAO;AAAA,IACxE,EAAE,OAAO,eAAe,OAAO,OAAO,eAAe,CAAC,UAAU,UAAU,OAAO;AAAA,IACjF,EAAE,OAAO,kBAAkB,OAAO,MAAM,OAAO,EAAE,GAAG,eAAe,CAAC,aAAa,YAAY,MAAM,SAAS,IAAI,UAAU,WAAW;AAAA,IACrI,EAAE,OAAO,WAAW,OAAO,gFAA+B,eAAe,MAAM,UAAU,OAAO;AAAA,IAChG,EAAE,OAAO,sBAAsB,OAAO,6BAA6B,eAAe,MAAM,UAAU,OAAO;AAAA,IACzG,EAAE,OAAO,aAAa,OAAO,eAAe,eAAe,MAAM,UAAU,OAAO;AAAA,EACpF;AACA,MAAI,UAAW,OAAM,KAAK,EAAE,OAAO,cAAc,SAAS,KAAK,OAAO,IAAI,OAAO,KAAK,IAAI,GAAG,YAAY,CAAC,CAAC,GAAG,eAAe,OAAO,UAAU,WAAW,CAAC;AAC1J,MAAI,UAAW,OAAM,KAAK,EAAE,OAAO,cAAc,SAAS,KAAK,OAAO,IAAI,OAAO,YAAY,CAAC,GAAG,eAAe,OAAO,UAAU,WAAW,CAAC;AAC7I,SAAO;AACT;AAEA,SAAS,oBAAoB,KAAc,KAA2B;AACpE,QAAM,OAAO,QAAQ,SAAY,WAAW,GAAG,IAAI;AACnD,QAAM,OAAO,QAAQ,SAAY,WAAW,GAAG,IAAI;AACnD,SAAO;AAAA,IACL,EAAE,OAAO,gBAAgB,OAAO,MAAM,eAAe,MAAM,UAAU,QAAQ;AAAA,IAC7E,EAAE,OAAO,QAAQ,OAAO,KAAK,eAAe,SAAS,UAAa,QAAQ,GAAG,UAAU,WAAW;AAAA,IAClG,EAAE,OAAO,YAAY,OAAO,MAAM,eAAe,SAAS,UAAa,OAAO,GAAG,UAAU,WAAW;AAAA,IACtG,EAAE,OAAO,WAAW,OAAO,QAAQ,eAAe,MAAM,UAAU,QAAQ;AAAA,IAC1E,EAAE,OAAO,kBAAkB,OAAO,cAAc,eAAe,OAAO,UAAU,UAAU;AAAA,IAC1F,EAAE,OAAO,SAAS,OAAO,IAAI,eAAe,OAAO,UAAU,OAAO;AAAA,IACpE,GAAI,SAAS,SAAY,CAAC,EAAE,OAAO,cAAc,GAAG,KAAK,OAAO,OAAO,OAAO,CAAC,GAAG,eAAe,OAAO,UAAU,WAAoB,CAAC,IAAI,CAAC;AAAA,IAC5I,GAAI,SAAS,SAAY,CAAC,EAAE,OAAO,cAAc,GAAG,KAAK,OAAO,OAAO,OAAO,CAAC,GAAG,eAAe,OAAO,UAAU,WAAoB,CAAC,IAAI,CAAC;AAAA,EAC9I;AACF;AAEA,SAAS,oBAAoB,SAAiC;AAC5D,MAAI,CAAC,SAAS,OAAQ,QAAO,CAAC,EAAE,OAAO,gBAAgB,OAAO,IAAI,eAAe,MAAM,UAAU,QAAQ,CAAC;AAC1G,SAAO;AAAA,IACL,EAAE,OAAO,iBAAiB,QAAQ,CAAC,CAAC,KAAK,OAAO,QAAQ,CAAC,GAAG,eAAe,MAAM,UAAU,QAAQ;AAAA,IACnG,EAAE,OAAO,kBAAkB,OAAO,sBAAsB,eAAe,OAAO,UAAU,UAAU;AAAA,IAClG,EAAE,OAAO,mBAAmB,OAAO,IAAI,eAAe,OAAO,UAAU,OAAO;AAAA,IAC9E,GAAI,QAAQ,SAAS,IAAI,CAAC,EAAE,OAAO,gBAAgB,QAAQ,QAAQ,SAAS,CAAC,CAAC,KAAK,OAAO,QAAQ,QAAQ,SAAS,CAAC,GAAG,eAAe,MAAM,UAAU,QAAiB,CAAC,IAAI,CAAC;AAAA,EAC/K;AACF;AAEO,SAAS,mBAAmB,OAA+B;AAChE,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAY,aAAO,mBAAmB;AAAA,IAC3C,KAAK;AAAY,aAAO,sBAAsB,MAAM,WAAW,MAAM,SAAS;AAAA,IAC9E,KAAK;AAAY,aAAO,oBAAoB,MAAM,KAAK,MAAM,GAAG;AAAA,IAChE,KAAK;AAAY,aAAO,oBAAoB,MAAM,OAAO;AAAA,IACzD,KAAK;AAAY,aAAO;AAAA,QACtB,EAAE,OAAO,WAAW,OAAO,QAAQ,eAAe,MAAM,UAAU,QAAQ;AAAA,QAC1E,EAAE,OAAO,aAAa,OAAO,SAAS,eAAe,CAAC,MAAM,UAAU,UAAU,MAAM,WAAW,YAAY,QAAQ;AAAA,MACvH;AAAA,IACA,KAAK;AAAY,aAAO;AAAA,QACtB,EAAE,OAAO,cAAc,OAAO,cAAc,eAAe,MAAM,UAAU,QAAQ;AAAA,QACnF,EAAE,OAAO,gBAAgB,OAAO,cAAc,eAAe,OAAO,UAAU,UAAU;AAAA,QACxF,EAAE,OAAO,SAAS,OAAO,IAAI,eAAe,CAAC,MAAM,UAAU,UAAU,OAAO;AAAA,MAChF;AAAA,IACA,KAAK;AAAY,aAAO;AAAA,QACtB,EAAE,OAAO,aAAa,OAAO,uBAAuB,eAAe,MAAM,UAAU,QAAQ;AAAA,QAC3F,EAAE,OAAO,oBAAoB,OAAO,eAAe,eAAe,OAAO,UAAU,UAAU;AAAA,QAC7F,EAAE,OAAO,SAAS,OAAO,IAAI,eAAe,CAAC,MAAM,UAAU,UAAU,OAAO;AAAA,MAChF;AAAA,IACA;AACE,aAAO,kBAAkB,MAAM,WAAW,MAAM,WAAW,MAAM,QAAQ;AAAA,EAC7E;AACF;AAQO,SAAS,SAAS,MAA6D;AACpF,SAAO;AAAA,IACL,WAAW,KAAK;AAAA,IAChB,SAAS,KAAK;AAAA,IACd,YAAY,KAAK,OAAO,IAAI,YAAU,EAAE,OAAO,OAAO,mBAAmB,KAAK,EAAE,EAAE;AAAA,EACpF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Probe — Phase 2 Dynamic Observation
|
|
3
|
+
*
|
|
4
|
+
* The static crawl captures DOM structure at rest. This module runs AFTER the static crawl
|
|
5
|
+
* to observe dynamic behaviour by actually interacting with the UI:
|
|
6
|
+
*
|
|
7
|
+
* 1. Empty submit → captures required-field validation error messages
|
|
8
|
+
* 2. Invalid format → captures format validation errors (bad email, short password)
|
|
9
|
+
* 3. Button clicks → captures modal/dialog contents
|
|
10
|
+
* 4. Select changes → captures conditional reveals (show/hide logic)
|
|
11
|
+
* 5. Success paths → captures toast/banner messages (where input is safe)
|
|
12
|
+
*
|
|
13
|
+
* Results are stored as KnowledgeChunks (sourceType='probe') and update the
|
|
14
|
+
* ERROR_CATALOGUE + INTERACTION_PATTERNS skill files with real observed data
|
|
15
|
+
* instead of LLM inference.
|
|
16
|
+
*
|
|
17
|
+
* Call signature: probeScreen(page, screenId, elements, opts)
|
|
18
|
+
* Called from crawlProject() after static element extraction when opts.interactive=true.
|
|
19
|
+
*/
|
|
20
|
+
import type { Page } from 'playwright';
|
|
21
|
+
export interface ProbeElementFact {
|
|
22
|
+
meaning: string;
|
|
23
|
+
role: string;
|
|
24
|
+
expectedData?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ValidationError {
|
|
27
|
+
field: string;
|
|
28
|
+
trigger: 'empty_submit' | 'invalid_format' | 'boundary';
|
|
29
|
+
errorText: string;
|
|
30
|
+
}
|
|
31
|
+
export interface SuccessMessage {
|
|
32
|
+
type: 'toast' | 'inline_success' | 'redirect';
|
|
33
|
+
content: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ModalObservation {
|
|
36
|
+
triggerElement: string;
|
|
37
|
+
title: string;
|
|
38
|
+
content: string;
|
|
39
|
+
fields: string[];
|
|
40
|
+
stateId?: string;
|
|
41
|
+
domSnapshot?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ConditionalReveal {
|
|
44
|
+
triggerElement: string;
|
|
45
|
+
triggerValue: string;
|
|
46
|
+
revealedText: string;
|
|
47
|
+
stateId?: string;
|
|
48
|
+
domSnapshot?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface TooltipCapture {
|
|
51
|
+
triggerLabel: string;
|
|
52
|
+
tooltipText: string;
|
|
53
|
+
}
|
|
54
|
+
export interface TabPanelCapture {
|
|
55
|
+
tabLabel: string;
|
|
56
|
+
panelContent: string;
|
|
57
|
+
panelHeading?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface CarouselSlide {
|
|
60
|
+
slideIndex: number;
|
|
61
|
+
heading?: string;
|
|
62
|
+
content: string;
|
|
63
|
+
}
|
|
64
|
+
export interface WizardStep {
|
|
65
|
+
stepIndex: number;
|
|
66
|
+
stepLabel?: string;
|
|
67
|
+
content: string;
|
|
68
|
+
fields: string[];
|
|
69
|
+
}
|
|
70
|
+
export interface FocusTrapResult {
|
|
71
|
+
modalTrigger: string;
|
|
72
|
+
focusTrapped: boolean;
|
|
73
|
+
sampledFocused: string[];
|
|
74
|
+
}
|
|
75
|
+
export interface ContextMenuCapture {
|
|
76
|
+
trigger: string;
|
|
77
|
+
items: string[];
|
|
78
|
+
}
|
|
79
|
+
export interface ProbeResult {
|
|
80
|
+
screenId: string;
|
|
81
|
+
url: string;
|
|
82
|
+
validationErrors: ValidationError[];
|
|
83
|
+
successMessages: SuccessMessage[];
|
|
84
|
+
modals: ModalObservation[];
|
|
85
|
+
conditionals: ConditionalReveal[];
|
|
86
|
+
loadingPatterns: string[];
|
|
87
|
+
tooltips?: TooltipCapture[];
|
|
88
|
+
tabPanels?: TabPanelCapture[];
|
|
89
|
+
carouselSlides?: CarouselSlide[];
|
|
90
|
+
wizardSteps?: WizardStep[];
|
|
91
|
+
focusTraps?: FocusTrapResult[];
|
|
92
|
+
skipNavIssues?: string[];
|
|
93
|
+
contextMenus?: ContextMenuCapture[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Run interactive probing on a single screen page.
|
|
97
|
+
* The page must already be navigated to the screen URL.
|
|
98
|
+
* `elements` is the output of the static extractElements pass.
|
|
99
|
+
*/
|
|
100
|
+
export declare function probeScreen(page: Page, screenId: string, url: string, elements: ProbeElementFact[]): Promise<ProbeResult>;
|
|
101
|
+
/** Phase 5: Convert ProbeResult to typed ProbeObservationFact rows for direct DB storage. */
|
|
102
|
+
export declare function probeResultToObservations(result: ProbeResult): Array<{
|
|
103
|
+
elementMeaning: string;
|
|
104
|
+
observationType: string;
|
|
105
|
+
observedText: string;
|
|
106
|
+
triggeredBy: string;
|
|
107
|
+
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Convert a ProbeResult into markdown to store as KnowledgeChunks
|
|
110
|
+
* and update ERROR_CATALOGUE + INTERACTION_PATTERNS skill files.
|
|
111
|
+
*/
|
|
112
|
+
export declare function probeResultToMarkdown(result: ProbeResult): {
|
|
113
|
+
errorCatalogueChunk: string;
|
|
114
|
+
interactionPatternsChunk: string;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Run interactive probing for all screens discovered in a crawl session.
|
|
118
|
+
* Called from crawlProject() when opts.interactive = true.
|
|
119
|
+
*/
|
|
120
|
+
export declare function probeAllScreens(page: any, tenantId: string, projectId: string, discovered: Array<{
|
|
121
|
+
url: string;
|
|
122
|
+
screenId?: string;
|
|
123
|
+
elements?: any[];
|
|
124
|
+
}>, onProgress?: (pct: number, step: string) => Promise<void>, jobId?: string): Promise<void>;
|
|
125
|
+
export interface FocusableElement {
|
|
126
|
+
tag: string;
|
|
127
|
+
role: string | null;
|
|
128
|
+
ariaLabel: string | null;
|
|
129
|
+
text: string | null;
|
|
130
|
+
hasFocusIndicator: boolean;
|
|
131
|
+
tabIndex: number | null;
|
|
132
|
+
}
|
|
133
|
+
export interface KeyboardNavResult {
|
|
134
|
+
focusableCount: number;
|
|
135
|
+
elementsWithNoFocusIndicator: number;
|
|
136
|
+
sequence: FocusableElement[];
|
|
137
|
+
issues: string[];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Probe keyboard navigation accessibility by pressing Tab up to 50 times and
|
|
141
|
+
* recording each focused element's properties and focus-indicator visibility.
|
|
142
|
+
* Stops early if focus wraps back to the start or hits the same element twice.
|
|
143
|
+
*/
|
|
144
|
+
export declare function probeKeyboardNav(page: Page): Promise<KeyboardNavResult>;
|