/**
 * Structured brain error so the *kind* of failure is machine-distinguishable end-to-end (the message
 * is prefixed `[code]`, which the Runner lifts into `TaskResult.errorCode`). This lets an external
 * caller react correctly without string-matching: `auth` → the API key is wrong, **stop and fix it**
 * (it's not retried, so the caller gets a fast failure); `rate_limit` → back off; `network`/`server`
 * → a transient outage worth retrying. Only `network`/`server`/`rate_limit` are retried by the brains.
 */
import type { Usage } from "../internal/llm.js";
/** A zeroed `Usage` for synthetic error/short-circuit assistant messages (no tokens spent). Shared by
 *  the circuit-breaker, degradation, and routing brains so the empty-usage shape lives in one place. */
export declare const ZERO_USAGE: Usage;
/** The single source of truth for brain error codes — the type, the `[code]` parser, and the prefix
 *  stripper all derive from this one list, so adding a code can't silently diverge across call sites.
 *
 *  The last three are IN-BAND terminal-output codes: stamped on errored assistant MESSAGES
 *  (never thrown as BrainError) so `TaskResult.errorCode` covers the error family end-to-end and
 *  downstream consumers can bucket without string-matching. Behavior-neutral on the transport side:
 *  the circuit breaker's default countCodes excludes them (model-output problems, not provider
 *  outages) and degradation maps them to nothing. Subagent retry classification gives each of them a
 *  ROW of its own (`SUBAGENT_ERROR_KIND_BY_CODE`): a lost stream is the transient `network` class, a
 *  policy refusal and a spent output cap are `logic`. They rode the `logic` fall-through together
 *  until then, which told a parent "do not re-delegate" about a dropped response.
 *    - `stream_torn`  — the stream ended with no content and no finish/stop reason (response lost)
 *    - `refusal`      — policy refusal / provider content filter withheld the output
 *    - `length_empty` — max_tokens exhausted with no answer text (pairs with errorKind "length_empty") */
declare const BRAIN_ERROR_CODES: readonly ["auth", "rate_limit", "invalid_request", "server", "network", "http", "stream_torn", "refusal", "length_empty"];
export type BrainErrorCode = (typeof BRAIN_ERROR_CODES)[number];
/** The full code list as a value, exported for exhaustive drift guards (e.g. the `errorClassOf` copy in
 *  tool-errors.ts must classify every member — a code added here but missed there folds to "unknown"). */
export declare const ALL_BRAIN_ERROR_CODES: readonly BrainErrorCode[];
/** The in-band terminal-output subset (see the list doc above). The circuit breaker collapses these
 *  to the legacy `"http"` bucket before counting: its taxonomy is TRANSPORT-level,
 *  and before these codes existed the same failures reached it as the unprefixed→"http" fallback — a
 *  custom `countCodes: ["http"]` policy must keep counting them exactly as it always did. */
export declare const IN_BAND_OUTPUT_CODES: ReadonlySet<BrainErrorCode>;
export declare class BrainError extends Error {
    readonly code: BrainErrorCode;
    readonly status?: number;
    /** design/374 slice 2 — STRUCTURAL cause seat: the provider stated (in a provenance-checked
     *  diagnostic field or status, see `input-too-long.ts`) that the request INPUT exceeds its
     *  context limit. The engine's terminal-shell mint lifts it onto `AssistantMessage.errorKind:
     *  "input_too_long"`, which the loop's prompt-too-long classifier reads instead of regexing the
     *  human-facing message. Never inferred from `detail` prose after construction. */
    readonly inputTooLong?: true;
    /** The AUTHORITATIVE-NEGATIVE half (adversarial-review r1): the classifier RAN with provenance
     *  and this failure is NOT input-too-long (wrong status family, or the provider's own envelope
     *  states a different error). Lifted onto `AssistantMessage.inputTooLongRuledOut`, which
     *  suppresses the loop's prose fallback — a reflected "prompt is too long" inside an unrelated
     *  error body must not drive a context-shrinking recovery. Mutually exclusive with
     *  `inputTooLong`; BOTH absent = classification could not establish provenance ("unknown"),
     *  and the prose fallback keeps its historic reach. */
    readonly inputTooLongRuledOut?: true;
    /**
     * This failure was produced AT THE PROVIDER BOUNDARY — a transport attempt was made against the
     * serving endpoint, or the provider itself answered with a failure (an HTTP error response, an
     * in-band SSE error frame, a connect/first-token/idle stall on a live request). It is what lifts
     * `AssistantMessage.isApiErrorMessage` at the terminal-shell mint, so a consumer can tell "the
     * provider/network failed this turn" from "this deployment refused to send the request at all".
     *
     * DECLARED BY THE MINTER, never inferred from the class: `BrainError` is also the carrier for
     * PRE-FLIGHT refusals that never touch the wire (the route adjudicator's credential-pairing
     * refusal is an `invalid_request` minted before any `fetch`), and treating those as provider
     * faults would point an operator at the wrong system. Absent = not claimed, which is the
     * conservative reading for every pre-existing and third-party construction site.
     */
    readonly apiError?: true;
    /** The provider's own word for a REFUSED request (a 4xx answer), read from its JSON error envelope by
     *  {@link readProviderErrorCode} at the HTTP throw. Lifted onto `AssistantMessage.apiErrorCode` at the terminal-shell
     *  mint. Absent when the answer was not a 4xx or the envelope stated no word in the echo shape. */
    readonly providerCode?: string;
    constructor(code: BrainErrorCode, detail: string, status?: number, opts?: {
        inputTooLong?: boolean;
        inputTooLongRuledOut?: boolean;
        apiError?: boolean;
        providerCode?: string;
    });
}
/** The provider's diagnostic object out of a JSON error body, or undefined when the body establishes no provenance
 *  for one: both the Anthropic `{type:"error",error:{…}}` and the OpenAI `{error:{…}}` envelopes reduce to an object
 *  `error` member; a plain-text body, a string `error`, a torn read are refused. */
