export type ProviderFailureKind = 'dns_error' | 'connect_error' | 'tls_error' | 'timeout' | 'abort' | 'http_4xx' | 'http_5xx'
/** Stream closed BEFORE the provider sent any token — typical "half-stop"
 *  failure in continuation / tool-result follow-up turns. Caller should
 *  surface it as a continuation failure, not a no-response. */
 | 'stream_interrupted_before_first_token'
/** Stream closed AFTER some content had already streamed. Partial output
 *  may still be worth keeping; this is generally retryable for the
 *  remainder. */
 | 'stream_interrupted'
/** 0.13.97: first-token watchdog fired — the stream stayed open but no
 *  visible chunk arrived within `middleware.streamFirstTokenTimeoutMs`.
 *  Distinct from `stream_interrupted_before_first_token` (which means the
 *  upstream connection actually closed). User has nothing yet, so
 *  recovery is "switch model / retry"; partialOutputSeen is always false. */
 | 'stream_first_token_timeout'
/** 0.13.97: between-chunks idle watchdog fired AFTER first-token had
 *  arrived. Upstream may still be alive but went silent past
 *  `middleware.streamIdleTimeoutMs` (or per-route `timeoutMs`).
 *  partialOutputSeen is true by definition; transcript already shows
 *  whatever arrived. */
 | 'stream_idle_timeout' | 'unknown_fetch_error';
export interface ProviderRequestDiagnostic {
    provider: string;
    model: string;
    kind: ProviderFailureKind;
    message: string;
    status?: number;
    requestId?: string;
    retryable: boolean;
    detail: string;
    rawCauseCode?: string;
    errno?: string | number;
    syscall?: string;
    upstreamRequestId?: string;
    /** 0.13.97: true when the proxy saw at least one content_block_delta /
     *  content_block_start before the failure. Used by frontend recovery
     *  guidance to distinguish "nothing reached the user" (suggest /model)
     *  from "partial output is in transcript" (suggest follow-up). Defaults
     *  to undefined for diagnostics built outside the streaming loop. */
    partialOutputSeen?: boolean;
}
export interface ProviderDiagnosticContext {
    provider?: string;
    model?: string;
    endpointUrl?: string;
    headers?: Record<string, string>;
    requestId?: string;
    status?: number;
    detail?: string;
    retryable?: boolean;
    upstreamRequestId?: string;
}
export declare class ProviderRequestError extends Error {
    readonly diagnostic: ProviderRequestDiagnostic;
    constructor(diagnostic: ProviderRequestDiagnostic);
}
export declare function inferProviderName(context: Pick<ProviderDiagnosticContext, 'provider' | 'endpointUrl' | 'headers'>): string;
export declare function detailLooksLikeRateLimit(rawDetail: string | undefined | null): boolean;
export declare function createProviderHttpDiagnostic(status: number, rawDetail: string, context?: ProviderDiagnosticContext): ProviderRequestDiagnostic;
export declare function createStreamInterruptedDiagnostic(context?: ProviderDiagnosticContext, options?: {
    beforeFirstToken?: boolean;
    detail?: string;
}): ProviderRequestDiagnostic;
/** 0.13.97: first-token watchdog fired — upstream stayed open but produced
 *  no visible chunk within `streamFirstTokenTimeoutMs`. Always
 *  `partialOutputSeen: false` by definition. */
export declare function createStreamFirstTokenTimeoutDiagnostic(context: ProviderDiagnosticContext | undefined, options: {
    timeoutMs: number;
}): ProviderRequestDiagnostic;
/** 0.13.97: between-chunks idle watchdog fired AFTER first-token already
 *  arrived. Always `partialOutputSeen: true` by definition. */
export declare function createStreamIdleTimeoutDiagnostic(context: ProviderDiagnosticContext | undefined, options: {
    timeoutMs: number;
}): ProviderRequestDiagnostic;
export declare function classifyProviderRequestError(error: unknown, context?: ProviderDiagnosticContext): ProviderRequestDiagnostic;
export declare function diagnosticToAnthropicError(diagnostic: ProviderRequestDiagnostic): {
    httpStatus: number;
    body: {
        type: 'error';
        error: {
            type: 'invalid_request_error' | 'api_error' | 'overloaded_error' | 'rate_limit_error' | 'not_found_error';
            message: string;
            diagnostic: ProviderRequestDiagnostic;
        };
    };
};
export declare function formatProviderDiagnostic(diagnostic: ProviderRequestDiagnostic, options?: {
    includeRequestId?: boolean;
}): string;
/**
 * Continuation context for stream-interrupted-before-first-token failures.
 * Captures whether the preceding turn had tool results (the "tool completed
 * but model continuation failed" case) vs a plain user continue prompt.
 */
export type ContinuationContext = 'tool-success' | 'user-continue' | 'none';
/**
 * Single-line user-facing sentence for a provider failure, contextualised
 * with continuation semantics. Exists so every call site — REPL transcript,
 * slash output, agent tool — emits identical phrasing for the same failure
 * class, with no duplicate trailing "(No response from …) · No tokens
 * reported" tail that used to slip in from the REPL fallback path.
 */
export declare function formatContinuationFailure(diagnostic: ProviderRequestDiagnostic, continuation?: ContinuationContext, options?: {
    includeRequestId?: boolean;
}): string;
export declare function parseProviderDiagnosticFromPayload(payload: unknown): ProviderRequestDiagnostic | null;
export declare function parseProviderDiagnosticFromString(raw: string): ProviderRequestDiagnostic | null;
export declare function upstreamRequestIdFromHeaders(headers: Headers | undefined): string | undefined;
