import type { AIProviderName } from "../constants/enums.js";
import { BaseProvider } from "../core/baseProvider.js";
import { ProviderError } from "../types/index.js";
import type { DecisionError, DecisionQuestion, DecisionRequest, DecisionResult, DecisionPreparedMedia, DecisionState, LanguageModel, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
/**
 * Generous enough for a cold start (measured at 2.0–2.7s after idle on Jev)
 * while still bounded. Every internal caller is fail-open, so this only bites
 * on a genuine stall.
 */
export declare const DEFAULT_DECISION_TIMEOUT_MS = 5000;
export declare const isRecord: (v: unknown) => v is Record<string, unknown>;
export declare const asNumber: (v: unknown) => number | undefined;
/**
 * FastAPI's request-validation envelope, `{"detail":[{loc, msg, input}]}`,
 * reduced to its field paths and messages. `input` echoes the caller's own
 * request back — possibly the whole state — so it is never surfaced.
 */
export declare function describeValidationErrors(detail: readonly unknown[]): string;
/**
 * A LiteLLM proxy echoes credentials back in its error texts, in more than one
 * wording: a masked key plus its hash on a rejected key, the whole key when it
 * does not look like a LiteLLM key, a key hash on a rate limit. None of it
 * belongs in an error message or a log, whatever the wording, so the
 * configured key, anything shaped like a LiteLLM key, any long hex run and any
 * embedded `data:` URL are all removed.
 */
export declare function redactCredentials(message: string, apiKey: string): string;
/**
 * The shared half of every "System One" decision provider — a model that takes
 * one `state` plus typed questions and returns one typed answer each, with no
 * text anywhere.
 *
 * Vendors differ in where the request goes, how it is authenticated, what the
 * body carries and what their error envelopes look like. They do not differ in
 * anything else, so everything else lives here: the missing-key check, the
 * auth circuit breaker, the timeout and retry loop, answer parsing and usage.
 * A new decision provider implements the abstract hooks and nothing more.
 */
export declare abstract class SystemOneDecisionProvider extends BaseProvider {
    protected readonly proxyFetch: typeof fetch;
    private readonly maxRetries;
    /**
     * Set once the key has been rejected. A bad key cannot fix itself, and
     * without this every later request would pay a full round trip (~265ms
     * measured on Jev) to be told so again — a permanent tax on the hot path for
     * a misconfiguration.
     */
    private authFailed;
    protected constructor(modelName: string | undefined, providerName: AIProviderName, sdk: unknown);
    /** Short vendor name for messages and logs, e.g. "TypeSafe". */
    protected abstract vendorLabel(): string;
    /** How the model is named when describing it, e.g. "TypeSafe (Jev)". */
    protected abstract vendorDisplayName(): string;
    protected abstract decisionApiKey(): string;
    protected abstract missingKeyMessage(): string;
    /**
     * Why this instance cannot send a request even though it has a key, such as
     * a provider with no built-in endpoint and none configured. Undefined when
     * nothing is missing.
     */
    protected missingConfigMessage(): string | undefined;
    /**
     * Where the request goes. The model asked for is passed in because one
     * vendor names it in the URL path; every other provider ignores it.
     */
    protected abstract decisionEndpoint(model: string): string;
    protected abstract decisionHeaders(): Record<string, string>;
    protected abstract buildDecisionBody(state: DecisionState, questions: Record<string, Record<string, unknown>>, model: string, media?: DecisionPreparedMedia): Record<string, unknown>;
    protected abstract parseDecisionError(status: number, payload: unknown, requestId: string | undefined): DecisionError;
    protected abstract readRequestId(headers: Headers): string | undefined;
    /**
     * The System One wire calls the yes/no primitive `noul`; this codebase and
     * every SDK exposing it call it `boolean`.
     */
    protected encodeQuestion(question: DecisionQuestion): Record<string, unknown>;
    /**
     * How long a rate-limited or unavailable response asks the caller to wait.
     * Undefined keeps the default backoff. A wait longer than what is left of the
     * attempt's timeout is not taken: the error is thrown at once, so a fail-open
     * consumer is not held for the length of a vendor's cooldown.
     */
    protected readRetryAfterMs(_headers: Headers): number | undefined;
    /**
     * The per-attempt timeout when the caller sets none. A provider whose latency
     * grows with the number of questions scales the descriptor's allowance here.
     */
    protected defaultTimeoutMs(_questionCount: number): number | undefined;
    /**
     * The part of a successful response that holds `answers`, `usage` and
     * `model`. The default is the response itself; a vendor that wraps every
     * answer in an envelope returns what is inside it. Errors are not passed
     * through here: they are read from the whole response.
     */
    protected readDecisionPayload(payload: unknown): unknown;
    /** Per-question confidence a transport reports outside the answer objects. */
    protected reportedConfidence(_payload: unknown): Record<string, number>;
    protected resolveResponseModel(payload: Record<string, unknown>, requestedModel: string): string;
    /** Extra fields for the credential-rejected warning. */
    protected diagnosticContext(): Record<string, unknown>;
    protected getProviderName(): AIProviderName;
    protected getDefaultDecisionModel(): string | undefined;
    supportsTools(): boolean;
    /**
     * A decision model produces no text, so there is no chat model behind it.
     * Unreachable while the descriptor declares `inferenceKinds: ["decide"]`;
     * kept actionable for the case where something routes here anyway.
     */
    protected getAISDKModel(): LanguageModel;
    protected executeStream(_options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
    /**
     * Must RETURN the error, never throw it (CLAUDE.md rule 6).
     */
    protected formatProviderError(error: unknown): Error;
    /**
     * Evaluate a state against a batch of typed questions.
     *
     * Throws a {@link ProviderError} carrying a normalised {@link DecisionError}
     * in `cause`. Internal hot paths should prefer `NeuroLink.tryDecide()`,
     * which returns null instead.
     */
    decide(request: DecisionRequest): Promise<DecisionResult>;
    /**
     * Turn the request's images and video into data URLs, or refuse it. Refused
     * as a non-retryable `invalid_request`: resending the same media cannot help.
     */
    private prepareMedia;
    /**
     * The encoded body, not just the media, is what the server's size limit
     * applies to.
     */
    private assertWithinRequestBytes;
    /**
     * Refuse a request the model cannot read in full. An encoder cuts the state
     * off past its window without saying so, so without this a decision would
     * be made on input the model never saw — and reported as if it had.
     */
    private assertWithinDecisionLimits;
    /**
     * Wrap a normalised decision failure in the provider error type, keeping
     * the structured detail reachable via `cause` for callers that branch on
     * `kind` (authentication vs rate_limit vs max_tokens_exceeded).
     */
    protected decisionError(detail: DecisionError): ProviderError;
}
