/** * Provider Optimizer * * Lives above provider implementations. Routes requests based on capability * contracts from ProviderCapabilityRegistry. Supports auto/manual/pinned * routing modes with deterministic, fully-explainable decisions. * * Optimizer off → zero behavior change (selectRoute returns null). * Optimizer on → deterministic route explanation for every request profile. */ import { ProviderCapabilityRegistry, type RequestProfile, type RouteExplanation } from './capabilities.js'; import type { ProviderRegistry } from './registry.js'; import type { ProviderHealthRecord } from '../runtime/store/domains/provider-health.js'; /** Optimizer routing mode. */ export type OptimizerMode = 'auto' | 'manual' | 'pinned'; /** A single fallback transition log entry. */ export interface FallbackTransition { /** Epoch ms when the transition occurred. */ readonly ts: number; /** Provider/model that failed or was skipped. */ readonly from: string; /** Provider/model selected as fallback. */ readonly to: string; /** Human-readable reason for the transition. */ readonly reason: string; } /** Result of a route selection decision. */ export interface RouteDecision { /** Provider ID selected. */ readonly providerId: string; /** Model ID selected. */ readonly modelId: string; /** Full route explanation from the capability registry. */ readonly explanation: RouteExplanation; /** All candidates considered (accepted and rejected). */ readonly allCandidates: readonly RouteExplanation[]; /** Epoch ms when this decision was made. */ readonly decidedAt: number; /** Whether this decision was constrained by a pin. */ readonly pinned: boolean; } /** Result of a fallback chain test. */ export interface FallbackTestResult { /** Ordered nodes in the simulated fallback chain. */ readonly chain: ReadonlyArray<{ readonly position: number; readonly providerId: string; readonly modelId: string; readonly capable: boolean; readonly explanation: RouteExplanation; }>; /** Number of nodes that satisfy the empty request profile. */ readonly viableCount: number; /** Total nodes tested. */ readonly totalCount: number; /** Epoch ms when the test was run. */ readonly testedAt: number; } /** * Optimizer that selects the best provider/model for a given request profile. * * When disabled (`enabled = false`) every method returns null/empty, the * optimizer has zero effect on normal request flow. * * When enabled, routing decisions are driven entirely by `ProviderCapabilityRegistry` * capability contracts. The selection algorithm is deterministic: candidates are * evaluated in registry order (custom → synthetic → catalog → discovered), and * the first capable model wins. Ties are never broken by opaque scoring. */ export declare class ProviderOptimizer { private _mode; private _enabled; private _pinnedProvider; private _pinnedModel; private readonly _fallbackLog; private static readonly MAX_LOG_ENTRIES; private readonly _clock; private readonly registry; private readonly capabilityRegistry; constructor(registry: Pick, capabilityRegistry: ProviderCapabilityRegistry, enabled?: boolean, clock?: () => number); /** Current routing mode. */ get mode(): OptimizerMode; /** Whether the optimizer is active. When false, selectRoute always returns null. */ get enabled(): boolean; /** Enable or disable the optimizer. */ setEnabled(enabled: boolean): void; /** * Set the routing mode. * - `auto` , optimizer selects the best capable provider for each request profile. * - `manual`, optimizer is advisory only; caller drives provider selection. * - `pinned`, optimizer always returns the pinned provider/model (if capable). */ setMode(mode: OptimizerMode): void; /** * Pin routing to a specific provider and model. * Automatically switches mode to `pinned`. * * @param providerId - Provider name (e.g. `'anthropic'`). * @param modelId - Model ID (e.g. `'claude-opus-4-5'`). */ pin(providerId: string, modelId: string): void; /** Remove the current pin and return to `manual` mode. */ unpin(): void; /** Current pin target, or null if not pinned. */ get pinnedTarget(): { providerId: string; modelId: string; } | null; /** * Select the best route for the given request profile. * * Returns `null` when the optimizer is disabled, callers must handle null * and fall through to their own provider selection logic. * * @param profile - Capability requirements for the request. * @param healthSnapshot - Optional map of provider health records for filtering * unhealthy providers in `auto` mode. * @returns A `RouteDecision` or `null` when optimizer is off. * * @remarks * `selectRoute` is wired by the orchestrator when the `provider-optimizer` * gate is on (provider.optimizerMode). This follows the same deferred-integration pattern * as session emitters, the method is fully functional but called externally * only when the feature is active. Until then it is a no-op (returns `null`). */ selectRoute(profile: RequestProfile, healthSnapshot?: ReadonlyMap): RouteDecision | null; /** * Explain the current routing decision for the active model without changing it. * Always returns a full explanation even when the optimizer is in manual mode. * * @param profile - Optional request profile; defaults to empty (no requirements). */ explainCurrentRoute(profile?: RequestProfile): RouteExplanation; /** Returns a fully-typed rejection explanation when no candidates are available. */ private _emptyExplanation; /** * Simulate the fallback chain by evaluating all selectable models against * the given profile. Returns an ordered list of results (capable first, * then incapable) so operators can visualize the full fallback topology. * * @param profile - Capability requirements to test against. */ testFallback(profile?: RequestProfile): FallbackTestResult; /** * Record a fallback transition. Called by orchestration layers when a * provider fails and routing switches to a fallback. * * Transitions are always recorded regardless of optimizer enabled state * so that manual fallbacks are also visible in the log. */ recordFallbackTransition(from: string, to: string, reason: string): void; /** All recorded fallback transitions (oldest first). */ get fallbackLog(): readonly FallbackTransition[]; /** Clear the fallback transition log. */ clearFallbackLog(): void; } //# sourceMappingURL=optimizer.d.ts.map