import { r as KodaXProviderConfig, m as KodaXMessage, X as KodaXToolDefinition, F as KodaXReasoningRequest, z as KodaXProviderStreamOptions, J as KodaXStreamResult, n as KodaXModelDescriptor, q as KodaXProviderCapabilityProfile, C as KodaXReasoningCapability, E as KodaXReasoningOverride } from './types.d-B1uGoVTE.js';

/**
 * Retry-After header parsing — FEATURE_130 (v0.7.36).
 *
 * Handles the four forms KodaX's 12 provider adapters encounter when a
 * model returns 429 (rate limit) or 503/529 (overloaded):
 *
 *   1. `Retry-After: 120`               — integer seconds (HTTP 7231 standard)
 *   2. `Retry-After: <HTTP-date>`       — RFC 7231 IMF-fixdate
 *      e.g. "Wed, 21 Oct 2026 07:28:00 GMT"
 *   3. `retry-after-ms: 45000`          — Anthropic millisecond extension
 *   4. (no Retry-After header present)  — falls back to exponential backoff
 *      capped at `maxBackoffMs`, with optional jitter for the
 *      "thundering herd" protection.
 *
 * All return values are normalized to whole milliseconds and clamped to
 * a sensible upper bound — never block the user for more than 120s, and
 * never honor a header advertising a wait longer than `maxHeaderWaitMs`
 * (default 120s). Beyond that limit we still extract the header but cap
 * it; the calling provider can check `cappedFromHeader` to decide
 * whether to surface a "rate limit exceeded — please wait" error to the
 * user instead of silently sleeping for two minutes.
 *
 * Pattern-B (FEATURE_119) interaction: the helper is referentially
 * transparent and stateless — it can be invoked concurrently by N
 * parallel children without coordination. The retry loop in each
 * provider holds its own attempt counter; this helper only translates
 * headers/attempts into wait durations.
 *
 * Reference: opencode session/retry.ts:14-123 (4-form coverage).
 */
type RetryAfterSource = 'retry-after-seconds' | 'retry-after-date' | 'retry-after-ms' | 'exponential-backoff';
type RetryAfterResult = {
    readonly type: 'header';
    readonly waitMs: number;
    readonly source: 'retry-after-seconds' | 'retry-after-date' | 'retry-after-ms';
    /** True when the header value exceeded `maxHeaderWaitMs` and was clamped. */
    readonly cappedFromHeader: boolean;
} | {
    readonly type: 'backoff';
    readonly waitMs: number;
    readonly source: 'exponential-backoff';
    readonly attempt: number;
};
interface ParseRetryAfterOptions {
    /** Zero-based attempt index used by the backoff branch (0 = first retry). */
    readonly attempt: number;
    /** Base delay for exponential backoff. Default 1000ms. */
    readonly baseBackoffMs?: number;
    /** Maximum exponential backoff cap. Default 30000ms. */
    readonly maxBackoffMs?: number;
    /** Maximum wait honored from a header. Default 120000ms. */
    readonly maxHeaderWaitMs?: number;
    /**
     * Override the "now" reference used by the HTTP-date branch.
     * Test-only escape hatch — production code should leave this undefined.
     */
    readonly now?: () => number;
    /**
     * Whether the backoff branch adds 0-25% jitter on top of the base
     * exponential. Default true (matches the legacy `withRateLimit`
     * jitter contract). Tests can pass `false` for deterministic output.
     */
    readonly withJitter?: boolean;
}
type HeadersLike = Headers | Record<string, string | string[] | undefined> | undefined;
/**
 * Parse rate-limit/overload retry-after headers (4 forms) and decide
 * how long the caller should sleep before retrying. Returns either:
 *
 *  - `{type: 'header', ...}` when one of the supported headers was found
 *    and converted into a wait duration; OR
 *  - `{type: 'backoff', ...}` falling back to exponential backoff for
 *    the given `attempt` index when no header is present.
 */
declare function parseRetryAfter(headers: HeadersLike, options: ParseRetryAfterOptions): RetryAfterResult;
/**
 * Pull headers off a thrown error in the various shapes produced across
 * provider SDKs (Anthropic, OpenAI, fetch-based custom providers).
 * Returns `undefined` when no headers can be located — the helper then
 * falls through to exponential backoff.
 */
declare function extractHeadersFromError(error: unknown): HeadersLike;

/**
 * KodaX Base Provider
 *
 * Provider 抽象基类 - 所有 Provider 的公共基础
 */

