/** * AgentGuard Spend: spend-and-policy-aware model router. * * `createRouter(...)` composes the EXISTING pieces of this SDK into one call * that: * 1. selects a candidate model across providers by a routing policy * (cost-first / explicit priority / capability-tag filter), * 2. enforces the spend cap using the EXISTING enforcement path * (`SpendGuard.decide` -> `evaluatePolicy`) — block / downgrade / allow, * 3. executes via the candidate's provider client, * 4. FAILS OVER to the next viable candidate on a provider error/timeout OR a * cap breach (block) on the chosen model — this removes vendor lock-in, * 5. signs a routing receipt that records the decision, hash-chained onto the * SAME signed log as the enforcement decisions using the EXISTING Ed25519 + * canonical-JSON receipt infra (`SpendGuard.recordRoutingReceipt`). * * ZERO DATA PLANE: prompts, completions and provider keys never leave the * process, and the routing receipt is payload-minimized (provider + model + * projected cost only — never content). * * Patent notice: Protected by U.S. patent-pending technology * (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626; * 64/071,781; 64/071,789). */ import { SpendGuard, type SpendGuardConfig } from './spend-guard'; import type { CapabilityTier, SignedDecisionLogEntry, SpendDecision, SpendPolicy, SpendScope } from './types'; /** A provider the router knows how to dispatch a call to. */ export type RouterProvider = 'openai' | 'anthropic' | 'bedrock' | 'openrouter'; /** One routable model on a concrete provider client. */ export interface RouterCandidate { /** Provider family. Drives cost lookup, dispatch and receipt labeling. */ provider: RouterProvider; /** Model id as passed to the provider. */ model: string; /** The provider SDK client used to execute the call. */ client: any; /** Optional capability tags for capability-filter routing (e.g. 'vision'). */ capabilities?: string[]; } /** How the router chooses among candidates. */ export interface RouterPolicy { /** * - `cost`: cheapest capable candidate first (projected cents ascending). * - `priority`: honor the given candidate order (explicit failover order). * - `capability`: keep only candidates whose `capabilities` include * `requireCapability`, then order cheapest-first. */ mode: 'cost' | 'priority' | 'capability'; /** Required capability tag when `mode === 'capability'`. */ requireCapability?: string; } export interface CreateRouterConfig { /** Ordered list of routable candidates across providers. */ candidates: RouterCandidate[]; /** Selection policy. Defaults to cost-first. */ policy?: RouterPolicy; /** The spend policy enforced by the EXISTING enforcement path. */ spendPolicy: SpendPolicy; /** Ed25519 signing keys for the receipt chain. Reused, not re-invented. */ signingKeys?: SpendGuardConfig['signingKeys']; /** Decision log store shared by enforcement + routing receipts. */ logStore?: SpendGuardConfig['logStore']; /** Spend state store. */ spendStore?: SpendGuardConfig['spendStore']; /** Any remaining SpendGuard config (posture, license, locale, hooks, ...). */ guardConfig?: Omit; } /** A single inference request routed across candidates. */ export interface RouterRequest { /** Identity scope for enforcement. Defaults to the spend policy scope. */ scope?: SpendScope; /** Provider-native messages (openai/anthropic style). Used for token estimate. */ messages?: unknown[]; /** Extra provider params merged into the call (max_tokens, temperature, ...). */ params?: Record; /** Explicit input token count. Overrides estimation from `messages`. */ inputTokens?: number; /** Expected output token count. Falls back to params.max_tokens or 512. */ outputTokens?: number; /** Capability tier claim forwarded to enforcement. */ capabilityClaim?: CapabilityTier; /** Optional label for the call (metadata only). */ label?: string; } export type RouteReason = 'cost' | 'priority' | 'capability' | 'failover' | 'downgrade'; /** A candidate that was considered but not chosen, and why. */ export interface RouteFallback { provider: RouterProvider; model: string; /** 'cap_breach' (blocked by spend cap) or 'provider_error'. */ reason: 'cap_breach' | 'provider_error'; detail?: string; } export interface RouteResult { /** The provider response from the winning candidate. */ response: T; /** Chosen provider + model actually executed. */ chosen: { provider: RouterProvider; model: string; }; /** Why this candidate won. */ reason: RouteReason; /** Resolved cost in cents (settled from usage when available, else projected). */ resolvedCents: number; /** Candidates skipped before the winner, with cause. */ fallbacks: RouteFallback[]; /** The winning enforcement decision (already signed onto the chain). */ decision: SpendDecision; /** The signed routing receipt entry (null when signing keys are absent). */ routingReceipt: SignedDecisionLogEntry | null; } export declare class RoutingExhaustedError extends Error { fallbacks: RouteFallback[]; constructor(fallbacks: RouteFallback[]); } export interface ModelRouter { route(request: RouterRequest): Promise>; /** The underlying SpendGuard (shared enforcement + signed chain). */ readonly guard: SpendGuard; } export declare function createRouter(config: CreateRouterConfig): ModelRouter; //# sourceMappingURL=router-engine.d.ts.map