{"version":3,"file":"all-CVvzcMFq.mjs","names":[],"sources":["../src/core/types.ts","../src/core/search-filters.ts","../src/core/all.ts"],"sourcesContent":["export interface SearchResult {\n  url: string;\n  title: string;\n  snippet: string;\n  score?: number;\n  publishedDate?: string;\n  author?: string;\n  image?: string;\n  favicon?: string;\n  text?: string;\n  highlights?: string[];\n  summary?: string;\n  metadata?: Record<string, unknown>;\n}\n\nexport type ReadonlySearchResult = Readonly<Omit<SearchResult, \"highlights\" | \"metadata\">> & {\n  readonly highlights?: readonly string[];\n  readonly metadata?: Readonly<Record<string, unknown>>;\n};\n\nexport interface SearchResponse {\n  results: SearchResult[];\n  metadata?: Record<string, unknown>;\n}\n\n/** Normalized state of one provider's search sequence. */\nexport type SearchPagination =\n  | { readonly status: \"next\"; readonly continuation: string }\n  | { readonly status: \"unknown\"; readonly continuation: string }\n  | { readonly status: \"end\" }\n  | { readonly status: \"unsupported\" };\n\n/** Controls shared by every network-backed operation. */\nexport interface ExecutionOptions {\n  /** Cancels in-flight provider requests. */\n  readonly signal?: Readonly<AbortSignal>;\n  /** Absolute Unix timestamp in milliseconds at which the operation is cancelled. */\n  readonly deadline?: number;\n  /** Maximum requests started concurrently by fan-out and batch helpers. */\n  readonly concurrency?: number;\n}\n\nexport interface SearchOptions extends ExecutionOptions {\n  /** Positive integer result limit. */\n  maxResults?: number;\n  highlights?: boolean;\n  summary?: boolean;\n  fullText?: boolean;\n  includeDomains?: string[];\n  excludeDomains?: string[];\n  sources?: string[];\n  categories?: string[];\n  startPublishedDate?: string;\n  endPublishedDate?: string;\n  category?: string;\n}\n\nexport type SearchRequestOptions = Readonly<\n  Omit<SearchOptions, \"includeDomains\" | \"excludeDomains\" | \"sources\" | \"categories\">\n> & {\n  readonly includeDomains?: readonly string[];\n  readonly excludeDomains?: readonly string[];\n  readonly sources?: readonly string[];\n  readonly categories?: readonly string[];\n};\n\n/** Detailed search options with an opaque token for one provider and query. */\nexport type SearchPageOptions = SearchRequestOptions & {\n  readonly continuation?: string;\n  /** Keeps favicon URLs on results. Defaults to true; the agent surfaces pass false unless the model asks. */\n  readonly favicon?: boolean;\n};\n\nexport const searchFilterNames = [\n  \"includeDomains\",\n  \"excludeDomains\",\n  \"sources\",\n  \"categories\",\n  \"category\",\n  \"startPublishedDate\",\n  \"endPublishedDate\",\n] as const;\n\nexport type SearchFilterName = (typeof searchFilterNames)[number];\n\n/** Search filters a provider forwards, including any accepted singular category values. */\nexport interface SearchFilterCapabilities {\n  readonly filters: readonly SearchFilterName[];\n  readonly categories?: readonly string[];\n}\n\n/** One public page and image returned by reverse image search. */\nexport interface ImageSearchResult {\n  pageUrl: string;\n  imageUrl: string;\n  title: string;\n  provider: string;\n  source?: string;\n  thumbnailUrl?: string;\n  imageWidth?: number;\n  imageHeight?: number;\n  thumbnailWidth?: number;\n  thumbnailHeight?: number;\n  position?: number;\n  exactMatch?: boolean;\n}\n\n/** Options shared by reverse image search providers. */\nexport interface ImageSearchOptions extends ExecutionOptions {\n  maxResults?: number;\n}\n\n/** Immutable reverse image search options accepted by providers. */\nexport type ImageSearchRequestOptions = Readonly<ImageSearchOptions>;\n\nexport interface ReadResult {\n  url: string;\n  title?: string;\n  description?: string;\n  content: string;\n  text?: string;\n  html?: string;\n  publishedDate?: string;\n  image?: string;\n  links?: string[];\n  images?: string[];\n  metadata?: Record<string, unknown>;\n  truncated?: boolean;\n  continuation?: string;\n}\n\nexport interface ReadOptions extends ExecutionOptions {\n  format?: \"markdown\" | \"text\" | \"html\";\n  maxTokens?: number;\n  targetSelector?: string;\n  removeSelector?: string;\n  timeout?: number;\n  noCache?: boolean;\n}\n\n/** OAuth access for the ChatGPT Codex backend, not an OpenAI API key. */\nexport interface CodexCredentials {\n  readonly accessToken: string;\n  /** Defaults to the chatgpt_account_id claim in the access token. */\n  readonly accountId?: string;\n}\n\n/** Refresh is requested at most once, after the backend rejects authentication. */\nexport interface CodexCredentialRequest {\n  readonly refresh: boolean;\n  readonly signal: Readonly<AbortSignal>;\n}\n\n/** The caller owns token storage, expiry checks, refresh, and concurrent refresh coordination. */\nexport type CodexCredentialProvider = (\n  request: CodexCredentialRequest,\n) => CodexCredentials | Promise<CodexCredentials>;\n\n/** Native login selection; none disables automatic local and host credentials. */\nexport type CodexAuthSource = \"auto\" | \"codex\" | \"pi\" | \"omp\" | \"opencode\" | \"none\";\n\n/** Explicit Codex configuration takes precedence over environment credentials and model. */\nexport interface CodexConfig {\n  readonly credentials?: CodexCredentials | CodexCredentialProvider;\n  readonly model?: string;\n  /** Defaults to auto, or OPENAI_CODEX_AUTH_SOURCE when set. */\n  readonly authSource?: CodexAuthSource;\n}\n\nexport interface ProviderConfig {\n  apiKey?: string;\n  baseURL?: string;\n  readBaseURL?: string;\n  codex?: CodexConfig;\n}\n\nexport interface ClientOptions {\n  readonly maxRetries?: number;\n  baseDelay?: number;\n  timeout?: number;\n  userAgent?: string;\n}\n","import { getSearchFilterCapabilities } from \"./registry.ts\";\nimport { searchFilterNames, type SearchFilterName, type SearchRequestOptions } from \"./types.ts\";\n\n/** Requested filters that a named provider ignores or has not declared. */\nexport interface SearchFilterReport {\n  readonly provider: string;\n  readonly ignoredFilters: readonly SearchFilterName[];\n  readonly undeclaredFilters: readonly SearchFilterName[];\n}\n\n/**\n * Compare concrete search options with the provider's registered capabilities.\n * @param provider - Effective provider name.\n * @param options - Search options requested by the caller.\n * @returns {SearchFilterReport} Filters the provider ignores or has not declared.\n */\nexport function searchFilterReport(\n  provider: string,\n  options?: Readonly<SearchRequestOptions>,\n): SearchFilterReport {\n  const requested = searchFilterNames.filter((filter) => isRequested(filter, options));\n  const capabilities = getSearchFilterCapabilities(provider);\n  if (!capabilities) {\n    return { provider, ignoredFilters: [], undeclaredFilters: requested };\n  }\n\n  const ignoredFilters = requested.filter((filter) => {\n    if (!capabilities.filters.includes(filter)) return true;\n    if (filter !== \"category\" || !capabilities.categories) return false;\n    return !capabilities.categories.includes(options?.category ?? \"\");\n  });\n  return { provider, ignoredFilters, undeclaredFilters: [] };\n}\n\n/**\n * Check whether a report contains a filter the caller needs to know about.\n * @param report - Effective provider filter report.\n * @returns {boolean} Whether the report contains ignored or undeclared filters.\n */\nexport function hasSearchFilterWarning(report: Readonly<SearchFilterReport>): boolean {\n  return report.ignoredFilters.length > 0 || report.undeclaredFilters.length > 0;\n}\n\nfunction isRequested(filter: SearchFilterName, options?: Readonly<SearchRequestOptions>): boolean {\n  const value = options?.[filter];\n  return Array.isArray(value) ? value.length > 0 : typeof value === \"string\" && value.length > 0;\n}\n","import type {\n  ReadonlySearchResult,\n  SearchFilterName,\n  SearchPageOptions,\n  SearchPagination,\n  SearchRequestOptions,\n  SearchResponse,\n  SearchResult,\n} from \"./types.ts\";\nimport {\n  hasSearchFilterWarning,\n  searchFilterReport,\n  type SearchFilterReport,\n} from \"./search-filters.ts\";\nimport {\n  UnknownProviderError,\n  NoProviderConfiguredError,\n  NoProviderAvailableError,\n  EmptyQueryError,\n  InvalidSearchContinuationError,\n  validateDateFilters,\n  validateMaxResults,\n} from \"./errors.ts\";\nimport {\n  isFallbackEligible,\n  providerFailure,\n  ProviderFallbackError,\n  type ProviderFailure,\n} from \"./fallback.ts\";\nimport { createSearchProvider, has } from \"./registry.ts\";\nimport { isDetailedSearchProvider, isPaginatedSearchProvider } from \"./provider.ts\";\nimport { decodeSearchContinuation, encodeSearchContinuation } from \"./search-continuation.ts\";\nimport {\n  detectAvailableProviders,\n  detectAvailableProvidersAsync,\n  probeConfiguredProvider,\n} from \"./resolve.ts\";\nimport {\n  providerRequestOptions,\n  settleWithConcurrency,\n  throwIfAborted,\n  throwIfCancelled,\n  withExecutionBudget,\n} from \"./execution.ts\";\n\nconst DEFAULT_MAX_RESULTS = 10;\n\nexport type SearchAllOptions = SearchPageOptions & {\n  readonly providers?: readonly string[];\n};\n\n/** One provider record retained as evidence for a deduplicated result. */\nexport interface SearchAllEvidence extends SearchResult {\n  provider: string;\n}\n\n/** Stable representative plus every provider record for one normalized URL. */\nexport interface SearchAllResult extends SearchAllEvidence {\n  providers: string[];\n  evidence: SearchAllEvidence[];\n}\n\nexport interface ProviderError {\n  provider: string;\n  error: Error;\n}\n\nexport interface SearchProviderMetadata {\n  readonly provider: string;\n  readonly metadata: Readonly<Record<string, unknown>>;\n}\n\n/** One provider's independent continuation state in a fanout response. */\nexport interface SearchProviderPagination {\n  readonly provider: string;\n  readonly pagination: SearchPagination;\n}\n\nexport interface SearchAllResponse {\n  results: SearchAllResult[];\n  successfulProviders: string[];\n  errors: ProviderError[];\n  filterReports: SearchFilterReport[];\n  providerPagination: SearchProviderPagination[];\n  providerMetadata?: SearchProviderMetadata[];\n}\n\n/** Results from one named provider with effective filter diagnostics. */\nexport interface SearchProviderResult {\n  readonly provider: string;\n  readonly results: readonly SearchResult[];\n  readonly ignoredFilters: readonly SearchFilterName[];\n  readonly undeclaredFilters: readonly SearchFilterName[];\n  readonly pagination: SearchPagination;\n  readonly metadata?: Readonly<Record<string, unknown>>;\n}\n\n/** Result from automatic search with ordered provider-attempt diagnostics. */\nexport interface SearchWithFallbackResult extends SearchProviderResult {\n  readonly provider: string;\n  readonly attempts: readonly string[];\n  readonly failures: readonly ProviderFailure[];\n}\n\n/** Automatic search prepared with one snapshot of configured providers. */\nexport type PreparedSearchWithFallback = (query: string) => Promise<SearchWithFallbackResult>;\n\n/**\n * Query multiple providers in parallel and return deduplicated results.\n * Providers are auto-detected from env vars unless explicitly specified.\n * Individual provider failures don't affect other results.\n * @param {string} query - Search query.\n * @param {SearchAllOptions} options - Provider and result options.\n * @returns {Promise<SearchAllResult[]>} Deduplicated provider results.\n */\nexport async function searchAll(\n  query: string,\n  options?: SearchAllOptions,\n): Promise<SearchAllResult[]> {\n  const response = await searchAllDetailed(query, options);\n  return response.results;\n}\n\n/**\n * Like {@link searchAll}, but also returns successful provider names,\n * filter diagnostics, and errors for each provider. A `deadline` keeps the\n * providers that finished and lists the rest in `errors`. A cancelled\n * `signal` still rejects. Automatic selection probes reachability inside each\n * provider's slot, so a hanging endpoint costs only that provider.\n * @param {string} query - Search query.\n * @param {SearchAllOptions} options - Provider and result options.\n * @returns {Promise<SearchAllResponse>} Results and provider failures.\n */\nexport async function searchAllDetailed(\n  query: string,\n  options?: SearchAllOptions,\n): Promise<SearchAllResponse> {\n  validateSearchInput(query, options);\n\n  const { providers: requestedProviders, continuation, ...searchOptions } = options ?? {};\n  if (continuation !== undefined) {\n    throw new TypeError(\"continuation is not supported with provider=all\");\n  }\n  validateProviderNames(requestedProviders);\n  const maxResults = searchOptions.maxResults ?? DEFAULT_MAX_RESULTS;\n  const effectiveSearchOptions = withExecutionBudget({ ...searchOptions, maxResults });\n  throwIfAborted(effectiveSearchOptions.signal);\n  const providerNames = fanoutProviderNames(requestedProviders);\n  const settled = await searchProviders(\n    providerNames,\n    query,\n    effectiveSearchOptions,\n    requestedProviders === undefined,\n  );\n  throwIfCancelled(effectiveSearchOptions);\n  return collectProviderResults(reachableAttempts(providerNames, settled), maxResults);\n}\n\n/**\n * Search through automatic providers in order, continuing after eligible transient failures.\n * @param query - Search query.\n * @param options - Search options forwarded to the selected provider.\n * @returns {Promise<SearchWithFallbackResult>} Results, provider, and attempt diagnostics.\n */\nexport async function searchWithFallback(\n  query: string,\n  options?: Readonly<SearchPageOptions>,\n): Promise<SearchWithFallbackResult> {\n  validateSearchInput(query, options);\n  const effectiveOptions = withExecutionBudget(options);\n  throwIfAborted(effectiveOptions.signal);\n\n  const continuation = options?.continuation;\n  if (continuation !== undefined) {\n    const { continuation: _continuation, ...searchOptions } = effectiveOptions;\n    const payload = decodeSearchContinuation(continuation, query, searchOptions);\n    const response = await searchProvider(payload.provider, query, effectiveOptions);\n    return { ...response, attempts: [payload.provider], failures: [] };\n  }\n\n  const providerNames = await resolveAutomaticProviderNames(effectiveOptions);\n  return searchProviderNamesWithFallback(providerNames, query, effectiveOptions);\n}\n\n/**\n * Search one named provider and report filters it could not apply.\n * @param providerName - Registered provider name.\n * @param query - Search query.\n * @param options - Search options forwarded to the provider.\n * @returns {Promise<SearchProviderResult>} Results and effective filter diagnostics.\n */\nexport async function searchProviderDetailed(\n  providerName: string,\n  query: string,\n  options?: Readonly<SearchPageOptions>,\n): Promise<SearchProviderResult> {\n  validateSearchInput(query, options);\n  validateProviderNames([providerName]);\n  return searchProvider(providerName, query, options);\n}\n\n/**\n * Resolve the automatic provider order once for a batch of searches.\n * @param options - Search options forwarded to every selected provider.\n * @returns {Promise<PreparedSearchWithFallback>} Search function using the resolved provider order.\n */\nexport async function prepareSearchWithFallback(\n  options?: Readonly<Omit<SearchPageOptions, \"continuation\">>,\n): Promise<PreparedSearchWithFallback> {\n  validateMaxResults(options?.maxResults);\n  validateDateFilters(options?.startPublishedDate, options?.endPublishedDate);\n  const effectiveOptions = withExecutionBudget(options);\n  throwIfAborted(effectiveOptions.signal);\n  const providerNames = await resolveAutomaticProviderNames(effectiveOptions);\n  return (query) => {\n    if (!query.trim()) throw new EmptyQueryError();\n    return searchProviderNamesWithFallback(providerNames, query, effectiveOptions);\n  };\n}\n\nasync function searchProviderNamesWithFallback(\n  providerNames: readonly string[],\n  query: string,\n  options?: Readonly<SearchPageOptions>,\n): Promise<SearchWithFallbackResult> {\n  const attempts: string[] = [];\n  const failures: ProviderFailure[] = [];\n  let lastError: unknown;\n\n  for (const providerName of providerNames) {\n    throwIfAborted(options?.signal);\n    attempts.push(providerName);\n    try {\n      const response = await searchProvider(providerName, query, options);\n      return { ...response, attempts, failures };\n    } catch (error) {\n      const failure = providerFailure(providerName, error);\n      if (!isFallbackEligible(error, providerName, \"search\")) {\n        if (failures.length === 0) throw error;\n        failures.push(failure);\n        throw new ProviderFallbackError(\"search\", failures, error);\n      }\n      failures.push(failure);\n      lastError = error;\n    }\n  }\n  if (lastError === undefined) throw new NoProviderAvailableError(providerNames);\n  throw new ProviderFallbackError(\"search\", failures, lastError);\n}\n\nfunction validateSearchInput(query: string, options?: Readonly<SearchPageOptions>): void {\n  if (!query.trim()) {\n    throw new EmptyQueryError();\n  }\n  validateMaxResults(options?.maxResults);\n  validateDateFilters(options?.startPublishedDate, options?.endPublishedDate);\n}\n\nfunction validateProviderNames(providerNames?: readonly string[]): void {\n  const unknown = providerNames?.find((name) => !has(name));\n  if (unknown) throw new UnknownProviderError(unknown);\n}\n\nfunction fanoutProviderNames(requestedProviders?: readonly string[]): readonly string[] {\n  const providerNames = requestedProviders ?? detectAvailableProviders();\n  if (providerNames.length === 0) throw new NoProviderConfiguredError();\n  return providerNames;\n}\n\nasync function resolveAutomaticProviderNames(\n  options?: Readonly<SearchRequestOptions>,\n): Promise<readonly string[]> {\n  const providerNames = await detectAvailableProvidersAsync(options);\n  if (providerNames.length > 0) return providerNames;\n\n  const configuredProviders = detectAvailableProviders();\n  if (configuredProviders.length === 0) throw new NoProviderConfiguredError();\n  throw new NoProviderAvailableError(configuredProviders);\n}\n\nasync function searchProvider<TProvider extends string>(\n  providerName: TProvider,\n  query: string,\n  options?: Readonly<SearchPageOptions>,\n): Promise<SearchProviderResult & { readonly provider: TProvider }> {\n  const { continuation, favicon, ...searchOptions } = options ?? {};\n  const effectiveSearchOptions = withExecutionBudget(searchOptions);\n  throwIfAborted(effectiveSearchOptions.signal);\n  const requestOptions = providerRequestOptions(effectiveSearchOptions);\n  const payload =\n    continuation === undefined\n      ? undefined\n      : decodeSearchContinuation(continuation, query, requestOptions);\n  if (payload !== undefined && payload.provider !== providerName) {\n    throw new InvalidSearchContinuationError();\n  }\n\n  const provider = await createSearchProvider(providerName);\n  throwIfAborted(effectiveSearchOptions.signal);\n  const paginated = isPaginatedSearchProvider(provider);\n  let response: SearchResponseWithContinuation;\n  try {\n    response = await searchResponse(\n      provider,\n      paginated,\n      query,\n      requestOptions,\n      payload?.providerContinuation,\n    );\n  } catch (error) {\n    throwIfAborted(effectiveSearchOptions.signal);\n    throw error;\n  }\n  throwIfAborted(effectiveSearchOptions.signal);\n  const pagination = normalizedPagination(providerName, query, requestOptions, response, paginated);\n  const report = searchFilterReport(providerName, requestOptions);\n  return {\n    ...report,\n    provider: providerName,\n    results: dropsFavicons(favicon, response.results)\n      ? response.results.map(({ favicon: _favicon, ...rest }) => rest)\n      : response.results,\n    pagination,\n    ...(response.metadata === undefined ? {} : { metadata: { ...response.metadata } }),\n  };\n}\n\n/**\n * Whether the caller declined favicons and a result carries one, so a provider that maps none costs nothing.\n * @param favicon - The caller's `favicon` option.\n * @param results - Results as the provider mapped them.\n * @returns {boolean} Whether the favicon URLs have to be stripped.\n */\nfunction dropsFavicons(\n  favicon: boolean | undefined,\n  results: readonly ReadonlySearchResult[],\n): boolean {\n  return favicon === false && results.some((result) => result.favicon !== undefined);\n}\n\ntype SearchResponseWithContinuation = SearchResponse & {\n  readonly continuation?: string;\n  readonly continuationStatus?: \"next\" | \"unknown\";\n};\n\nasync function searchResponse(\n  provider: Readonly<Awaited<ReturnType<typeof createSearchProvider>>>,\n  paginated: boolean,\n  query: string,\n  options: Readonly<SearchRequestOptions>,\n  providerContinuation?: string,\n): Promise<SearchResponseWithContinuation> {\n  if (paginated && isPaginatedSearchProvider(provider)) {\n    return provider.searchPage(query, options, providerContinuation);\n  }\n  if (providerContinuation !== undefined) throw new InvalidSearchContinuationError();\n  return isDetailedSearchProvider(provider)\n    ? provider.searchDetailed(query, options)\n    : { results: await provider.search(query, options) };\n}\n\nfunction normalizedPagination(\n  providerName: string,\n  query: string,\n  options: Readonly<SearchRequestOptions>,\n  response: Readonly<Pick<SearchResponseWithContinuation, \"continuation\" | \"continuationStatus\">>,\n  paginated: boolean,\n): SearchPagination {\n  if (!paginated) return { status: \"unsupported\" };\n  if (response.continuation === undefined) return { status: \"end\" };\n  return {\n    status: response.continuationStatus ?? \"next\",\n    continuation: encodeSearchContinuation(providerName, query, options, response.continuation),\n  };\n}\n\ntype ReadonlySearchProviderResult = Readonly<Omit<SearchProviderResult, \"results\">> & {\n  readonly results: readonly ReadonlySearchResult[];\n};\n\ntype ProviderSearchOutcome =\n  | { readonly status: \"fulfilled\"; readonly value: ReadonlySearchProviderResult }\n  | { readonly status: \"rejected\"; readonly reason: unknown };\n\ntype ProviderSearchSettlement =\n  | { readonly status: \"fulfilled\"; readonly value: ReadonlySearchProviderResult | null }\n  | { readonly status: \"rejected\"; readonly reason: unknown };\n\ntype ProviderSearchAttempt = readonly [provider: string, outcome: ProviderSearchOutcome];\n\nfunction searchProviders(\n  providerNames: readonly string[],\n  query: string,\n  options: Readonly<Omit<SearchPageOptions, \"continuation\">>,\n  probeReachability: boolean,\n): Promise<readonly ProviderSearchSettlement[]> {\n  return settleWithConcurrency(\n    providerNames,\n    async (name, _index, signal) => {\n      if (probeReachability && (await probeConfiguredProvider(name, signal)) === false) return null;\n      return searchProvider(name, query, options);\n    },\n    options,\n  );\n}\n\nfunction reachableAttempts(\n  providerNames: readonly string[],\n  settled: readonly ProviderSearchSettlement[],\n): readonly ProviderSearchAttempt[] {\n  const attempts = settled.flatMap((outcome, index): ProviderSearchAttempt[] => {\n    if (outcome.status === \"rejected\") return [[providerNames[index], outcome]];\n    return outcome.value === null\n      ? []\n      : [[providerNames[index], { status: \"fulfilled\", value: outcome.value }]];\n  });\n  if (attempts.length === 0) throw new NoProviderAvailableError(providerNames);\n  return attempts;\n}\n\nfunction collectProviderResults(\n  attempts: readonly ProviderSearchAttempt[],\n  maxResults?: number,\n): SearchAllResponse {\n  const results: SearchAllEvidence[] = [];\n  const successfulProviders = new Set<string>();\n  const errors: ProviderError[] = [];\n  const filterReports: SearchFilterReport[] = [];\n  const providerMetadata: SearchProviderMetadata[] = [];\n  const providerPagination: SearchProviderPagination[] = [];\n  for (const [provider, outcome] of attempts) {\n    if (outcome.status === \"fulfilled\") {\n      successfulProviders.add(outcome.value.provider);\n      results.push(\n        ...outcome.value.results.map((result) =>\n          mutableResultWithProvider(result, outcome.value.provider),\n        ),\n      );\n      if (hasSearchFilterWarning(outcome.value)) {\n        const { provider, ignoredFilters, undeclaredFilters } = outcome.value;\n        filterReports.push({ provider, ignoredFilters, undeclaredFilters });\n      }\n      providerPagination.push({\n        provider: outcome.value.provider,\n        pagination: outcome.value.pagination,\n      });\n      if (outcome.value.metadata !== undefined) {\n        providerMetadata.push({\n          provider: outcome.value.provider,\n          metadata: { ...outcome.value.metadata },\n        });\n      }\n    } else {\n      errors.push({\n        provider,\n        error: outcome.reason instanceof Error ? outcome.reason : new Error(String(outcome.reason)),\n      });\n    }\n  }\n  const deduplicatedResults = deduplicateByUrl(results);\n  return {\n    results:\n      maxResults === undefined ? deduplicatedResults : deduplicatedResults.slice(0, maxResults),\n    successfulProviders: [...successfulProviders],\n    errors,\n    filterReports,\n    providerPagination,\n    ...(providerMetadata.length === 0 ? {} : { providerMetadata }),\n  };\n}\n\nfunction mutableResultWithProvider(\n  result: ReadonlySearchResult,\n  provider: string,\n): SearchAllEvidence {\n  const { highlights, metadata, ...rest } = result;\n  return {\n    ...rest,\n    ...(highlights ? { highlights: [...highlights] } : {}),\n    ...(metadata ? { metadata: { ...metadata } } : {}),\n    provider,\n  };\n}\n\ntype ReadonlySearchAllEvidence = ReadonlySearchResult & { readonly provider: string };\n\nfunction deduplicateByUrl(results: readonly ReadonlySearchAllEvidence[]): SearchAllResult[] {\n  const seen = new Map<string, SearchAllResult>();\n\n  for (const result of results) {\n    const normalized = normalizeUrl(result.url);\n    const existing = seen.get(normalized);\n\n    if (!existing) {\n      seen.set(normalized, {\n        ...mutableResultWithProvider(result, result.provider),\n        providers: [result.provider],\n        evidence: [mutableResultWithProvider(result, result.provider)],\n      });\n      continue;\n    }\n\n    if (!existing.providers.includes(result.provider)) {\n      existing.providers.push(result.provider);\n    }\n    existing.evidence.push(mutableResultWithProvider(result, result.provider));\n  }\n\n  return Array.from(seen.values());\n}\n\nfunction normalizeUrl(url: string): string {\n  try {\n    const parsed = new URL(url);\n    parsed.hash = \"\";\n    const path = parsed.pathname.replace(/\\/+$/, \"\") || \"/\";\n    const search = canonicalizeSearchParams(parsed.search);\n    return `${parsed.protocol}//${parsed.host}${path}${search}`;\n  } catch {\n    return url;\n  }\n}\n\nfunction canonicalizeSearchParams(serializedSearchParams: string): string {\n  const searchParams = new URLSearchParams(serializedSearchParams);\n  const filteredSortedEntries = Array.from(searchParams.entries())\n    .filter(([key]) => !isTrackingParam(key))\n    .map(([key, value], index) => ({ key, value, index }))\n    .sort((a, b) => {\n      const keyOrder = a.key.localeCompare(b.key, \"en\");\n      if (keyOrder !== 0) {\n        return keyOrder;\n      }\n\n      return a.index - b.index;\n    })\n    .map(({ key, value }): [string, string] => [key, value]);\n\n  if (filteredSortedEntries.length === 0) {\n    return \"\";\n  }\n\n  return `?${new URLSearchParams(filteredSortedEntries).toString()}`;\n}\n\nfunction isTrackingParam(key: string): boolean {\n  return key.toLowerCase().startsWith(\"utm_\");\n}\n"],"mappings":"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"}