/**
 * ProviderFallbackManager — tracks provider health and orchestrates
 * automatic fallback when a provider fails.
 *
 * When an LLM provider returns auth errors (401/402/403), accumulates
 * network failures, or exhausts stream silence retries, the manager
 * disables it with a cooldown and switches config.provider to the next
 * healthy provider in the server-provided priority list.
 *
 * Cooldowns:
 *   - Auth errors (401/402/403): 60 minutes
 *   - Network failures (3+ consecutive): 15 minutes
 *   - Stream silence exhausted: 15 minutes
 *
 * When all providers are exhausted, the manager notifies the owner,
 * sleeps 15 minutes, and resets all provider states.
 *
 * A server-side priority change (detected on heartbeat) resets all
 * states immediately so the new ordering takes effect.
 */
import { type Provider, type VisionClawConfig } from "../config/types.js";
export type ProviderFailReason = "auth" | "network" | "silence_exhausted";
export interface DisabledProviderInfo {
    provider: Provider;
    reason: ProviderFailReason;
    disabledUntil: string;
}
/**
 * Invoked after this manager has actually mutated `config.provider`.
 * Implementations should invalidate any provider-bound caches (e.g. the
 * Claude pre-warmed subprocess, which bakes provider env in at warm time
 * and is otherwise reused unchanged on the next turn).
 *
 * Best-effort: errors are swallowed by the manager so a failed
 * invalidation cannot block fallback itself.
 */
export type ProviderSwitchedCallback = (from: Provider, to: Provider) => void | Promise<void>;
export declare class ProviderFallbackManager {
    private readonly config;
    private priorityList;
    private states;
    private onSwitched;
    constructor(config: VisionClawConfig);
    /**
     * Register a callback to run after every provider switch performed by
     * this manager. The callback fires only when `config.provider` actually
     * changed — both via `disableAndSwitch()` and via `resetAll()`.
     *
     * The most important consumer is `SessionManager.discardAllWarmQueries()`
     * — without it, a Claude warm subprocess can silently keep using the
     * previous provider for one more turn after fallback.
     */
    setOnProviderSwitched(cb: ProviderSwitchedCallback | null): void;
    private notifySwitched;
    /**
     * Initialize or update the priority list from the server. If the list
     * changed, all provider states are reset so the new ordering takes
     * effect cleanly.
     */
    setPriorityList(serverPriority: string[]): void;
    get activeProvider(): Provider;
    get disabledProviders(): DisabledProviderInfo[];
    /**
     * Record a retryable network failure for the current provider.
     * Returns true if the threshold was reached and a provider switch
     * should be attempted.
     */
    recordNetworkFailure(): boolean;
    /** Reset the network failure counter for the current provider (on success). */
    clearNetworkFailures(): void;
    /**
     * Disable the current provider and attempt to switch to the next one.
     * Returns true if a switch was made, false if all providers are exhausted.
     */
    disableAndSwitch(reason: ProviderFailReason): boolean;
    /**
     * Find the next healthy provider from the priority list.
     * A provider is healthy if it's not disabled (or cooldown has expired)
     * and has valid credentials.
     */
    private findNextProvider;
    /**
     * Reset all provider states and switch to the first healthy provider.
     * Called after the all-exhausted sleep or when the server sends a new
     * priority list.
     */
    resetAll(): void;
    /**
     * Sleep for the all-exhausted period, then reset.
     * The caller should await this and then retry.
     */
    sleepAndReset(): Promise<void>;
    /** Whether the fallback manager has a priority list configured. */
    get hasPriorityList(): boolean;
    private getOrCreateState;
}
//# sourceMappingURL=provider-fallback.d.ts.map