/**
 * FEATURE_130 (v0.7.36): structured payload fired through
 * `KodaXEvents.onRetryAfter` whenever a provider's `withRateLimit`
 * loop catches a 429 / 503 / 529 response and decides to wait. The
 * `source` field carries which retry-after header form (or fallback)
 * produced the wait duration so UI surfaces can show "provider asked
 * us to wait 45s" vs "no header, exp-backoff guess of 4s".
 */
interface KodaXRetryAfterEvent {
    readonly provider: string;
    readonly waitMs: number;
    readonly reason: 'rate-limit' | 'overloaded';
    readonly source: RetryAfterSource;
    readonly attempt: number;
    readonly maxAttempts: number;
}
type KodaXOnRetryAfterCallback = (event: KodaXRetryAfterEvent) => void;
declare abstract class KodaXBaseProvider {
    abstract readonly name: string;
    abstract readonly supportsThinking: boolean;
    protected abstract readonly config: KodaXProviderConfig;
    /**
     * Per-request override for `max_tokens` in the next provider call. Consumed
     * once and cleared in `withRateLimit` after the next successful response.
     * Two callers set this:
     *   1. Context-overflow recovery inside `withRateLimit` (reduces budget
     *      when the model reports "prompt too long").
     *   2. The agent loop's max_tokens escalation path, which flips this to
     *      `KODAX_ESCALATED_MAX_OUTPUT_TOKENS` when a capped-budget turn
     *      returns `stop_reason: max_tokens`. See `coding/src/agent.ts`.
     */
    protected maxOutputTokensOverride?: number;
    /**
     * Public setter for the one-shot override above. Callers outside the
     * provider package (notably the agent loop's escalation branch) use this
     * to stage a larger budget for the next stream call in the same logical
     * turn. Pass `undefined` to clear a stale override explicitly.
     */
    setMaxOutputTokensOverride(value: number | undefined): void;
    /**
     * Returns the max_tokens value the provider will currently use on its
     * next request. Precedence (highest to lowest):
     *   1. One-shot override (agent escalation, context-overflow recovery)
     *   2. User env var `KODAX_MAX_OUTPUT_TOKENS` (explicit user intent)
     *   3. Active model descriptor's `maxOutputTokens` (FEATURE_098)
     *   4. Provider config default
     *   5. Global `KODAX_MAX_TOKENS` fallback
     * Used by provider stream() paths and by the agent loop to decide
     * whether escalation is applicable (see `coding/src/agent.ts`).
     */
    getEffectiveMaxOutputTokens(model?: string): number;
    /**
     * Hard cap on a single streaming request's wall-clock duration (ms).
     * Returns undefined when no cap is configured. Consumed by the
     * resilience layer to abort a doomed stream before the server-side
     * kill window fires; routed through `non_streaming_fallback`.
     *
     * Cascade (highest to lowest):
     *   1. Active model descriptor's `streamMaxDurationMs`
     *   2. Provider config default
     *   3. undefined (watchdog disabled)
     */
    getStreamMaxDurationMs(model?: string): number | undefined;
    /**
     * Resolves whether OpenAI-compat `reasoning_content` should echo back
     * on replayed assistant messages for the given model. Same cascade as
     * `getStreamMaxDurationMs`. Defaults to false when neither layer sets it.
     */
    getEffectiveReplayReasoningContent(model?: string): boolean;
    /**
     * Resolves whether Anthropic-style thinking signatures must verify
     * strictly (Anthropic proper only). Same cascade as
     * `getStreamMaxDurationMs`. Defaults to false (lenient) when neither
     * layer sets it — matches third-party Anthropic-compat behavior.
     */
    getEffectiveStrictThinkingSignature(model?: string): boolean;
    abstract stream(messages: KodaXMessage[], tools: KodaXToolDefinition[], system: string, reasoning?: boolean | KodaXReasoningRequest, streamOptions?: KodaXProviderStreamOptions, signal?: AbortSignal): Promise<KodaXStreamResult>;
    supportsNonStreamingFallback(): boolean;
    complete(_messages: KodaXMessage[], _tools: KodaXToolDefinition[], _system: string, _reasoning?: boolean | KodaXReasoningRequest, _streamOptions?: KodaXProviderStreamOptions, _signal?: AbortSignal): Promise<KodaXStreamResult>;
    isConfigured(): boolean;
    getModel(): string;
    getAvailableModels(): string[];
    getModelDescriptor(modelId?: string): KodaXModelDescriptor | undefined;
    getBaseUrl(): string | undefined;
    getApiKeyEnv(): string;
    getCapabilityProfile(): KodaXProviderCapabilityProfile;
    getConfiguredReasoningCapability(modelOverride?: string): KodaXReasoningCapability;
    getReasoningCapability(modelOverride?: string): KodaXReasoningCapability;
    getReasoningOverride(modelOverride?: string): KodaXReasoningOverride | undefined;
    getReasoningOverrideKey(modelOverride?: string): string;
    protected persistReasoningCapabilityOverride(capability: KodaXReasoningCapability, modelOverride?: string): void;
    protected shouldFallbackForReasoningError(error: unknown, ...terms: string[]): boolean;
    protected shouldFallbackForSpecificReasoningError(error: unknown, ...terms: string[]): boolean;
    protected getReasoningFallbackChain(capability: KodaXReasoningCapability): KodaXReasoningCapability[];
    /**
     * 获取模型的上下文窗口大小
     *
     * Backwards-compatible no-arg form: resolves against the provider's
     * default model descriptor. New call sites that know the active
     * model should use `getEffectiveContextWindow(model)` directly.
     * @returns 上下文窗口大小 (tokens)
     */
    getContextWindow(): number;
    /**
     * Resolves the context window for a specific model.
     * Precedence (highest to lowest):
     *   1. Active model descriptor's `contextWindow` (FEATURE_098)
     *   2. Provider config default
     *   3. 200_000 fallback
     * The user-level `compaction.contextWindow` is layered on top of
     * this at the call site, so it remains the highest-priority manual
     * override.
     */
    getEffectiveContextWindow(model?: string): number;
    protected getApiKey(): string;
    protected shouldLogStreamDiagnostics(): boolean;
    protected logStreamDiagnostic(...args: unknown[]): void;
    protected normalizeReasoning(reasoning?: boolean | KodaXReasoningRequest): Required<KodaXReasoningRequest>;
    /**
     * Called when ECONNRESET/EPIPE is detected, indicating a stale keep-alive
     * socket.  Subclasses should override to rebuild their HTTP client with a
     * fresh connection pool so the next retry uses a new TCP connection.
     */
    protected onStaleConnection(): void;
    protected isRateLimitError(error: unknown): boolean;
    /**
     * FEATURE_130: classify a rate-limit error as either a 429-style
     * "rate-limit" or a 503/529-style "overloaded" condition. The
     * distinction matters for UI: "rate-limit" usually surfaces a
     * provider-supplied retry-after window; "overloaded" tends to fall
     * through to exponential backoff with no header. Both flow through
     * the same retry path; this only labels the event.
     */
    protected classifyRateLimitReason(error: unknown): 'rate-limit' | 'overloaded';
    /**
     * Extract Retry-After delay from error headers (429/529 responses).
     * Returns milliseconds, or undefined when no usable header is present.
     *
     * FEATURE_130 (v0.7.36): now delegates to the shared `parseRetryAfter`
     * helper so all 12 provider adapters get 4-form coverage without each
     * adapter rolling its own parser. The 4 forms supported are:
     *   - `Retry-After: <integer-seconds>`
     *   - `Retry-After: <HTTP-date>`
     *   - `retry-after-ms: <milliseconds>` (Anthropic extension)
     *   - exponential-backoff fallback (returned via `withRateLimit`,
     *     not through this helper — it is `undefined` here when no
     *     header is present, which the caller then resolves to backoff)
     */
    protected extractRetryAfterMs(error: unknown): number | undefined;
    /**
     * Detect "prompt too long / context window exceeded" errors and compute
     * a reduced max_tokens for retry.  Returns undefined if not a context
     * overflow error.
     */
    protected parseContextOverflow(error: unknown): number | undefined;
    protected isContextOverflowError(error: unknown): boolean;
    protected withRateLimit<T>(fn: () => Promise<T>, signal?: AbortSignal, retries?: number, onRateLimit?: (attempt: number, maxRetries: number, delayMs: number) => void, onRetryAfter?: KodaXOnRetryAfterCallback): Promise<T>;
}

