From 452d51b9b93b892d8e16e835867baf2072ab6f48 Mon Sep 17 00:00:00 2001 From: Nur Ad-Duja Date: Sun, 19 Jul 2026 20:23:23 +0700 Subject: [PATCH] fix(codex): current client_version + refresh-aware model sync The codex models config sent client_version=1.0.0 to /codex/models. That endpoint gates each catalog entry by minimal_client_version, and codex CLI's own manifest already requires 0.144.0 for its newest models, so an old client_version comes back 200 with those entries silently missing instead of erroring. Bump the version, add the originator header codex requests already send everywhere else in this codebase (registry, image provider, usage tracking), and move the codex entry onto the same buildOAuthResolver pattern gemini-cli and grok-cli already use. That gives model sync the same refresh-on-401 retry those providers get (codex had none before) and surfaces a warning in the response instead of a silent empty list when the upstream call still comes back with zero models. --- src/app/api/providers/[id]/models/route.js | 29 ++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/app/api/providers/[id]/models/route.js b/src/app/api/providers/[id]/models/route.js index 89b1ca4b913..e8940620806 100644 --- a/src/app/api/providers/[id]/models/route.js +++ b/src/app/api/providers/[id]/models/route.js @@ -2,7 +2,7 @@ import { NextResponse } from "next/server"; import { getProviderConnectionById } from "@/models"; import { isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/shared/constants/providers"; import { GEMINI_CONFIG } from "@/lib/oauth/constants/oauth"; -import { refreshGoogleToken, updateProviderCredentials } from "@/sse/services/tokenRefresh"; +import { refreshGoogleToken, refreshCodexToken, updateProviderCredentials } from "@/sse/services/tokenRefresh"; import { resolveOllamaLocalHost } from "open-sse/config/providers.js"; import { getModelsByProviderId } from "open-sse/config/providerModels.js"; import { resolveKiroModels } from "open-sse/services/kiroModels.js"; @@ -13,6 +13,13 @@ import { resolveConnectionProxyConfig } from "@/lib/network/connectionProxy"; const GEMINI_CLI_MODELS_URL = "https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels"; +// The /codex/models endpoint gates each entry by minimal_client_version against this +// value, and codex CLI's own manifest (openai/codex codex-rs/models-manager/models.json) +// already requires 0.144.0 for its newest models, so a stale client_version here comes +// back 200 with those entries quietly missing instead of erroring. +const CODEX_CLIENT_VERSION = "0.144.6"; +const CODEX_MODELS_URL = `https://chatgpt.com/backend-api/codex/models?client_version=${CODEX_CLIENT_VERSION}`; + const parseOpenAIStyleModels = (data) => { if (Array.isArray(data)) return data; return data?.data || data?.models || data?.results || []; @@ -157,12 +164,20 @@ const PROVIDER_MODELS_CONFIG = { parseResponse: (data) => data.data || [] }, codex: { - url: "https://chatgpt.com/backend-api/codex/models?client_version=1.0.0", - method: "GET", - headers: { "Content-Type": "application/json", "Accept": "application/json" }, - authHeader: "Authorization", - authPrefix: "Bearer ", - parseResponse: parseCodexModels + customResolver: buildOAuthResolver({ + refreshFn: (conn) => refreshCodexToken(conn.refreshToken), + fetchFn: (token) => fetch(CODEX_MODELS_URL, { + method: "GET", + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + "Authorization": `Bearer ${token}`, + "originator": "codex_cli_rs" + } + }), + parseFn: parseCodexModels, + errorLabel: "Failed to fetch Codex models" + }) }, antigravity: { url: "https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:models",