diff --git a/src/lib/ai/__tests__/codex-slug-fallback.test.ts b/src/lib/ai/__tests__/codex-slug-fallback.test.ts index d6de7e3a7..98c8c2a9d 100644 --- a/src/lib/ai/__tests__/codex-slug-fallback.test.ts +++ b/src/lib/ai/__tests__/codex-slug-fallback.test.ts @@ -337,6 +337,39 @@ describe("Codex slug fallback chain", () => { expect(helper(400, "unrelated 400")).toBe(false); }); + it("DEFAULT_SLUG_FALLBACK_CHAIN tracks the current ChatGPT-auth ladder", () => { + // The backend rotated its ChatGPT-auth slugs onto the gpt-5.x line on + // 2026-06-02; the in-code default must match the accepted set, in order. + expect([...__test.DEFAULT_SLUG_FALLBACK_CHAIN]).toEqual([ + "gpt-5.5", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.3-codex", + "gpt-5.2", + ]); + }); + + it("loadFallbackChain falls back to the default ladder with no env override", () => { + const origModel = process.env.CODEX_MODEL; + const origChain = process.env.CODEX_MODEL_FALLBACK_CHAIN; + delete process.env.CODEX_MODEL; + delete process.env.CODEX_MODEL_FALLBACK_CHAIN; + try { + expect(__test.loadFallbackChain()).toEqual([ + "gpt-5.5", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.3-codex", + "gpt-5.2", + ]); + } finally { + if (origModel === undefined) delete process.env.CODEX_MODEL; + else process.env.CODEX_MODEL = origModel; + if (origChain === undefined) delete process.env.CODEX_MODEL_FALLBACK_CHAIN; + else process.env.CODEX_MODEL_FALLBACK_CHAIN = origChain; + } + }); + it("loadFallbackChain folds CODEX_MODEL into position 0", () => { const orig = process.env.CODEX_MODEL; process.env.CODEX_MODEL = "custom-pinned-slug"; @@ -344,7 +377,7 @@ describe("Codex slug fallback chain", () => { const chain = __test.loadFallbackChain(); expect(chain[0]).toBe("custom-pinned-slug"); // Defaults still present after position 0. - expect(chain).toContain("gpt-5.3-codex"); + expect(chain).toContain("gpt-5.5"); // No duplicates. const seen = new Set(chain); expect(seen.size).toBe(chain.length); diff --git a/src/lib/ai/codex-client.ts b/src/lib/ai/codex-client.ts index 0309abcdd..1c0c6b375 100644 --- a/src/lib/ai/codex-client.ts +++ b/src/lib/ai/codex-client.ts @@ -33,16 +33,23 @@ import { const CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses"; /** - * Default fallback chain — most-current-first as of 2026-05-09. Override + * Default fallback chain — most-current-first as of 2026-06-02. Override * via `CODEX_MODEL_FALLBACK_CHAIN` (comma-separated) on apps01 if a * specific plan ladder needs different ordering. `CODEX_MODEL` is * folded into position 0 of the chain when set; duplicates are dropped. + * + * The ChatGPT Codex backend rotated its ChatGPT-auth slugs off the + * `-codex` specialist line onto the plain `gpt-5.x` line on 2026-06-02; + * the former `-codex` defaults are now rejected with a 503 "all + * configured Codex slugs were rejected". The ladder below tracks the + * current accepted set. */ const DEFAULT_SLUG_FALLBACK_CHAIN = [ - "gpt-5.3-codex", // verified accepted on Plus/Pro 2026-05-09 - "gpt-5-codex", // historical default — kept as second-chance retry; backend may flip back - "gpt-5", // bare slug — rejected on ChatGPT-auth as of 2026-05; safe to keep as ladder-rung - "gpt-4o", // last-ditch capability fallback + "gpt-5.5", // current default across paid tiers as of 2026-06-02 + "gpt-5.4", // documented fallback + "gpt-5.4-mini", // documented lighter-weight fallback + "gpt-5.3-codex", // late rung — still accepted intermittently + "gpt-5.2", // legacy floor ] as const; function loadFallbackChain(): string[] {