fix(web-search): reduce domain entries on every route, not just site: - #931
Merged
Merged
Conversation
`normalizeDomain` ran only on the way into a `site:` operator, so a provider declaring `domainFilter: "native"` received the caller's raw entry. `includeDomains: ["https://arxiv.org/"]` restricted the search on one route and reached Tavily, OpenAI, Anthropic or OpenRouter as a scheme-bearing value on the other — all of which document bare hosts. The caller then gets no results for a filter that should have matched, or, for a vendor that skips an entry it cannot parse, an unrestricted search reported as successful with nothing saying the filter was dropped. With `"auto"` the route is picked at run time, so it is not reproducible from the input either. `adaptRequest` now reduces both lists before either direction is decided, so the native list and the operator translation read the same value. An entry that names no domain is still refused up front, unchanged. `domainInput` is exported from the barrel so a host writing its own native adapter can apply the same reduction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T8DU24G9GWuRUJncc5TJFZ
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.
What was wrong
normalizeDomain— which strips a scheme, awww.prefix and trailing slashes — was applied in exactly one place:normalizeAllinsidequeryOperators.ts, on the way into asite:operator. A provider declaringdomainFilter: "native"received the caller's entry verbatim.unusableDomainEntriesvalidates against the normalized form on purpose (" https://a.com/ "is a perfectly good domain), so a scheme-bearing,www.-prefixed or trailing-slash entry passes validation on every route and is then reduced on one route only. The raw value is forwarded tobody.include_domains(Tavily),tool.filters.allowed_domains(OpenAI),tool.allowed_domains/blocked_domains(Anthropic) andplugin.include_domains(OpenRouter) — all of which document bare hosts.The concrete failure
{ provider: "auto", includeDomains: ["https://arxiv.org/"] }:cats site:arxiv.organd the restriction holds;"https://arxiv.org/"— either zero results for a filter that should have matched, or, for a vendor that skips an entry it cannot parse, an unrestricted web search reported as successful, withproviderset and nothing saying the filter was discarded.That is the trade this package refuses everywhere else — the date-filter rule and the empty-entry refusal both say a bound reported as honored on a search that ran unfiltered is worse than a refused request. It is also not reproducible from the caller's side, because
"auto"picks the route at run time.What changed
adaptRequestreducesincludeDomains/excludeDomainsonce, before either direction is decided, and both the native pass-through and thesite:translation read that same value. The two directions stay decided separately, so a split provider (domainFilter: "native",excludeDomainFilter: "query-operator") gets a reduced native include list and a reduced-site:clause.assertUsableDomainsstill runs first, for every provider, and an entry that names no domain is still an error rather than a silent drop.normalizeAll's filter stays inqueryOperatorsas the structural backstop it was added to be — nothing spliced into a query can restructure it whether or not a call site validated first.domainInputis now exported fromcommon.ts, so a host writing its own native provider can apply the same reduction instead of re-deriving it.No new refusals and no new normalization rule — the same reduction, on both routes.
Tests
Two new cases in
WebSearchTask.test.ts, both run red against the unfixed code and green after (confirmed by running them):includeDomains: ["https://ArXiv.org/"]/excludeDomains: ["www.spam.example"], asserting the native adapter sees["arxiv.org"]/["spam.example"]and the operator route buildscats site:arxiv.org -site:spam.example;One existing test was renamed from "passes domain lists through untouched to a native provider" to "…rather than into the query" — its assertion is unchanged, but "untouched" now contradicts the contract.
Verified
bunx vitest run packages/web-search/src— 15 files, 137 tests, all pass (includes the existing "domain entries that name no domain" refusal block).bunx vitest runover the four vendor*WebSearchProvider.test.tssuites (gemini, anthropic, openai, openrouter) — 50 tests, all pass.bunx turbo run build-typesfor@workglow/web-searchand the four vendor packages — clean.bunx oxfmt --check packages/web-search/srcandbunx oxlint packages/web-search/src— clean.Not verified here: the full repo test suite,
bun run lintacross the whole tree, and the SearXNG integration test (it is skipped withoutWEB_SEARCH_SEARXNG_URL). No live vendor API was called — the adapter assertions are on the request objects, as the existing suites already are.🤖 Generated with Claude Code
https://claude.ai/code/session_01T8DU24G9GWuRUJncc5TJFZ
Generated by Claude Code