/**
 * The provider dialect table — what each provider endpoint MEANS by the way it fails, declared once per
 * endpoint and read by every seat that reports a provider failure.
 *
 * KEY. An endpoint is named by (wire family, host suffix + path): the same brand can serve two endpoints whose
 * failures read in opposite ways (Moonshot's open platform states an exhausted balance as a 429, its coding
 * subscription states a spent usage window as a 403 and keeps 429 for momentary overload), and the same word
 * can mean opposite things on two brands (`insufficient_quota` is a per-minute token limit on DashScope and an
 * empty balance on OpenAI). So the table is keyed by where the request went, never by vendor name or by word.
 * A request whose endpoint matches no key reads only the GENERIC rows: the statements whose meaning does not
 * depend on who said them.
 *
 * COLUMNS. A dialect is a record of named columns about one endpoint. `failures` is the failure-classification
 * column: rows that turn a status, the envelope's word (`error.code`, else `error.type` — the same word
 * `apiErrorCode` carries) and the envelope's sentence (`error.message`) into one {@link ProviderCondition}. The
 * context-limit refusal is a flag on the same rows (`inputTooLong`), so "this 400 is the input being too long"
 * and "this 400 is something else the provider named" are read off one row and cannot disagree.
 *
 * ONE VERDICT, TWO SEATS. {@link judgeHttpFailure} answers once per failed response; the retry decision, the
 * retry frame (`BrainStatus.providerCondition`) and the terminal (`BrainError` → `AssistantMessage` →
 * `terminal.detail`) all read that answer. An in-band error frame (a provider error delivered inside a 200
 * stream) is judged by {@link judgeInBandError} over the same rows.
 *
 * DEGRADATION DIRECTION. Every row whose evidence is prose is fragile (a provider rewords and the row stops
 * matching). A row that stops matching falls to the endpoint's own status row, then to the generic rows, then
 * to the status alone — which in every case is the retrying reading, never the stopping one: a missed quota
 * costs a backoff ladder, a false quota costs the user a run.
 */
import type { Model } from "../internal/llm.js";
import type { AssertAllKeysHandled } from "../core/ask-origin.js";
import { BrainError, type FailedBody } from "./errors.js";
/**
 * What the provider said about the account or its own capacity when it failed a request — the one closed set
 * both the retry frame and the terminal report:
 *  - `quota_exhausted` — the account cannot be served until someone acts or a window resets (an empty balance,
 *    an overdue bill, a spent usage window, a free tier used up). Not retried.
 *  - `throttled` — slow down: a request / token rate limit that clears on its own. Retried (backoff, the
 *    provider's `Retry-After` as the floor).
 *  - `overloaded` — the provider's own capacity, not the account's. Retried.
 *  - `stop_other` — a refusal that resending cannot change (credentials, model access, the request itself, its
 *    content, the plan's tier). Not retried. A context-limit refusal is one of these and is ALSO typed
 *    `input_too_long` on its own seat.
 *  - `unknown` — the endpoint said nothing this table can read. Retried exactly as the status alone would be.
 */
export declare const PROVIDER_CONDITIONS: readonly ["quota_exhausted", "throttled", "overloaded", "stop_other", "unknown"];
export type ProviderCondition = (typeof PROVIDER_CONDITIONS)[number];
/**
 * Which evidence the condition rests on:
 *  - `unified_header` — a subscription quota header (`anthropic-ratelimit-unified-representative-claim` /
 *    `-overage-status` / `-overage-disabled-reason`) on a 429.
 *  - `provider_code` — a row keyed on the envelope's word (`error.code`, else `error.type`) or its sentence
 *    (`error.message`) matched.
 *  - `status` — no row read the envelope (none arrived, it did not end, or no row names its word or sentence): the
 *    default for what arrived — the endpoint's row for the status, else the generic row, else the status alone; an
 *    in-band error frame, which states no status, defaults to `unknown`.
 */
export declare const PROVIDER_CONDITION_SOURCES: readonly ["unified_header", "provider_code", "status"];
export type ProviderConditionSource = (typeof PROVIDER_CONDITION_SOURCES)[number];
/**
 * What each condition means to this engine — the one place retryability lives:
 *  - `retryable` — the connect ladder re-sends a response judged so (the provider's explicit `x-should-retry`
 *    verdict still outranks it, in both directions);
 *  - `inBandCode` — the brain error code an in-band error frame carries (it has no status to classify by).
 */