/**
 * KodaX Cost Rates - Multi-Provider pricing table
 *
 * 成本费率表 - 所有 Provider 的计费标准
 * 支持 11 个内置 Provider 的成本追踪，用户可以覆盖默认费率
 */
interface CostRate {
    readonly inputPer1M: number;
    readonly outputPer1M: number;
    readonly cachePer1M?: number;
}
declare const DEFAULT_COST_RATES: Readonly<Record<string, Readonly<Record<string, CostRate>>>>;
declare function getCostRate(provider: string, model: string, userOverrides?: Readonly<Record<string, Readonly<Record<string, CostRate>>>>): CostRate | undefined;
declare function calculateCost(rate: CostRate, inputTokens: number, outputTokens: number, cacheTokens?: number): number;

/**
 * KodaX Cost Tracker - Immutable session cost tracking
 *
 * 成本追踪器 - 不可变的会话成本追踪
 * 使用 Immutable 模式，每次操作都返回新对象而不修改原有对象
 */

interface TokenUsageRecord {
    readonly timestamp: number;
    readonly provider: string;
    readonly model: string;
    readonly inputTokens: number;
    readonly outputTokens: number;
    readonly cacheReadTokens: number;
    readonly cacheWriteTokens: number;
    readonly cost: number;
    readonly role?: string;
}
interface ProviderCostSummary {
    readonly cost: number;
    readonly calls: number;
    readonly inputTokens: number;
    readonly outputTokens: number;
}
/**
 * FEATURE_130 (v0.7.36) — per-retry record. Captures the wait the
 * provider asked us to take so `/cost` can report "X retries, Ys total
 * wait" alongside the token cost. Lives in the same tracker as token
 * records to keep one source of truth for the session.
 */
