diff --git a/docs/concepts/unified-interface.md b/docs/concepts/unified-interface.md index 55d9d4fc..db1b793d 100644 --- a/docs/concepts/unified-interface.md +++ b/docs/concepts/unified-interface.md @@ -61,6 +61,8 @@ The only required change is model selection. Everything else stays unchanged. | Model | Alias | |---|---| +| GPT-5.4 | `gpt-5.4` | +| GPT-5.4 Pro | `gpt-5.4-pro` | | GPT-5.3 Codex | `gpt-5.3-codex` | | GPT-5.3 Codex Spark | `gpt-5.3-codex-spark` | | GPT-5.2 Codex | `gpt-5.2-codex` | @@ -76,7 +78,7 @@ The only required change is model selection. Everything else stays unchanged. Locus infers the provider from the model name: 1. Known Claude aliases (`opus`, `sonnet`, `haiku`) → Claude -2. Known Codex aliases → Codex +2. Known Codex models (`gpt-5.4`, `gpt-5.4-pro`, `gpt-5.3-codex`, etc.) → Codex 3. Model name starts with `claude-` → Claude 4. Model name contains `codex` → Codex diff --git a/packages/cli/__tests__/codex-runner.test.ts b/packages/cli/__tests__/codex-runner.test.ts index 5f0fffb5..5c39335f 100644 --- a/packages/cli/__tests__/codex-runner.test.ts +++ b/packages/cli/__tests__/codex-runner.test.ts @@ -20,4 +20,20 @@ describe("buildCodexArgs", () => { expect(args).not.toContain("--approval-mode"); expect(args.at(-1)).toBe("-"); }); + + test("includes gpt-5.4 model", () => { + const args = buildCodexArgs("gpt-5.4"); + + expect(args).toContain("--model"); + expect(args).toContain("gpt-5.4"); + expect(args.at(-1)).toBe("-"); + }); + + test("includes gpt-5.4-pro model", () => { + const args = buildCodexArgs("gpt-5.4-pro"); + + expect(args).toContain("--model"); + expect(args).toContain("gpt-5.4-pro"); + expect(args.at(-1)).toBe("-"); + }); }); diff --git a/packages/cli/__tests__/config.test.ts b/packages/cli/__tests__/config.test.ts index be715396..9aaccedb 100644 --- a/packages/cli/__tests__/config.test.ts +++ b/packages/cli/__tests__/config.test.ts @@ -118,6 +118,17 @@ describe("config", () => { expect(config.ai.provider).toBe("codex"); expect(config.ai.model).toBe("gpt-5.3-codex"); }); + + it("infers codex provider from gpt-5.4 model on load", () => { + setupProject({ + version: "3.0.0", + github: { owner: "custom", repo: "mine", defaultBranch: "develop" }, + ai: { provider: "claude", model: "gpt-5.4" }, + }); + const config = loadConfig(TEST_DIR); + expect(config.ai.provider).toBe("codex"); + expect(config.ai.model).toBe("gpt-5.4"); + }); }); describe("saveConfig", () => { @@ -175,6 +186,20 @@ describe("config", () => { expect(updated.ai.provider).toBe("codex"); }); + it("updates provider when model changes to gpt-5.4", () => { + setupProject(); + const updated = updateConfigValue(TEST_DIR, "ai.model", "gpt-5.4"); + expect(updated.ai.model).toBe("gpt-5.4"); + expect(updated.ai.provider).toBe("codex"); + }); + + it("updates provider when model changes to gpt-5.4-pro", () => { + setupProject(); + const updated = updateConfigValue(TEST_DIR, "ai.model", "gpt-5.4-pro"); + expect(updated.ai.model).toBe("gpt-5.4-pro"); + expect(updated.ai.provider).toBe("codex"); + }); + it("auto-coerces string 'true' to boolean", () => { setupProject(); const updated = updateConfigValue(TEST_DIR, "agent.autoLabel", "false"); diff --git a/packages/cli/__tests__/repl-model-config.test.ts b/packages/cli/__tests__/repl-model-config.test.ts index b6e3388b..7ef66836 100644 --- a/packages/cli/__tests__/repl-model-config.test.ts +++ b/packages/cli/__tests__/repl-model-config.test.ts @@ -43,4 +43,17 @@ describe("repl model config persistence", () => { expect(reloaded.ai.model).toBe("gpt-5.3-codex"); expect(reloaded.ai.provider).toBe("codex"); }); + + it("persists gpt-5.4 model and infers codex provider", () => { + const inMemoryConfig = loadConfig(TEST_DIR); + + persistReplModelSelection(TEST_DIR, inMemoryConfig, "gpt-5.4"); + + expect(inMemoryConfig.ai.model).toBe("gpt-5.4"); + expect(inMemoryConfig.ai.provider).toBe("codex"); + + const reloaded = loadConfig(TEST_DIR); + expect(reloaded.ai.model).toBe("gpt-5.4"); + expect(reloaded.ai.provider).toBe("codex"); + }); }); diff --git a/packages/cli/src/core/ai-models.ts b/packages/cli/src/core/ai-models.ts index b12890f8..7cd7f3ab 100644 --- a/packages/cli/src/core/ai-models.ts +++ b/packages/cli/src/core/ai-models.ts @@ -13,6 +13,8 @@ const CLAUDE_MODELS = [ ] as const; const CODEX_MODELS = [ + "gpt-5.4", + "gpt-5.4-pro", "gpt-5.3-codex", "gpt-5.3-codex-spark", "gpt-5.2-codex",