feat(scraper): harden fetch fallbacks, llms.txt parsing, and version resolution - #488
Open
ahmedhosnypro wants to merge 4 commits into
Open
ahmedhosnypro wants to merge 4 commits into
ahmedhosnypro wants to merge 4 commits into
Conversation
Customizations to the scraper fetchers, scraping strategies, llms.txt parsing, document management service, and embedding factory.
# Conflicts: # src/scraper/strategies/BaseScraperStrategy.test.ts # src/scraper/strategies/BaseScraperStrategy.ts
…behavior - add scrapeMode to FetchOptions and pass it through createFetchOptions - use supported apiKey field for OpenAIEmbeddings configuration - avoid any-typed catch in AutoDetectFetcher - update tests for llms.txt headerless parsing and findBestVersion fallback
4 tasks
There was a problem hiding this comment.
🟡 Changes recommended
findBestVersion can select the wrong fallback version and can return { bestMatch: null, hasUnversioned: false } without throwing, which can cause incorrect downstream behavior.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR strengthens the scraping pipeline’s resilience (fetcher fallbacks, Playwright realism, llms.txt robustness, GitHub scoping) and expands documentation version resolution behavior, while updating/adding tests to cover the new paths.
Changes:
- Hardened web scraping against anti-bot responses and improved Playwright fingerprinting/context defaults (UA/viewport/Chromium launch/executable discovery).
- Expanded llms.txt support (headerless files,
<pre>-wrapped text) and ensured llms.txt-seeded 404s don’t abort scrapes (includinginitialQueuecoverage). - Broadened version resolution to support named/non-semver versions and new fallback behavior; updated embedding configuration to pass OpenAI credentials/base URL via supported fields.
File summaries
| File | Description |
|---|---|
| src/store/embeddings/EmbeddingFactory.ts | Passes OpenAI apiKey/baseURL via apiKey/configuration for embeddings. |
| src/store/DocumentManagementService.ts | Updates findBestVersion to support named versions and fallback behavior. |
| src/store/DocumentManagementService.test.ts | Adjusts tests to reflect new version-resolution fallbacks. |
| src/scraper/utils/llmsTxtParser.ts | Adds headerless parsing and unwraps <pre>-wrapped llms.txt content; expands bullet parsing. |
| src/scraper/utils/llmsTxtParser.test.ts | Adds/updates tests for headerless parsing and stricter “invalid content” coverage. |
| src/scraper/strategies/WebScraperStrategy.ts | Propagates scrapeMode to fetch options; expands llms.txt candidate probing; avoids root-only behaviors for fromLlmsTxt. |
| src/scraper/strategies/WebScraperStrategy.test.ts | Updates fetch expectations to include scrapeMode. |
| src/scraper/strategies/GitHubScraperStrategy.ts | Tightens scoping so discovered links stay within the same owner/repo on github.com. |
| src/scraper/strategies/BaseScraperStrategy.ts | Treats llms.txt-seeded items as non-root for fail-fast and failure-rate counting purposes. |
| src/scraper/strategies/BaseScraperStrategy.test.ts | Adds coverage ensuring initialQueue llms.txt-seeded 404s don’t abort the scrape. |
| src/scraper/middleware/HtmlPlaywrightMiddleware.ts | Sets a realistic user agent + viewport on browser contexts. |
| src/scraper/fetcher/types.ts | Extends FetchOptions with scrapeMode. |
| src/scraper/fetcher/BrowserFetcher.ts | Adds realistic UA/viewport; hardens Chromium launch args and discovers system Chromium paths. |
| src/scraper/fetcher/AutoDetectFetcher.ts | Honors scrapeMode=playwright and falls back to browser fetcher on more anti-bot indicators. |
| .gitignore | Ignores .playwright-mcp/. |
Review details
- Files reviewed: 14/15 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- use the semver-sorted version list for invalid-format fallbacks - throw VersionNotFoundInStoreError when no match exists and there are no unversioned documents, instead of returning a null bestMatch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR hardens the scraping pipeline,
llms.txtparsing, and version resolution logic. It improves resilience against anti-bot blocks, refines fallback strategies when resolving library versions, and prevents scraping failures on non-criticalllms.txtseed errors.Scraper fetchers & anti-bot resilience
AutoDetectFetcher: falls back to the browser fetcher on403/429anti-bot blocks (not just challenge pages), and honorsscrapeMode: "playwright"by going straight to the browser fetcherBrowserFetcher/HtmlPlaywrightMiddleware: realistic user agent and viewport, hardened Chromium launch flags (--disable-blink-features=AutomationControlled, new headless mode), and system Chromium path discovery (PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH, common distro locations)llms.txt handling
llmsTxtParser: accepts headerless llms.txt files (uses the first non-empty line as the name) and unwraps content delivered inside a<pre>tag when a server renders plain text via HTMLBaseScraperStrategy: a 404 on an llms.txt-seeded URL no longer aborts the whole scrape (complementary to the fix that landed upstream in fix(scraper): don't abort scrape when only an llms.txt-seeded url 404s #479; adds coverage forinitialQueue-seeded items)GitHub strategy
owner/repoon github.com while still honoring include/exclude patternsVersion resolution
findBestVersionnow supports named/non-semver versions (latest,canary, ...) and falls back to the latest available version for invalid target formats instead of failingEmbeddings
EmbeddingFactory: passes the OpenAI API key and optionalOPENAI_API_BASEexplicitly via the supportedapiKey/configurationfieldsChanges
Scraper and Fetcher Hardening
BrowserFetcheron 403 or 429 status codes, or whenscrapeModeis set to"playwright". 19llms.txt. 22, 23, 24shouldProcessUrlto restrict processing to the target repository's owner and name. 12llms.txtand bypassed archive/canonical checks forllms.txtitems. 8, 9, 10Parsing and Versioning Improvements
<pre>tags, additional bullet characters, and missing H1 headings. 16, 17findBestVersionto fall back to the latest semver version on invalid target formats. 1, 2, 3apiKeyin the configuration object toOpenAIEmbeddings. 7Verification
Automated Tests
Run the updated test suites to verify the new fallback and parsing behaviors:
Test plan
npm run lint— clean (Biome)npm run typecheck— clean (tsc --noEmit)npm run build— cleannpm test— all unit/integration suites pass; tests updated where the patches intentionally change behavior (llms.txt headerless parsing,findBestVersionfallback)initialQueueitemsCloses #185