From a42d8d7be256da74b2da893a07cd5f04124ad5b4 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sat, 7 Mar 2026 21:29:58 +0000 Subject: [PATCH 1/2] feat: add GPT-5.4 and GPT-5.4-Codex to OpenAI Codex (ChatGPT Plus/Pro) provider --- packages/types/src/providers/openai-codex.ts | 32 ++++++++++- .../providers/__tests__/openai-codex.spec.ts | 53 ++++++++++++++----- 2 files changed, 71 insertions(+), 14 deletions(-) diff --git a/packages/types/src/providers/openai-codex.ts b/packages/types/src/providers/openai-codex.ts index f8d9bd25df3..b79d20d9a70 100644 --- a/packages/types/src/providers/openai-codex.ts +++ b/packages/types/src/providers/openai-codex.ts @@ -16,7 +16,7 @@ import type { ModelInfo } from "../model.js" export type OpenAiCodexModelId = keyof typeof openAiCodexModels -export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.3-codex" +export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.4-codex" /** * Models available through the Codex OAuth flow. @@ -24,6 +24,36 @@ export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.3-codex" * Costs are 0 as they are covered by the subscription. */ export const openAiCodexModels = { + "gpt-5.4-codex": { + maxTokens: 128000, + contextWindow: 1_050_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["low", "medium", "high", "xhigh"], + reasoningEffort: "medium", + inputPrice: 0, + outputPrice: 0, + supportsTemperature: false, + description: + "GPT-5.4 Codex: OpenAI's latest flagship coding model with 1M token context via ChatGPT subscription", + }, + "gpt-5.4": { + maxTokens: 128000, + contextWindow: 1_050_000, + includedTools: ["apply_patch"], + excludedTools: ["apply_diff", "write_to_file"], + supportsImages: true, + supportsPromptCache: true, + supportsReasoningEffort: ["none", "low", "medium", "high", "xhigh"], + reasoningEffort: "none", + inputPrice: 0, + outputPrice: 0, + supportsVerbosity: true, + supportsTemperature: false, + description: "GPT-5.4: Most capable model with upfront planning and deep reasoning via ChatGPT subscription", + }, "gpt-5.1-codex-max": { maxTokens: 128000, contextWindow: 400000, diff --git a/src/api/providers/__tests__/openai-codex.spec.ts b/src/api/providers/__tests__/openai-codex.spec.ts index 2e164fe469f..a936fc86a41 100644 --- a/src/api/providers/__tests__/openai-codex.spec.ts +++ b/src/api/providers/__tests__/openai-codex.spec.ts @@ -3,27 +3,54 @@ import { OpenAiCodexHandler } from "../openai-codex" describe("OpenAiCodexHandler.getModel", () => { - it.each(["gpt-5.1", "gpt-5", "gpt-5.1-codex", "gpt-5-codex", "gpt-5-codex-mini", "gpt-5.3-codex-spark"])( - "should return specified model when a valid model id is provided: %s", - (apiModelId) => { - const handler = new OpenAiCodexHandler({ apiModelId }) - const model = handler.getModel() - - expect(model.id).toBe(apiModelId) - expect(model.info).toBeDefined() - // Default reasoning effort for GPT-5 family - expect(model.info.reasoningEffort).toBe("medium") - }, - ) + it.each([ + "gpt-5.1", + "gpt-5", + "gpt-5.1-codex", + "gpt-5-codex", + "gpt-5-codex-mini", + "gpt-5.3-codex-spark", + "gpt-5.4-codex", + ])("should return specified model when a valid model id is provided: %s", (apiModelId) => { + const handler = new OpenAiCodexHandler({ apiModelId }) + const model = handler.getModel() + + expect(model.id).toBe(apiModelId) + expect(model.info).toBeDefined() + // Default reasoning effort for GPT-5 family + expect(model.info.reasoningEffort).toBe("medium") + }) it("should fall back to default model when an invalid model id is provided", () => { const handler = new OpenAiCodexHandler({ apiModelId: "not-a-real-model" }) const model = handler.getModel() - expect(model.id).toBe("gpt-5.3-codex") + expect(model.id).toBe("gpt-5.4-codex") expect(model.info).toBeDefined() }) + it("should use GPT-5.4 with thinking/non-thinking reasoning effort levels", () => { + const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.4" }) + const model = handler.getModel() + + expect(model.id).toBe("gpt-5.4") + expect(model.info.contextWindow).toBe(1_050_000) + expect(model.info.supportsReasoningEffort).toContain("none") + expect(model.info.supportsReasoningEffort).toContain("xhigh") + expect(model.info.reasoningEffort).toBe("none") + }) + + it("should use GPT-5.4 Codex with 1M token context window", () => { + const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.4-codex" }) + const model = handler.getModel() + + expect(model.id).toBe("gpt-5.4-codex") + expect(model.info.contextWindow).toBe(1_050_000) + expect(model.info.reasoningEffort).toBe("medium") + expect(model.info.inputPrice).toBe(0) + expect(model.info.outputPrice).toBe(0) + }) + it("should use Spark-specific limits and capabilities", () => { const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.3-codex-spark" }) const model = handler.getModel() From 8357f330a0d9e36091bc7fd6f9f503f1ff5f619a Mon Sep 17 00:00:00 2001 From: Hannes Rudolph Date: Sat, 7 Mar 2026 18:58:48 -0700 Subject: [PATCH 2/2] fix: remove gpt-5.4-codex (does not exist), update default to gpt-5.4, fix minimal->none --- packages/types/src/providers/openai-codex.ts | 19 ++----------------- .../providers/__tests__/openai-codex.spec.ts | 14 +------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/packages/types/src/providers/openai-codex.ts b/packages/types/src/providers/openai-codex.ts index b79d20d9a70..fd1d80198c3 100644 --- a/packages/types/src/providers/openai-codex.ts +++ b/packages/types/src/providers/openai-codex.ts @@ -16,7 +16,7 @@ import type { ModelInfo } from "../model.js" export type OpenAiCodexModelId = keyof typeof openAiCodexModels -export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.4-codex" +export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.4" /** * Models available through the Codex OAuth flow. @@ -24,21 +24,6 @@ export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.4-codex" * Costs are 0 as they are covered by the subscription. */ export const openAiCodexModels = { - "gpt-5.4-codex": { - maxTokens: 128000, - contextWindow: 1_050_000, - includedTools: ["apply_patch"], - excludedTools: ["apply_diff", "write_to_file"], - supportsImages: true, - supportsPromptCache: true, - supportsReasoningEffort: ["low", "medium", "high", "xhigh"], - reasoningEffort: "medium", - inputPrice: 0, - outputPrice: 0, - supportsTemperature: false, - description: - "GPT-5.4 Codex: OpenAI's latest flagship coding model with 1M token context via ChatGPT subscription", - }, "gpt-5.4": { maxTokens: 128000, contextWindow: 1_050_000, @@ -149,7 +134,7 @@ export const openAiCodexModels = { excludedTools: ["apply_diff", "write_to_file"], supportsImages: true, supportsPromptCache: true, - supportsReasoningEffort: ["minimal", "low", "medium", "high"], + supportsReasoningEffort: ["none", "low", "medium", "high"], reasoningEffort: "medium", // Subscription-based: no per-token costs inputPrice: 0, diff --git a/src/api/providers/__tests__/openai-codex.spec.ts b/src/api/providers/__tests__/openai-codex.spec.ts index a936fc86a41..2e4ad110dd7 100644 --- a/src/api/providers/__tests__/openai-codex.spec.ts +++ b/src/api/providers/__tests__/openai-codex.spec.ts @@ -10,7 +10,6 @@ describe("OpenAiCodexHandler.getModel", () => { "gpt-5-codex", "gpt-5-codex-mini", "gpt-5.3-codex-spark", - "gpt-5.4-codex", ])("should return specified model when a valid model id is provided: %s", (apiModelId) => { const handler = new OpenAiCodexHandler({ apiModelId }) const model = handler.getModel() @@ -25,7 +24,7 @@ describe("OpenAiCodexHandler.getModel", () => { const handler = new OpenAiCodexHandler({ apiModelId: "not-a-real-model" }) const model = handler.getModel() - expect(model.id).toBe("gpt-5.4-codex") + expect(model.id).toBe("gpt-5.4") expect(model.info).toBeDefined() }) @@ -40,17 +39,6 @@ describe("OpenAiCodexHandler.getModel", () => { expect(model.info.reasoningEffort).toBe("none") }) - it("should use GPT-5.4 Codex with 1M token context window", () => { - const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.4-codex" }) - const model = handler.getModel() - - expect(model.id).toBe("gpt-5.4-codex") - expect(model.info.contextWindow).toBe(1_050_000) - expect(model.info.reasoningEffort).toBe("medium") - expect(model.info.inputPrice).toBe(0) - expect(model.info.outputPrice).toBe(0) - }) - it("should use Spark-specific limits and capabilities", () => { const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.3-codex-spark" }) const model = handler.getModel()