export declare function providerErrorObject(body: string): {
    message?: unknown;
    code?: unknown;
    type?: unknown;
} | undefined;
/**
 * The provider's own word for a refused request, from its JSON error envelope: `error.code` when it is a string (the
 * OpenAI-family code, e.g. `context_length_exceeded`), else `error.type` (the Anthropic-family word, e.g.
 * `invalid_request_error`). Read structurally, never from prose. Carried only in the provider echo shape
 * ({@link isProviderEchoShape}); a word outside it is dropped whole — absent, never truncated — and counted as one
 * `echo_dropped` event (`field: "apiErrorCode"`). An envelope that states neither yields nothing.
 */
export declare function readProviderErrorCode(body: string): string | undefined;
export { isProviderEchoShape, PROVIDER_ECHO_SHAPE } from "./provider-echo-shape.js";
/** How the brains read one provider echo value: a non-string or the empty string states nothing (`absent` — no field,
 *  nothing counted); a string in {@link isProviderEchoShape} is `carried`; any other string is `refused` (dropped and
 *  counted as `echo_dropped`). */
export declare function providerEchoReading(value: unknown): "absent" | "carried" | "refused";
/**
 * Lift the provider's own request identifier off a response, when it stated one in a shape worth
 * carrying ({@link isProviderEchoShape}). This is the handle a provider's support channel asks for, and
 * without it a failed turn's only evidence is prose the operator cannot correlate upstream.
 *
 * A response whose header values were all refused by the shape yields no id and one `echo_dropped`
 * telemetry event (`field: "requestId"`, bridged to the `brain.echo_dropped` trace frame) — one per
 * response, whichever header was refused; a response that states no id at all (no header, or an empty one:
 * {@link providerEchoReading}) yields none.
 *
 * Duck-typed on `headers.get` rather than requiring a real `Response`: the engine's transport is a
 * caller-injected `fetch`, so a deployment (or a test) may hand back any response-shaped object, and
 * a missing/throwing header bag must degrade to "no id" instead of failing the call it is describing.
 */
export declare function readProviderRequestId(res: {
    headers?: {
        get?: (name: string) => string | null;
    };
} | undefined): string | undefined;
/**
 * Does this HTTP status NAME the failure it is being attached to? The one predicate governing every
 * seat on which this engine publishes a provider status — the terminal assistant frame's
 * `apiErrorStatus` and the retry-wait status frame's `errorStatus` (#506 ㋑). One helper on purpose:
 * both seats promise the same three-state discipline, and two copies of the rule would drift.
 *
 * Two distinct shapes are refused, and both are reachable:
 *  · The engine's "no status" SENTINEL, 0 — the terminal HTTP throw carries `r?.status ?? 0` when a
 *    transport hands back neither a response nor a throw. Publishing it would be absence rendered as a
 *    number a consumer may format, which is worse than silence.
 *  · A SUCCESS status. The connect loop only streams a response that is `ok` AND has a body, so an
 *    `ok` response with a NULL body (an empty 200 from a proxy, a 204) reaches the terminal throw
 *    carrying 200 — and a provider's own `x-should-retry` verdict can send that same 2xx into a RETRY
 *    wait. The boundary really did fail, but the status is not what failed, and a consumer routing or
 *    rendering by a 2xx is exactly the misreading these seats exist to prevent.
 * Stalls, connect failures and in-band error frames inside a 200 leave the seat absent by the same rule.
 */
export declare function namesTheFailure(status: number | undefined): status is number;
/** Did the provider REFUSE the request as sent — a 4xx answer (400–499)? The one predicate for the refusal family: the
 *  envelope word's read ({@link readProviderErrorCode}), its lift (`AssistantMessage.apiErrorCode`) and the run's
 *  `terminal.detail` (`provider_rejected`). An auth refusal (401 / 403) and a rate limit (429) are refusals too; which
 *  one is the status's own statement. */
