/**
 * ClassifierRouter — the single "classify → pick model + tools → run" engine.
 *
 * Given a request snapshot it (1) classifies difficulty (heuristic or a cheap
 * LLM), (2) selects the best provider/model from the host-declared base pool —
 * cheaper/faster for easy tiers, more capable for hard tiers — enriching pool
 * members with real cost/quality metadata from the model registry, and
 * (3) narrows the tool set via per-difficulty directives or classifier hints.
 *
 * Pure of provider imports (mirrors ModelPool): the LLM caller is injected.
 * The only data dependency is the read-only `ModelResolver` registry lookup,
 * used purely for metadata enrichment and never for provider construction.
 */
import type { ClassifierRouterConfig, ClassifierRouterDecision, ClassifierRouterDeps, ClassifierRouterInput, ClassifierRouterPoolMember } from "../types/index.js";
export declare class ClassifierRouter {
    private readonly config;
    private readonly deps;
    private readonly metaCache;
    /**
     * The effective pool: what the host declared, plus catalogue-derived members
     * when `catalog.enabled`. Mutable so a long-lived host can widen or narrow
     * it without rebuilding the router — the constructor-frozen pool was the one
     * thing preventing a runtime model catalogue.
     */
    private pool;
    /** Registry index for candidate enrichment; built once, on first use. */
    private registryIndex?;
    constructor(config: ClassifierRouterConfig, deps?: ClassifierRouterDeps);
    /**
     * Merge the declared pool with the catalogue. Declared members win on a
     * duplicate `provider/model`, because a host that spelled a member out has
     * said something about it (a region, a description, an explicit tier) that
     * the registry does not know.
     */
    private static composePool;
    /**
     * Replace the routable pool at runtime. Returns the new size.
     *
     * Clears the metadata cache, since a member's declared cost/quality is
     * cached per `provider::model` and a replacement pool may declare different
     * values for the same pair.
     */
    setPool(members: ClassifierRouterPoolMember[]): number;
    /** The pool currently routed over, declared plus catalogue. */
    getPool(): ClassifierRouterPoolMember[];
    /** Rebuild the catalogue half of the pool (e.g. after credentials change). */
    refreshCatalog(): number;
    /**
     * Classify the request and produce a combined model + tool decision, or
     * `null` when nothing should change. Never throws (fails open).
     */
    route(input: ClassifierRouterInput): Promise<ClassifierRouterDecision | null>;
    /**
     * Resolve "auto" (the default) to a concrete strategy. Jev is preferred the
     * moment a decision provider is configured; without one the behaviour is
     * exactly what it was before Jev existed.
     */
    private resolveStrategy;
    /** Run the chosen strategy; every one falls back to heuristic on failure. */
    private classify;
    /**
     * Build LLM-facing model descriptors + an id→member map so the classifier can
     * pick a model directly. Works for ANY pool, registry-backed or not.
     */
    private buildCandidates;
    /**
     * Resolve the ranked model list for a decision. Prefers the LLM's direct pick
     * (`selectedModelId`); otherwise falls back to difficulty-based tierMap /
     * metadata scoring.
     */
    private selectModels;
    /**
     * Whether a directly-picked model clears the bar that applies to it.
     *
     * The bars are asymmetric because the two mistakes do not cost the same, and
     * which one a pick risks depends on what the difficulty tier would otherwise
     * have chosen. Picking something COSTLIER than the tier's own choice risks
     * spending more than necessary, so it clears the low upgrade bar. Picking
     * something CHEAPER risks handing the task to a model that cannot do it, so
     * it must clear the high downgrade bar. Agreeing with the tier needs no bar
     * at all.
     *
     * A strategy that reports no confidence for its pick — the LLM classifier —
     * is honoured exactly as before. Its self-reported numbers are not
     * calibrated, so a bar over them would be arithmetic on noise, and imposing
     * one would silently change the behaviour of a shipped, unrelated strategy.
     */
    private pickClearsBar;
    /** The difficulty-based ranking, independent of any direct pick. */
    private rankForDifficulty;
    /**
     * Whether a member's context window can hold the estimated request. Unknown
     * windows pass — the registry does not know every model, and starving the
     * pool on missing metadata is worse than an occasional retry.
     */
    private fitsRequest;
    /** Drop members too small for the request, unless that empties the pool. */
    private withRoomFor;
    /** Candidate members for a difficulty: explicit tierMap or eligible pool. */
    private candidatesFor;
    /** Drop members that cannot satisfy the required capabilities (lenient). */
    private filterByCapabilities;
    /** Rank candidates best-first for the difficulty's strategy. */
    private rank;
    /**
     * Turn the classifier's context reading into a compaction threshold.
     *
     * Returns undefined — meaning "leave the 0.8 default alone" — whenever the
     * feature is off, no scope was read, or the scope is the widest one. The
     * mapping can only ever LOWER the threshold, which is enforced in
     * `contextScopeToThreshold` rather than here, because the consequence of
     * getting it wrong in the other direction is not recoverable: a
     * `context_window` error puts the model into ModelPool's 10-year cooldown.
     */
    private selectContextBudget;
    /** Tool narrowing: per-difficulty directive, then classifier hints. */
    private selectTools;
    /**
     * Resolve cost/quality/capabilities for a member. Declared values win;
     * gaps are filled from the model registry (by model name/alias) when known.
     * Results are cached per (provider/model) for the router's lifetime.
     */
    private metaFor;
}
