/**
 * Stream-error recovery — extracted phase of the tool loop (CC withRetry.ts parity).
 *
 * Handles an error thrown while streaming the LLM round. This is the loop's densest,
 * most regression-prone branch, so it is pulled out behind a small control-flow
 * protocol: the generator yields any user-facing events (recovery / error / heartbeat)
 * and RETURNS a decision the loop acts on, instead of `continue`/`return`-ing the outer
 * loop itself (which a sub-generator cannot do):
 *
 *   - { kind: "continue", patch } → loop applies `state = { ...state, ...patch }` and retries
 *   - { kind: "return" }          → loop returns (a terminal error event was already yielded)
 *   - { kind: "streamError", … }  → loop sets streamError and falls through to error withholding
 *
 * Behavior is byte-for-byte the same as the former inline catch block, including the
 * in-place `consecutive529Errors` increment (so the count persists onto the loop's State
 * whether we continue or fall through). Covered by tool-loop.states.test.ts:
 * fallback / stale-connection / max-tokens-overflow / 429-retry.
 */
import type { AgentLogger, TokenUsage, ToolLoopTransition, TurnEvent } from "../types.js";
/** Subset of the loop's State this phase reads / mutates in place. */
export interface StreamErrorState {
    consecutive529Errors: number;
    consecutiveApiRetries: number;
    currentModel: string;
    totalUsage: TokenUsage;
}
/** Fields the loop should merge into State before continuing. */
export interface StreamErrorPatch {
    currentModel?: string;
    consecutive529Errors?: number;
    consecutiveApiRetries?: number;
    maxOutputTokensOverride?: number;
    transition?: ToolLoopTransition | undefined;
}
export type StreamErrorDecision = {
    kind: "continue";
    patch: StreamErrorPatch;
} | {
    kind: "return";
} | {
    kind: "streamError";
    streamError: {
        status?: number;
        message: string;
    };
};
export interface StreamErrorCtx {
    state: StreamErrorState;
    guardState: {
        currentMaxOutputTokens: number;
    };
    fallbackModel: string | undefined;
    signal: AbortSignal | undefined;
    querySource: string | undefined;
    turnId: string;
    log: AgentLogger;
    emitRecovery: (action: string, detail?: string) => TurnEvent;
}
export declare function handleStreamError(err: unknown, ctx: StreamErrorCtx): AsyncGenerator<TurnEvent, StreamErrorDecision>;
