diff --git a/src/common/constants/codexOAuth.test.ts b/src/common/constants/codexOAuth.test.ts index c6725b9455..eafd6c04c6 100644 --- a/src/common/constants/codexOAuth.test.ts +++ b/src/common/constants/codexOAuth.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from "bun:test"; import { + getCodexOauthContextWindowOverride, isCodexOauthAllowedModel, isCodexOauthAllowedModelId, isCodexOauthRequiredModel, @@ -21,11 +22,20 @@ describe("codexOAuth model gating", () => { it("allows the GPT-5.6 family through Codex OAuth without requiring it", () => { // Includes the bare alias: it is a servable model id (OpenAI routes it to Sol). - for (const model of ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]) { + const contextLimits = { + "gpt-5.6": 272_000, + "gpt-5.6-sol": 272_000, + "gpt-5.6-terra": 128_000, + "gpt-5.6-luna": 128_000, + } as const; + + for (const [model, contextLimit] of Object.entries(contextLimits)) { expect(isCodexOauthAllowedModelId(model)).toBe(true); expect(isCodexOauthAllowedModelId(`openai:${model}`)).toBe(true); expect(isCodexOauthRequiredModelId(model)).toBe(false); expect(isCodexOauthRequiredModelId(`openai:${model}`)).toBe(false); + expect(getCodexOauthContextWindowOverride(model)).toBe(contextLimit); + expect(getCodexOauthContextWindowOverride(`openai:${model}`)).toBe(contextLimit); } }); diff --git a/src/common/constants/codexOAuth.ts b/src/common/constants/codexOAuth.ts index 75f591088e..d83dc9c015 100644 --- a/src/common/constants/codexOAuth.ts +++ b/src/common/constants/codexOAuth.ts @@ -131,9 +131,14 @@ export const CODEX_OAUTH_REQUIRED_MODELS = new Set([ * still use the public OpenAI limits. */ const CODEX_OAUTH_CONTEXT_WINDOW_OVERRIDES: Record = { - // User-reported routing limit: GPT-5.5's public API window is 1.05M, but the - // ChatGPT/Codex OAuth backend rejects prompts near that size and must compact at ~270K. + // The public API exposes a 1.05M window for these models, but the ChatGPT/Codex + // OAuth routing layer has smaller tier-specific limits. Keep the auth-route caps + // separate from model metadata so API-key requests retain the full public window. "gpt-5.5": 272_000, + "gpt-5.6": 272_000, + "gpt-5.6-sol": 272_000, + "gpt-5.6-terra": 128_000, + "gpt-5.6-luna": 128_000, }; function normalizeCodexOauthModelId(modelId: string): string { diff --git a/src/common/utils/compaction/contextLimit.test.ts b/src/common/utils/compaction/contextLimit.test.ts index fcf7703f2f..58f7d9b5f6 100644 --- a/src/common/utils/compaction/contextLimit.test.ts +++ b/src/common/utils/compaction/contextLimit.test.ts @@ -77,9 +77,6 @@ describe("getEffectiveContextLimit", () => { expect(defaultOauthLimit).toBe(272_000); }); - // Pinned to the literal "gpt-5.5" (not KNOWN_MODELS.GPT.id): the GPT alias now - // tracks gpt-5.6-sol, which has no Codex OAuth context override, while the cap - // under test belongs to the retired-but-still-priced gpt-5.5 model string. test("inherits the Codex OAuth context cap from a mapped OpenAI model", () => { const limit = getEffectiveContextLimit( "openai:team-gpt", @@ -93,13 +90,22 @@ describe("getEffectiveContextLimit", () => { expect(limit).toBe(272_000); }); - test("does not cap GPT-5.6 Sol under Codex OAuth (no context-window override published)", () => { - const oauthOnlyLimit = getEffectiveContextLimit( - "openai:gpt-5.6-sol", - false, - providersWithOpenAI({ codexOauthSet: true }) - ); - expect(oauthOnlyLimit).toBe(1_050_000); + test("caps the GPT-5.6 family at each tier's Codex OAuth context window", () => { + const contextLimits = { + "gpt-5.6": 272_000, + "gpt-5.6-sol": 272_000, + "gpt-5.6-terra": 128_000, + "gpt-5.6-luna": 128_000, + } as const; + + for (const [model, contextLimit] of Object.entries(contextLimits)) { + const oauthOnlyLimit = getEffectiveContextLimit( + `openai:${model}`, + false, + providersWithOpenAI({ codexOauthSet: true }) + ); + expect(oauthOnlyLimit).toBe(contextLimit); + } }); test("does not apply the GPT-5.5 OAuth cap to gateway-routed models", () => { diff --git a/src/common/utils/tokens/tokenMeterUtils.test.ts b/src/common/utils/tokens/tokenMeterUtils.test.ts index b6c0be88cf..56b7579449 100644 --- a/src/common/utils/tokens/tokenMeterUtils.test.ts +++ b/src/common/utils/tokens/tokenMeterUtils.test.ts @@ -77,8 +77,6 @@ describe("calculateTokenMeterData", () => { }); test("uses the Codex OAuth cap for GPT-5.5 token meter percentages", () => { - // Pin to the literal model string: gpt-5.5's 272K Codex OAuth cap remains in - // production even though KNOWN_MODELS.GPT now points at gpt-5.6-sol. const result = calculateTokenMeterData(SAMPLE_USAGE, "openai:gpt-5.5", false, false, { openai: { apiKeySet: false, @@ -92,7 +90,7 @@ describe("calculateTokenMeterData", () => { expect(result.totalPercentage).toBeCloseTo((11_000 / 272_000) * 100); }); - test("does not cap GPT-5.6 Sol under Codex OAuth (no context-window override published)", () => { + test("uses the Codex OAuth cap for GPT-5.6 token meter percentages", () => { const result = calculateTokenMeterData(SAMPLE_USAGE, "openai:gpt-5.6-sol", false, false, { openai: { apiKeySet: false, @@ -102,9 +100,8 @@ describe("calculateTokenMeterData", () => { }, }); - // GA model page: 1.05M-token context window for every GPT-5.6 tier. - expect(result.maxTokens).toBe(1_050_000); - expect(result.totalPercentage).toBeCloseTo((11_000 / 1_050_000) * 100); + expect(result.maxTokens).toBe(272_000); + expect(result.totalPercentage).toBeCloseTo((11_000 / 272_000) * 100); }); test("uses Claude Sonnet 4.6's native 1M context even when the beta toggle is off", () => {