/**
 * Error/budget-aware **degradation cascade** (1.39, design/21, design/17 §5C).
 *
 * Unlike failover (a *peer* backup whose goal is "same quality, a gateway that's actually up"),
 * degradation **deliberately downgrades** to a cheaper / different-provider model to KEEP SERVING when
 * the primary is rate-limited or its circuit breaker is open — accepting some quality loss instead of
 * failing the task. Opt-in; the served turn is tagged so the Runner can surface `TaskResult.degraded`.
 *
 * This file handles the four **reactive** triggers visible at the brain layer — `rate_limit`,
 * `breaker_open`, `server_error` and `last_resort` (design/126; all four are the default gate, narrow it
 * with `downgradeOn`). The proactive **near-budget** trigger needs the task budget (only the Runner sees
 * it) and is not implemented here; `"budget"` is reserved in `DegradeReason` for it.
 *
 * Detection is **structural**, not literal string-matching: the breaker-open signal is
 * `CIRCUIT_OPEN_MARKER` (exported from circuit-breaker.ts) and the code comes from the shared
 * `extractErrorCode`. Degradation must be the **outermost** brain in a stack (so it sees the inner
 * failover/breaker/timeout outcomes and can downgrade on them), and the downgrade target is the ordered
 * `fallbacks` chain (RB-482 #3 — the single `fallback`+`fallbackModel` pair is retired):
 *   `createDegradingBrain({ primary: failover(breaker(timeout(brain))), fallbacks: [{ brain, model }] })`.
 */
import { type AssistantMessageDiagnostic, type Model } from "../internal/llm.js";
import type { Brain } from "../core/types.js";
/** Diagnostic `type` the decorator stamps on a degraded turn's message; the Runner reads it back. */
export declare const DEGRADED_DIAGNOSTIC_TYPE = "degraded";
/** Why a turn was degraded. `"budget"` is reserved for the v2 near-budget trigger (Runner-level).
 *  design/126 (CC 批 β) widens the reactive set: `"server_error"` = a `server`-class failure (5xx incl.
 *  529 overloaded, 408/409) that ESCAPED the inner brain's own retry budget (CC parity: retry in place
 *  first, then fall back — CC :600552); `"last_resort"` = an `http`-class status error (404
 *  model-not-found and other non-retryable statuses — CC :600513/:600588 folds both into "try the next
 *  model instead of dying"). Deliberate deviations from CC, documented in design/126 D2: `rate_limit`
 *  stays a trigger (CC waits in place; an unattended headless task waiting forever is a dead task), and
 *  `auth` (401/403) NEVER triggers (CC falls back on 403; silently swapping models over a
 *  permission/key misconfiguration is worse than failing loud for headless). */
export type DegradeReason = "breaker_open" | "rate_limit" | "budget" | "server_error" | "last_resort";
export interface DegradationInfo {
    /** The model id that was meant to serve (the primary). */
    from: string;
    /** The cheaper model id that actually served (or the LAST model attempted when the chain failed too). */
    to: string;
    /** The FIRST trigger that started the downgrade walk (later hops may fail for other reasons). */
    reason: DegradeReason;
    /** design/126: the model ids attempted after the primary, in order (length 1 = the classic single
     *  hop). Optional — absent on markers written by pre-chain versions. */
    chain?: string[];
}
interface DegradingBrainBaseOptions {
    /** The preferred brain (typically `failover(breaker(timeout(openai)))`). */
    primary: Brain;
    /**
     * Which reactive triggers cause a downgrade. Default = all four reactive classes
     * (`rate_limit`/`breaker_open`/`server_error`/`last_resort`). Pass it explicitly to narrow.
     */
    downgradeOn?: DegradeReason[];
}
/** RB-482 #3 (ruled 2026-08-03): ONE form — the ordered `fallbacks` chain. The legacy single
 *  `fallback`+`fallbackModel` pair is retired (a chain-of-one is `fallbacks: [{brain, model}]`), and
 *  its pre-126 two-trigger default retires with it: every construction gets the full four-class gate
 *  unless `downgradeOn` narrows it explicitly. */
export type DegradingBrainOptions = DegradingBrainBaseOptions & {
    /**
     * design/126 (CC 批 β) — the ORDERED downgrade chain (up to 3 entries, CC `Kjd` parity; excess is
     * truncated, duplicate model ids deduped, and an entry whose model id equals the model that just
     * failed is skipped at walk time). Each hop carries its OWN brain — carry its credentials in its
     * config (e.g. `createOpenAIBrain({ apiKey, baseUrl })`): the decorator clears the primary's
     * per-call `apiKey`/`headers`/`metadata` for every hop so a hop never leaks the primary's identity
     * to a different provider.
     */
    fallbacks: Array<{
        brain: Brain;
        model: Model;
    }>;
};
/** Pull a degradation marker off a served message (used by the Runner to fill `TaskResult.degraded`). */
export declare function readDegradation(msg: {
    diagnostics?: AssistantMessageDiagnostic[];
} | undefined): DegradationInfo | undefined;
/**
 * design/131 — resilience-standdown pass-through: forward one brain's stream
 * verbatim, but keep the decorator discipline that a REJECTING inner brain (throw instead of an
 * error event) still leaves a terminal on the returned stream — otherwise `result()` never
 * resolves and the harness hangs (the same class as the degradation-brain blocker).
 *
 * HRD-BRN-5: that discipline covered only the REJECT shape. An inner stream ENDED BARE (`end()` with no
 * terminal event) drained the `for await` loop and then pushed nothing, so `result()` stayed pending
 * forever — the exact hang class this function's contract claims to prevent, and reached through the
 * two standdown knobs (`resilience.allowFailover:false` / `allowDegrade:false`) that a benchmark or eval
 * harness turns on to see a provider's TRUE failure shape. Standing resilience down was therefore
 * strictly MORE hang-prone than leaving it on, since the normal failover path awaits `inner.result()`
 * and lands in its catch. Both shapes now leave exactly one terminal.
 */
export declare function passthroughStream(brain: Brain, model: Model, context: Parameters<Brain["stream"]>[1], options: Parameters<Brain["stream"]>[2]): ReturnType<Brain["stream"]>;
export declare function createDegradingBrain(opts: DegradingBrainOptions): Brain;
export {};
