import type { SearchResultItem } from '../types.js'; import { type SmartRouter } from '../fetch/router.js'; export interface FetchContentContext { contentMaxChars: number; maxContentChars?: number; maxTotalChars: number; fetchTimeoutMs: number; totalDeadline: number; forceRefresh: boolean; maxFetches?: number; /** Fetch-stage wall-clock budget in ms. When absent, behavior is equivalent * to today's legacy path: no stage timer, per-URL timeoutSignal is the * only cancellation mechanism. */ stageBudgetMs?: number; /** Per-URL budget for anti-bot/TLS-first domains * (stackoverflow.com et al.). These are routed through the TLS-impersonation * tier first; a working TLS attempt takes ~1-5s and is starved by the small * `fetchTimeoutMs`. When absent, a default larger budget is derived from * `fetchTimeoutMs`/`stageBudgetMs` so existing call sites benefit. Always * clamped to the stage budget so the overall stage stays bounded. */ antiBotFetchTimeoutMs?: number; /** Number of candidates the caller intends to hydrate (typically the fetched * slice size). Used with {@link narrowSetBudgetMs} to scale the per-URL * budget up for a NARROW set — a structural signal, never a domain * allowlist. When absent, no narrow-set scaling applies. */ candidateCount?: number; /** Total per-URL budget pool (ms) shared across the candidate set. With a * narrow set (few candidates), each URL's budget scales toward * `narrowSetBudgetMs / candidateCount`, floored at the small base * `fetchTimeoutMs` and clamped to `stageBudgetMs`. Absent ⇒ legacy path * (no narrow-set bump). */ narrowSetBudgetMs?: number; /** When true, a per-URL/stage/total TIMEOUT falls back to the result's own * snippet as `markdown_content` (flagged `content_from_snippet`) so callers * get evidence text instead of empty content. The failure is still recorded * in `fetch_failed`. Absent/false ⇒ legacy path (empty content on timeout). */ snippetFallback?: boolean; /** Force the browser-render path (renderJs:'always') for a NARROW candidate * set. JS-heavy documentation SPAs served over the HTTP tier hand back an * empty JS shell — extraction "succeeds" with near-empty content, so neither * the timeout path nor the snippet fallback fires and callers get a * content-poor result. When set AND {@link candidateCount} ≤ `maxCandidates`, * the enrichment fetch renders the SPA so real content is recovered. Keys on * `candidateCount` — a STRUCTURAL signal — never a domain allowlist, so cost * stays bounded to a few URLs. Absent ⇒ legacy auto path for every URL * (broad searches never pay the browser cold-start). */ renderNarrowSet?: { maxCandidates: number; }; } export declare function fetchContentForResults(results: SearchResultItem[], router: SmartRouter, ctx: FetchContentContext): Promise; //# sourceMappingURL=content-fetch.d.ts.map