From fc8a1559017f1e581cfa971aa3cef11a507a4975 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 25 May 2026 12:30:04 +0200 Subject: [PATCH] fix(ai): honor Codex Responses maxRetries --- packages/ai/src/providers/openai-codex-responses.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/ai/src/providers/openai-codex-responses.ts b/packages/ai/src/providers/openai-codex-responses.ts index 70df0810..7909e925 100644 --- a/packages/ai/src/providers/openai-codex-responses.ts +++ b/packages/ai/src/providers/openai-codex-responses.ts @@ -50,7 +50,7 @@ import { buildBaseOptions } from "./simple-options.ts"; const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api"; const JWT_CLAIM_PATH = "https://api.openai.com/auth" as const; -const MAX_RETRIES = 3; +const DEFAULT_MAX_RETRIES = 3; const BASE_DELAY_MS = 1000; const CODEX_TOOL_CALL_PROVIDERS = new Set(["openai", "openai-codex", "opencode"]); const WEBSOCKET_MESSAGE_TOO_BIG_CLOSE_CODE = 1009; @@ -231,8 +231,9 @@ export const streamOpenAICodexResponses: StreamFunction<"openai-codex-responses" // Fetch with retry logic for rate limits and transient errors let response: Response | undefined; let lastError: Error | undefined; + const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES; - for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { + for (let attempt = 0; attempt <= maxRetries; attempt++) { if (options?.signal?.aborted) { throw new Error("Request was aborted"); } @@ -254,7 +255,7 @@ export const streamOpenAICodexResponses: StreamFunction<"openai-codex-responses" } const errorText = await response.text(); - if (attempt < MAX_RETRIES && isRetryableError(response.status, errorText)) { + if (attempt < maxRetries && isRetryableError(response.status, errorText)) { let delayMs = BASE_DELAY_MS * 2 ** attempt; const retryAfterMs = response.headers.get("retry-after-ms"); @@ -297,7 +298,7 @@ export const streamOpenAICodexResponses: StreamFunction<"openai-codex-responses" } lastError = error instanceof Error ? error : new Error(String(error)); // Network errors are retryable - if (attempt < MAX_RETRIES && !lastError.message.includes("usage limit")) { + if (attempt < maxRetries && !lastError.message.includes("usage limit")) { const delayMs = BASE_DELAY_MS * 2 ** attempt; await sleep(delayMs, options?.signal); continue;