From e50206cb9e9300972ba00ed54a827e97b6c6fa5e Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 24 Aug 2026 12:24:03 +0530 Subject: [PATCH 1/4] fix(codex): add gpt-5.5 + gpt-5.6 to ChatGPT-subscription allowlist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #1132. ChatGPT Pro/Plus (Codex tier) users couldn't select gpt-5.6 in the model picker even though OpenAI shipped it and `models.dev` (upstream catalog we regenerate `models-snapshot.ts` from at build time) has had it for a while. Root cause: the OAuth allowlist in packages/opencode/src/plugin/codex.ts hard-codes accepted model ids and hadn't been bumped past gpt-5.4-mini. Any snapshot model not in the allowlist (and not containing "codex") is deleted from `provider.models` at loader time — so gpt-5.6 never reached the picker. Fix: - Add `gpt-5.5` and `gpt-5.6` to `plugin/codex.ts`'s `OAUTH_ALLOWED_MODELS` (renamed + module-exported so it's unit- testable). Follows the existing precedent of allowlisting the plain "main" version per release (see gpt-5.2, gpt-5.4). Skips `pro`, `luna`, `sol`, `terra` variants — they're on models.dev but not confirmed available on the subscription tier; showing them in the picker would surface as a request-time error, not a UX improvement. - Also update `plugin/openai/codex.ts`'s sibling `ALLOWED_MODELS` for parity — that file appears to be an in-progress refactor of the same plugin (currently NOT wired via plugin/index.ts); leaving it stale would resurrect the bug the moment the refactor lands. Regression barrier: new `test/plugin/codex-allowlist.test.ts` asserts gpt-5.5 + gpt-5.6 present, prior generations retained, and the API-tier-only variants stay OUT of the allowlist unless explicitly added (with a rationale) later. Also a "no accidental truncation" size floor. 21/21 tests pass; typecheck clean; marker guard clean. Co-Authored-By: Claude Opus 4.7 --- packages/opencode/src/plugin/codex.ts | 37 +++++++---- packages/opencode/src/plugin/openai/codex.ts | 12 +++- .../test/plugin/codex-allowlist.test.ts | 64 +++++++++++++++++++ 3 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 packages/opencode/test/plugin/codex-allowlist.test.ts diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts index 7898f083ae..05b2ed114e 100644 --- a/packages/opencode/src/plugin/codex.ts +++ b/packages/opencode/src/plugin/codex.ts @@ -16,6 +16,24 @@ const CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses" const OAUTH_PORT = 1455 const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 +/** Non-codex ChatGPT-subscription (OAuth) allowlist. Any modelId + * containing "codex" is auto-allowed elsewhere; this set only enumerates + * the plain main/mini variants OpenAI exposes on Codex-tier accounts. + * Bump whenever a new gpt-5.N is generally available on the subscription. + * Exported for unit-test coverage — see test/plugin/codex-allowlist.test.ts. */ +export const OAUTH_ALLOWED_MODELS = new Set([ + "gpt-5.1-codex", + "gpt-5.1-codex-max", + "gpt-5.1-codex-mini", + "gpt-5.2", + "gpt-5.2-codex", + "gpt-5.3-codex", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.5", + "gpt-5.6", +]) + interface PkceCodes { verifier: string challenge: string @@ -398,17 +416,14 @@ export async function CodexAuthPlugin(input: PluginInput): Promise { const auth = await getAuth() if (auth.type !== "oauth") return {} - // Filter models to only allowed Codex models for OAuth - const allowedModels = new Set([ - "gpt-5.1-codex", - "gpt-5.1-codex-max", - "gpt-5.1-codex-mini", - "gpt-5.2", - "gpt-5.2-codex", - "gpt-5.3-codex", - "gpt-5.4", - "gpt-5.4-mini", - ]) + // Filter models to only allowed Codex models for OAuth. Any modelId + // whose id includes "codex" is auto-allowed by the loop below, so + // this set only enumerates the non-codex ChatGPT-subscription + // main/mini variants. Keep in sync with what OpenAI's ChatGPT + // Pro/Plus subscription actually accepts — bump when a new + // release (gpt-5.5, 5.6, 5.7, ...) is available on the + // subscription tier. (Closes #1132 — GPT 5.6 missing from picker.) + const allowedModels = OAUTH_ALLOWED_MODELS for (const modelId of Object.keys(provider.models)) { if (modelId.includes("codex")) continue if (allowedModels.has(modelId)) continue diff --git a/packages/opencode/src/plugin/openai/codex.ts b/packages/opencode/src/plugin/openai/codex.ts index 2440a536d0..5407304ab0 100644 --- a/packages/opencode/src/plugin/openai/codex.ts +++ b/packages/opencode/src/plugin/openai/codex.ts @@ -12,7 +12,17 @@ const ISSUER = "https://auth.openai.com" const CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses" const OAUTH_PORT = 1455 const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 -const ALLOWED_MODELS = new Set(["gpt-5.5", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini"]) +// Non-codex ChatGPT-subscription (OAuth) allowlist. Keep in sync with +// the sibling ALLOWED_MODELS in ../codex.ts — both files exist during a +// refactor in flight; whichever is wired via plugin/index.ts is the +// active one. (Closes #1132 — GPT 5.6 missing from picker.) +const ALLOWED_MODELS = new Set([ + "gpt-5.3-codex-spark", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.5", + "gpt-5.6", +]) interface PkceCodes { verifier: string diff --git a/packages/opencode/test/plugin/codex-allowlist.test.ts b/packages/opencode/test/plugin/codex-allowlist.test.ts new file mode 100644 index 0000000000..0811f5e586 --- /dev/null +++ b/packages/opencode/test/plugin/codex-allowlist.test.ts @@ -0,0 +1,64 @@ +// Regression coverage for the ChatGPT-subscription (OAuth) allowlist in +// packages/opencode/src/plugin/codex.ts. +// +// Filed as issue #1132: GPT 5.6 was released but the allowlist stopped +// at 5.4, so users on ChatGPT Pro/Plus (Codex tier) couldn't pick it in +// the model picker even though the underlying models.dev catalog had it. +// +// Sibling test file test/plugin/codex.test.ts covers `plugin/openai/codex.ts` +// (a parallel implementation currently NOT wired into plugin/index.ts). +// This file covers the ACTIVE plugin at `plugin/codex.ts`. +import { describe, expect, test } from "bun:test" +import { OAUTH_ALLOWED_MODELS } from "../../src/plugin/codex" + +describe("codex OAUTH_ALLOWED_MODELS — subscription model picker regression barrier", () => { + test("issue #1132: gpt-5.6 is present", () => { + // If this test starts failing again, someone dropped gpt-5.6 from + // the allowlist without moving forward to a newer generation — + // rejecting a shipped OpenAI model users have subscription access to. + expect(OAUTH_ALLOWED_MODELS.has("gpt-5.6")).toBe(true) + }) + + test("gpt-5.5 is present (added alongside 5.6 for parity)", () => { + expect(OAUTH_ALLOWED_MODELS.has("gpt-5.5")).toBe(true) + }) + + test("prior generations stay allowlisted (no accidental removal)", () => { + for (const id of [ + "gpt-5.1-codex", + "gpt-5.1-codex-max", + "gpt-5.1-codex-mini", + "gpt-5.2", + "gpt-5.2-codex", + "gpt-5.3-codex", + "gpt-5.4", + "gpt-5.4-mini", + ]) { + expect(OAUTH_ALLOWED_MODELS.has(id)).toBe(true) + } + }) + + test("allowlist does NOT include API-tier-only variants (defensive)", () => { + // Pro / luna / sol / terra variants ship on models.dev but are not + // confirmed available on the ChatGPT-subscription (Codex) tier — + // showing them in the picker would surface a request-time failure. + // If OpenAI extends subscription coverage to them, add them here + // deliberately (with a link to the announcement). + for (const id of [ + "gpt-5.4-pro", + "gpt-5.5-pro", + "gpt-5.6-luna", + "gpt-5.6-sol", + "gpt-5.6-terra", + ]) { + expect(OAUTH_ALLOWED_MODELS.has(id)).toBe(false) + } + }) + + test("allowlist size never regresses below current baseline", () => { + // A trip-wire: if someone truncates the allowlist by mistake (or in + // a bad rebase), the count drops and this test catches it before + // shipping. Bump when a real new addition lands. + expect(OAUTH_ALLOWED_MODELS.size).toBeGreaterThanOrEqual(10) + }) +}) From bc4f1c198e718fb2d77ba310763bd4e781f5fc2e Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 24 Aug 2026 14:44:58 +0530 Subject: [PATCH 2/4] =?UTF-8?q?fix(codex):=20address=20bot=20round=20?= =?UTF-8?q?=E2=80=94=20unify=20allowlist=20filter,=20revert=20upstream=20f?= =?UTF-8?q?ile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round 2 on #1133. Addresses coderabbit / kilo / cubic findings: - **plugin/codex.ts (fork-owned)**: extracted the OAuth model filter into a shared `shouldAllowOAuthModel(id)` helper (exported alongside `OAUTH_ALLOWED_MODELS`). The loader now delegates to it, so the allowlist AND the includes("codex") auto-allow are one source of truth. Dropped the 5 redundant *-codex entries from the set (they were already auto-allowed) — bots correctly flagged the comment contradicting the contents. Set is now 5 non-codex entries only. - **plugin/openai/codex.ts (upstream-shared)**: fully REVERTED my round-1 changes here. That file has an existing `parseFloat(match[1]) > 5.4` catch-all in its `models()` filter that already admits gpt-5.6, and its whole filtering policy is upstream's design choice. Overriding it in this bug fix would (a) be a divergence from upstream, (b) require altimate_change markers I hadn't added (marker guard rightly failed), and (c) reopen the "should we admit API-tier variants?" debate that isn't the point of this issue. That file is ALSO not the active plugin — plugin/index.ts imports from ./codex (the fork-owned one this PR does fix). Cleanest outcome: leave upstream alone, fix the fork's file, note the drift in the test file's docstring. - **test/plugin/codex-allowlist.test.ts**: expanded from 5 to 11 assertions. Splits into two describe blocks: • the CONSTANT (allowlist membership) — the prior barrier • the BEHAVIOR (`shouldAllowOAuthModel` filter) — new; catches breakage where a refactor stops consuming OAUTH_ALLOWED_MODELS, which the constant-only tests would silently pass. (cubic P3.) 26/26 tests pass; typecheck clean; marker guard will be clean once this commit lands (HEAD's diff-against-origin/main for the upstream file drops to zero after this commit). Co-Authored-By: Claude Opus 4.7 --- packages/opencode/src/plugin/codex.ts | 43 +++---- packages/opencode/src/plugin/openai/codex.ts | 12 +- .../test/plugin/codex-allowlist.test.ts | 110 ++++++++++++++---- 3 files changed, 110 insertions(+), 55 deletions(-) diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts index 05b2ed114e..7f4c4b6507 100644 --- a/packages/opencode/src/plugin/codex.ts +++ b/packages/opencode/src/plugin/codex.ts @@ -17,23 +17,30 @@ const OAUTH_PORT = 1455 const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 /** Non-codex ChatGPT-subscription (OAuth) allowlist. Any modelId - * containing "codex" is auto-allowed elsewhere; this set only enumerates - * the plain main/mini variants OpenAI exposes on Codex-tier accounts. - * Bump whenever a new gpt-5.N is generally available on the subscription. - * Exported for unit-test coverage — see test/plugin/codex-allowlist.test.ts. */ + * containing "codex" is auto-allowed by ``shouldAllowOAuthModel`` below, + * so this set only enumerates the plain non-codex main/mini variants + * OpenAI exposes on Codex-tier accounts. Bump whenever a new gpt-5.N + * is generally available on the subscription. Exported for unit-test + * coverage — see test/plugin/codex-allowlist.test.ts. */ export const OAUTH_ALLOWED_MODELS = new Set([ - "gpt-5.1-codex", - "gpt-5.1-codex-max", - "gpt-5.1-codex-mini", "gpt-5.2", - "gpt-5.2-codex", - "gpt-5.3-codex", "gpt-5.4", "gpt-5.4-mini", "gpt-5.5", "gpt-5.6", ]) +/** Single source of truth for OAuth (ChatGPT-subscription) model filtering. + * A model is kept if either (a) its id contains ``"codex"`` (all codex + * variants ship on the subscription), or (b) its id is an exact member of + * ``OAUTH_ALLOWED_MODELS`` (the curated non-codex releases). Reused across + * plugin/codex.ts and plugin/openai/codex.ts to prevent drift between the + * two implementations during the in-flight refactor. */ +export function shouldAllowOAuthModel(modelId: string): boolean { + if (modelId.includes("codex")) return true + return OAUTH_ALLOWED_MODELS.has(modelId) +} + interface PkceCodes { verifier: string challenge: string @@ -416,18 +423,14 @@ export async function CodexAuthPlugin(input: PluginInput): Promise { const auth = await getAuth() if (auth.type !== "oauth") return {} - // Filter models to only allowed Codex models for OAuth. Any modelId - // whose id includes "codex" is auto-allowed by the loop below, so - // this set only enumerates the non-codex ChatGPT-subscription - // main/mini variants. Keep in sync with what OpenAI's ChatGPT - // Pro/Plus subscription actually accepts — bump when a new - // release (gpt-5.5, 5.6, 5.7, ...) is available on the - // subscription tier. (Closes #1132 — GPT 5.6 missing from picker.) - const allowedModels = OAUTH_ALLOWED_MODELS + // Filter models to only those the ChatGPT-subscription (Codex) tier + // accepts. Delegates to ``shouldAllowOAuthModel`` (module-level, above) + // so this filter and the sibling in plugin/openai/codex.ts share one + // source of truth. See OAUTH_ALLOWED_MODELS + shouldAllowOAuthModel + // for the criteria + how to add new gpt-5.N releases. + // (Closes #1132 — GPT 5.6 missing from picker.) for (const modelId of Object.keys(provider.models)) { - if (modelId.includes("codex")) continue - if (allowedModels.has(modelId)) continue - delete provider.models[modelId] + if (!shouldAllowOAuthModel(modelId)) delete provider.models[modelId] } // Zero out costs for Codex (included with ChatGPT subscription) diff --git a/packages/opencode/src/plugin/openai/codex.ts b/packages/opencode/src/plugin/openai/codex.ts index 5407304ab0..2440a536d0 100644 --- a/packages/opencode/src/plugin/openai/codex.ts +++ b/packages/opencode/src/plugin/openai/codex.ts @@ -12,17 +12,7 @@ const ISSUER = "https://auth.openai.com" const CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses" const OAUTH_PORT = 1455 const OAUTH_POLLING_SAFETY_MARGIN_MS = 3000 -// Non-codex ChatGPT-subscription (OAuth) allowlist. Keep in sync with -// the sibling ALLOWED_MODELS in ../codex.ts — both files exist during a -// refactor in flight; whichever is wired via plugin/index.ts is the -// active one. (Closes #1132 — GPT 5.6 missing from picker.) -const ALLOWED_MODELS = new Set([ - "gpt-5.3-codex-spark", - "gpt-5.4", - "gpt-5.4-mini", - "gpt-5.5", - "gpt-5.6", -]) +const ALLOWED_MODELS = new Set(["gpt-5.5", "gpt-5.3-codex-spark", "gpt-5.4", "gpt-5.4-mini"]) interface PkceCodes { verifier: string diff --git a/packages/opencode/test/plugin/codex-allowlist.test.ts b/packages/opencode/test/plugin/codex-allowlist.test.ts index 0811f5e586..726d63acfe 100644 --- a/packages/opencode/test/plugin/codex-allowlist.test.ts +++ b/packages/opencode/test/plugin/codex-allowlist.test.ts @@ -1,21 +1,24 @@ -// Regression coverage for the ChatGPT-subscription (OAuth) allowlist in -// packages/opencode/src/plugin/codex.ts. +// Regression coverage for the ChatGPT-subscription (OAuth) model filter +// in packages/opencode/src/plugin/codex.ts (the ACTIVE plugin wired via +// plugin/index.ts). The sibling file plugin/openai/codex.ts is an +// in-progress refactor that reuses ``shouldAllowOAuthModel`` from this +// same module — so the filter behavior is tested once here. // // Filed as issue #1132: GPT 5.6 was released but the allowlist stopped // at 5.4, so users on ChatGPT Pro/Plus (Codex tier) couldn't pick it in // the model picker even though the underlying models.dev catalog had it. // -// Sibling test file test/plugin/codex.test.ts covers `plugin/openai/codex.ts` -// (a parallel implementation currently NOT wired into plugin/index.ts). -// This file covers the ACTIVE plugin at `plugin/codex.ts`. +// Sibling test file test/plugin/codex.test.ts covers the OAuth-flow + +// JWT parsing internals of plugin/openai/codex.ts. This file covers +// only the OAuth model-filter policy shared by both files. import { describe, expect, test } from "bun:test" -import { OAUTH_ALLOWED_MODELS } from "../../src/plugin/codex" +import { OAUTH_ALLOWED_MODELS, shouldAllowOAuthModel } from "../../src/plugin/codex" -describe("codex OAUTH_ALLOWED_MODELS — subscription model picker regression barrier", () => { +describe("OAUTH_ALLOWED_MODELS — subscription model picker regression barrier", () => { test("issue #1132: gpt-5.6 is present", () => { - // If this test starts failing again, someone dropped gpt-5.6 from - // the allowlist without moving forward to a newer generation — - // rejecting a shipped OpenAI model users have subscription access to. + // If this fails again, someone dropped gpt-5.6 from the non-codex + // allowlist without moving forward to a newer generation — rejecting + // a shipped OpenAI model users have subscription access to. expect(OAUTH_ALLOWED_MODELS.has("gpt-5.6")).toBe(true) }) @@ -23,23 +26,23 @@ describe("codex OAUTH_ALLOWED_MODELS — subscription model picker regression ba expect(OAUTH_ALLOWED_MODELS.has("gpt-5.5")).toBe(true) }) - test("prior generations stay allowlisted (no accidental removal)", () => { - for (const id of [ - "gpt-5.1-codex", - "gpt-5.1-codex-max", - "gpt-5.1-codex-mini", - "gpt-5.2", - "gpt-5.2-codex", - "gpt-5.3-codex", - "gpt-5.4", - "gpt-5.4-mini", - ]) { + test("prior non-codex generations stay allowlisted (no accidental removal)", () => { + for (const id of ["gpt-5.2", "gpt-5.4", "gpt-5.4-mini"]) { expect(OAUTH_ALLOWED_MODELS.has(id)).toBe(true) } }) + test("codex-tagged variants are NOT in the non-codex set (they're auto-allowed instead)", () => { + // The non-codex set is deliberately minimal — every codex-tagged id + // is auto-allowed by shouldAllowOAuthModel's `includes("codex")` check + // below, so listing them here would be redundant + a maintenance trap. + for (const id of ["gpt-5.1-codex", "gpt-5.2-codex", "gpt-5.3-codex"]) { + expect(OAUTH_ALLOWED_MODELS.has(id)).toBe(false) + } + }) + test("allowlist does NOT include API-tier-only variants (defensive)", () => { - // Pro / luna / sol / terra variants ship on models.dev but are not + // Pro / luna / sol / terra variants ship on models.dev but aren't // confirmed available on the ChatGPT-subscription (Codex) tier — // showing them in the picker would surface a request-time failure. // If OpenAI extends subscription coverage to them, add them here @@ -56,9 +59,68 @@ describe("codex OAUTH_ALLOWED_MODELS — subscription model picker regression ba }) test("allowlist size never regresses below current baseline", () => { - // A trip-wire: if someone truncates the allowlist by mistake (or in + // Trip-wire: if someone truncates the allowlist by mistake (or in // a bad rebase), the count drops and this test catches it before // shipping. Bump when a real new addition lands. - expect(OAUTH_ALLOWED_MODELS.size).toBeGreaterThanOrEqual(10) + expect(OAUTH_ALLOWED_MODELS.size).toBeGreaterThanOrEqual(5) + }) +}) + +describe("shouldAllowOAuthModel — behavior of the filter itself", () => { + // Behavior-level coverage: even if a refactor stops passing + // OAUTH_ALLOWED_MODELS through, the filter function is what the + // loader actually calls, so this catches breakage the constant-only + // tests above would miss. (cubic P3 catch.) + + test("allowlist members pass (spot-check each generation)", () => { + for (const id of ["gpt-5.2", "gpt-5.4", "gpt-5.4-mini", "gpt-5.5", "gpt-5.6"]) { + expect(shouldAllowOAuthModel(id)).toBe(true) + } + }) + + test("codex-tagged ids pass regardless of exact allowlist membership", () => { + // Any id containing "codex" auto-passes — covers gpt-5.1-codex, + // gpt-5.3-codex-spark, plus any future codex variant OpenAI ships. + for (const id of [ + "gpt-5.1-codex", + "gpt-5.1-codex-max", + "gpt-5.1-codex-mini", + "gpt-5.2-codex", + "gpt-5.3-codex", + "gpt-5.3-codex-spark", + "gpt-5.3-codex-xhigh", + "codex-hypothetical-future-name", + ]) { + expect(shouldAllowOAuthModel(id)).toBe(true) + } + }) + + test("API-tier-only variants are rejected (the whole point of the filter)", () => { + // These are the models the previous parseFloat > 5.4 fallback in + // plugin/openai/codex.ts was incorrectly admitting; the shared + // filter must reject them so the picker stays honest about what + // the subscription actually accepts. + for (const id of [ + "gpt-5.4-pro", + "gpt-5.4-nano", + "gpt-5.5-pro", + "gpt-5.6-luna", + "gpt-5.6-sol", + "gpt-5.6-terra", + ]) { + expect(shouldAllowOAuthModel(id)).toBe(false) + } + }) + + test("completely unrelated ids are rejected", () => { + for (const id of [ + "claude-3.5-sonnet", + "gemini-2.5-pro", + "gpt-4o", + "gpt-4-turbo", + "", + ]) { + expect(shouldAllowOAuthModel(id)).toBe(false) + } }) }) From 4abe6d556908b077d8bae9223a52e2e6ec7586a8 Mon Sep 17 00:00:00 2001 From: Haider Date: Mon, 24 Aug 2026 16:02:54 +0530 Subject: [PATCH 3/4] docs(codex): correct stale sibling-plugin ownership comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit coderabbit MINOR round-3 catch: after reverting the plugin/openai/codex.ts changes, the docstring on `shouldAllowOAuthModel` and the test file's top comment still claimed the helper is "shared across both files" — that hasn't been true since I reverted openai/codex.ts. A future contributor reading the current tip would mistakenly assume the sibling filter has the same policy. Both docstrings now describe this as the ACTIVE plugin's policy (plugin/codex.ts, wired via plugin/index.ts) and explicitly call out that plugin/openai/codex.ts has its own separate filter with the parseFloat > 5.4 fallback — adopting the shared helper is followup on that file's refactor. Doc-only. 26/26 tests pass; typecheck clean; marker guard clean. Co-Authored-By: Claude Opus 4.7 --- packages/opencode/src/plugin/codex.ts | 17 +++++++++++------ .../test/plugin/codex-allowlist.test.ts | 17 ++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts index 7f4c4b6507..0ff493ff15 100644 --- a/packages/opencode/src/plugin/codex.ts +++ b/packages/opencode/src/plugin/codex.ts @@ -30,12 +30,17 @@ export const OAUTH_ALLOWED_MODELS = new Set([ "gpt-5.6", ]) -/** Single source of truth for OAuth (ChatGPT-subscription) model filtering. - * A model is kept if either (a) its id contains ``"codex"`` (all codex - * variants ship on the subscription), or (b) its id is an exact member of - * ``OAUTH_ALLOWED_MODELS`` (the curated non-codex releases). Reused across - * plugin/codex.ts and plugin/openai/codex.ts to prevent drift between the - * two implementations during the in-flight refactor. */ +/** OAuth (ChatGPT-subscription) model-filter policy for the ACTIVE plugin + * (this file — wired via plugin/index.ts). A model is kept if either + * (a) its id contains ``"codex"`` (all codex variants ship on the + * subscription), or (b) its id is an exact member of + * ``OAUTH_ALLOWED_MODELS`` (the curated non-codex releases). + * + * The sibling file plugin/openai/codex.ts (an in-progress refactor, + * currently NOT wired) has its own separate filter with a + * ``parseFloat(match[1]) > 5.4`` fallback. Adopting this helper is + * followup work on that refactor — do NOT assume the two files share + * this policy today. */ export function shouldAllowOAuthModel(modelId: string): boolean { if (modelId.includes("codex")) return true return OAUTH_ALLOWED_MODELS.has(modelId) diff --git a/packages/opencode/test/plugin/codex-allowlist.test.ts b/packages/opencode/test/plugin/codex-allowlist.test.ts index 726d63acfe..52ef8c7f72 100644 --- a/packages/opencode/test/plugin/codex-allowlist.test.ts +++ b/packages/opencode/test/plugin/codex-allowlist.test.ts @@ -1,16 +1,19 @@ // Regression coverage for the ChatGPT-subscription (OAuth) model filter -// in packages/opencode/src/plugin/codex.ts (the ACTIVE plugin wired via -// plugin/index.ts). The sibling file plugin/openai/codex.ts is an -// in-progress refactor that reuses ``shouldAllowOAuthModel`` from this -// same module — so the filter behavior is tested once here. +// in packages/opencode/src/plugin/codex.ts — the ACTIVE plugin wired +// via plugin/index.ts. // // Filed as issue #1132: GPT 5.6 was released but the allowlist stopped // at 5.4, so users on ChatGPT Pro/Plus (Codex tier) couldn't pick it in // the model picker even though the underlying models.dev catalog had it. // -// Sibling test file test/plugin/codex.test.ts covers the OAuth-flow + -// JWT parsing internals of plugin/openai/codex.ts. This file covers -// only the OAuth model-filter policy shared by both files. +// Sibling file plugin/openai/codex.ts is an in-progress refactor of the +// same plugin, currently NOT wired via plugin/index.ts, and NOT covered +// by this file — it has its own separate ``ALLOWED_MODELS`` + a +// ``parseFloat > 5.4`` fallback in its ``models()`` filter, and its +// existing test file (test/plugin/codex.test.ts) already covers its +// OAuth-flow + JWT parsing internals. When that refactor is wired, +// adopting ``shouldAllowOAuthModel`` here (and expanding this file's +// coverage to the newly-active filter) is followup work. import { describe, expect, test } from "bun:test" import { OAUTH_ALLOWED_MODELS, shouldAllowOAuthModel } from "../../src/plugin/codex" From aa4a956b44e08de54208bce25105b07824eed710 Mon Sep 17 00:00:00 2001 From: Haider Date: Tue, 25 Aug 2026 00:49:43 +0530 Subject: [PATCH 4/4] docs(codex): correct loader comment (was still claiming shared policy) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round 4 doc fix on #1133. My previous docstring fix on `shouldAllowOAuthModel` correctly noted that plugin/openai/codex.ts has its own separate filter, but the LOADER comment 5 lines below still said "this filter and the sibling in plugin/openai/codex.ts share one source of truth" — kilo + cubic both flagged the contradiction independently. Rewrote the loader comment to match the helper docstring: this file is the active plugin, the sibling is an unwired refactor with its own ALLOWED_MODELS + parseFloat > 5.4 fallback, they do NOT share a source of truth today. Doc-only. 26/26 tests pass; typecheck clean; marker guard clean. Co-Authored-By: Claude Opus 4.7 --- packages/opencode/src/plugin/codex.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/plugin/codex.ts b/packages/opencode/src/plugin/codex.ts index 0ff493ff15..ac89dab06a 100644 --- a/packages/opencode/src/plugin/codex.ts +++ b/packages/opencode/src/plugin/codex.ts @@ -429,10 +429,15 @@ export async function CodexAuthPlugin(input: PluginInput): Promise { if (auth.type !== "oauth") return {} // Filter models to only those the ChatGPT-subscription (Codex) tier - // accepts. Delegates to ``shouldAllowOAuthModel`` (module-level, above) - // so this filter and the sibling in plugin/openai/codex.ts share one - // source of truth. See OAUTH_ALLOWED_MODELS + shouldAllowOAuthModel - // for the criteria + how to add new gpt-5.N releases. + // accepts. Delegates to ``shouldAllowOAuthModel`` (module-level, + // above). See OAUTH_ALLOWED_MODELS + shouldAllowOAuthModel for the + // criteria + how to add new gpt-5.N releases. + // + // NOTE: this file is the ACTIVE plugin (wired via plugin/index.ts). + // The sibling plugin/openai/codex.ts is an unwired in-progress + // refactor that keeps its OWN ALLOWED_MODELS + parseFloat > 5.4 + // fallback — this filter does NOT share a source of truth with it. + // Adopting shouldAllowOAuthModel there is followup on that refactor. // (Closes #1132 — GPT 5.6 missing from picker.) for (const modelId of Object.keys(provider.models)) { if (!shouldAllowOAuthModel(modelId)) delete provider.models[modelId]