import type { Config, ProviderConfig } from "./config.js"; import { type CredentialSlot } from "./credential-fleet.js"; import { ModelCatalog } from "./catalog.js"; /** * Describe a thrown error WITHOUT quoting it. * * `KeyCheckResult.message` is printed by `llm-relay keys`, so it must describe outcomes * (an env-var NAME, an HTTP status, a quota percent) and can never carry the credential. * Interpolating `(e as Error).message` broke that: an error text is uncontrolled and * routinely echoes the request — a provider that takes its key in the query string, a * proxy that quotes the failing URL, or an injected `fetchFn` that stringifies its own * init all put the key inside it. Classifying instead of quoting removes the whole class: * the only thing that survives is an error CODE or NAME, and anything that is not a bare * identifier is dropped rather than trimmed or masked. */ export declare function describeFailure(e: unknown): string; export interface KeyCheckResult { provider: string; credentialId: string; label: string; authEnv?: string | undefined; hasEnvKey: boolean; status: "valid" | "invalid_key" | "rate_limited" | "missing_env" | "unreachable" | "unverified" | "disabled" | "no_models"; httpStatus?: number | undefined; message: string; quotaPercent?: number | null | undefined; modelsFound?: number | undefined; } /** * Choose the probe model for the authenticated completion escalation. * * Order of preference (first match wins): * 1. A routed model (in config order) that the slot allows AND `assessCost` calls free-class. * 2. A model from the provider's /models listing that the slot allows AND `assessCost` calls * free-class. * 3. Otherwise EXACTLY the pre-2026-09-09 choice, byte for byte: the FIRST routed model when the * slot allows it, else the slot's own first declared model, else the first listed id. * * `tierType` reaches `assessCost` so a zero-priced model with NO catalog row on a * `tierType: "free"` provider is still free-class (the `provider-tier` basis): a null row is not * evidence of a price. A catalog that knows nothing therefore changes nothing — steps 1–2 find no * free-class model and step 3 is the legacy rule, so a provider with no free model behaves as it * did before the free-model preference existed. */ export declare function chooseProbeModel(providerName: string, routedModels: Map, listedModels: string[], slot: CredentialSlot, catalog: Pick, tierType: ProviderConfig["tierType"]): string | undefined; /** * Pre-flight check all configured provider API keys. * * Providers are checked CONCURRENTLY. A rich config can declare a dozen-plus providers, and * one unreachable host (a local daemon that isn't running) must not add its whole timeout to * everyone else's wait — checked serially that turns a status command into a minutes-long one. * Result order still follows config order. */ export declare function validateProviderKeys(cfg: Config, fetchFn?: typeof fetch, opts?: { budgetMs?: number; env?: NodeJS.ProcessEnv; catalog?: Pick; }): Promise;