/** * Observability Hooks * * Structured lifecycle events for LLM provider operations. * Callers inject an ObservabilityHooks implementation to receive * typed events at every interesting moment in the request lifecycle. * * This replaces string-based logger calls for telemetry. The Logger * interface stays for debug output; hooks are for structured observability. */ import type { CacheObservability, CircuitBreakerState, ProviderBalance, QuotaCheckInput, QuotaCheckResult, TokenUsage } from '../types.js'; export interface RequestStartEvent { provider: string; model: string; requestId?: string; tenantId?: string; timestamp: number; } export interface RequestEndEvent { provider: string; model: string; requestId?: string; tenantId?: string; durationMs: number; usage: TokenUsage; finishReason?: string; cache?: CacheObservability; timestamp: number; } export interface CacheEvent { provider?: string; model?: string; requestId?: string; tenantId?: string; layer: 'provider-prefix' | 'ai-gateway-response' | 'factory-response'; status: string; cache: CacheObservability; timestamp: number; } export interface RequestErrorEvent { provider: string; model: string; requestId?: string; tenantId?: string; error: Error; errorCode?: string; attempt: number; willRetry: boolean; timestamp: number; } export interface RetryEvent { provider: string; requestId?: string; attempt: number; maxAttempts: number; delayMs: number; error: Error; timestamp: number; } export interface FallbackEvent { fromProvider: string; toProvider: string; requestId?: string; reason: string; errorCode?: string; timestamp: number; } export interface CircuitStateChangeEvent { provider: string; fromState: CircuitBreakerState['state']; toState: CircuitBreakerState['state']; consecutiveFailures: number; trafficPct: number; timestamp: number; } export interface QuotaExhaustedEvent { provider: string; resetAfterMs: number; timestamp: number; } export interface BudgetThresholdEvent { provider: string; tier: 'warning' | 'critical' | 'emergency'; utilizationPct: number; spend: number; budget: number; timestamp: number; } export interface QuotaCheckEvent { input: QuotaCheckInput; result: QuotaCheckResult; timestamp: number; } export interface QuotaDeniedEvent { input: QuotaCheckInput; reason?: string; timestamp: number; } export interface ProviderBalanceEvent { provider: string; balance: ProviderBalance; timestamp: number; } export interface SchemaDriftEvent { provider: string; model?: string; requestId?: string; path: string; expected: string; actual: string; timestamp: number; } export interface ObservabilityHooks { onRequestStart?(event: RequestStartEvent): void; onRequestEnd?(event: RequestEndEvent): void; onCache?(event: CacheEvent): void; onRequestError?(event: RequestErrorEvent): void; onRetry?(event: RetryEvent): void; onFallback?(event: FallbackEvent): void; onCircuitStateChange?(event: CircuitStateChangeEvent): void; onQuotaExhausted?(event: QuotaExhaustedEvent): void; onBudgetThreshold?(event: BudgetThresholdEvent): void; onQuotaCheck?(event: QuotaCheckEvent): void; onQuotaDenied?(event: QuotaDeniedEvent): void; onProviderBalance?(event: ProviderBalanceEvent): void; onSchemaDrift?(event: SchemaDriftEvent): void; } /** Silent hooks — default. */ export declare const noopHooks: ObservabilityHooks; /** * Merge multiple hook implementations. Each matching handler is called * in order. Errors in one handler don't block others. */ export declare function composeHooks(...implementations: ObservabilityHooks[]): ObservabilityHooks; //# sourceMappingURL=hooks.d.ts.map