export declare const PROVIDER_CONDITION_TRAITS: {
    readonly quota_exhausted: {
        readonly retryable: false;
        readonly inBandCode: "rate_limit";
    };
    readonly throttled: {
        readonly retryable: true;
        readonly inBandCode: "rate_limit";
    };
    readonly overloaded: {
        readonly retryable: true;
        readonly inBandCode: "server";
    };
    readonly stop_other: {
        readonly retryable: false;
        readonly inBandCode: "invalid_request";
    };
    readonly unknown: {
        readonly retryable: true;
        readonly inBandCode: "server";
    };
};
/** Compile-time fence: every condition has a traits row. */
export type ConditionTraitsCoverEveryCondition = AssertAllKeysHandled<Exclude<ProviderCondition, keyof typeof PROVIDER_CONDITION_TRAITS>>;
/** Membership read for a value that crossed a seat (a brand-read error member, a host-minted message). */
export declare function isProviderCondition(v: unknown): v is ProviderCondition;
export declare function isProviderConditionSource(v: unknown): v is ProviderConditionSource;
/**
 * The context-limit refusal FAMILY, anchored at the START of the provider's diagnostic (`error.message`). The
 * two error directions cost asymmetrically, and the asymmetry is what sets the width: a FALSE POSITIVE (a bare
 * "Input is too long" prefix that is really field-length validation) costs one bounded recovery attempt on a
 * request that already failed — the retry fails identically and the original error surfaces, self-limiting. A
 * FALSE NEGATIVE (an unlisted GENUINE refusal read as an authoritative negative) permanently suppresses
 * recovery for that turn: the task dies where it would have recovered. So within a PARSED provider envelope the
 * whole conservative family classifies when it matches AT POSITION 0 of the diagnostic — "a provider stating
 * this error states it first"; a reflection arrives behind a preamble ("validation failed; offending prompt: …")
 * and the position-0 anchor is what separates the two. A prefixed genuine refusal inside a parsed envelope
 * therefore reads as ruled-out — the residual narrowing, accepted (prose-only bodies keep the historic prose
 * reach through the "unknown" arm).
 *
 * Members, by provenance: the loop's historic prose patterns re-anchored at position 0; the llama.cpp openings
 * ("the request exceeds the available context size", "request (N tokens) exceeds …"); Gemini / Vertex through
 * an OpenAI-compatible gateway ("the input token count (N) exceeds the maximum number of tokens allowed (M)");
 * llama.cpp-family /v1 servers ("requested tokens (N) exceed context window of M"); two conservative gateway
 * paraphrases ("your input exceeds the context window …", "the number of tokens in the request exceeds …");
 * DashScope ("Range of input length should be [1, N]"); Moonshot's open platform ("Input token length too
 * long"); Moonshot's coding endpoint ("Invalid request: Your request exceeded model token limit: N …" and
 * "total message size N exceeds limit M"); Z.AI ("Prompt too long"). An unlisted subject-first provider spelling
 * is a member to ADD; the anchor stays. A provider that names this refusal with a STRUCTURAL code says so on its
 * own row instead (`context_length_exceeded` below, GLM's `1261`), and a code row outranks every sentence.
 */
export declare const INPUT_TOO_LONG_ANCHORED_RE: RegExp;
/** True when the (provider-authored) diagnostic OPENS with the context-limit refusal family. */
export declare function startsWithInputTooLongAnchor(diagnostic: string): boolean;
/**
 * Three-state context-limit verdict: `"yes"` — the provider stated it, on a row that says so; `"no"` — the
 * status cannot carry it, or the provider's envelope parsed and states something else; `"unknown"` — a status
 * that can carry it whose body established no provenance (a text/plain gateway, or a body that did not end — the
 * terminal marks the latter `errorBodyIncomplete`, so no seat reads its prose either).
 */
