From f019bb3abfd44cbedb304c8cce8728b4e05388a8 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Fri, 3 Jul 2026 14:51:00 -0400 Subject: [PATCH] fix(core): tighten ChatGPT codex model eligibility Replace the codex-substring heuristic with the empirically verified allow/disallow lists plus the >5.4 version rule; the ChatGPT backend rejects models like gpt-5.3-codex that the substring rule admitted. --- packages/core/src/plugin/provider/openai.ts | 13 ++++++++++--- packages/core/test/plugin/provider-openai.test.ts | 10 ++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/core/src/plugin/provider/openai.ts b/packages/core/src/plugin/provider/openai.ts index 12412841db..4facbd22b2 100644 --- a/packages/core/src/plugin/provider/openai.ts +++ b/packages/core/src/plugin/provider/openai.ts @@ -181,7 +181,7 @@ export const OpenAIPlugin = define({ if (!chatgpt) continue for (const model of item.models.values()) { evt.model.update(item.provider.id, model.id, (draft) => { - if (!eligible(draft)) { + if (!eligible(draft.api.id)) { draft.enabled = false return } @@ -316,8 +316,15 @@ function isChatGPT(credential: { readonly type: string; readonly methodID?: stri ) } -function eligible(model: { readonly id: string }) { - return model.id.includes("codex") +const chatgptAllowed = new Set(["gpt-5.5", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini"]) +const chatgptDisallowed = new Set(["gpt-5.5-pro"]) + +/** Which API model ids a ChatGPT subscription may call through the codex backend. */ +function eligible(apiID: string) { + if (chatgptAllowed.has(apiID)) return true + if (chatgptDisallowed.has(apiID)) return false + const match = apiID.match(/^gpt-(\d+\.\d+)/) + return match ? Number.parseFloat(match[1]) > 5.4 : false } function claim(token: string) { diff --git a/packages/core/test/plugin/provider-openai.test.ts b/packages/core/test/plugin/provider-openai.test.ts index e49862e55c..e82ab78099 100644 --- a/packages/core/test/plugin/provider-openai.test.ts +++ b/packages/core/test/plugin/provider-openai.test.ts @@ -182,8 +182,8 @@ describe("OpenAIPlugin", () => { catalog.provider.update(item.id, (draft) => { draft.api = item.api }) - catalog.model.update(item.id, ModelV2.ID.make("gpt-5-codex"), (draft) => { - draft.api = { id: ModelV2.ID.make("gpt-5-codex"), type: "aisdk", package: "@ai-sdk/openai" } + catalog.model.update(item.id, ModelV2.ID.make("gpt-5.3-codex-spark"), (draft) => { + draft.api = { id: ModelV2.ID.make("gpt-5.3-codex-spark"), type: "aisdk", package: "@ai-sdk/openai" } draft.cost = [{ input: 1, output: 2, cache: { read: 3, write: 4 } }] }) catalog.model.update(item.id, ModelV2.ID.make("gpt-5"), (draft) => { @@ -204,11 +204,13 @@ describe("OpenAIPlugin", () => { yield* addPlugin() - expect(required(yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("gpt-5-codex")))).toMatchObject({ + expect( + required(yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("gpt-5.3-codex-spark"))), + ).toMatchObject({ enabled: true, api: { type: "native", - id: "gpt-5-codex", + id: "gpt-5.3-codex-spark", package: "@opencode-ai/llm/providers/openai/codex", settings: { store: false }, },