import type { Model } from "../internal/llm.js"; import type { Brain } from "../core/types.js"; import { type BrainErrorCode } from "./errors.js"; /** Stable prefix of an open-breaker error's detail (`[network] circuit open for `). Exported so * the degradation cascade can detect breaker-open **structurally** instead of string-matching a literal * (council #1) — reword the message only by changing this constant. */ export declare const CIRCUIT_OPEN_MARKER = "circuit open for "; export type BreakerPhase = "closed" | "open" | "half-open"; export interface BreakerSnapshot { phase: BreakerPhase; /** Consecutive failures while closed. */ failures: number; /** When the breaker opened (epoch ms), for cooldown. */ openedAt?: number; /** Probes currently allowed through while half-open. */ halfOpenInFlight?: number; } /** Pluggable breaker state. In-memory by default; a deployment can back it with Redis/TiDB so all * replicas share one circuit (otherwise each replica trips independently and reacts slowly). * * ATOMICITY: the breaker does read-modify-write (`get` → decide → `set`). The in-process Map is safe * under Node's single-threaded run-to-completion. A shared async backend MUST make get/set * **linearizable** (or expose CAS) — otherwise concurrent transitions (closed→open, open→half-open) * race (TOCTOU). Implement it with a Lua script / transaction / optimistic-version on the store. */ export interface BreakerState { get(key: string): BreakerSnapshot | undefined; set(key: string, snap: BreakerSnapshot): void; } export interface CircuitBreakerOptions { /** Consecutive transient failures that trip the breaker. Default 5. */ failureThreshold?: number; /** How long the breaker stays open before a half-open probe. Default 30_000 ms. */ cooldownMs?: number; /** Probes allowed through while half-open. Default 1. */ halfOpenProbes?: number; /** Error codes that count toward tripping. Default `["network","server","rate_limit"]`. */ countCodes?: BrainErrorCode[]; /** Breaker key from a model. Default `":"` (per model+provider). */ key?: (model: Model) => string; /** State backend. Default in-memory (per process). */ state?: BreakerState; /** Clock, injectable for tests. */ now?: () => number; } export declare function createCircuitBreakerBrain(inner: Brain, opts?: CircuitBreakerOptions): Brain; //# sourceMappingURL=circuit-breaker.d.ts.map