export type InputTooLongVerdict = "yes" | "no" | "unknown";
/** One row of the failure column. A row with no `status` applies to every status. */
export interface FailureRow {
    readonly status?: readonly number[];
    /** The envelope's word (`error.code` when a string, else `error.type`), compared exactly. */
    readonly word?: readonly string[];
    /** Matched against the envelope's `error.message`. Anchored unless the row's evidence says otherwise. */
    readonly sentence?: RegExp;
    readonly condition: ProviderCondition;
    /** This row's statement IS the context-limit refusal. */
    readonly inputTooLong?: true;
}
/** Where a dialect applies: the wire families it was evidenced for, its host suffixes, an optional path prefix. */
export interface DialectKey {
    readonly wires: readonly Model["api"][];
    /** A request host equal to one of these, or ending in `.` + one. */
    readonly hosts: readonly string[];
    /** A path prefix, matched at a segment boundary. Absent = every path on the host. */
    readonly path?: string;
}
/** One endpoint's declared dialect: its key and its columns. */
export interface ProviderDialect {
    readonly name: string;
    readonly key: DialectKey;
    readonly failures: readonly FailureRow[];
}
/**
 * The declared dialects. Each row's source is the provider's own error documentation as collected in the
 * per-provider matrix (status, word, sentence → condition); a `sentence` row is the fragile kind and degrades
 * as the module note says.
 */
export declare const PROVIDER_DIALECTS: readonly ProviderDialect[];
/**
 * The rows every endpoint answers to beneath its own, and the only rows an unrecognized endpoint has. Each
 * states something whose meaning no provider in the table overloads: Payment Required, OpenAI's spend codes,
 * the structural context-limit code and the context-limit sentences, the transport's 413. The cross-provider
 * word `insufficient_quota` is pinned to `unknown` here on purpose — on an endpoint nobody declared, it is as
 * likely a token-rate limit as an empty balance.
 */
export declare const GENERIC_FAILURES: readonly FailureRow[];
/**
 * The TRANSIENT statuses — the server family and the two transient 4xx (408 request timeout, 409 lock timeout;
 * CC's own retry predicate treats them like 5xx). Two readers, one fact: unread, such a status defaults to
 * `unknown` (retried), and no row turns one into a stop (pinned), so the connect ladder decides them without
 * reading the body (a stalled error body must not cost each retry the body's read bound); the terminal still
 * reads and judges it.
 */
export declare function isTransientStatus(status: number): boolean;
/** The endpoint a request went to, or `undefined` when no dialect declares it. */
export declare function resolveProviderDialect(url: string, wire: Model["api"]): ProviderDialect | undefined;
/** One failure's reading off the table. */
export interface ProviderVerdict {
    readonly condition: ProviderCondition;
    readonly source: ProviderConditionSource;
    /** When the condition is `quota_exhausted` and the provider stated when it lifts: wall-clock epoch ms. */
    readonly resetAtMs?: number;
    readonly inputTooLong: InputTooLongVerdict;
}
type HeaderBag = {
    get?: (name: string) => string | null;
} | undefined | null;
/**
 * Judge one failed HTTP response. `body` is the error body as read (`endedNormally` false = cut by a bound or
 * torn): only a body that ENDED may steer, so a cut one is read as stating nothing — the endpoint's status row
 * and the generic rows still apply. Absent `body` = not read (a status whose verdict no body can change).
 */
export declare function judgeHttpFailure(args: {
    dialect: ProviderDialect | undefined;
    status: number;
    headers?: HeaderBag;
    body?: FailedBody;
}): ProviderVerdict;
/** Judge an in-band error frame's envelope object (a provider error delivered inside a 200 stream). */
export declare function judgeInBandError(dialect: ProviderDialect | undefined, envelope: {
    message?: unknown;
    code?: unknown;
    type?: unknown;
}): ProviderVerdict;
/**
 * The failure an in-band error frame states, as the brain error the stream's terminal carries: the code its
 * condition reads as ({@link PROVIDER_CONDITION_TRAITS}), the provider's word and sentence in the message, the word
 * on the echo seat, the verdict, and the context-limit reading of the same row. A frame the provider sent on its
 * own stream is a provider failure by construction (`apiError`); it states no status.
 */
export declare function inBandProviderError(dialect: ProviderDialect | undefined, envelope: {
    message?: unknown;
    code?: unknown;
    type?: unknown;
}, label: string): BrainError;
export {};