export declare function refusedTheRequest(status: number | undefined): status is number;
/** Map an HTTP status to an error class. 401/403 = auth (don't retry); 429 = rate limit; 5xx = server. */
export declare function classifyHttp(status: number): BrainErrorCode;
/** Lift the machine-readable code back out of a `[code] …` prefixed `errorMessage` (the single shared
 *  parser — circuit breaker, degradation, and the Runner all read the prefix this way, council #7). */
export declare function extractErrorCode(errorMessage: string | undefined): BrainErrorCode | undefined;
/** Strip a leading `[code] ` prefix (including the trailing space) from an `errorMessage`, leaving the
 *  human text. Pairs with {@link extractErrorCode} so a caller can lift the code and clean the message
 *  without re-hardcoding the code list (the Runner does both when assembling `TaskResult`). */
export declare function stripErrorCodePrefix(errorMessage: string): string;
/**
 * Whether a transport-level connect failure is DETERMINISTIC (see {@link DETERMINISTIC_CONNECT_CODES})
 * or gives no such verdict. Classification is by `code` along the error graph — never by message text,
 * which providers and runtimes reword freely. (Distinct question from {@link classifyFetchThrow}, which
 * does not classify a failure at all: it reads the runtime's own fixed shell to tell whether a request
 * was ever built.)
 *
 * The graph, not just the chain: undici nests the actionable error under `cause`, and a dual-stack
 * connect nests one `AggregateError` whose `errors[]` hold the per-family results. A code outside the
 * set ANYWHERE in the graph returns `"indeterminate"`, and every AGGREGATE LEG must reach a
 * deterministic verdict of its own. Position decides how silence is read: a WRAPPER with no code (the
 * `fetch failed` shell, an `AbortSignal.timeout` DOMException whose `code` is a number) is structural
 * and defers to what it wraps, while a LEG with nothing readable is an outcome nobody accounted for and
 * blocks the verdict. Fail-safe by construction — every uncertain outcome (empty aggregate, unreadable
 * leg, a graph past the node budget, no deterministic code at all) answers `"indeterminate"`, i.e. the
 * pre-existing behavior.
 */
export type ConnectFailureClass = "deterministic" | "indeterminate";
export declare function classifyConnectFailure(e: unknown): ConnectFailureClass;
/** What a throw out of `fetch` was about: the NETWORK (retryable — the historic reading of every throw
 *  here), or the REQUEST ITSELF, which is deterministic: identical arguments reproduce it every time. */
export type FetchThrowClass = "transport" | "request_unbuildable";
/** Classify a throw out of `fetch` — the fold point where a request-shaped defect used to be laundered into
 *  a transient network failure and handed to the retry ladder (founding case: a base URL with userinfo
 *  throws a `TypeError` with no `code` and no `cause`, so the connect classifier answered indeterminate and
 *  the call spent its whole backoff budget on a request the runtime never built).
 *
 *  ONE question — is there TRANSPORT EVIDENCE? — in its two forms: the runtime's own shell sentence, or a
 *  `cause` that is a transport fact rather than a parse verdict. A `TypeError` with neither was never built.
 *  Measured over ten real shapes; non-`TypeError` stays on the transport arm and an unreadable value answers
 *  `transport`, the pre-existing behavior. Stated cost: KL-933a. */
export declare function classifyFetchThrow(e: unknown): FetchThrowClass;
/** The cancellation NAME an untrusted rejection states, or `undefined`. Five sites hand-rolled
 *  `e instanceof Error && e.name === "AbortError"` on a value an injected brain threw, each able to
 *  raise inside an async IIFE with no `.catch`. One guarded, realm-independent read here; WHICH names
 *  count stays at each site, because that is policy and it differs (the breaker excludes `TimeoutError`). */
export declare function abortLikeName(err: unknown): "AbortError" | "TimeoutError" | undefined;
/** The brain code an untrusted rejection carries, or `undefined`. Reads the WORD against the code list
 *  rather than testing `instanceof BrainError`, which walks a chain a revoked proxy traps — and the one
 *  site that did so sits in an async IIFE with no `.catch`. */
export declare function brainErrorCodeOf(e: unknown): BrainErrorCode | undefined;
/** Render a transport-level error WITHOUT folding away its cause chain: undici rejects with
 *  `TypeError("fetch failed", { cause })` where the CAUSE carries the actionable fact, and the shell
 *  alone reads the same for refused / DNS / mid-stream disconnect. Walks the chain (bounded), appending
 *  each layer's `code:`-prefixed message and skipping layers the parent's message already contains;
 *  a causeless error renders as its plain message. */
export declare function describeNetworkError(e: unknown): string;
