{"version":3,"file":"resolve-C9qYA-9N.mjs","names":[],"sources":["../src/core/resolve.ts"],"sourcesContent":["import { builtinProviders, providerDetectionOrder } from \"./providers.ts\";\nimport {\n  create,\n  getProviderApiKeyEnvVar,\n  getProviderCapabilities,\n  getSearchFilterCapabilities,\n  probesAvailability,\n  isProviderConfigured,\n  providers,\n  searchProviders,\n} from \"./registry.ts\";\nimport { NoProviderAvailableError, NoProviderConfiguredError } from \"./errors.ts\";\nimport { isAvailabilityProvider, type ProviderCapabilities } from \"./provider.ts\";\nimport { settleWithConcurrency, throwIfAborted, withExecutionBudget } from \"./execution.ts\";\nimport type { ExecutionOptions, SearchFilterName } from \"./types.ts\";\n\nexport { isProviderConfigured } from \"./registry.ts\";\n\nexport function detectAvailableProviders(): string[] {\n  return orderedSearchProviders().filter(isProviderConfigured);\n}\n\nexport function resolveDefaultProvider(): string {\n  const provider = detectAvailableProviders()[0];\n  if (provider !== undefined) return provider;\n  throw new NoProviderConfiguredError();\n}\n\nexport interface ProviderStatus {\n  name: string;\n  configured: boolean;\n  envVar: string | null;\n  /**\n   * Set by {@link listProvidersAsync} when the provider implements\n   * {@link AvailabilityProvider.isAvailable}. `true` = probe succeeded,\n   * `false` = probe failed (host down / unreachable / timeout), `undefined` =\n   * no reachability probe was performed (trust `configured`).\n   */\n  reachable?: boolean;\n  readonly searchFilters?: readonly SearchFilterName[];\n  readonly searchCategories?: readonly string[];\n  readonly capabilities: ProviderCapabilities;\n}\n\nexport function listProviders(): ProviderStatus[] {\n  return orderedRegisteredProviders().map((name) =>\n    providerStatus(name, isProviderConfigured(name)),\n  );\n}\n\n/**\n * Async variant: returns only providers that are both declaratively configured\n * (env var present or registered) AND — if they implement `isAvailable()` —\n * pass the reachability probe. Use for fan-out flows (`searchAll`) where an\n * unreachable self-hosted endpoint should be skipped instead of producing a\n * connection-refused error. Sync {@link detectAvailableProviders} stays the\n * declarative source of truth for env-var inspection.\n * @param options - Shared cancellation, deadline, and concurrency controls.\n * @returns {Promise<string[]>} Configured and reachable provider names.\n */\nexport async function detectAvailableProvidersAsync(\n  options?: Readonly<ExecutionOptions>,\n): Promise<string[]> {\n  const candidates = detectAvailableProviders();\n  const executionOptions = withExecutionBudget(options);\n  const signal = executionOptions.signal;\n  throwIfAborted(signal);\n  const probes = await settleWithConcurrency(\n    candidates,\n    async (name, _index, workerSignal) => {\n      const reachable = await probeConfiguredProvider(name, workerSignal);\n      return reachable === false ? null : name;\n    },\n    executionOptions,\n  );\n  throwIfAborted(signal);\n  return probes.flatMap((probe) =>\n    probe.status === \"fulfilled\" && probe.value !== null ? [probe.value] : [],\n  );\n}\n\n/**\n * Async variant of {@link listProviders} that also runs the per-provider\n * reachability probe and surfaces it as `reachable` on each row. Providers\n * without an `isAvailable()` probe get `reachable: undefined` (trust\n * `configured`).\n * @param options - Shared cancellation, deadline, and concurrency controls.\n * @returns {Promise<ProviderStatus[]>} Provider status rows.\n */\nexport async function listProvidersAsync(\n  options?: Readonly<ExecutionOptions>,\n): Promise<ProviderStatus[]> {\n  const executionOptions = withExecutionBudget(options);\n  const signal = executionOptions.signal;\n  throwIfAborted(signal);\n  const statuses = await settleWithConcurrency(\n    orderedRegisteredProviders(),\n    async (name, _index, workerSignal) => {\n      const configured = isProviderConfigured(name);\n      const base = providerStatus(name, configured);\n      if (!configured) return base;\n      const reachable = await probeConfiguredProvider(name, workerSignal);\n      return reachable === undefined ? base : { ...base, reachable };\n    },\n    executionOptions,\n  );\n  throwIfAborted(signal);\n  return statuses.flatMap((status) => (status.status === \"fulfilled\" ? [status.value] : []));\n}\n\n/**\n * Async variant of {@link resolveDefaultProvider}: returns the first provider\n * that is configured AND (if it has an `isAvailable()` probe) reachable. Use\n * in flows that should not crash when the env-preferred default is down\n * (e.g. SearXNG on `localhost:8080` without a running instance).\n * @param options - Shared cancellation and deadline controls.\n * @returns {Promise<string>} First reachable configured provider.\n */\nexport async function resolveDefaultProviderAsync(\n  options?: Readonly<ExecutionOptions>,\n): Promise<string> {\n  const candidates = detectAvailableProviders();\n  const signal = withExecutionBudget(options).signal;\n  for (const name of candidates) {\n    throwIfAborted(signal);\n    const reachable = await probeConfiguredProvider(name, signal);\n    throwIfAborted(signal);\n    if (reachable !== false) {\n      return name;\n    }\n  }\n\n  if (candidates.length === 0) {\n    throw new NoProviderConfiguredError();\n  }\n  throw new NoProviderAvailableError(candidates);\n}\n\nfunction providerStatus(name: string, configured: boolean): ProviderStatus {\n  const searchCapabilities = getSearchFilterCapabilities(name);\n  const capabilities = getProviderCapabilities(name);\n  if (capabilities === undefined) {\n    throw new TypeError(`Registered provider ${name} has no capability metadata`);\n  }\n  return {\n    name,\n    configured,\n    envVar: getProviderApiKeyEnvVar(name),\n    ...(searchCapabilities === undefined ? {} : { searchFilters: searchCapabilities.filters }),\n    ...(searchCapabilities?.categories === undefined\n      ? {}\n      : { searchCategories: searchCapabilities.categories }),\n    capabilities,\n  };\n}\n\n/**\n * Runs the provider's reachability probe when the registry says one may exist, so a listing\n * loads no built-in module for the providers that have none.\n * @param name - Registered provider name.\n * @param signal - Effective operation signal.\n * @returns {Promise<boolean | undefined>} Probe verdict, undefined without a probe.\n */\nexport async function probeConfiguredProvider(\n  name: string,\n  signal?: Readonly<AbortSignal>,\n): Promise<boolean | undefined> {\n  if (!probesAvailability(name)) return undefined;\n  try {\n    const provider = await create(name);\n    if (!isAvailabilityProvider(provider)) return undefined;\n    return await provider.isAvailable(signal);\n  } catch {\n    throwIfAborted(signal);\n    return false;\n  }\n}\n\nfunction orderedRegisteredProviders(): string[] {\n  const registered = providers();\n  const builtins = builtinProviders.filter((name) => registered.includes(name));\n  const custom = registered.filter(\n    (name) => !(builtinProviders as readonly string[]).includes(name),\n  );\n  return [...builtins, ...custom];\n}\n\nfunction orderedSearchProviders(): string[] {\n  const registered = searchProviders();\n  const known = providerDetectionOrder.filter((name) => registered.includes(name));\n  const knownNames = new Set<string>(known);\n  const custom = registered.filter(\n    (name) => !(builtinProviders as readonly string[]).includes(name),\n  );\n  const remainingBuiltins = builtinProviders.filter(\n    (name) => registered.includes(name) && !knownNames.has(name),\n  );\n  return [...known, ...custom, ...remainingBuiltins];\n}\n"],"mappings":"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"}