/** * Pool liveness probing — `llm-relay pools [--probe]`. * * Nothing used to detect a dead pool member. A model can be listed in a provider's catalogue * and still refuse every request (de-listed behind the scenes, gated to a paid tier, or * routed to a function that no longer exists), so config-time validation cannot see it. The * observed failure mode: a pool whose top-ranked member 404'd on every call while the pool * looked healthy, leaving offload running on a single live model with failover that existed * only on paper. * * The only trustworthy signal is a real completion, so that is what `--probe` sends. */ import type { Config } from "./config.js"; export type MemberVerdict = "live" | "empty" | "auth" | "denied" | "rate_limited" | "missing" | "error"; export interface MemberHealth { pool: string; spec: string; /** Stable slot identity only; never the credential value. */ credentialId?: string; verdict: MemberVerdict; httpStatus?: number | undefined; latencyMs?: number | undefined; detail?: string | undefined; } /** * Verdicts that mean "this member will never answer until someone changes something". * * `auth` is a CONFIG fact (no enabled credential slot has a present key, so no request was * sent); `denied` is a SERVER response (401/403) whose cause we deliberately do not infer — * it may be the credential, but it may also be an entitlement wall on a model this key * legitimately cannot touch. Both are surfaced to the operator, but only `auth` carries a * credential-rotation recommendation in the CLI advice. */ export declare const DEAD_VERDICTS: ReadonlySet; /** * Send one real completion to a single pool member. * * `maxTokens` defaults to 400 rather than a token or two because reasoning models spend * their budget thinking: at a low cap they return a 200 with EMPTY content, which reads as * a broken model when it is only a truncated one. */ export declare function probeMember(pool: string, spec: string, cfg: Config, fetchFn?: typeof fetch, maxTokens?: number, now?: () => number): Promise; /** Pull assistant text out of either an OpenAI or an Anthropic shaped response. */ export declare function extractContent(raw: string): string; /** * Probe every member of every pool. Concurrency-limited so a wide config can't fan out unbounded. * * A dynamic catalog target commonly belongs to several pools. Probe each unique provider/model * deployment once, then project that result back onto every pool membership. Membership reporting * remains complete without charging the provider for duplicate completions in the same command. */ export declare function probeAllPools(cfg: Config, fetchFn?: typeof fetch, concurrency?: number): Promise;