feat: add GPT-5.4 and GPT-5.4-Codex to OpenAI Codex (ChatGPT Plus/Pro) provider

This commit is contained in:
Roo Code 2026-03-07 21:29:58 +00:00
parent 0892455db2
commit a42d8d7be2
2 changed files with 70 additions and 13 deletions

View file

@ -16,7 +16,7 @@ import type { ModelInfo } from "../model.js"
export type OpenAiCodexModelId = keyof typeof openAiCodexModels 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. * 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. * Costs are 0 as they are covered by the subscription.
*/ */
export const openAiCodexModels = { 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": { "gpt-5.1-codex-max": {
maxTokens: 128000, maxTokens: 128000,
contextWindow: 400000, contextWindow: 400000,

View file

@ -3,27 +3,54 @@
import { OpenAiCodexHandler } from "../openai-codex" import { OpenAiCodexHandler } from "../openai-codex"
describe("OpenAiCodexHandler.getModel", () => { 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"])( it.each([
"should return specified model when a valid model id is provided: %s", "gpt-5.1",
(apiModelId) => { "gpt-5",
const handler = new OpenAiCodexHandler({ apiModelId }) "gpt-5.1-codex",
const model = handler.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()
expect(model.id).toBe(apiModelId) expect(model.id).toBe(apiModelId)
expect(model.info).toBeDefined() expect(model.info).toBeDefined()
// Default reasoning effort for GPT-5 family // Default reasoning effort for GPT-5 family
expect(model.info.reasoningEffort).toBe("medium") expect(model.info.reasoningEffort).toBe("medium")
}, })
)
it("should fall back to default model when an invalid model id is provided", () => { it("should fall back to default model when an invalid model id is provided", () => {
const handler = new OpenAiCodexHandler({ apiModelId: "not-a-real-model" }) const handler = new OpenAiCodexHandler({ apiModelId: "not-a-real-model" })
const model = handler.getModel() const model = handler.getModel()
expect(model.id).toBe("gpt-5.3-codex") expect(model.id).toBe("gpt-5.4-codex")
expect(model.info).toBeDefined() 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", () => { it("should use Spark-specific limits and capabilities", () => {
const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.3-codex-spark" }) const handler = new OpenAiCodexHandler({ apiModelId: "gpt-5.3-codex-spark" })
const model = handler.getModel() const model = handler.getModel()