From f7bdbccf80755b4b2a09dc2550009773ee5129b3 Mon Sep 17 00:00:00 2001 From: Jacob Kim Date: Fri, 10 Jul 2026 09:48:10 +0900 Subject: [PATCH] feat(providers): adopt gpt-5.6 model family and new codex effort tiers - Replace the Codex picker lineup with gpt-5.6-sol/terra/luna plus gpt-5.5 as the previous-generation fallback; gpt-5.4 variants and codex-spark move to legacy display names only - Make gpt-5.6-terra the Codex default model (shortcuts, presets, recommended group) and switch the turn-summary light model to gpt-5.6-luna - Extend codexReasoningEffort with max/ultra across provider types, IPC schemas, store settings, effort cycle, and the settings picker; drop legacy minimal from selectable options while still validating and normalizing persisted values to low - Claude effort scale reviewed: no new tiers upstream, no changes needed Co-Authored-By: Claude Fable 5 --- docs/features/command-palette.md | 4 +- .../features/workspace-latest-turn-summary.md | 2 +- docs/providers/provider-runtimes.md | 13 +++-- electron/main/ipc/schemas.ts | 2 + src/components/ai-elements/prompt-input.tsx | 2 +- src/components/session/chat-input.runtime.ts | 5 +- src/lib/providers/codex-runtime-options.ts | 4 +- src/lib/providers/model-catalog.ts | 58 ++++++++++--------- src/lib/providers/model-shortcuts.ts | 4 +- src/lib/providers/provider.types.ts | 11 +++- src/lib/providers/runtime-option-contract.ts | 6 +- src/lib/task-presets.ts | 12 ++-- src/store/app.store.ts | 11 +++- tests/chat-input.runtime.test.ts | 8 ++- tests/codex-runtime-options.test.ts | 24 ++++++++ tests/ipc-schemas.test.ts | 14 +++++ tests/model-catalog.test.ts | 28 +++++++-- tests/model-selector-utils.test.ts | 20 +++---- tests/model-shortcuts.test.ts | 6 +- tests/task-presets.test.ts | 2 +- 20 files changed, 165 insertions(+), 71 deletions(-) diff --git a/docs/features/command-palette.md b/docs/features/command-palette.md index b3bcc5c..cd9873b 100644 --- a/docs/features/command-palette.md +++ b/docs/features/command-palette.md @@ -88,8 +88,8 @@ This is usually faster than opening Settings and browsing manually. Default bindings: - `Alt+1` → `Claude Opus 4.8` -- `Alt+2` → `GPT-5.5` -- `Alt+3` → `GPT-5.4` +- `Alt+2` → `GPT-5.6 Terra` +- `Alt+3` → `GPT-5.6 Sol` ### Work Mostly From The Keyboard diff --git a/docs/features/workspace-latest-turn-summary.md b/docs/features/workspace-latest-turn-summary.md index 164c087..2e4dd5c 100644 --- a/docs/features/workspace-latest-turn-summary.md +++ b/docs/features/workspace-latest-turn-summary.md @@ -64,7 +64,7 @@ This rendered example shows the Information panel with the latest-turn summary p ```json { - "workspaceTurnSummaryPrimaryModel": "gpt-5.4-mini", + "workspaceTurnSummaryPrimaryModel": "gpt-5.6-luna", "workspaceTurnSummaryFallbackModel": "claude-haiku-4-5" } ``` diff --git a/docs/providers/provider-runtimes.md b/docs/providers/provider-runtimes.md index 3c6c380..1f740d7 100644 --- a/docs/providers/provider-runtimes.md +++ b/docs/providers/provider-runtimes.md @@ -251,12 +251,15 @@ If you want the user-facing setup workflow instead of the runtime internals, use - `untrusted`: App Server-aligned low-friction default; pause only for actions treated as untrusted. - `on-request`: ask when approval is needed. - `reasoning effort` - - `minimal` / `low`: fastest. + - `low`: fastest. - `medium`: balanced default. - `high` / `xhigh`: slower, more deliberate. - - Codex App Server turns normalize `minimal` to `low` because the current - upstream model API rejects built-in tools such as `image_gen` and - `web_search` with `reasoning.effort = minimal`. + - `max` / `ultra`: deepest reasoning tiers introduced with the GPT-5.6 + Codex CLI scale. + - `minimal` is a legacy persisted value that is no longer selectable in the + UI; Codex App Server turns normalize it to `low` because the upstream + model API rejects built-in tools such as `image_gen` and `web_search` + with `reasoning.effort = minimal`. - `reasoning summary` - `auto`: let Codex decide. - `concise`: short summary. @@ -283,7 +286,7 @@ When a task switches from one Codex model to another, Stave does not attempt to - Codex App Server transport: local `codex app-server` from Codex CLI `0.142.0` - Codex CLI baseline: `0.142.0` -- Current Stave-supported Codex model IDs: `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex-spark` +- Current Stave-supported Codex model IDs: `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5` (default: `gpt-5.6-terra`) Stave requires a user-installed Codex CLI (`codex` ≥ 0.142.0). Users must have Codex CLI available in their PATH or configured via `runtimeOptions.codexBinaryPath` / `STAVE_CODEX_CLI_PATH`. A user-configured binary path still takes precedence over auto-discovery. diff --git a/electron/main/ipc/schemas.ts b/electron/main/ipc/schemas.ts index ba53150..e97c6e3 100644 --- a/electron/main/ipc/schemas.ts +++ b/electron/main/ipc/schemas.ts @@ -392,6 +392,8 @@ export const RuntimeOptionsObjectSchema = z z.literal("medium"), z.literal("high"), z.literal("xhigh"), + z.literal("max"), + z.literal("ultra"), ]) .optional(), codexWebSearch: z diff --git a/src/components/ai-elements/prompt-input.tsx b/src/components/ai-elements/prompt-input.tsx index 2a05596..79ba1e7 100644 --- a/src/components/ai-elements/prompt-input.tsx +++ b/src/components/ai-elements/prompt-input.tsx @@ -300,7 +300,7 @@ function getPromptToolbarAccentClass( } function isHighestEffortValue(value?: string) { - return value === "max" || value === "xhigh"; + return value === "ultra" || value === "max" || value === "xhigh"; } function getEffortIconToneClass(value?: string) { diff --git a/src/components/session/chat-input.runtime.ts b/src/components/session/chat-input.runtime.ts index 8072c6e..001c899 100644 --- a/src/components/session/chat-input.runtime.ts +++ b/src/components/session/chat-input.runtime.ts @@ -70,12 +70,15 @@ type CommandCatalogRuntimeArgs = Pick< const CLAUDE_EFFORT_CYCLE_ORDER = CLAUDE_EFFORT_OPTIONS.map( (option) => option.value, ); +// Legacy "minimal" is intentionally absent — cycling from a persisted +// "minimal" value falls back to the first entry ("low"). const CODEX_EFFORT_CYCLE_ORDER = [ "low", "medium", "high", "xhigh", - "minimal", + "max", + "ultra", ] as const satisfies readonly AppSettings["codexReasoningEffort"][]; function cycleOptionValue(args: { diff --git a/src/lib/providers/codex-runtime-options.ts b/src/lib/providers/codex-runtime-options.ts index 3391aa7..338e082 100644 --- a/src/lib/providers/codex-runtime-options.ts +++ b/src/lib/providers/codex-runtime-options.ts @@ -55,7 +55,9 @@ export function resolveCodexAppServerReasoningEffort(args: { args.reasoningEffort !== "low" && args.reasoningEffort !== "medium" && args.reasoningEffort !== "high" && - args.reasoningEffort !== "xhigh" + args.reasoningEffort !== "xhigh" && + args.reasoningEffort !== "max" && + args.reasoningEffort !== "ultra" ) { return undefined; } diff --git a/src/lib/providers/model-catalog.ts b/src/lib/providers/model-catalog.ts index a263f33..a19a84e 100644 --- a/src/lib/providers/model-catalog.ts +++ b/src/lib/providers/model-catalog.ts @@ -42,12 +42,15 @@ export const CLAUDE_SDK_MODEL_OPTIONS = [ // Source: // - local `codex app-server` / CLI baseline support -// - https://developers.openai.com/codex/models +// - https://developers.openai.com/codex/models (GPT-5.6 family, 2026-07-09) +// GPT-5.6 ships as Sol (flagship), Terra (balanced), and Luna (fast/cheap). +// gpt-5.5 is kept as the previous-generation fallback; gpt-5.4 variants and +// codex-spark moved to legacy display names only. export const CODEX_MODEL_OPTIONS = [ + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", "gpt-5.5", - "gpt-5.4", - "gpt-5.4-mini", - "gpt-5.3-codex-spark", ] as const; export interface ProviderDescriptor { @@ -87,7 +90,7 @@ export const PROVIDER_DESCRIPTORS = [ iconUrl: CODEX_COLOR_ICON_URL, fallbackLabel: "O", models: CODEX_MODEL_OPTIONS, - defaultModel: "gpt-5.5", + defaultModel: "gpt-5.6-terra", sessionLabel: "Codex thread ID", capabilities: { nativeCommandCatalog: true, @@ -227,14 +230,6 @@ export const MODEL_TIER_ORDER = [ "frontier", ] as const satisfies readonly ModelTier[]; -const GENERAL_CODING_TASK_TYPES = [ - "quick_edit", - "implementation", - "debug", - "review", - "general", -] as const satisfies readonly TaskType[]; - export const MODEL_CAPABILITIES: Record = { [CLAUDE_FABLE_MODEL]: { providerId: "claude-code", @@ -285,32 +280,32 @@ export const MODEL_CAPABILITIES: Record = { taskTypes: ["quick_edit", "general"], defaultClaudeEffort: "medium", }, - "gpt-5.5": { + "gpt-5.6-sol": { providerId: "codex", - model: "gpt-5.5", + model: "gpt-5.6-sol", tier: "frontier", taskTypes: ["plan", "implementation", "debug", "review", "safety"], defaultCodexReasoningEffort: "high", }, - "gpt-5.4": { + "gpt-5.6-terra": { providerId: "codex", - model: "gpt-5.4", - tier: "standard", - taskTypes: GENERAL_CODING_TASK_TYPES, + model: "gpt-5.6-terra", + tier: "heavy", + taskTypes: ["plan", "implementation", "debug", "review", "safety"], defaultCodexReasoningEffort: "medium", }, - "gpt-5.4-mini": { + "gpt-5.6-luna": { providerId: "codex", - model: "gpt-5.4-mini", + model: "gpt-5.6-luna", tier: "light", taskTypes: ["quick_edit", "general"], defaultCodexReasoningEffort: "low", }, - "gpt-5.3-codex-spark": { + "gpt-5.5": { providerId: "codex", - model: "gpt-5.3-codex-spark", - tier: "heavy", - taskTypes: ["implementation", "debug", "review"], + model: "gpt-5.5", + tier: "frontier", + taskTypes: ["plan", "implementation", "debug", "review", "safety"], defaultCodexReasoningEffort: "high", }, }; @@ -419,10 +414,14 @@ export function resolveDefaultCodexEffortForModel(args: { } const normalizedModel = args.model.trim().toLowerCase(); - if (normalizedModel.includes("mini")) { + if (normalizedModel.includes("mini") || normalizedModel.includes("luna")) { return "low"; } - if (normalizedModel.includes("spark") || normalizedModel.includes("5.5")) { + if ( + normalizedModel.includes("spark") || + normalizedModel.includes("sol") || + normalizedModel.includes("5.5") + ) { return "high"; } return "medium"; @@ -492,7 +491,12 @@ export function toHumanModelName(args: { model: string }) { "claude-sonnet-4-6": "Claude Sonnet 4.6", "claude-sonnet-4-6[1m]": "Claude Sonnet 4.6 (1M)", "claude-haiku-4-5": "Claude Haiku 4.5", + "gpt-5.6-sol": "GPT-5.6 Sol", + "gpt-5.6-terra": "GPT-5.6 Terra", + "gpt-5.6-luna": "GPT-5.6 Luna", "gpt-5.5": "GPT-5.5", + // Legacy Codex labels kept so historical chat/turn records still render + // recognizable names after the picker lineup moved to GPT-5.6. "gpt-5.4": "GPT-5.4", "gpt-5.4-mini": "GPT-5.4 Mini", "gpt-5-codex": "GPT-5-Codex", diff --git a/src/lib/providers/model-shortcuts.ts b/src/lib/providers/model-shortcuts.ts index 9751035..473aa9e 100644 --- a/src/lib/providers/model-shortcuts.ts +++ b/src/lib/providers/model-shortcuts.ts @@ -20,8 +20,8 @@ export const MODEL_SHORTCUT_SLOT_LABELS = [ export const DEFAULT_MODEL_SHORTCUT_KEYS = [ "claude-code:claude-opus-4-8", - "codex:gpt-5.5", - "codex:gpt-5.4", + "codex:gpt-5.6-terra", + "codex:gpt-5.6-sol", "", "", "", diff --git a/src/lib/providers/provider.types.ts b/src/lib/providers/provider.types.ts index 8652272..309b041 100644 --- a/src/lib/providers/provider.types.ts +++ b/src/lib/providers/provider.types.ts @@ -582,7 +582,16 @@ export interface ProviderRuntimeOptions { codexNetworkAccess?: boolean; codexApprovalPolicy?: "never" | "on-request" | "on-failure" | "untrusted"; codexBinaryPath?: string; - codexReasoningEffort?: "minimal" | "low" | "medium" | "high" | "xhigh"; + // "minimal" is a legacy value kept for persisted settings; the runtime maps + // it to "low". "max" and "ultra" arrived with the GPT-5.6 Codex CLI scale. + codexReasoningEffort?: + | "minimal" + | "low" + | "medium" + | "high" + | "xhigh" + | "max" + | "ultra"; codexWebSearch?: "disabled" | "cached" | "live"; codexShowRawReasoning?: boolean; codexReasoningSummary?: "auto" | "concise" | "detailed" | "none"; diff --git a/src/lib/providers/runtime-option-contract.ts b/src/lib/providers/runtime-option-contract.ts index f97b9b7..2ede547 100644 --- a/src/lib/providers/runtime-option-contract.ts +++ b/src/lib/providers/runtime-option-contract.ts @@ -65,12 +65,16 @@ export const CODEX_SANDBOX_MODE_OPTIONS = [ { value: "danger-full-access", label: "danger-full-access" }, ] as const satisfies readonly SelectOption>[]; +// "minimal" was dropped from the Codex CLI effort scale with GPT-5.6 and is +// no longer selectable; legacy persisted values still validate and map to +// "low" at runtime (see resolveCodexAppServerReasoningEffort). export const CODEX_EFFORT_OPTIONS = [ - { value: "minimal", label: "Minimal" }, { value: "low", label: "Low" }, { value: "medium", label: "Medium" }, { value: "high", label: "High" }, { value: "xhigh", label: "X-High" }, + { value: "max", label: "Max" }, + { value: "ultra", label: "Ultra" }, ] as const satisfies readonly SelectOption>[]; export const CODEX_WEB_SEARCH_OPTIONS = [ diff --git a/src/lib/task-presets.ts b/src/lib/task-presets.ts index 54655e6..efa4c94 100644 --- a/src/lib/task-presets.ts +++ b/src/lib/task-presets.ts @@ -30,7 +30,8 @@ export interface TaskPreset { /** * Reasoning effort applied to `task` presets. Claude presets accept * `low | medium | high | xhigh | max`; Codex presets accept - * `minimal | low | medium | high | xhigh`. When omitted, the model's + * `low | medium | high | xhigh | max | ultra` (legacy persisted `minimal` + * still validates and maps to `low` at runtime). When omitted, the model's * default effort is used at launch. Ignored for CLI sessions. */ effort?: TaskPresetEffort; @@ -46,7 +47,8 @@ export type TaskPresetEffort = | "medium" | "high" | "xhigh" - | "max"; + | "max" + | "ultra"; /** * Effort options selectable for a `task` preset, scoped to the provider's @@ -91,11 +93,11 @@ export const DEFAULT_TASK_PRESETS: readonly TaskPreset[] = [ model: DEFAULT_CLAUDE_OPUS_MODEL, }, { - id: "default-gpt-5-5-task", - label: "GPT-5.5", + id: "default-gpt-5-6-task", + label: "GPT-5.6", kind: "task", provider: "codex", - model: "gpt-5.5", + model: "gpt-5.6-terra", }, { id: "default-claude-cli-session", diff --git a/src/store/app.store.ts b/src/store/app.store.ts index e948392..341b704 100644 --- a/src/store/app.store.ts +++ b/src/store/app.store.ts @@ -1470,7 +1470,14 @@ export interface AppSettings { codexNetworkAccess: boolean; codexApprovalPolicy: "never" | "on-request" | "on-failure" | "untrusted"; codexBinaryPath: string; - codexReasoningEffort: "minimal" | "low" | "medium" | "high" | "xhigh"; + codexReasoningEffort: + | "minimal" + | "low" + | "medium" + | "high" + | "xhigh" + | "max" + | "ultra"; codexWebSearch: "disabled" | "cached" | "live"; codexShowRawReasoning: boolean; codexReasoningSummary: "auto" | "concise" | "detailed" | "none"; @@ -2675,7 +2682,7 @@ const defaultSettings: AppSettings = { promptResponseStyle: DEFAULT_PROMPT_RESPONSE_STYLE, promptPrDescription: DEFAULT_PROMPT_PR_DESCRIPTION, promptInlineCompletion: DEFAULT_PROMPT_INLINE_COMPLETION, - workspaceTurnSummaryPrimaryModel: "gpt-5.4-mini", + workspaceTurnSummaryPrimaryModel: "gpt-5.6-luna", workspaceTurnSummaryFallbackModel: "claude-haiku-4-5", workspaceTurnSummaryPrompt: DEFAULT_PROMPT_WORKSPACE_TURN_SUMMARY, diff --git a/tests/chat-input.runtime.test.ts b/tests/chat-input.runtime.test.ts index e169db1..2b45392 100644 --- a/tests/chat-input.runtime.test.ts +++ b/tests/chat-input.runtime.test.ts @@ -45,11 +45,15 @@ describe("chat-input runtime helpers", () => { expect(cycleClaudeEffortValue("max")).toBe("low"); }); - test("cycles Codex effort with minimal at the end of the loop", () => { + test("cycles Codex effort through max and ultra, mapping legacy minimal to low", () => { expect(cycleCodexEffortValue("low")).toBe("medium"); expect(cycleCodexEffortValue("medium")).toBe("high"); expect(cycleCodexEffortValue("high")).toBe("xhigh"); - expect(cycleCodexEffortValue("xhigh")).toBe("minimal"); + expect(cycleCodexEffortValue("xhigh")).toBe("max"); + expect(cycleCodexEffortValue("max")).toBe("ultra"); + expect(cycleCodexEffortValue("ultra")).toBe("low"); + // Legacy persisted "minimal" is no longer in the cycle; it falls back to + // the first entry. expect(cycleCodexEffortValue("minimal")).toBe("low"); }); diff --git a/tests/codex-runtime-options.test.ts b/tests/codex-runtime-options.test.ts index 32d2e3a..4c62ea0 100644 --- a/tests/codex-runtime-options.test.ts +++ b/tests/codex-runtime-options.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test"; import { + resolveCodexAppServerReasoningEffort, resolveEffectiveCodexApprovalPolicy, resolveEffectiveCodexFileAccessMode, } from "@/lib/providers/codex-runtime-options"; @@ -42,3 +43,26 @@ describe("resolveEffectiveCodexApprovalPolicy", () => { })).toBe("untrusted"); }); }); + +describe("resolveCodexAppServerReasoningEffort", () => { + test("passes through the GPT-5.6 max and ultra effort tiers", () => { + expect( + resolveCodexAppServerReasoningEffort({ reasoningEffort: "max" }), + ).toBe("max"); + expect( + resolveCodexAppServerReasoningEffort({ reasoningEffort: "ultra" }), + ).toBe("ultra"); + }); + + test("normalizes legacy minimal to low", () => { + expect( + resolveCodexAppServerReasoningEffort({ reasoningEffort: "minimal" }), + ).toBe("low"); + }); + + test("returns undefined for unknown or missing efforts", () => { + expect( + resolveCodexAppServerReasoningEffort({ reasoningEffort: undefined }), + ).toBeUndefined(); + }); +}); diff --git a/tests/ipc-schemas.test.ts b/tests/ipc-schemas.test.ts index 3817f88..c56541a 100644 --- a/tests/ipc-schemas.test.ts +++ b/tests/ipc-schemas.test.ts @@ -45,6 +45,20 @@ describe("provider IPC schemas", () => { expect(parsed.success).toBe(true); }); + test("accepts Codex max/ultra efforts and legacy minimal in runtime options", () => { + for (const effort of ["max", "ultra", "minimal"] as const) { + const parsed = StreamTurnArgsSchema.safeParse({ + providerId: "codex", + prompt: "continue", + runtimeOptions: { + codexReasoningEffort: effort, + }, + }); + + expect(parsed.success).toBe(true); + } + }); + test("accepts provider timeout windows up to 24 hours", () => { expect(StreamTurnArgsSchema.safeParse({ providerId: "codex", diff --git a/tests/model-catalog.test.ts b/tests/model-catalog.test.ts index 97d6850..eb7d15e 100644 --- a/tests/model-catalog.test.ts +++ b/tests/model-catalog.test.ts @@ -35,10 +35,10 @@ describe("model catalog", () => { test("includes the verified Codex model set", () => { expect(CODEX_MODEL_OPTIONS).toEqual([ + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", "gpt-5.5", - "gpt-5.4", - "gpt-5.4-mini", - "gpt-5.3-codex-spark", ]); }); @@ -52,8 +52,10 @@ describe("model catalog", () => { }); test("formats current GPT models with canonical labels", () => { + expect(toHumanModelName({ model: "gpt-5.6-sol" })).toBe("GPT-5.6 Sol"); + expect(toHumanModelName({ model: "gpt-5.6-terra" })).toBe("GPT-5.6 Terra"); + expect(toHumanModelName({ model: "gpt-5.6-luna" })).toBe("GPT-5.6 Luna"); expect(toHumanModelName({ model: "gpt-5.5" })).toBe("GPT-5.5"); - expect(toHumanModelName({ model: "gpt-5.4" })).toBe("GPT-5.4"); expect(toHumanModelName({ model: "claude-sonnet-5" })).toBe( "Claude Sonnet 5", ); @@ -86,7 +88,7 @@ describe("model catalog", () => { "claude-sonnet-5", ); expect(getDefaultModelForProvider({ providerId: "codex" })).toBe( - "gpt-5.5", + "gpt-5.6-terra", ); }); @@ -116,6 +118,20 @@ describe("model catalog", () => { }); test("returns the default Codex effort from model capabilities", () => { + expect(resolveDefaultCodexEffortForModel({ model: "gpt-5.6-luna" })).toBe( + "low", + ); + expect(resolveDefaultCodexEffortForModel({ model: "gpt-5.6-terra" })).toBe( + "medium", + ); + expect(resolveDefaultCodexEffortForModel({ model: "gpt-5.6-sol" })).toBe( + "high", + ); + expect(resolveDefaultCodexEffortForModel({ model: "gpt-5.5" })).toBe( + "high", + ); + // Legacy models removed from the picker still resolve via the heuristic + // fallback so historical settings keep sane defaults. expect(resolveDefaultCodexEffortForModel({ model: "gpt-5.4-mini" })).toBe( "low", ); @@ -150,7 +166,7 @@ describe("model catalog", () => { resolveTierModel({ providerId: "claude-code", tier: "frontier" }), ).toBe(CLAUDE_FABLE_MODEL); expect(resolveTierModel({ providerId: "codex", tier: "light" })).toBe( - "gpt-5.4-mini", + "gpt-5.6-luna", ); expect( resolveTierModel({ diff --git a/tests/model-selector-utils.test.ts b/tests/model-selector-utils.test.ts index 40bb435..4a4f158 100644 --- a/tests/model-selector-utils.test.ts +++ b/tests/model-selector-utils.test.ts @@ -92,8 +92,8 @@ describe("model selector utils", () => { ), ).toEqual([ "claude-code:claude-opus-4-8", - "codex:gpt-5.5", - "codex:gpt-5.4", + "codex:gpt-5.6-terra", + "codex:gpt-5.6-sol", ]); }); @@ -127,20 +127,20 @@ describe("model selector utils", () => { test("passes enrichment data (description, isDefault) into built options", () => { const enrichment = new Map([ - ["gpt-5.4", { description: "Flagship model", isDefault: true }], + ["gpt-5.6-sol", { description: "Flagship model", isDefault: true }], ]); const options = buildModelSelectorOptions({ providerIds: ["codex"], enrichmentByModel: enrichment, }); - const gpt54 = options.find((option) => option.model === "gpt-5.4"); - expect(gpt54).toBeDefined(); - expect(gpt54?.description).toBe("Flagship model"); - expect(gpt54?.isDefault).toBe(true); + const sol = options.find((option) => option.model === "gpt-5.6-sol"); + expect(sol).toBeDefined(); + expect(sol?.description).toBe("Flagship model"); + expect(sol?.isDefault).toBe(true); // Other models without enrichment should have no description - const mini = options.find((option) => option.model === "gpt-5.4-mini"); - expect(mini?.description).toBeUndefined(); - expect(mini?.isDefault).toBeUndefined(); + const luna = options.find((option) => option.model === "gpt-5.6-luna"); + expect(luna?.description).toBeUndefined(); + expect(luna?.isDefault).toBeUndefined(); }); }); diff --git a/tests/model-shortcuts.test.ts b/tests/model-shortcuts.test.ts index 3e10fc1..3e923da 100644 --- a/tests/model-shortcuts.test.ts +++ b/tests/model-shortcuts.test.ts @@ -10,10 +10,10 @@ import { describe("model shortcuts", () => { test("fills missing slots from the default shortcut map", () => { expect(normalizeModelShortcutKeys()).toEqual(DEFAULT_MODEL_SHORTCUT_KEYS); - expect(normalizeModelShortcutKeys(["codex:gpt-5.4-mini", ""])).toEqual([ - "codex:gpt-5.4-mini", + expect(normalizeModelShortcutKeys(["codex:gpt-5.6-luna", ""])).toEqual([ + "codex:gpt-5.6-luna", "", - "codex:gpt-5.4", + "codex:gpt-5.6-sol", "", "", "", diff --git a/tests/task-presets.test.ts b/tests/task-presets.test.ts index 4628af0..69c2468 100644 --- a/tests/task-presets.test.ts +++ b/tests/task-presets.test.ts @@ -16,7 +16,7 @@ describe("task preset defaults", () => { expect(presets).toHaveLength(4); expect(presets.map((preset) => preset.id)).toEqual([ "default-claude-opus-4-8-task", - "default-gpt-5-5-task", + "default-gpt-5-6-task", "default-claude-cli-session", "default-codex-cli-session", ]);