Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/common/constants/codexOAuth.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, it } from "bun:test";
import {
getCodexOauthContextWindowOverride,
isCodexOauthAllowedModel,
isCodexOauthAllowedModelId,
isCodexOauthRequiredModel,
Expand All @@ -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);
}
});

Expand Down
9 changes: 7 additions & 2 deletions src/common/constants/codexOAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,14 @@ export const CODEX_OAUTH_REQUIRED_MODELS = new Set<string>([
* still use the public OpenAI limits.
*/
const CODEX_OAUTH_CONTEXT_WINDOW_OVERRIDES: Record<string, number> = {
// 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 {
Expand Down
26 changes: 16 additions & 10 deletions src/common/utils/compaction/contextLimit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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", () => {
Expand Down
9 changes: 3 additions & 6 deletions src/common/utils/tokens/tokenMeterUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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", () => {
Expand Down
Loading