/** * API key rotation pool — for users with multiple OpenRouter (or any * compatible) accounts who want to round-robin / failover across them * when one hits a rate limit or runs out of free credits. * * Pool composition: config.apiKey + config.apiKeys (deduplicated, order * preserved). The single `apiKey` field always becomes pool[0] so users * with only the legacy config see no change in behavior. * * Rotation strategy: on 401 / 429 / quota errors, the failing key is * marked "cool" for `COOL_DOWN_MS`, the next healthy key takes over. * If all keys are cool, the request fails normally — the user will see * the last error message. Health state lives in module memory; restart * = fresh start. * * Why module-level vs persisted: rate-limit windows are usually 60s-5m * and reset naturally. Persisting cool-down across processes would * make the agent worse at recovering from transient blips. */ /** * Build the pool from a config snapshot. Idempotent; if the same keys * are passed in the same order, the existing state is preserved * (so cool-downs persist across rebuilds in the same process). */ export declare function setPool(primary: string, extras?: string[]): void; /** * Pick the next healthy key to use. Round-robin from the current cursor. * Returns null if the pool is empty or all keys are cool. */ export declare function pickKey(): string | null; /** * Mark a key as failed. The classifier distinguishes: * * KEY problems (cool the key down): * - quota/credit exhausted → 1h cool * - auth rejected → 1h cool * - rate-limited → 60s cool * * NOT key problems (don't touch the key — surface upward instead): * - 404 model-not-found → model name wrong, no key swap helps * - 5xx server errors → provider issue, retry-here doesn't help * - timeout / network → may be transient, but not key-specific * - any other 4xx (bad request, content filter) * * The previous version defaulted unknown errors to a 60s cool, which * pooled BOTH keys into "cooling" when the user typo'd a model name — * a false positive that made it look like both keys were dead. */ export declare function reportFailure(key: string, err: unknown): void; /** Mark a key as having succeeded — clears any cool-down + records stat. */ export declare function reportSuccess(key: string): void; /** * Snapshot for /keys status output. Truncates keys to last 4 chars * so the UI never prints the full secret. */ export interface KeyStatus { index: number; tail: string; healthy: boolean; coolDownRemainingSec?: number; successes: number; failures: number; lastReason?: string; } export declare function listStatus(): KeyStatus[]; /** Currently-active pool size (post-dedup). */ export declare function poolSize(): number;