interface RetryRecord {
    readonly timestamp: number;
    readonly provider: string;
    readonly waitMs: number;
    readonly reason: 'rate-limit' | 'overloaded';
    readonly source: 'retry-after-seconds' | 'retry-after-date' | 'retry-after-ms' | 'exponential-backoff';
}
interface SessionCostSummary {
    readonly totalCost: number;
    readonly totalInputTokens: number;
    readonly totalOutputTokens: number;
    readonly totalCacheTokens: number;
    /** FEATURE_116 (v0.7.37): cumulative cache-read input tokens across the
     * session. Splits `totalCacheTokens` into the read half so the hit rate
     * (`cacheHitRate = totalCacheReadTokens / totalCacheTokens`) is
     * derivable for `/cost` reporting. */
    readonly totalCacheReadTokens: number;
    /** FEATURE_116 (v0.7.37): cumulative cache-write (creation) input tokens. */
    readonly totalCacheWriteTokens: number;
    /** FEATURE_116 (v0.7.37): cache-read share of all cache tokens this
     * session, in [0, 1]. Computed as `totalCacheReadTokens /
     * (totalCacheReadTokens + totalCacheWriteTokens)`. Returns 0 when no
     * cache activity has been recorded — a session with zero cache
     * activity is not "0% hit rate", just untracked. */
    readonly cacheHitRate: number;
    readonly callCount: number;
    /** FEATURE_130: total retries triggered across the session. */
    readonly retryCount: number;
    /** FEATURE_130: cumulative milliseconds spent in retry-after sleeps. */
    readonly retryWaitMs: number;
    readonly byProvider: Readonly<Record<string, ProviderCostSummary>>;
    readonly byRole: Readonly<Record<string, ProviderCostSummary>>;
}
interface CostTracker {
    readonly records: readonly TokenUsageRecord[];
    /** FEATURE_130 (v0.7.36): retry-wait records, append-only and immutable. */
    readonly retries: readonly RetryRecord[];
}
declare function createCostTracker(): CostTracker;
/**
 * FEATURE_130 (v0.7.36): record a retry-after wait. The InkREPL spinner
 * (or any other consumer of `KodaXEvents.onRetryAfter`) calls this so
 * `/cost` can surface accurate session-wide retry telemetry.
 */
declare function recordRetry(tracker: CostTracker, entry: {
    readonly provider: string;
    readonly waitMs: number;
    readonly reason: 'rate-limit' | 'overloaded';
    readonly source: 'retry-after-seconds' | 'retry-after-date' | 'retry-after-ms' | 'exponential-backoff';
}): CostTracker;
declare function recordUsage(tracker: CostTracker, entry: {
    readonly provider: string;
    readonly model: string;
    readonly inputTokens: number;
    readonly outputTokens: number;
    readonly cacheReadTokens?: number;
    readonly cacheWriteTokens?: number;
    readonly role?: string;
}, userCostOverrides?: Readonly<Record<string, Readonly<Record<string, CostRate>>>>): CostTracker;
declare function getSummary(tracker: CostTracker): SessionCostSummary;
declare function formatCost(usd: number): string;
declare function formatCostReport(summary: SessionCostSummary): string;

export { DEFAULT_COST_RATES as D, KodaXBaseProvider as K, calculateCost as g, createCostTracker as h, extractHeadersFromError as i, formatCost as j, formatCostReport as k, getCostRate as l, getSummary as m, recordUsage as n, parseRetryAfter as p, recordRetry as r };
export type { CostRate as C, ParseRetryAfterOptions as P, RetryAfterResult as R, SessionCostSummary as S, TokenUsageRecord as T, CostTracker as a, KodaXOnRetryAfterCallback as b, KodaXRetryAfterEvent as c, ProviderCostSummary as d, RetryAfterSource as e, RetryRecord as f };
