/**
 * Codex (OpenAI ChatGPT) Proxy Routes
 *
 * Exposes `POST /backend-api/codex/responses` — the ChatGPT-backend Responses
 * API endpoint the Codex CLI talks to — and pools it across multiple ChatGPT
 * OAuth accounts, mirroring the Anthropic Claude pool engine.
 *
 * A Codex CLI configured with `model_providers.<name>.base_url` pointing at this
 * proxy sends its own OAuth token; the proxy strips it, selects a pooled
 * `codex:*` account, attaches that account's Bearer + matching chatgpt-account-id,
 * forwards to https://chatgpt.com/backend-api/codex, and relays the SSE stream.
 * On quota exhaustion (429 / usage limit) the account is cooled and the next
 * account is tried — so the user never has to switch accounts by hand.
 *
 * This engine is deliberately leaner than claudeProxyRoutes.ts: it reuses the
 * shared cooldown/quota persistence (keyed by the `codex:` account key so it
 * never collides with anthropic entries) and does pre-commit rotation only, not
 * the full transient-budget / admission machinery.
 */
import type { AccountQuota, CodexRefreshTokenStore, CodexResponseEnvelope, CodexResponseStream, CodexRuntimeAccount, CodexTokenRefresher, RateLimitCoolingReason, RouteGroup, ServerContext, ProxyRuntimeConfigProvider } from "../../types/index.js";
declare function refreshCodexTokenOnceWithDependencies(key: string, refreshToken: string, store: CodexRefreshTokenStore, refresh: CodexTokenRefresher): Promise<{
    accessToken: string;
    refreshToken: string;
    expiresAt?: number;
}>;
/** Refresh an account's token at most once at a time. */
declare function refreshCodexTokenOnce(key: string, refreshToken: string): Promise<{
    accessToken: string;
    refreshToken: string;
    expiresAt?: number;
}>;
/**
 * Load the Codex account pool from the token store, refreshing expired OAuth
 * tokens and hydrating cooldown + quota state from disk.
 */
declare function loadCodexProxyAccounts(): Promise<CodexRuntimeAccount[]>;
/**
 * Order non-cooling accounts ahead of cooling ones, then defer rejected quota.
 * Within each group, probe unknown quota first and otherwise fill the least-used
 * session so fresh accounts get observed rather than starved.
 */
declare function orderCodexAccounts(accounts: CodexRuntimeAccount[], now: number): CodexRuntimeAccount[];
/** Build the upstream request headers, replacing client auth with the account's. */
declare function buildCodexUpstreamHeaders(clientHeaders: Record<string, string>, account: CodexRuntimeAccount): Record<string, string>;
/** Honor known quota resets while bounding unscoped or transient account cooldowns. */
declare function planCodexCooldown(quota: AccountQuota | null, retryAfterMs: number, now: number, errorText?: string): {
    coolingUntil: number;
    reason: RateLimitCoolingReason;
};
/**
 * Drive a `CodexResponseStream`'s `frames` generator into a `Response` body,
 * calling `onSettled` exactly once with the outcome: the terminal envelope on
 * a normal finish, the thrown error on the (never expected, still handled)
 * post-commit failure, or `cancelled` when the consumer cancels the
 * `ReadableStream` first (client disconnect, or an upstream timeout/abort).
 *
 * `createAnthropicFallbackStream`'s generator never throws once past its own
 * internal preflight (codexToAnthropicFallback.ts:220-517) — every
 * post-commit failure is instead serialized as a `response.failed` frame and
 * the generator completes normally — so the `catch` branch here is a
 * defensive backstop, not the documented failure path.
 */
declare function wrapCodexOutboundResponseStream(codecStream: CodexResponseStream, headers: Record<string, string>, onSettled: (result: {
    kind: "completed";
    envelope: CodexResponseEnvelope;
} | {
    kind: "error";
    error: unknown;
} | {
    kind: "cancelled";
}) => void): Response;
/** Core pooled handler for POST /backend-api/codex/responses. */
export declare function handleCodexResponsesRequest(ctx: ServerContext, runtimeConfigProvider?: ProxyRuntimeConfigProvider, loopbackPort?: number, internalDispatch?: (request: Request) => Response | Promise<Response>): Promise<Response>;
/**
 * Create Codex proxy routes.
 *
 * @param basePath - Base path prefix (default "").
 * @param runtimeConfigProvider - Optional runtime config snapshot reader.
 *   Gates the Codex-outbound fallback dispatcher at all four insertion
 *   points in `dispatch()`: omitting it (or a snapshot with the feature
 *   disabled / no targets configured) reproduces today's behavior exactly.
 * @param loopbackPort - The in-process HTTP port the outbound-fallback leg's
 *   Anthropic-pool loopback request targets (mirrors `createOpenAIProxyRoutes`'s
 *   bridge). Required only for an `anthropic` target; the `vertex` target
 *   dispatches via `executeVertexAnthropicFallback` and never reads it.
 * @param internalDispatch - Optional in-process fetch (`(request) =>
 *   app.fetch(request)`), so the outbound-fallback loopback never re-enters
 *   the public listener. Falls back to a real `fetch` against
 *   `loopbackPort` when omitted.
 * @returns RouteGroup with the Codex backend Responses endpoint.
 */
export declare function createCodexProxyRoutes(basePath?: string, runtimeConfigProvider?: ProxyRuntimeConfigProvider, loopbackPort?: number, internalDispatch?: (request: Request) => Response | Promise<Response>): RouteGroup;
export declare const __testHooks: {
    loadCodexProxyAccounts: typeof loadCodexProxyAccounts;
    orderCodexAccounts: typeof orderCodexAccounts;
    buildCodexUpstreamHeaders: typeof buildCodexUpstreamHeaders;
    planCodexCooldown: typeof planCodexCooldown;
    refreshCodexTokenOnce: typeof refreshCodexTokenOnce;
    refreshCodexTokenOnceWithDependencies: typeof refreshCodexTokenOnceWithDependencies;
    codexRefreshInFlightSize: () => number;
    setOutboundFallbackTimeoutMsForTests: (ms: number | null) => void;
    wrapCodexOutboundResponseStream: typeof wrapCodexOutboundResponseStream;
};
export {};
