diff --git a/AGENTS.md b/AGENTS.md index 3989271f4..98e9640e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -204,14 +204,14 @@ oh-my-opencode/ | Agent | Model | Purpose | |-------|-------|---------| -| Sisyphus | anthropic/claude-opus-4-5 | Primary orchestrator (fallback: kimi-k2.5 → glm-4.7 → gpt-5.2-codex → gemini-3-pro) | -| Hephaestus | openai/gpt-5.2-codex | Autonomous deep worker, "The Legitimate Craftsman" (requires gpt-5.2-codex, no fallback) | +| Sisyphus | anthropic/claude-opus-4-6 | Primary orchestrator (fallback: kimi-k2.5 → glm-4.7 → gpt-5.3-codex → gemini-3-pro) | +| Hephaestus | openai/gpt-5.3-codex | Autonomous deep worker, "The Legitimate Craftsman" (requires gpt-5.3-codex, no fallback) | | Atlas | anthropic/claude-sonnet-4-5 | Master orchestrator (fallback: kimi-k2.5 → gpt-5.2) | | oracle | openai/gpt-5.2 | Consultation, debugging | | librarian | zai-coding-plan/glm-4.7 | Docs, GitHub search (fallback: glm-4.7-free) | | explore | xai/grok-code-fast-1 | Fast codebase grep (fallback: claude-haiku-4-5 → gpt-5-mini → gpt-5-nano) | | multimodal-looker | google/gemini-3-flash | PDF/image analysis | -| Prometheus | anthropic/claude-opus-4-5 | Strategic planning (fallback: kimi-k2.5 → gpt-5.2) | +| Prometheus | anthropic/claude-opus-4-6 | Strategic planning (fallback: kimi-k2.5 → gpt-5.2) | ## COMMANDS diff --git a/docs/category-skill-guide.md b/docs/category-skill-guide.md index 217b05b1e..b3de37a3d 100644 --- a/docs/category-skill-guide.md +++ b/docs/category-skill-guide.md @@ -22,12 +22,12 @@ A Category is an agent configuration preset optimized for specific domains. | Category | Default Model | Use Cases | |----------|---------------|-----------| | `visual-engineering` | `google/gemini-3-pro` | Frontend, UI/UX, design, styling, animation | -| `ultrabrain` | `openai/gpt-5.2-codex` (xhigh) | Deep logical reasoning, complex architecture decisions requiring extensive analysis | -| `deep` | `openai/gpt-5.2-codex` (medium) | Goal-oriented autonomous problem-solving. Thorough research before action. For hairy problems requiring deep understanding. | +| `ultrabrain` | `openai/gpt-5.3-codex` (xhigh) | Deep logical reasoning, complex architecture decisions requiring extensive analysis | +| `deep` | `openai/gpt-5.3-codex` (medium) | Goal-oriented autonomous problem-solving. Thorough research before action. For hairy problems requiring deep understanding. | | `artistry` | `google/gemini-3-pro` (max) | Highly creative/artistic tasks, novel ideas | | `quick` | `anthropic/claude-haiku-4-5` | Trivial tasks - single file changes, typo fixes, simple modifications | | `unspecified-low` | `anthropic/claude-sonnet-4-5` | Tasks that don't fit other categories, low effort required | -| `unspecified-high` | `anthropic/claude-opus-4-5` (max) | Tasks that don't fit other categories, high effort required | +| `unspecified-high` | `anthropic/claude-opus-4-6` (max) | Tasks that don't fit other categories, high effort required | | `writing` | `google/gemini-3-flash` | Documentation, prose, technical writing | ### Usage @@ -159,7 +159,7 @@ You can fine-tune categories in `oh-my-opencode.json`. | Field | Type | Description | |-------|------|-------------| | `description` | string | Human-readable description of the category's purpose. Shown in delegate_task prompt. | -| `model` | string | AI model ID to use (e.g., `anthropic/claude-opus-4-5`) | +| `model` | string | AI model ID to use (e.g., `anthropic/claude-opus-4-6`) | | `variant` | string | Model variant (e.g., `max`, `xhigh`) | | `temperature` | number | Creativity level (0.0 ~ 2.0). Lower is more deterministic. | | `top_p` | number | Nucleus sampling parameter (0.0 ~ 1.0) | @@ -191,7 +191,7 @@ You can fine-tune categories in `oh-my-opencode.json`. // 3. Configure thinking model and restrict tools "deep-reasoning": { - "model": "anthropic/claude-opus-4-5", + "model": "anthropic/claude-opus-4-6", "thinking": { "type": "enabled", "budgetTokens": 32000 diff --git a/docs/configurations.md b/docs/configurations.md index 7111f5c8b..648ee75ac 100644 --- a/docs/configurations.md +++ b/docs/configurations.md @@ -693,7 +693,7 @@ Configure concurrency limits for background agent tasks. This controls how many "google": 10 }, "modelConcurrency": { - "anthropic/claude-opus-4-5": 2, + "anthropic/claude-opus-4-6": 2, "google/gemini-3-flash": 10 } } @@ -705,7 +705,7 @@ Configure concurrency limits for background agent tasks. This controls how many | `defaultConcurrency` | - | Default maximum concurrent background tasks for all providers/models | | `staleTimeoutMs` | `180000` | Stale timeout in milliseconds - interrupt tasks with no activity for this duration (minimum: 60000 = 1 minute) | | `providerConcurrency` | - | Per-provider concurrency limits. Keys are provider names (e.g., `anthropic`, `openai`, `google`) | -| `modelConcurrency` | - | Per-model concurrency limits. Keys are full model names (e.g., `anthropic/claude-opus-4-5`). Overrides provider limits. | +| `modelConcurrency` | - | Per-model concurrency limits. Keys are full model names (e.g., `anthropic/claude-opus-4-6`). Overrides provider limits. | **Priority Order**: `modelConcurrency` > `providerConcurrency` > `defaultConcurrency` @@ -725,11 +725,11 @@ All 7 categories come with optimal model defaults, but **you must configure them | Category | Built-in Default Model | Description | | -------------------- | ---------------------------------- | -------------------------------------------------------------------- | | `visual-engineering` | `google/gemini-3-pro-preview` | Frontend, UI/UX, design, styling, animation | -| `ultrabrain` | `openai/gpt-5.2-codex` (xhigh) | Deep logical reasoning, complex architecture decisions | +| `ultrabrain` | `openai/gpt-5.3-codex` (xhigh) | Deep logical reasoning, complex architecture decisions | | `artistry` | `google/gemini-3-pro-preview` (max)| Highly creative/artistic tasks, novel ideas | | `quick` | `anthropic/claude-haiku-4-5` | Trivial tasks - single file changes, typo fixes, simple modifications| | `unspecified-low` | `anthropic/claude-sonnet-4-5` | Tasks that don't fit other categories, low effort required | -| `unspecified-high` | `anthropic/claude-opus-4-5` (max) | Tasks that don't fit other categories, high effort required | +| `unspecified-high` | `anthropic/claude-opus-4-6` (max) | Tasks that don't fit other categories, high effort required | | `writing` | `google/gemini-3-flash-preview` | Documentation, prose, technical writing | ### ⚠️ Critical: Model Resolution Priority @@ -768,7 +768,7 @@ All 7 categories come with optimal model defaults, but **you must configure them "model": "google/gemini-3-pro-preview" }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh" }, "artistry": { @@ -782,7 +782,7 @@ All 7 categories come with optimal model defaults, but **you must configure them "model": "anthropic/claude-sonnet-4-5" }, "unspecified-high": { - "model": "anthropic/claude-opus-4-5", + "model": "anthropic/claude-opus-4-6", "variant": "max" }, "writing": { @@ -870,9 +870,9 @@ At runtime, Oh My OpenCode uses a 3-step resolution process to determine which m │ │ anthropic → github-copilot → opencode → antigravity │ │ │ │ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ -│ │ Try: anthropic/claude-opus-4-5 │ │ -│ │ Try: github-copilot/claude-opus-4-5 │ │ -│ │ Try: opencode/claude-opus-4-5 │ │ +│ │ Try: anthropic/claude-opus-4-6 │ │ +│ │ Try: github-copilot/claude-opus-4-6 │ │ +│ │ Try: opencode/claude-opus-4-6 │ │ │ │ ... │ │ │ │ │ │ │ │ Found in available models? → Return matched model │ │ @@ -894,13 +894,13 @@ Each agent has a defined provider priority chain. The system tries providers in | Agent | Model (no prefix) | Provider Priority Chain | |-------|-------------------|-------------------------| -| **Sisyphus** | `claude-opus-4-5` | anthropic → kimi-for-coding → zai-coding-plan → openai → google | +| **Sisyphus** | `claude-opus-4-6` | anthropic → kimi-for-coding → zai-coding-plan → openai → google | | **oracle** | `gpt-5.2` | openai → google → anthropic | | **librarian** | `glm-4.7` | zai-coding-plan → opencode → anthropic | | **explore** | `claude-haiku-4-5` | anthropic → github-copilot → opencode | | **multimodal-looker** | `gemini-3-flash` | google → openai → zai-coding-plan → kimi-for-coding → anthropic → opencode | -| **Prometheus (Planner)** | `claude-opus-4-5` | anthropic → kimi-for-coding → openai → google | -| **Metis (Plan Consultant)** | `claude-opus-4-5` | anthropic → kimi-for-coding → openai → google | +| **Prometheus (Planner)** | `claude-opus-4-6` | anthropic → kimi-for-coding → openai → google | +| **Metis (Plan Consultant)** | `claude-opus-4-6` | anthropic → kimi-for-coding → openai → google | | **Momus (Plan Reviewer)** | `gpt-5.2` | openai → anthropic → google | | **Atlas** | `claude-sonnet-4-5` | anthropic → kimi-for-coding → openai → google | @@ -911,12 +911,12 @@ Categories follow the same resolution logic: | Category | Model (no prefix) | Provider Priority Chain | |----------|-------------------|-------------------------| | **visual-engineering** | `gemini-3-pro` | google → anthropic → zai-coding-plan | -| **ultrabrain** | `gpt-5.2-codex` | openai → google → anthropic | -| **deep** | `gpt-5.2-codex` | openai → anthropic → google | +| **ultrabrain** | `gpt-5.3-codex` | openai → google → anthropic | +| **deep** | `gpt-5.3-codex` | openai → anthropic → google | | **artistry** | `gemini-3-pro` | google → anthropic → openai | | **quick** | `claude-haiku-4-5` | anthropic → google → opencode | | **unspecified-low** | `claude-sonnet-4-5` | anthropic → openai → google | -| **unspecified-high** | `claude-opus-4-5` | anthropic → openai → google | +| **unspecified-high** | `claude-opus-4-6` | anthropic → openai → google | | **writing** | `gemini-3-flash` | google → anthropic → zai-coding-plan → openai | ### Checking Your Configuration @@ -949,7 +949,7 @@ Override any agent or category model in `oh-my-opencode.json`: }, "categories": { "visual-engineering": { - "model": "anthropic/claude-opus-4-5" + "model": "anthropic/claude-opus-4-6" } } } diff --git a/docs/features.md b/docs/features.md index 25284af5b..b750ce7d6 100644 --- a/docs/features.md +++ b/docs/features.md @@ -10,8 +10,8 @@ Oh-My-OpenCode provides 11 specialized AI agents. Each has distinct expertise, o | Agent | Model | Purpose | |-------|-------|---------| -| **Sisyphus** | `anthropic/claude-opus-4-5` | **The default orchestrator.** Plans, delegates, and executes complex tasks using specialized subagents with aggressive parallel execution. Todo-driven workflow with extended thinking (32k budget). Fallback: kimi-k2.5 → glm-4.7 → gpt-5.2-codex → gemini-3-pro. | -| **Hephaestus** | `openai/gpt-5.2-codex` | **The Legitimate Craftsman.** Autonomous deep worker inspired by AmpCode's deep mode. Goal-oriented execution with thorough research before action. Explores codebase patterns, completes tasks end-to-end without premature stopping. Named after the Greek god of forge and craftsmanship. Requires gpt-5.2-codex (no fallback - only activates when this model is available). | +| **Sisyphus** | `anthropic/claude-opus-4-6` | **The default orchestrator.** Plans, delegates, and executes complex tasks using specialized subagents with aggressive parallel execution. Todo-driven workflow with extended thinking (32k budget). Fallback: kimi-k2.5 → glm-4.7 → gpt-5.3-codex → gemini-3-pro. | +| **Hephaestus** | `openai/gpt-5.3-codex` | **The Legitimate Craftsman.** Autonomous deep worker inspired by AmpCode's deep mode. Goal-oriented execution with thorough research before action. Explores codebase patterns, completes tasks end-to-end without premature stopping. Named after the Greek god of forge and craftsmanship. Requires gpt-5.3-codex (no fallback - only activates when this model is available). | | **oracle** | `openai/gpt-5.2` | Architecture decisions, code review, debugging. Read-only consultation - stellar logical reasoning and deep analysis. Inspired by AmpCode. | | **librarian** | `zai-coding-plan/glm-4.7` | Multi-repo analysis, documentation lookup, OSS implementation examples. Deep codebase understanding with evidence-based answers. Fallback: glm-4.7-free → claude-sonnet-4-5. | | **explore** | `anthropic/claude-haiku-4-5` | Fast codebase exploration and contextual grep. Fallback: gpt-5-mini → gpt-5-nano. | @@ -21,9 +21,9 @@ Oh-My-OpenCode provides 11 specialized AI agents. Each has distinct expertise, o | Agent | Model | Purpose | |-------|-------|---------| -| **Prometheus** | `anthropic/claude-opus-4-5` | Strategic planner with interview mode. Creates detailed work plans through iterative questioning. Fallback: kimi-k2.5 → gpt-5.2 → gemini-3-pro. | -| **Metis** | `anthropic/claude-opus-4-5` | Plan consultant - pre-planning analysis. Identifies hidden intentions, ambiguities, and AI failure points. Fallback: kimi-k2.5 → gpt-5.2 → gemini-3-pro. | -| **Momus** | `openai/gpt-5.2` | Plan reviewer - validates plans against clarity, verifiability, and completeness standards. Fallback: gpt-5.2 → claude-opus-4-5 → gemini-3-pro. | +| **Prometheus** | `anthropic/claude-opus-4-6` | Strategic planner with interview mode. Creates detailed work plans through iterative questioning. Fallback: kimi-k2.5 → gpt-5.2 → gemini-3-pro. | +| **Metis** | `anthropic/claude-opus-4-6` | Plan consultant - pre-planning analysis. Identifies hidden intentions, ambiguities, and AI failure points. Fallback: kimi-k2.5 → gpt-5.2 → gemini-3-pro. | +| **Momus** | `openai/gpt-5.2` | Plan reviewer - validates plans against clarity, verifiability, and completeness standards. Fallback: gpt-5.2 → claude-opus-4-6 → gemini-3-pro. | ### Invoking Agents diff --git a/docs/guide/installation.md b/docs/guide/installation.md index 0f6dff32d..bac440348 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -196,7 +196,7 @@ When GitHub Copilot is the best available provider, oh-my-opencode uses these mo | Agent | Model | | ------------- | -------------------------------- | -| **Sisyphus** | `github-copilot/claude-opus-4.5` | +| **Sisyphus** | `github-copilot/claude-opus-4.6` | | **Oracle** | `github-copilot/gpt-5.2` | | **Explore** | `opencode/gpt-5-nano` | | **Librarian** | `zai-coding-plan/glm-4.7` (if Z.ai available) or fallback | @@ -218,13 +218,13 @@ If Z.ai is the only provider available, all agents will use GLM models: #### OpenCode Zen -OpenCode Zen provides access to `opencode/` prefixed models including `opencode/claude-opus-4-5`, `opencode/gpt-5.2`, `opencode/gpt-5-nano`, and `opencode/glm-4.7-free`. +OpenCode Zen provides access to `opencode/` prefixed models including `opencode/claude-opus-4-6`, `opencode/gpt-5.2`, `opencode/gpt-5-nano`, and `opencode/glm-4.7-free`. When OpenCode Zen is the best available provider (no native or Copilot), these models are used: | Agent | Model | | ------------- | -------------------------------- | -| **Sisyphus** | `opencode/claude-opus-4-5` | +| **Sisyphus** | `opencode/claude-opus-4-6` | | **Oracle** | `opencode/gpt-5.2` | | **Explore** | `opencode/gpt-5-nano` | | **Librarian** | `opencode/glm-4.7-free` | diff --git a/docs/guide/understanding-orchestration-system.md b/docs/guide/understanding-orchestration-system.md index 8af82b444..148de716f 100644 --- a/docs/guide/understanding-orchestration-system.md +++ b/docs/guide/understanding-orchestration-system.md @@ -277,7 +277,7 @@ This "boulder pushing" mechanism is why the system is named after Sisyphus. ```typescript // OLD: Model name creates distributional bias delegate_task(agent="gpt-5.2", prompt="...") // Model knows its limitations -delegate_task(agent="claude-opus-4.5", prompt="...") // Different self-perception +delegate_task(agent="claude-opus-4.6", prompt="...") // Different self-perception ``` **The Solution: Semantic Categories:** diff --git a/docs/orchestration-guide.md b/docs/orchestration-guide.md index 08a113ae2..0eac77567 100644 --- a/docs/orchestration-guide.md +++ b/docs/orchestration-guide.md @@ -275,7 +275,7 @@ flowchart TD ### 🔮 Prometheus (The Planner) -- **Model**: `anthropic/claude-opus-4-5` +- **Model**: `anthropic/claude-opus-4-6` - **Role**: Strategic planning, requirements interviews, work plan creation - **Constraint**: **READ-ONLY**. Can only create/modify markdown files within `.sisyphus/` directory. - **Characteristic**: Never writes code directly, focuses solely on "how to do it". diff --git a/sisyphus-prompt.md b/sisyphus-prompt.md index 263e9c040..177a97c8f 100644 --- a/sisyphus-prompt.md +++ b/sisyphus-prompt.md @@ -7,7 +7,7 @@ | Field | Value | |-------|-------| -| Model | `anthropic/claude-opus-4-5` | +| Model | `anthropic/claude-opus-4-6` | | Max Tokens | `64000` | | Mode | `primary` | | Thinking | Budget: 32000 | diff --git a/src/agents/AGENTS.md b/src/agents/AGENTS.md index b1c05c4cc..79366d796 100644 --- a/src/agents/AGENTS.md +++ b/src/agents/AGENTS.md @@ -33,16 +33,16 @@ agents/ ## AGENT MODELS | Agent | Model | Temp | Purpose | |-------|-------|------|---------| -| Sisyphus | anthropic/claude-opus-4-5 | 0.1 | Primary orchestrator (fallback: kimi-k2.5 → glm-4.7 → gpt-5.2-codex → gemini-3-pro) | -| Hephaestus | openai/gpt-5.2-codex | 0.1 | Autonomous deep worker, "The Legitimate Craftsman" (requires gpt-5.2-codex, no fallback) | +| Sisyphus | anthropic/claude-opus-4-6 | 0.1 | Primary orchestrator (fallback: kimi-k2.5 → glm-4.7 → gpt-5.3-codex → gemini-3-pro) | +| Hephaestus | openai/gpt-5.3-codex | 0.1 | Autonomous deep worker, "The Legitimate Craftsman" (requires gpt-5.3-codex, no fallback) | | Atlas | anthropic/claude-sonnet-4-5 | 0.1 | Master orchestrator (fallback: kimi-k2.5 → gpt-5.2) | | oracle | openai/gpt-5.2 | 0.1 | Consultation, debugging | | librarian | zai-coding-plan/glm-4.7 | 0.1 | Docs, GitHub search (fallback: glm-4.7-free) | | explore | xai/grok-code-fast-1 | 0.1 | Fast contextual grep (fallback: claude-haiku-4-5 → gpt-5-mini → gpt-5-nano) | | multimodal-looker | google/gemini-3-flash | 0.1 | PDF/image analysis | -| Prometheus | anthropic/claude-opus-4-5 | 0.1 | Strategic planning (fallback: kimi-k2.5 → gpt-5.2) | -| Metis | anthropic/claude-opus-4-5 | 0.3 | Pre-planning analysis (fallback: kimi-k2.5 → gpt-5.2) | -| Momus | openai/gpt-5.2 | 0.1 | Plan validation (fallback: claude-opus-4-5) | +| Prometheus | anthropic/claude-opus-4-6 | 0.1 | Strategic planning (fallback: kimi-k2.5 → gpt-5.2) | +| Metis | anthropic/claude-opus-4-6 | 0.3 | Pre-planning analysis (fallback: kimi-k2.5 → gpt-5.2) | +| Momus | openai/gpt-5.2 | 0.1 | Plan validation (fallback: claude-opus-4-6) | | Sisyphus-Junior | anthropic/claude-sonnet-4-5 | 0.1 | Category-spawned executor | ## HOW TO ADD diff --git a/src/agents/utils.test.ts b/src/agents/utils.test.ts index 1da865cf7..8c0bda46e 100644 --- a/src/agents/utils.test.ts +++ b/src/agents/utils.test.ts @@ -6,14 +6,14 @@ import * as connectedProvidersCache from "../shared/connected-providers-cache" import * as modelAvailability from "../shared/model-availability" import * as shared from "../shared" -const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-5" +const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-6" describe("createBuiltinAgents with model overrides", () => { test("Sisyphus with default model has thinking config when all models available", async () => { // #given const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( new Set([ - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", "kimi-for-coding/k2p5", "opencode/kimi-k2.5-free", "zai-coding-plan/glm-4.7", @@ -26,7 +26,7 @@ describe("createBuiltinAgents with model overrides", () => { const agents = await createBuiltinAgents([], {}, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], {}) // #then - expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-5") + expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-6") expect(agents.sisyphus.thinking).toEqual({ type: "enabled", budgetTokens: 32000 }) expect(agents.sisyphus.reasoningEffort).toBeUndefined() } finally { @@ -81,7 +81,7 @@ describe("createBuiltinAgents with model overrides", () => { test("Sisyphus is created on first run when no availableModels or cache exist", async () => { // #given - const systemDefaultModel = "anthropic/claude-opus-4-5" + const systemDefaultModel = "anthropic/claude-opus-4-6" const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(null) const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(new Set()) @@ -218,7 +218,7 @@ describe("createBuiltinAgents without systemDefaultModel", () => { ]) const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( new Set([ - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", "kimi-for-coding/k2p5", "opencode/kimi-k2.5-free", "zai-coding-plan/glm-4.7", @@ -232,7 +232,7 @@ describe("createBuiltinAgents without systemDefaultModel", () => { // #then expect(agents.sisyphus).toBeDefined() - expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-5") + expect(agents.sisyphus.model).toBe("anthropic/claude-opus-4-6") } finally { cacheSpy.mockRestore() fetchSpy.mockRestore() @@ -244,7 +244,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () => test("hephaestus is not created when no required provider is connected", async () => { // #given - only anthropic models available, not in hephaestus requiresProvider const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( - new Set(["anthropic/claude-opus-4-5"]) + new Set(["anthropic/claude-opus-4-6"]) ) const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["anthropic"]) @@ -263,7 +263,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () => test("hephaestus is created when openai provider is connected", async () => { // #given - openai provider has models available const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( - new Set(["openai/gpt-5.2-codex"]) + new Set(["openai/gpt-5.3-codex"]) ) try { @@ -280,7 +280,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () => test("hephaestus is created when github-copilot provider is connected", async () => { // #given - github-copilot provider has models available const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( - new Set(["github-copilot/gpt-5.2-codex"]) + new Set(["github-copilot/gpt-5.3-codex"]) ) try { @@ -297,7 +297,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () => test("hephaestus is created when opencode provider is connected", async () => { // #given - opencode provider has models available const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( - new Set(["opencode/gpt-5.2-codex"]) + new Set(["opencode/gpt-5.3-codex"]) ) try { @@ -322,7 +322,7 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () => // #then expect(agents.hephaestus).toBeDefined() - expect(agents.hephaestus.model).toBe("openai/gpt-5.2-codex") + expect(agents.hephaestus.model).toBe("openai/gpt-5.3-codex") } finally { cacheSpy.mockRestore() fetchSpy.mockRestore() @@ -332,10 +332,10 @@ describe("createBuiltinAgents with requiresProvider gating (hephaestus)", () => test("hephaestus is created when explicit config provided even if provider unavailable", async () => { // #given const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( - new Set(["anthropic/claude-opus-4-5"]) + new Set(["anthropic/claude-opus-4-6"]) ) const overrides = { - hephaestus: { model: "anthropic/claude-opus-4-5" }, + hephaestus: { model: "anthropic/claude-opus-4-6" }, } try { @@ -354,7 +354,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => { test("sisyphus is created when at least one fallback model is available", async () => { // #given const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue( - new Set(["anthropic/claude-opus-4-5"]) + new Set(["anthropic/claude-opus-4-6"]) ) try { @@ -390,7 +390,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => { // #given const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(new Set()) const overrides = { - sisyphus: { model: "anthropic/claude-opus-4-5" }, + sisyphus: { model: "anthropic/claude-opus-4-6" }, } try { @@ -426,7 +426,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => { describe("buildAgent with category and skills", () => { const { buildAgent } = require("./utils") - const TEST_MODEL = "anthropic/claude-opus-4-5" + const TEST_MODEL = "anthropic/claude-opus-4-6" beforeEach(() => { clearSkillCache() @@ -572,7 +572,7 @@ describe("buildAgent with category and skills", () => { const agent = buildAgent(source["test-agent"], TEST_MODEL) // #then - category's built-in model and skills are applied - expect(agent.model).toBe("openai/gpt-5.2-codex") + expect(agent.model).toBe("openai/gpt-5.3-codex") expect(agent.variant).toBe("xhigh") expect(agent.prompt).toContain("Role: Designer-Turned-Developer") expect(agent.prompt).toContain("Task description") @@ -685,9 +685,9 @@ describe("override.category expansion in createBuiltinAgents", () => { // #when const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) - // #then - ultrabrain category: model=openai/gpt-5.2-codex, variant=xhigh + // #then - ultrabrain category: model=openai/gpt-5.3-codex, variant=xhigh expect(agents.oracle).toBeDefined() - expect(agents.oracle.model).toBe("openai/gpt-5.2-codex") + expect(agents.oracle.model).toBe("openai/gpt-5.3-codex") expect(agents.oracle.variant).toBe("xhigh") }) @@ -754,9 +754,9 @@ describe("override.category expansion in createBuiltinAgents", () => { // #when const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) - // #then - ultrabrain category: model=openai/gpt-5.2-codex, variant=xhigh + // #then - ultrabrain category: model=openai/gpt-5.3-codex, variant=xhigh expect(agents.sisyphus).toBeDefined() - expect(agents.sisyphus.model).toBe("openai/gpt-5.2-codex") + expect(agents.sisyphus.model).toBe("openai/gpt-5.3-codex") expect(agents.sisyphus.variant).toBe("xhigh") }) @@ -769,9 +769,9 @@ describe("override.category expansion in createBuiltinAgents", () => { // #when const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL) - // #then - ultrabrain category: model=openai/gpt-5.2-codex, variant=xhigh + // #then - ultrabrain category: model=openai/gpt-5.3-codex, variant=xhigh expect(agents.atlas).toBeDefined() - expect(agents.atlas.model).toBe("openai/gpt-5.2-codex") + expect(agents.atlas.model).toBe("openai/gpt-5.3-codex") expect(agents.atlas.variant).toBe("xhigh") }) diff --git a/src/cli/__snapshots__/model-fallback.test.ts.snap b/src/cli/__snapshots__/model-fallback.test.ts.snap index 285f14f51..86193b65f 100644 --- a/src/cli/__snapshots__/model-fallback.test.ts.snap +++ b/src/cli/__snapshots__/model-fallback.test.ts.snap @@ -197,7 +197,7 @@ exports[`generateModelConfig single native provider uses OpenAI models when only "model": "opencode/gpt-5-nano", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -225,22 +225,22 @@ exports[`generateModelConfig single native provider uses OpenAI models when only }, "categories": { "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "opencode/glm-4.7-free", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "unspecified-low": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "visual-engineering": { @@ -264,7 +264,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa "model": "opencode/gpt-5-nano", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -292,14 +292,14 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa }, "categories": { "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "opencode/glm-4.7-free", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -307,7 +307,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa "variant": "high", }, "unspecified-low": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "visual-engineering": { @@ -451,7 +451,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal "model": "anthropic/claude-haiku-4-5", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -487,14 +487,14 @@ exports[`generateModelConfig all native providers uses preferred models from fal "variant": "high", }, "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -524,7 +524,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM "model": "anthropic/claude-haiku-4-5", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -560,14 +560,14 @@ exports[`generateModelConfig all native providers uses preferred models with isM "variant": "high", }, "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -598,14 +598,14 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on "model": "opencode/claude-haiku-4-5", }, "hephaestus": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "medium", }, "librarian": { "model": "opencode/glm-4.7-free", }, "metis": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, "momus": { @@ -620,11 +620,11 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on "variant": "high", }, "prometheus": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, "sisyphus": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, }, @@ -634,14 +634,14 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on "variant": "high", }, "deep": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "opencode/claude-haiku-4-5", }, "ultrabrain": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -671,14 +671,14 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is "model": "opencode/claude-haiku-4-5", }, "hephaestus": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "medium", }, "librarian": { "model": "opencode/glm-4.7-free", }, "metis": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, "momus": { @@ -693,11 +693,11 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is "variant": "high", }, "prometheus": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, "sisyphus": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, }, @@ -707,18 +707,18 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is "variant": "high", }, "deep": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "opencode/claude-haiku-4-5", }, "ultrabrain": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { - "model": "opencode/claude-opus-4-5", + "model": "opencode/claude-opus-4-6", "variant": "max", }, "unspecified-low": { @@ -745,14 +745,14 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when "model": "github-copilot/gpt-5-mini", }, "hephaestus": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "medium", }, "librarian": { "model": "github-copilot/claude-sonnet-4.5", }, "metis": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "momus": { @@ -767,11 +767,11 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when "variant": "high", }, "prometheus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "sisyphus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, }, @@ -781,14 +781,14 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when "variant": "high", }, "deep": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, "ultrabrain": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -818,14 +818,14 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with "model": "github-copilot/gpt-5-mini", }, "hephaestus": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "medium", }, "librarian": { "model": "github-copilot/claude-sonnet-4.5", }, "metis": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "momus": { @@ -840,11 +840,11 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with "variant": "high", }, "prometheus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "sisyphus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, }, @@ -854,18 +854,18 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with "variant": "high", }, "deep": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, "ultrabrain": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "unspecified-low": { @@ -1002,7 +1002,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen "model": "anthropic/claude-haiku-4-5", }, "hephaestus": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -1038,14 +1038,14 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen "variant": "high", }, "deep": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "opencode/gpt-5.2-codex", + "model": "opencode/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -1075,14 +1075,14 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb "model": "github-copilot/gpt-5-mini", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { "model": "github-copilot/claude-sonnet-4.5", }, "metis": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "momus": { @@ -1097,11 +1097,11 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb "variant": "high", }, "prometheus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "sisyphus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, }, @@ -1111,14 +1111,14 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb "variant": "high", }, "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -1275,14 +1275,14 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider "model": "opencode/claude-haiku-4-5", }, "hephaestus": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "medium", }, "librarian": { "model": "zai-coding-plan/glm-4.7", }, "metis": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "momus": { @@ -1297,11 +1297,11 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider "variant": "high", }, "prometheus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, "sisyphus": { - "model": "github-copilot/claude-opus-4.5", + "model": "github-copilot/claude-opus-4.6", "variant": "max", }, }, @@ -1311,14 +1311,14 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider "variant": "high", }, "deep": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "github-copilot/claude-haiku-4.5", }, "ultrabrain": { - "model": "github-copilot/gpt-5.2-codex", + "model": "github-copilot/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -1348,7 +1348,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe "model": "anthropic/claude-haiku-4-5", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -1384,14 +1384,14 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe "variant": "high", }, "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { @@ -1421,7 +1421,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is "model": "anthropic/claude-haiku-4-5", }, "hephaestus": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "librarian": { @@ -1457,14 +1457,14 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is "variant": "high", }, "deep": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "medium", }, "quick": { "model": "anthropic/claude-haiku-4-5", }, "ultrabrain": { - "model": "openai/gpt-5.2-codex", + "model": "openai/gpt-5.3-codex", "variant": "xhigh", }, "unspecified-high": { diff --git a/src/cli/config-manager.test.ts b/src/cli/config-manager.test.ts index 576206d30..3f98468ce 100644 --- a/src/cli/config-manager.test.ts +++ b/src/cli/config-manager.test.ts @@ -298,8 +298,8 @@ describe("generateOmoConfig - model fallback system", () => { // #when generating config const result = generateOmoConfig(config) - // #then Sisyphus uses Copilot (OR logic - copilot is in claude-opus-4-5 providers) - expect((result.agents as Record).sisyphus.model).toBe("github-copilot/claude-opus-4.5") + // #then Sisyphus uses Copilot (OR logic - copilot is in claude-opus-4-6 providers) + expect((result.agents as Record).sisyphus.model).toBe("github-copilot/claude-opus-4.6") }) test("uses ultimate fallback when no providers configured", () => { diff --git a/src/cli/doctor/checks/model-resolution.test.ts b/src/cli/doctor/checks/model-resolution.test.ts index 372990f9e..781564d5e 100644 --- a/src/cli/doctor/checks/model-resolution.test.ts +++ b/src/cli/doctor/checks/model-resolution.test.ts @@ -42,7 +42,7 @@ describe("model-resolution check", () => { // given: User has override for oracle agent const mockConfig = { agents: { - oracle: { model: "anthropic/claude-opus-4-5" }, + oracle: { model: "anthropic/claude-opus-4-6" }, }, } @@ -51,8 +51,8 @@ describe("model-resolution check", () => { // then: Oracle should show the override const oracle = info.agents.find((a) => a.name === "oracle") expect(oracle).toBeDefined() - expect(oracle!.userOverride).toBe("anthropic/claude-opus-4-5") - expect(oracle!.effectiveResolution).toBe("User override: anthropic/claude-opus-4-5") + expect(oracle!.userOverride).toBe("anthropic/claude-opus-4-6") + expect(oracle!.effectiveResolution).toBe("User override: anthropic/claude-opus-4-6") }) it("shows user override for category when configured", async () => { diff --git a/src/cli/index.ts b/src/cli/index.ts index 5a516fc59..a66a45fcb 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -43,7 +43,7 @@ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi): OpenAI Native openai/ models (GPT-5.2 for Oracle) Gemini Native google/ models (Gemini 3 Pro, Flash) Copilot github-copilot/ models (fallback) - OpenCode Zen opencode/ models (opencode/claude-opus-4-5, etc.) + OpenCode Zen opencode/ models (opencode/claude-opus-4-6, etc.) Z.ai zai-coding-plan/glm-4.7 (Librarian priority) Kimi kimi-for-coding/k2p5 (Sisyphus/Prometheus fallback) `) diff --git a/src/cli/install.ts b/src/cli/install.ts index c5c4a33be..a4143cd39 100644 --- a/src/cli/install.ts +++ b/src/cli/install.ts @@ -243,7 +243,7 @@ async function runTuiMode(detected: DetectedConfig): Promise { const result = generateModelConfig(config) // #then - expect(result.agents?.hephaestus?.model).toBe("openai/gpt-5.2-codex") + expect(result.agents?.hephaestus?.model).toBe("openai/gpt-5.3-codex") expect(result.agents?.hephaestus?.variant).toBe("medium") }) @@ -429,7 +429,7 @@ describe("generateModelConfig", () => { const result = generateModelConfig(config) // #then - expect(result.agents?.hephaestus?.model).toBe("github-copilot/gpt-5.2-codex") + expect(result.agents?.hephaestus?.model).toBe("github-copilot/gpt-5.3-codex") expect(result.agents?.hephaestus?.variant).toBe("medium") }) @@ -441,7 +441,7 @@ describe("generateModelConfig", () => { const result = generateModelConfig(config) // #then - expect(result.agents?.hephaestus?.model).toBe("opencode/gpt-5.2-codex") + expect(result.agents?.hephaestus?.model).toBe("opencode/gpt-5.3-codex") expect(result.agents?.hephaestus?.variant).toBe("medium") }) diff --git a/src/cli/model-fallback.ts b/src/cli/model-fallback.ts index 6d12b24ca..531b8ee40 100644 --- a/src/cli/model-fallback.ts +++ b/src/cli/model-fallback.ts @@ -71,7 +71,7 @@ function isProviderAvailable(provider: string, avail: ProviderAvailability): boo function transformModelForProvider(provider: string, model: string): string { if (provider === "github-copilot") { return model - .replace("claude-opus-4-5", "claude-opus-4.5") + .replace("claude-opus-4-6", "claude-opus-4.6") .replace("claude-sonnet-4-5", "claude-sonnet-4.5") .replace("claude-haiku-4-5", "claude-haiku-4.5") .replace("claude-sonnet-4", "claude-sonnet-4") diff --git a/src/features/background-agent/concurrency.test.ts b/src/features/background-agent/concurrency.test.ts index 9482ce8f3..2694e9a70 100644 --- a/src/features/background-agent/concurrency.test.ts +++ b/src/features/background-agent/concurrency.test.ts @@ -94,7 +94,7 @@ describe("ConcurrencyManager.getConcurrencyLimit", () => { // when const modelLimit = manager.getConcurrencyLimit("anthropic/claude-sonnet-4-5") - const providerLimit = manager.getConcurrencyLimit("anthropic/claude-opus-4-5") + const providerLimit = manager.getConcurrencyLimit("anthropic/claude-opus-4-6") const defaultLimit = manager.getConcurrencyLimit("google/gemini-3-pro") // then diff --git a/src/features/background-agent/manager.test.ts b/src/features/background-agent/manager.test.ts index cef1ef935..69dde4ddd 100644 --- a/src/features/background-agent/manager.test.ts +++ b/src/features/background-agent/manager.test.ts @@ -783,7 +783,7 @@ describe("BackgroundManager.notifyParentSession - dynamic message lookup", () => } const currentMessage: CurrentMessage = { agent: "sisyphus", - model: { providerID: "anthropic", modelID: "claude-opus-4-5" }, + model: { providerID: "anthropic", modelID: "claude-opus-4-6" }, } // when @@ -791,7 +791,7 @@ describe("BackgroundManager.notifyParentSession - dynamic message lookup", () => // then - uses currentMessage values, not task.parentModel/parentAgent expect(promptBody.agent).toBe("sisyphus") - expect(promptBody.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-5" }) + expect(promptBody.model).toEqual({ providerID: "anthropic", modelID: "claude-opus-4-6" }) }) test("should fallback to parentAgent when currentMessage.agent is undefined", async () => { @@ -997,7 +997,7 @@ describe("BackgroundManager.tryCompleteTask", () => { test("should release concurrency and clear key on completion", async () => { // given - const concurrencyKey = "anthropic/claude-opus-4-5" + const concurrencyKey = "anthropic/claude-opus-4-6" const concurrencyManager = getConcurrencyManager(manager) await concurrencyManager.acquire(concurrencyKey) @@ -1026,7 +1026,7 @@ describe("BackgroundManager.tryCompleteTask", () => { test("should prevent double completion and double release", async () => { // given - const concurrencyKey = "anthropic/claude-opus-4-5" + const concurrencyKey = "anthropic/claude-opus-4-6" const concurrencyManager = getConcurrencyManager(manager) await concurrencyManager.acquire(concurrencyKey) @@ -1657,7 +1657,7 @@ describe("BackgroundManager - Non-blocking Queue Integration", () => { description: "Task 1", prompt: "Do something", agent: "test-agent", - model: { providerID: "anthropic", modelID: "claude-opus-4-5" }, + model: { providerID: "anthropic", modelID: "claude-opus-4-6" }, parentSessionID: "parent-session", parentMessageID: "parent-message", } diff --git a/src/features/task-toast-manager/manager.test.ts b/src/features/task-toast-manager/manager.test.ts index 090ec8b62..f6a24111a 100644 --- a/src/features/task-toast-manager/manager.test.ts +++ b/src/features/task-toast-manager/manager.test.ts @@ -192,7 +192,7 @@ describe("TaskToastManager", () => { description: "Task with inherited model", agent: "sisyphus-junior", isBackground: false, - modelInfo: { model: "cliproxy/claude-opus-4-5", type: "inherited" as const }, + modelInfo: { model: "cliproxy/claude-opus-4-6", type: "inherited" as const }, } // when - addTask is called @@ -202,7 +202,7 @@ describe("TaskToastManager", () => { expect(mockClient.tui.showToast).toHaveBeenCalled() const call = mockClient.tui.showToast.mock.calls[0][0] expect(call.body.message).toContain("[FALLBACK]") - expect(call.body.message).toContain("cliproxy/claude-opus-4-5") + expect(call.body.message).toContain("cliproxy/claude-opus-4-6") expect(call.body.message).toContain("(inherited from parent)") }) diff --git a/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts b/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts index ed7e36e22..ca6d383c8 100644 --- a/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts +++ b/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts @@ -80,7 +80,7 @@ describe("executeCompact lock management", () => { let fakeTimeouts: FakeTimeouts const sessionID = "test-session-123" const directory = "/test/dir" - const msg = { providerID: "anthropic", modelID: "claude-opus-4-5" } + const msg = { providerID: "anthropic", modelID: "claude-opus-4-6" } beforeEach(() => { // given: Fresh state for each test @@ -332,7 +332,7 @@ describe("executeCompact lock management", () => { expect(mockClient.session.summarize).toHaveBeenCalledWith( expect.objectContaining({ path: { id: sessionID }, - body: { providerID: "anthropic", modelID: "claude-opus-4-5", auto: true }, + body: { providerID: "anthropic", modelID: "claude-opus-4-6", auto: true }, }), ) diff --git a/src/hooks/atlas/index.test.ts b/src/hooks/atlas/index.test.ts index a1b165e7c..b7d5e4207 100644 --- a/src/hooks/atlas/index.test.ts +++ b/src/hooks/atlas/index.test.ts @@ -47,7 +47,7 @@ describe("atlas hook", () => { } const messageData = { agent, - model: { providerID: "anthropic", modelID: "claude-opus-4-5" }, + model: { providerID: "anthropic", modelID: "claude-opus-4-6" }, } writeFileSync(join(messageDir, "msg_test001.json"), JSON.stringify(messageData)) } diff --git a/src/hooks/preemptive-compaction.test.ts b/src/hooks/preemptive-compaction.test.ts index b48cccb69..cb027ac7f 100644 --- a/src/hooks/preemptive-compaction.test.ts +++ b/src/hooks/preemptive-compaction.test.ts @@ -34,7 +34,7 @@ describe("preemptive-compaction", () => { info: { role: "assistant", providerID: "anthropic", - modelID: "claude-opus-4-5", + modelID: "claude-opus-4-6", tokens: { input: 180000, output: 0, @@ -69,7 +69,7 @@ describe("preemptive-compaction", () => { info: { role: "assistant", providerID: "anthropic", - modelID: "claude-opus-4-5", + modelID: "claude-opus-4-6", tokens: { input: 100000, output: 0, diff --git a/src/hooks/think-mode/index.test.ts b/src/hooks/think-mode/index.test.ts index b039ed31c..29e9a36a9 100644 --- a/src/hooks/think-mode/index.test.ts +++ b/src/hooks/think-mode/index.test.ts @@ -41,7 +41,7 @@ describe("createThinkModeHook integration", () => { const hook = createThinkModeHook() const input = createMockInput( "github-copilot", - "claude-opus-4-5", + "claude-opus-4-6", "Please think deeply about this problem" ) @@ -50,7 +50,7 @@ describe("createThinkModeHook integration", () => { // then should upgrade to high variant and inject thinking config const message = input.message as MessageWithInjectedProps - expect(input.message.model?.modelID).toBe("claude-opus-4-5-high") + expect(input.message.model?.modelID).toBe("claude-opus-4-6-high") expect(message.thinking).toBeDefined() expect((message.thinking as Record)?.type).toBe( "enabled" @@ -61,11 +61,11 @@ describe("createThinkModeHook integration", () => { }) it("should handle github-copilot Claude with dots in version", async () => { - // given a github-copilot Claude model with dot format (claude-opus-4.5) + // given a github-copilot Claude model with dot format (claude-opus-4.6) const hook = createThinkModeHook() const input = createMockInput( "github-copilot", - "claude-opus-4.5", + "claude-opus-4.6", "ultrathink mode" ) @@ -74,7 +74,7 @@ describe("createThinkModeHook integration", () => { // then should upgrade to high variant (hyphen format) const message = input.message as MessageWithInjectedProps - expect(input.message.model?.modelID).toBe("claude-opus-4-5-high") + expect(input.message.model?.modelID).toBe("claude-opus-4-6-high") expect(message.thinking).toBeDefined() }) @@ -179,7 +179,7 @@ describe("createThinkModeHook integration", () => { const hook = createThinkModeHook() const input = createMockInput( "github-copilot", - "claude-opus-4-5", + "claude-opus-4-6", "Just do this task" ) const originalModelID = input.message.model?.modelID @@ -271,7 +271,7 @@ describe("createThinkModeHook integration", () => { const hook = createThinkModeHook() const input = createMockInput( "github-copilot", - "claude-opus-4-5-high", + "claude-opus-4-6-high", "think deeply" ) @@ -280,7 +280,7 @@ describe("createThinkModeHook integration", () => { // then should NOT modify the model (already high) const message = input.message as MessageWithInjectedProps - expect(input.message.model?.modelID).toBe("claude-opus-4-5-high") + expect(input.message.model?.modelID).toBe("claude-opus-4-6-high") // No additional thinking config should be injected expect(message.thinking).toBeUndefined() }) @@ -341,13 +341,13 @@ describe("createThinkModeHook integration", () => { it("should handle empty prompt gracefully", async () => { // given empty prompt const hook = createThinkModeHook() - const input = createMockInput("github-copilot", "claude-opus-4-5", "") + const input = createMockInput("github-copilot", "claude-opus-4-6", "") // when the chat.params hook is called await hook["chat.params"](input, sessionID) // then should not upgrade (no think keyword) - expect(input.message.model?.modelID).toBe("claude-opus-4-5") + expect(input.message.model?.modelID).toBe("claude-opus-4-6") }) }) diff --git a/src/hooks/think-mode/switcher.test.ts b/src/hooks/think-mode/switcher.test.ts index 3efa98de5..9451fcb13 100644 --- a/src/hooks/think-mode/switcher.test.ts +++ b/src/hooks/think-mode/switcher.test.ts @@ -12,7 +12,7 @@ describe("think-mode switcher", () => { it("should resolve github-copilot Claude Opus to anthropic config", () => { // given a github-copilot provider with Claude Opus model const providerID = "github-copilot" - const modelID = "claude-opus-4-5" + const modelID = "claude-opus-4-6" // when getting thinking config const config = getThinkingConfig(providerID, modelID) @@ -38,8 +38,8 @@ describe("think-mode switcher", () => { }) it("should handle Claude with dots in version number", () => { - // given a model ID with dots (claude-opus-4.5) - const config = getThinkingConfig("github-copilot", "claude-opus-4.5") + // given a model ID with dots (claude-opus-4.6) + const config = getThinkingConfig("github-copilot", "claude-opus-4.6") // then should still return anthropic thinking config expect(config).not.toBeNull() @@ -127,18 +127,18 @@ describe("think-mode switcher", () => { describe("getHighVariant with dots vs hyphens", () => { it("should handle dots in Claude version numbers", () => { // given a Claude model ID with dot format - const variant = getHighVariant("claude-opus-4.5") + const variant = getHighVariant("claude-opus-4.6") // then should return high variant with hyphen format - expect(variant).toBe("claude-opus-4-5-high") + expect(variant).toBe("claude-opus-4-6-high") }) it("should handle hyphens in Claude version numbers", () => { // given a Claude model ID with hyphen format - const variant = getHighVariant("claude-opus-4-5") + const variant = getHighVariant("claude-opus-4-6") // then should return high variant - expect(variant).toBe("claude-opus-4-5-high") + expect(variant).toBe("claude-opus-4-6-high") }) it("should handle claude-opus-4-6 high variant", () => { @@ -177,7 +177,7 @@ describe("think-mode switcher", () => { it("should return null for already-high variants", () => { // given model IDs that are already high variants - expect(getHighVariant("claude-opus-4-5-high")).toBeNull() + expect(getHighVariant("claude-opus-4-6-high")).toBeNull() expect(getHighVariant("gpt-5-2-high")).toBeNull() expect(getHighVariant("gemini-3-pro-high")).toBeNull() }) @@ -193,7 +193,7 @@ describe("think-mode switcher", () => { describe("isAlreadyHighVariant", () => { it("should detect -high suffix", () => { // given model IDs with -high suffix - expect(isAlreadyHighVariant("claude-opus-4-5-high")).toBe(true) + expect(isAlreadyHighVariant("claude-opus-4-6-high")).toBe(true) expect(isAlreadyHighVariant("gpt-5-2-high")).toBe(true) expect(isAlreadyHighVariant("gemini-3-pro-high")).toBe(true) }) @@ -205,8 +205,8 @@ describe("think-mode switcher", () => { it("should return false for base models", () => { // given base model IDs without -high suffix - expect(isAlreadyHighVariant("claude-opus-4-5")).toBe(false) - expect(isAlreadyHighVariant("claude-opus-4.5")).toBe(false) + expect(isAlreadyHighVariant("claude-opus-4-6")).toBe(false) + expect(isAlreadyHighVariant("claude-opus-4.6")).toBe(false) expect(isAlreadyHighVariant("gpt-5.2")).toBe(false) expect(isAlreadyHighVariant("gemini-3-pro")).toBe(false) }) @@ -222,7 +222,7 @@ describe("think-mode switcher", () => { it("should return null for already-high variants", () => { // given already-high model variants expect( - getThinkingConfig("anthropic", "claude-opus-4-5-high") + getThinkingConfig("anthropic", "claude-opus-4-6-high") ).toBeNull() expect(getThinkingConfig("openai", "gpt-5-2-high")).toBeNull() expect(getThinkingConfig("google", "gemini-3-pro-high")).toBeNull() @@ -231,7 +231,7 @@ describe("think-mode switcher", () => { it("should return null for already-high variants via github-copilot", () => { // given already-high model variants via github-copilot expect( - getThinkingConfig("github-copilot", "claude-opus-4-5-high") + getThinkingConfig("github-copilot", "claude-opus-4-6-high") ).toBeNull() expect(getThinkingConfig("github-copilot", "gpt-5.2-high")).toBeNull() }) @@ -258,7 +258,7 @@ describe("think-mode switcher", () => { describe("Direct provider configs (backwards compatibility)", () => { it("should still work for direct anthropic provider", () => { // given direct anthropic provider - const config = getThinkingConfig("anthropic", "claude-opus-4-5") + const config = getThinkingConfig("anthropic", "claude-opus-4-6") // then should return anthropic thinking config expect(config).not.toBeNull() @@ -351,10 +351,10 @@ describe("think-mode switcher", () => { it("should handle prefixes with dots in version numbers", () => { // given a model ID with prefix and dots - const variant = getHighVariant("vertex_ai/claude-opus-4.5") + const variant = getHighVariant("vertex_ai/claude-opus-4.6") // then should normalize dots and preserve prefix - expect(variant).toBe("vertex_ai/claude-opus-4-5-high") + expect(variant).toBe("vertex_ai/claude-opus-4-6-high") }) it("should handle multiple different prefixes", () => { @@ -372,7 +372,7 @@ describe("think-mode switcher", () => { it("should return null for already-high prefixed models", () => { // given prefixed model IDs that are already high - expect(getHighVariant("vertex_ai/claude-opus-4-5-high")).toBeNull() + expect(getHighVariant("vertex_ai/claude-opus-4-6-high")).toBeNull() expect(getHighVariant("openai/gpt-5-2-high")).toBeNull() }) }) @@ -380,14 +380,14 @@ describe("think-mode switcher", () => { describe("isAlreadyHighVariant with prefixes", () => { it("should detect -high suffix in prefixed models", () => { // given prefixed model IDs with -high suffix - expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-5-high")).toBe(true) + expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-6-high")).toBe(true) expect(isAlreadyHighVariant("openai/gpt-5-2-high")).toBe(true) expect(isAlreadyHighVariant("custom/gemini-3-pro-high")).toBe(true) }) it("should return false for prefixed base models", () => { // given prefixed base model IDs without -high suffix - expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-5")).toBe(false) + expect(isAlreadyHighVariant("vertex_ai/claude-opus-4-6")).toBe(false) expect(isAlreadyHighVariant("openai/gpt-5-2")).toBe(false) }) @@ -410,7 +410,7 @@ describe("think-mode switcher", () => { it("should work with prefixed models on known providers", () => { // given known provider (anthropic) with prefixed model // This tests that the base model name is correctly extracted for capability check - const config = getThinkingConfig("anthropic", "custom-prefix/claude-opus-4-5") + const config = getThinkingConfig("anthropic", "custom-prefix/claude-opus-4-6") // then should return thinking config (base model is capable) expect(config).not.toBeNull() @@ -419,7 +419,7 @@ describe("think-mode switcher", () => { it("should return null for prefixed models that are already high", () => { // given prefixed already-high model - const config = getThinkingConfig("anthropic", "vertex_ai/claude-opus-4-5-high") + const config = getThinkingConfig("anthropic", "vertex_ai/claude-opus-4-6-high") // then should return null expect(config).toBeNull() @@ -452,11 +452,11 @@ describe("think-mode switcher", () => { it("should not break when switching to high variant in think mode", () => { // given think mode switching vertex_ai/claude model to high variant - const original = "vertex_ai/claude-opus-4-5" + const original = "vertex_ai/claude-opus-4-6" const high = getHighVariant(original) // then the high variant should be valid - expect(high).toBe("vertex_ai/claude-opus-4-5-high") + expect(high).toBe("vertex_ai/claude-opus-4-6-high") // #and should be recognized as already high expect(isAlreadyHighVariant(high!)).toBe(true) diff --git a/src/hooks/think-mode/switcher.ts b/src/hooks/think-mode/switcher.ts index b949c2c3a..677c28b35 100644 --- a/src/hooks/think-mode/switcher.ts +++ b/src/hooks/think-mode/switcher.ts @@ -38,14 +38,14 @@ function extractModelPrefix(modelID: string): { prefix: string; base: string } { /** * Normalizes model IDs to use consistent hyphen formatting. - * GitHub Copilot may use dots (claude-opus-4.5) but our maps use hyphens (claude-opus-4-5). + * GitHub Copilot may use dots (claude-opus-4.6) but our maps use hyphens (claude-opus-4-6). * This ensures lookups work regardless of format. * * @example - * normalizeModelID("claude-opus-4.5") // "claude-opus-4-5" + * normalizeModelID("claude-opus-4.6") // "claude-opus-4-6" * normalizeModelID("gemini-3.5-pro") // "gemini-3-5-pro" * normalizeModelID("gpt-5.2") // "gpt-5-2" - * normalizeModelID("vertex_ai/claude-opus-4.5") // "vertex_ai/claude-opus-4-5" + * normalizeModelID("vertex_ai/claude-opus-4.6") // "vertex_ai/claude-opus-4-6" */ function normalizeModelID(modelID: string): string { // Replace dots with hyphens when followed by a digit @@ -59,10 +59,10 @@ function normalizeModelID(modelID: string): string { * model provider (Anthropic, Google, OpenAI). * * @example - * resolveProvider("github-copilot", "claude-opus-4-5") // "anthropic" + * resolveProvider("github-copilot", "claude-opus-4-6") // "anthropic" * resolveProvider("github-copilot", "gemini-3-pro") // "google" * resolveProvider("github-copilot", "gpt-5.2") // "openai" - * resolveProvider("anthropic", "claude-opus-4-5") // "anthropic" (unchanged) + * resolveProvider("anthropic", "claude-opus-4-6") // "anthropic" (unchanged) */ function resolveProvider(providerID: string, modelID: string): string { // GitHub Copilot is a proxy - infer actual provider from model name @@ -89,7 +89,6 @@ const HIGH_VARIANT_MAP: Record = { // Claude "claude-sonnet-4-5": "claude-sonnet-4-5-high", "claude-opus-4-6": "claude-opus-4-6-high", - "claude-opus-4-5": "claude-opus-4-5-high", // Gemini "gemini-3-pro": "gemini-3-pro-high", "gemini-3-pro-low": "gemini-3-pro-high", diff --git a/src/index.ts b/src/index.ts index baf4f9590..c62c68b07 100644 --- a/src/index.ts +++ b/src/index.ts @@ -849,7 +849,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => { await compactionContextInjector({ sessionID: input.sessionID, providerID: "anthropic", - modelID: "claude-opus-4-5", + modelID: "claude-opus-4-6", usageRatio: 0.8, directory: ctx.directory, }); diff --git a/src/plugin-handlers/config-handler.test.ts b/src/plugin-handlers/config-handler.test.ts index 6f6fa3aed..2580fe5e3 100644 --- a/src/plugin-handlers/config-handler.test.ts +++ b/src/plugin-handlers/config-handler.test.ts @@ -63,7 +63,7 @@ beforeEach(() => { spyOn(mcpModule, "createBuiltinMcps" as any).mockReturnValue({}) spyOn(shared, "log" as any).mockImplementation(() => {}) - spyOn(shared, "fetchAvailableModels" as any).mockResolvedValue(new Set(["anthropic/claude-opus-4-5"])) + spyOn(shared, "fetchAvailableModels" as any).mockResolvedValue(new Set(["anthropic/claude-opus-4-6"])) spyOn(shared, "readConnectedProvidersCache" as any).mockReturnValue(null) spyOn(configDir, "getOpenCodeConfigPaths" as any).mockReturnValue({ @@ -73,7 +73,7 @@ beforeEach(() => { spyOn(permissionCompat, "migrateAgentConfig" as any).mockImplementation((config: Record) => config) - spyOn(modelResolver, "resolveModelWithFallback" as any).mockReturnValue({ model: "anthropic/claude-opus-4-5" }) + spyOn(modelResolver, "resolveModelWithFallback" as any).mockReturnValue({ model: "anthropic/claude-opus-4-6" }) }) afterEach(() => { @@ -123,7 +123,7 @@ describe("Plan agent demote behavior", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -154,7 +154,7 @@ describe("Plan agent demote behavior", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: { plan: { name: "plan", @@ -191,7 +191,7 @@ describe("Plan agent demote behavior", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: { plan: { name: "plan", @@ -228,7 +228,7 @@ describe("Plan agent demote behavior", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -263,7 +263,7 @@ describe("Agent permission defaults", () => { }) const pluginConfig: OhMyOpenCodeConfig = {} const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -295,7 +295,7 @@ describe("Prometheus category config resolution", () => { // then expect(config).toBeDefined() - expect(config?.model).toBe("openai/gpt-5.2-codex") + expect(config?.model).toBe("openai/gpt-5.3-codex") expect(config?.variant).toBe("xhigh") }) @@ -355,7 +355,7 @@ describe("Prometheus category config resolution", () => { // then - falls back to DEFAULT_CATEGORIES expect(config).toBeDefined() - expect(config?.model).toBe("openai/gpt-5.2-codex") + expect(config?.model).toBe("openai/gpt-5.3-codex") expect(config?.variant).toBe("xhigh") }) @@ -406,7 +406,7 @@ describe("Prometheus direct override priority over category", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -446,7 +446,7 @@ describe("Prometheus direct override priority over category", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -487,7 +487,7 @@ describe("Prometheus direct override priority over category", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -522,7 +522,7 @@ describe("Prometheus direct override priority over category", () => { }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const handler = createConfigHandler({ @@ -560,7 +560,7 @@ describe("Deadlock prevention - fetchAvailableModels must not receive client", ( }, } const config: Record = { - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", agent: {}, } const mockClient = { diff --git a/src/shared/agent-config-integration.test.ts b/src/shared/agent-config-integration.test.ts index 160410475..e663da9fc 100644 --- a/src/shared/agent-config-integration.test.ts +++ b/src/shared/agent-config-integration.test.ts @@ -8,9 +8,9 @@ describe("Agent Config Integration", () => { test("migrates old format agent keys to lowercase", () => { // given - config with old format keys const oldConfig = { - Sisyphus: { model: "anthropic/claude-opus-4-5" }, - Atlas: { model: "anthropic/claude-opus-4-5" }, - "Prometheus (Planner)": { model: "anthropic/claude-opus-4-5" }, + Sisyphus: { model: "anthropic/claude-opus-4-6" }, + Atlas: { model: "anthropic/claude-opus-4-6" }, + "Prometheus (Planner)": { model: "anthropic/claude-opus-4-6" }, "Metis (Plan Consultant)": { model: "anthropic/claude-sonnet-4-5" }, "Momus (Plan Reviewer)": { model: "anthropic/claude-sonnet-4-5" }, } @@ -33,9 +33,9 @@ describe("Agent Config Integration", () => { expect(result.migrated).not.toHaveProperty("Momus (Plan Reviewer)") // then - values are preserved - expect(result.migrated.sisyphus).toEqual({ model: "anthropic/claude-opus-4-5" }) - expect(result.migrated.atlas).toEqual({ model: "anthropic/claude-opus-4-5" }) - expect(result.migrated.prometheus).toEqual({ model: "anthropic/claude-opus-4-5" }) + expect(result.migrated.sisyphus).toEqual({ model: "anthropic/claude-opus-4-6" }) + expect(result.migrated.atlas).toEqual({ model: "anthropic/claude-opus-4-6" }) + expect(result.migrated.prometheus).toEqual({ model: "anthropic/claude-opus-4-6" }) // then - changed flag is true expect(result.changed).toBe(true) @@ -44,7 +44,7 @@ describe("Agent Config Integration", () => { test("preserves already lowercase keys", () => { // given - config with lowercase keys const config = { - sisyphus: { model: "anthropic/claude-opus-4-5" }, + sisyphus: { model: "anthropic/claude-opus-4-6" }, oracle: { model: "openai/gpt-5.2" }, librarian: { model: "opencode/glm-4.7-free" }, } @@ -62,9 +62,9 @@ describe("Agent Config Integration", () => { test("handles mixed case config", () => { // given - config with mixed old and new format const mixedConfig = { - Sisyphus: { model: "anthropic/claude-opus-4-5" }, + Sisyphus: { model: "anthropic/claude-opus-4-6" }, oracle: { model: "openai/gpt-5.2" }, - "Prometheus (Planner)": { model: "anthropic/claude-opus-4-5" }, + "Prometheus (Planner)": { model: "anthropic/claude-opus-4-6" }, librarian: { model: "opencode/glm-4.7-free" }, } @@ -172,8 +172,8 @@ describe("Agent Config Integration", () => { test("old config migrates and displays correctly", () => { // given - old format config const oldConfig = { - Sisyphus: { model: "anthropic/claude-opus-4-5", temperature: 0.1 }, - "Prometheus (Planner)": { model: "anthropic/claude-opus-4-5" }, + Sisyphus: { model: "anthropic/claude-opus-4-6", temperature: 0.1 }, + "Prometheus (Planner)": { model: "anthropic/claude-opus-4-6" }, } // when - config is migrated @@ -192,15 +192,15 @@ describe("Agent Config Integration", () => { expect(prometheusDisplay).toBe("Prometheus (Plan Builder)") // then - config values are preserved - expect(result.migrated.sisyphus).toEqual({ model: "anthropic/claude-opus-4-5", temperature: 0.1 }) - expect(result.migrated.prometheus).toEqual({ model: "anthropic/claude-opus-4-5" }) + expect(result.migrated.sisyphus).toEqual({ model: "anthropic/claude-opus-4-6", temperature: 0.1 }) + expect(result.migrated.prometheus).toEqual({ model: "anthropic/claude-opus-4-6" }) }) test("new config works without migration", () => { // given - new format config (already lowercase) const newConfig = { - sisyphus: { model: "anthropic/claude-opus-4-5" }, - atlas: { model: "anthropic/claude-opus-4-5" }, + sisyphus: { model: "anthropic/claude-opus-4-6" }, + atlas: { model: "anthropic/claude-opus-4-6" }, } // when - migration is applied (should be no-op) diff --git a/src/shared/agent-variant.test.ts b/src/shared/agent-variant.test.ts index 16c46e913..b36bade3b 100644 --- a/src/shared/agent-variant.test.ts +++ b/src/shared/agent-variant.test.ts @@ -84,14 +84,14 @@ describe("applyAgentVariant", () => { describe("resolveVariantForModel", () => { test("returns agent override variant when configured", () => { - // given - use a model in sisyphus chain (claude-opus-4-5 has default variant "max") + // given - use a model in sisyphus chain (claude-opus-4-6 has default variant "max") // to verify override takes precedence over fallback chain const config = { agents: { sisyphus: { variant: "high" }, }, } as OhMyOpenCodeConfig - const model = { providerID: "anthropic", modelID: "claude-opus-4-5" } + const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when const variant = resolveVariantForModel(config, "sisyphus", model) @@ -103,7 +103,7 @@ describe("resolveVariantForModel", () => { test("returns correct variant for anthropic provider", () => { // given const config = {} as OhMyOpenCodeConfig - const model = { providerID: "anthropic", modelID: "claude-opus-4-5" } + const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when const variant = resolveVariantForModel(config, "sisyphus", model) @@ -113,9 +113,9 @@ describe("resolveVariantForModel", () => { }) test("returns correct variant for openai provider (hephaestus agent)", () => { - // #given hephaestus has openai/gpt-5.2-codex with variant "medium" in its chain + // #given hephaestus has openai/gpt-5.3-codex with variant "medium" in its chain const config = {} as OhMyOpenCodeConfig - const model = { providerID: "openai", modelID: "gpt-5.2-codex" } + const model = { providerID: "openai", modelID: "gpt-5.3-codex" } // #when const variant = resolveVariantForModel(config, "hephaestus", model) @@ -151,7 +151,7 @@ describe("resolveVariantForModel", () => { test("returns undefined for unknown agent", () => { // given const config = {} as OhMyOpenCodeConfig - const model = { providerID: "anthropic", modelID: "claude-opus-4-5" } + const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when const variant = resolveVariantForModel(config, "nonexistent-agent", model) @@ -179,7 +179,7 @@ describe("resolveVariantForModel", () => { "custom-agent": { category: "ultrabrain" }, }, } as OhMyOpenCodeConfig - const model = { providerID: "openai", modelID: "gpt-5.2-codex" } + const model = { providerID: "openai", modelID: "gpt-5.3-codex" } // when const variant = resolveVariantForModel(config, "custom-agent", model) @@ -203,7 +203,7 @@ describe("resolveVariantForModel", () => { test("returns correct variant for oracle agent with anthropic", () => { // given const config = {} as OhMyOpenCodeConfig - const model = { providerID: "anthropic", modelID: "claude-opus-4-5" } + const model = { providerID: "anthropic", modelID: "claude-opus-4-6" } // when const variant = resolveVariantForModel(config, "oracle", model) diff --git a/src/shared/migration.test.ts b/src/shared/migration.test.ts index b2a9836a5..2ba28dc71 100644 --- a/src/shared/migration.test.ts +++ b/src/shared/migration.test.ts @@ -15,7 +15,7 @@ describe("migrateAgentNames", () => { test("migrates legacy OmO names to lowercase", () => { // given: Config with legacy OmO agent names const agents = { - omo: { model: "anthropic/claude-opus-4-5" }, + omo: { model: "anthropic/claude-opus-4-6" }, OmO: { temperature: 0.5 }, "OmO-Plan": { prompt: "custom prompt" }, } @@ -84,7 +84,7 @@ describe("migrateAgentNames", () => { test("migrates orchestrator-sisyphus to atlas", () => { // given: Config with legacy orchestrator-sisyphus agent name const agents = { - "orchestrator-sisyphus": { model: "anthropic/claude-opus-4-5" }, + "orchestrator-sisyphus": { model: "anthropic/claude-opus-4-6" }, } // when: Migrate agent names @@ -92,14 +92,14 @@ describe("migrateAgentNames", () => { // then: orchestrator-sisyphus should be migrated to atlas expect(changed).toBe(true) - expect(migrated["atlas"]).toEqual({ model: "anthropic/claude-opus-4-5" }) + expect(migrated["atlas"]).toEqual({ model: "anthropic/claude-opus-4-6" }) expect(migrated["orchestrator-sisyphus"]).toBeUndefined() }) test("migrates lowercase atlas to atlas", () => { // given: Config with lowercase atlas agent name const agents = { - atlas: { model: "anthropic/claude-opus-4-5" }, + atlas: { model: "anthropic/claude-opus-4-6" }, } // when: Migrate agent names @@ -107,7 +107,7 @@ describe("migrateAgentNames", () => { // then: lowercase atlas should remain atlas (no change needed) expect(changed).toBe(false) - expect(migrated["atlas"]).toEqual({ model: "anthropic/claude-opus-4-5" }) + expect(migrated["atlas"]).toEqual({ model: "anthropic/claude-opus-4-6" }) }) test("migrates Sisyphus variants to lowercase", () => { @@ -470,7 +470,7 @@ describe("migrateAgentConfigToCategory", () => { { model: "google/gemini-3-flash" }, { model: "openai/gpt-5.2" }, { model: "anthropic/claude-haiku-4-5" }, - { model: "anthropic/claude-opus-4-5" }, + { model: "anthropic/claude-opus-4-6" }, { model: "anthropic/claude-sonnet-4-5" }, ] @@ -550,7 +550,7 @@ describe("shouldDeleteAgentConfig", () => { // given: Config with custom model override const config = { category: "visual-engineering", - model: "anthropic/claude-opus-4-5", + model: "anthropic/claude-opus-4-6", } // when: Check if config should be deleted diff --git a/src/shared/migration.ts b/src/shared/migration.ts index e50042469..096a24869 100644 --- a/src/shared/migration.ts +++ b/src/shared/migration.ts @@ -85,7 +85,7 @@ export const MODEL_TO_CATEGORY_MAP: Record = { "google/gemini-3-flash": "writing", "openai/gpt-5.2": "ultrabrain", "anthropic/claude-haiku-4-5": "quick", - "anthropic/claude-opus-4-5": "unspecified-high", + "anthropic/claude-opus-4-6": "unspecified-high", "anthropic/claude-sonnet-4-5": "unspecified-low", } diff --git a/src/shared/model-availability.test.ts b/src/shared/model-availability.test.ts index d831ac279..80d637c74 100644 --- a/src/shared/model-availability.test.ts +++ b/src/shared/model-availability.test.ts @@ -33,7 +33,7 @@ describe("fetchAvailableModels", () => { it("#given cache file with models #when fetchAvailableModels called with connectedProviders #then returns Set of model IDs", async () => { writeModelsCache({ openai: { id: "openai", models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { id: "anthropic", models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { id: "anthropic", models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, google: { id: "google", models: { "gemini-3-pro": { id: "gemini-3-pro" } } }, }) @@ -44,7 +44,7 @@ describe("fetchAvailableModels", () => { expect(result).toBeInstanceOf(Set) expect(result.size).toBe(3) expect(result.has("openai/gpt-5.2")).toBe(true) - expect(result.has("anthropic/claude-opus-4-5")).toBe(true) + expect(result.has("anthropic/claude-opus-4-6")).toBe(true) expect(result.has("google/gemini-3-pro")).toBe(true) }) @@ -67,7 +67,7 @@ describe("fetchAvailableModels", () => { model: { list: async () => ({ data: [ - { id: "gpt-5.2-codex", provider: "openai" }, + { id: "gpt-5.3-codex", provider: "openai" }, { id: "gemini-3-pro", provider: "google" }, ], }), @@ -77,7 +77,7 @@ describe("fetchAvailableModels", () => { const result = await fetchAvailableModels(client) expect(result).toBeInstanceOf(Set) - expect(result.has("openai/gpt-5.2-codex")).toBe(true) + expect(result.has("openai/gpt-5.3-codex")).toBe(true) expect(result.has("google/gemini-3-pro")).toBe(false) }) @@ -96,7 +96,7 @@ describe("fetchAvailableModels", () => { model: { list: async () => ({ data: [ - { id: "gpt-5.2-codex", provider: "openai" }, + { id: "gpt-5.3-codex", provider: "openai" }, { id: "gemini-3-pro", provider: "google" }, ], }), @@ -106,14 +106,14 @@ describe("fetchAvailableModels", () => { const result = await fetchAvailableModels(client, { connectedProviders: ["openai", "google"] }) expect(result).toBeInstanceOf(Set) - expect(result.has("openai/gpt-5.2-codex")).toBe(true) + expect(result.has("openai/gpt-5.3-codex")).toBe(true) expect(result.has("google/gemini-3-pro")).toBe(true) }) it("#given cache read twice #when second call made with same providers #then reads fresh each time", async () => { writeModelsCache({ openai: { id: "openai", models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { id: "anthropic", models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { id: "anthropic", models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, }) const result1 = await fetchAvailableModels(undefined, { connectedProviders: ["openai"] }) @@ -134,7 +134,7 @@ describe("fetchAvailableModels", () => { it("#given cache file with various providers #when fetchAvailableModels called with all providers #then extracts all IDs correctly", async () => { writeModelsCache({ - openai: { id: "openai", models: { "gpt-5.2-codex": { id: "gpt-5.2-codex" } } }, + openai: { id: "openai", models: { "gpt-5.3-codex": { id: "gpt-5.3-codex" } } }, anthropic: { id: "anthropic", models: { "claude-sonnet-4-5": { id: "claude-sonnet-4-5" } } }, google: { id: "google", models: { "gemini-3-flash": { id: "gemini-3-flash" } } }, opencode: { id: "opencode", models: { "gpt-5-nano": { id: "gpt-5-nano" } } }, @@ -145,7 +145,7 @@ describe("fetchAvailableModels", () => { }) expect(result.size).toBe(4) - expect(result.has("openai/gpt-5.2-codex")).toBe(true) + expect(result.has("openai/gpt-5.3-codex")).toBe(true) expect(result.has("anthropic/claude-sonnet-4-5")).toBe(true) expect(result.has("google/gemini-3-flash")).toBe(true) expect(result.has("opencode/gpt-5-nano")).toBe(true) @@ -159,8 +159,8 @@ describe("fuzzyMatchModel", () => { it("should match substring in model name", () => { const available = new Set([ "openai/gpt-5.2", - "openai/gpt-5.2-codex", - "anthropic/claude-opus-4-5", + "openai/gpt-5.3-codex", + "anthropic/claude-opus-4-6", ]) const result = fuzzyMatchModel("gpt-5.2", available) expect(result).toBe("openai/gpt-5.2") @@ -185,7 +185,7 @@ describe("fuzzyMatchModel", () => { it("should prefer exact match over substring match", () => { const available = new Set([ "openai/gpt-5.2", - "openai/gpt-5.2-codex", + "openai/gpt-5.3-codex", "openai/gpt-5.2-ultra", ]) const result = fuzzyMatchModel("gpt-5.2", available) @@ -207,13 +207,13 @@ describe("fuzzyMatchModel", () => { // given available models with claude variants // when searching for claude-opus // then return matching claude-opus model - it("should match claude-opus to claude-opus-4-5", () => { + it("should match claude-opus to claude-opus-4-6", () => { const available = new Set([ - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", "anthropic/claude-sonnet-4-5", ]) const result = fuzzyMatchModel("claude-opus", available) - expect(result).toBe("anthropic/claude-opus-4-5") + expect(result).toBe("anthropic/claude-opus-4-6") }) // given available models from multiple providers @@ -222,7 +222,7 @@ describe("fuzzyMatchModel", () => { it("should filter by provider when providers array is given", () => { const available = new Set([ "openai/gpt-5.2", - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", "google/gemini-3", ]) const result = fuzzyMatchModel("gpt", available, ["openai"]) @@ -235,7 +235,7 @@ describe("fuzzyMatchModel", () => { it("should return null when provider filter excludes all matches", () => { const available = new Set([ "openai/gpt-5.2", - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", ]) const result = fuzzyMatchModel("claude", available, ["openai"]) expect(result).toBeNull() @@ -247,7 +247,7 @@ describe("fuzzyMatchModel", () => { it("should return null when no match found", () => { const available = new Set([ "openai/gpt-5.2", - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", ]) const result = fuzzyMatchModel("gemini", available) expect(result).toBeNull() @@ -259,7 +259,7 @@ describe("fuzzyMatchModel", () => { it("should match case-insensitively", () => { const available = new Set([ "openai/gpt-5.2", - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", ]) const result = fuzzyMatchModel("GPT-5.2", available) expect(result).toBe("openai/gpt-5.2") @@ -270,11 +270,11 @@ describe("fuzzyMatchModel", () => { // then return exact match first it("should prioritize exact match over longer variants", () => { const available = new Set([ - "anthropic/claude-opus-4-5", - "anthropic/claude-opus-4-5-extended", + "anthropic/claude-opus-4-6", + "anthropic/claude-opus-4-6-extended", ]) - const result = fuzzyMatchModel("claude-opus-4-5", available) - expect(result).toBe("anthropic/claude-opus-4-5") + const result = fuzzyMatchModel("claude-opus-4-6", available) + expect(result).toBe("anthropic/claude-opus-4-6") }) // given available models with similar model IDs (e.g., glm-4.7 and glm-4.7-free) @@ -319,7 +319,7 @@ describe("fuzzyMatchModel", () => { it("should search all specified providers", () => { const available = new Set([ "openai/gpt-5.2", - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", "google/gemini-3", ]) const result = fuzzyMatchModel("gpt", available, ["openai", "google"]) @@ -464,7 +464,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { it("should filter models by connected providers", async () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, google: { models: { "gemini-3-pro": { id: "gemini-3-pro" } } }, }) @@ -473,7 +473,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { }) expect(result.size).toBe(1) - expect(result.has("anthropic/claude-opus-4-5")).toBe(true) + expect(result.has("anthropic/claude-opus-4-6")).toBe(true) expect(result.has("openai/gpt-5.2")).toBe(false) expect(result.has("google/gemini-3-pro")).toBe(false) }) @@ -484,7 +484,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { it("should filter models by multiple connected providers", async () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, google: { models: { "gemini-3-pro": { id: "gemini-3-pro" } } }, }) @@ -493,7 +493,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { }) expect(result.size).toBe(2) - expect(result.has("anthropic/claude-opus-4-5")).toBe(true) + expect(result.has("anthropic/claude-opus-4-6")).toBe(true) expect(result.has("google/gemini-3-pro")).toBe(true) expect(result.has("openai/gpt-5.2")).toBe(false) }) @@ -504,7 +504,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { it("should return empty set when connectedProviders is empty", async () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, }) const result = await fetchAvailableModels(undefined, { @@ -520,7 +520,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { it("should return empty set when connectedProviders not specified", async () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, }) const result = await fetchAvailableModels() @@ -549,7 +549,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { it("should return models from providers that exist in both cache and connected list", async () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, }) const result = await fetchAvailableModels(undefined, { @@ -557,7 +557,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { }) expect(result.size).toBe(1) - expect(result.has("anthropic/claude-opus-4-5")).toBe(true) + expect(result.has("anthropic/claude-opus-4-6")).toBe(true) }) // given filtered fetch @@ -566,7 +566,7 @@ describe("fetchAvailableModels with connected providers filtering", () => { it("should not cache filtered results", async () => { writeModelsCache({ openai: { models: { "gpt-5.2": { id: "gpt-5.2" } } }, - anthropic: { models: { "claude-opus-4-5": { id: "claude-opus-4-5" } } }, + anthropic: { models: { "claude-opus-4-6": { id: "claude-opus-4-6" } } }, }) // First call with anthropic @@ -641,13 +641,13 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", writeProviderModelsCache({ models: { opencode: ["glm-4.7-free", "gpt-5-nano"], - anthropic: ["claude-opus-4-5"] + anthropic: ["claude-opus-4-6"] }, connected: ["opencode", "anthropic"] }) writeModelsCache({ opencode: { models: { "glm-4.7-free": {}, "gpt-5-nano": {}, "gpt-5.2": {} } }, - anthropic: { models: { "claude-opus-4-5": {}, "claude-sonnet-4-5": {} } } + anthropic: { models: { "claude-opus-4-6": {}, "claude-sonnet-4-5": {} } } }) const result = await fetchAvailableModels(undefined, { @@ -657,7 +657,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", expect(result.size).toBe(3) expect(result.has("opencode/glm-4.7-free")).toBe(true) expect(result.has("opencode/gpt-5-nano")).toBe(true) - expect(result.has("anthropic/claude-opus-4-5")).toBe(true) + expect(result.has("anthropic/claude-opus-4-6")).toBe(true) expect(result.has("opencode/gpt-5.2")).toBe(false) expect(result.has("anthropic/claude-sonnet-4-5")).toBe(false) }) @@ -708,7 +708,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", writeProviderModelsCache({ models: { opencode: ["glm-4.7-free"], - anthropic: ["claude-opus-4-5"], + anthropic: ["claude-opus-4-6"], google: ["gemini-3-pro"] }, connected: ["opencode", "anthropic", "google"] @@ -720,7 +720,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", expect(result.size).toBe(1) expect(result.has("opencode/glm-4.7-free")).toBe(true) - expect(result.has("anthropic/claude-opus-4-5")).toBe(false) + expect(result.has("anthropic/claude-opus-4-6")).toBe(false) expect(result.has("google/gemini-3-pro")).toBe(false) }) @@ -747,7 +747,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", it("should handle mixed string[] and object[] formats across providers", async () => { writeProviderModelsCache({ models: { - anthropic: ["claude-opus-4-5", "claude-sonnet-4-5"], + anthropic: ["claude-opus-4-6", "claude-sonnet-4-5"], ollama: [ { id: "ministral-3:14b-32k-agent", provider: "ollama" }, { id: "qwen3-coder:32k-agent", provider: "ollama" } @@ -761,7 +761,7 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", }) expect(result.size).toBe(4) - expect(result.has("anthropic/claude-opus-4-5")).toBe(true) + expect(result.has("anthropic/claude-opus-4-6")).toBe(true) expect(result.has("anthropic/claude-sonnet-4-5")).toBe(true) expect(result.has("ollama/ministral-3:14b-32k-agent")).toBe(true) expect(result.has("ollama/qwen3-coder:32k-agent")).toBe(true) @@ -794,10 +794,10 @@ describe("fetchAvailableModels with provider-models cache (whitelist-filtered)", describe("isModelAvailable", () => { it("returns true when model exists via fuzzy match", () => { // given - const available = new Set(["openai/gpt-5.2-codex", "anthropic/claude-opus-4-5"]) + const available = new Set(["openai/gpt-5.3-codex", "anthropic/claude-opus-4-6"]) // when - const result = isModelAvailable("gpt-5.2-codex", available) + const result = isModelAvailable("gpt-5.3-codex", available) // then expect(result).toBe(true) @@ -805,10 +805,10 @@ describe("isModelAvailable", () => { it("returns false when model not found", () => { // given - const available = new Set(["anthropic/claude-opus-4-5"]) + const available = new Set(["anthropic/claude-opus-4-6"]) // when - const result = isModelAvailable("gpt-5.2-codex", available) + const result = isModelAvailable("gpt-5.3-codex", available) // then expect(result).toBe(false) @@ -819,7 +819,7 @@ describe("isModelAvailable", () => { const available = new Set() // when - const result = isModelAvailable("gpt-5.2-codex", available) + const result = isModelAvailable("gpt-5.3-codex", available) // then expect(result).toBe(false) diff --git a/src/shared/model-availability.ts b/src/shared/model-availability.ts index f895d892b..6fa2fb173 100644 --- a/src/shared/model-availability.ts +++ b/src/shared/model-availability.ts @@ -20,7 +20,7 @@ import { readProviderModelsCache, hasProviderModelsCache, readConnectedProviders * If providers array is given, only models starting with "provider/" are considered. * * @example - * const available = new Set(["openai/gpt-5.2", "openai/gpt-5.2-codex", "anthropic/claude-opus-4-5"]) + * const available = new Set(["openai/gpt-5.2", "openai/gpt-5.3-codex", "anthropic/claude-opus-4-6"]) * fuzzyMatchModel("gpt-5.2", available) // → "openai/gpt-5.2" * fuzzyMatchModel("claude", available, ["openai"]) // → null (provider filter excludes anthropic) */ @@ -105,7 +105,7 @@ export function fuzzyMatchModel( /** * Check if a target model is available (fuzzy match by model name, no provider filtering) * - * @param targetModel - Model name to check (e.g., "gpt-5.2-codex") + * @param targetModel - Model name to check (e.g., "gpt-5.3-codex") * @param availableModels - Set of available models in "provider/model" format * @returns true if model is available, false otherwise */ diff --git a/src/shared/model-requirements.test.ts b/src/shared/model-requirements.test.ts index c332e544a..5ee4743e7 100644 --- a/src/shared/model-requirements.test.ts +++ b/src/shared/model-requirements.test.ts @@ -23,12 +23,12 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { expect(primary.variant).toBe("high") }) - test("sisyphus has claude-opus-4-6 as primary before claude-opus-4-5 and requiresAnyModel", () => { + test("sisyphus has claude-opus-4-6 as primary before claude-opus-4-6 and requiresAnyModel", () => { // #given - sisyphus agent requirement const sisyphus = AGENT_MODEL_REQUIREMENTS["sisyphus"] // #when - accessing Sisyphus requirement - // #then - fallbackChain has claude-opus-4-6 first, claude-opus-4-5 second, glm-4.7-free last + // #then - fallbackChain has claude-opus-4-6 first, claude-opus-4-6 second, glm-4.7-free last expect(sisyphus).toBeDefined() expect(sisyphus.fallbackChain).toBeArray() expect(sisyphus.fallbackChain).toHaveLength(6) @@ -41,7 +41,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { const secondary = sisyphus.fallbackChain[1] expect(secondary.providers[0]).toBe("anthropic") - expect(secondary.model).toBe("claude-opus-4-5") + expect(secondary.model).toBe("claude-opus-4-6") expect(secondary.variant).toBe("max") const last = sisyphus.fallbackChain[5] @@ -103,12 +103,12 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { expect(primary.model).toBe("gemini-3-flash") }) - test("prometheus has claude-opus-4-6 as primary before claude-opus-4-5", () => { + test("prometheus has claude-opus-4-6 as primary before claude-opus-4-6", () => { // #given - prometheus agent requirement const prometheus = AGENT_MODEL_REQUIREMENTS["prometheus"] // #when - accessing Prometheus requirement - // #then - claude-opus-4-6 is first, claude-opus-4-5 is second + // #then - claude-opus-4-6 is first, claude-opus-4-6 is second expect(prometheus).toBeDefined() expect(prometheus.fallbackChain).toBeArray() expect(prometheus.fallbackChain.length).toBeGreaterThan(1) @@ -119,17 +119,17 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { expect(primary.variant).toBe("max") const secondary = prometheus.fallbackChain[1] - expect(secondary.model).toBe("claude-opus-4-5") + expect(secondary.model).toBe("claude-opus-4-6") expect(secondary.providers[0]).toBe("anthropic") expect(secondary.variant).toBe("max") }) - test("metis has claude-opus-4-6 as primary before claude-opus-4-5", () => { + test("metis has claude-opus-4-6 as primary before claude-opus-4-6", () => { // #given - metis agent requirement const metis = AGENT_MODEL_REQUIREMENTS["metis"] // #when - accessing Metis requirement - // #then - claude-opus-4-6 is first, claude-opus-4-5 is second + // #then - claude-opus-4-6 is first, claude-opus-4-6 is second expect(metis).toBeDefined() expect(metis.fallbackChain).toBeArray() expect(metis.fallbackChain.length).toBeGreaterThan(1) @@ -140,7 +140,7 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { expect(primary.variant).toBe("max") const secondary = metis.fallbackChain[1] - expect(secondary.model).toBe("claude-opus-4-5") + expect(secondary.model).toBe("claude-opus-4-6") expect(secondary.providers[0]).toBe("anthropic") expect(secondary.variant).toBe("max") }) @@ -224,35 +224,35 @@ describe("AGENT_MODEL_REQUIREMENTS", () => { }) describe("CATEGORY_MODEL_REQUIREMENTS", () => { - test("ultrabrain has valid fallbackChain with gpt-5.2-codex as primary", () => { + test("ultrabrain has valid fallbackChain with gpt-5.3-codex as primary", () => { // given - ultrabrain category requirement const ultrabrain = CATEGORY_MODEL_REQUIREMENTS["ultrabrain"] // when - accessing ultrabrain requirement - // then - fallbackChain exists with gpt-5.2-codex as first entry + // then - fallbackChain exists with gpt-5.3-codex as first entry expect(ultrabrain).toBeDefined() expect(ultrabrain.fallbackChain).toBeArray() expect(ultrabrain.fallbackChain.length).toBeGreaterThan(0) const primary = ultrabrain.fallbackChain[0] expect(primary.variant).toBe("xhigh") - expect(primary.model).toBe("gpt-5.2-codex") + expect(primary.model).toBe("gpt-5.3-codex") expect(primary.providers[0]).toBe("openai") }) - test("deep has valid fallbackChain with gpt-5.2-codex as primary", () => { + test("deep has valid fallbackChain with gpt-5.3-codex as primary", () => { // given - deep category requirement const deep = CATEGORY_MODEL_REQUIREMENTS["deep"] // when - accessing deep requirement - // then - fallbackChain exists with gpt-5.2-codex as first entry, medium variant + // then - fallbackChain exists with gpt-5.3-codex as first entry, medium variant expect(deep).toBeDefined() expect(deep.fallbackChain).toBeArray() expect(deep.fallbackChain.length).toBeGreaterThan(0) const primary = deep.fallbackChain[0] expect(primary.variant).toBe("medium") - expect(primary.model).toBe("gpt-5.2-codex") + expect(primary.model).toBe("gpt-5.3-codex") expect(primary.providers[0]).toBe("openai") }) @@ -301,12 +301,12 @@ describe("CATEGORY_MODEL_REQUIREMENTS", () => { expect(primary.providers[0]).toBe("anthropic") }) - test("unspecified-high has claude-opus-4-6 as primary before claude-opus-4-5", () => { + test("unspecified-high has claude-opus-4-6 as primary before claude-opus-4-6", () => { // #given - unspecified-high category requirement const unspecifiedHigh = CATEGORY_MODEL_REQUIREMENTS["unspecified-high"] // #when - accessing unspecified-high requirement - // #then - claude-opus-4-6 is first, claude-opus-4-5 is second + // #then - claude-opus-4-6 is first, claude-opus-4-6 is second expect(unspecifiedHigh).toBeDefined() expect(unspecifiedHigh.fallbackChain).toBeArray() expect(unspecifiedHigh.fallbackChain.length).toBeGreaterThan(1) @@ -317,7 +317,7 @@ describe("CATEGORY_MODEL_REQUIREMENTS", () => { expect(primary.providers).toEqual(["anthropic"]) const secondary = unspecifiedHigh.fallbackChain[1] - expect(secondary.model).toBe("claude-opus-4-5") + expect(secondary.model).toBe("claude-opus-4-6") expect(secondary.variant).toBe("max") expect(secondary.providers[0]).toBe("anthropic") }) @@ -392,14 +392,14 @@ describe("FallbackEntry type", () => { // given - a valid FallbackEntry object const entry: FallbackEntry = { providers: ["anthropic", "github-copilot", "opencode"], - model: "claude-opus-4-5", + model: "claude-opus-4-6", variant: "high", } // when - accessing properties // then - all properties are accessible expect(entry.providers).toEqual(["anthropic", "github-copilot", "opencode"]) - expect(entry.model).toBe("claude-opus-4-5") + expect(entry.model).toBe("claude-opus-4-6") expect(entry.variant).toBe("high") }) @@ -421,7 +421,7 @@ describe("ModelRequirement type", () => { // given - a valid ModelRequirement object const requirement: ModelRequirement = { fallbackChain: [ - { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot"], model: "gpt-5.2", variant: "high" }, ], } @@ -430,7 +430,7 @@ describe("ModelRequirement type", () => { // then - fallbackChain is accessible with correct structure expect(requirement.fallbackChain).toBeArray() expect(requirement.fallbackChain).toHaveLength(2) - expect(requirement.fallbackChain[0].model).toBe("claude-opus-4-5") + expect(requirement.fallbackChain[0].model).toBe("claude-opus-4-6") expect(requirement.fallbackChain[1].model).toBe("gpt-5.2") }) @@ -480,12 +480,12 @@ describe("ModelRequirement type", () => { }) describe("requiresModel field in categories", () => { - test("deep category has requiresModel set to gpt-5.2-codex", () => { + test("deep category has requiresModel set to gpt-5.3-codex", () => { // given const deep = CATEGORY_MODEL_REQUIREMENTS["deep"] // when / #then - expect(deep.requiresModel).toBe("gpt-5.2-codex") + expect(deep.requiresModel).toBe("gpt-5.3-codex") }) test("artistry category has requiresModel set to gemini-3-pro", () => { diff --git a/src/shared/model-requirements.ts b/src/shared/model-requirements.ts index 709bec794..82a7c9ecb 100644 --- a/src/shared/model-requirements.ts +++ b/src/shared/model-requirements.ts @@ -16,7 +16,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { sisyphus: { fallbackChain: [ { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["zai-coding-plan"], model: "glm-4.7" }, @@ -26,7 +26,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { }, hephaestus: { fallbackChain: [ - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" }, + { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.3-codex", variant: "medium" }, ], requiresProvider: ["openai", "github-copilot", "opencode"], }, @@ -35,7 +35,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], }, librarian: { @@ -66,7 +66,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { prometheus: { fallbackChain: [ { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, @@ -76,7 +76,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { metis: { fallbackChain: [ { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, @@ -87,7 +87,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record = { fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" }, { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, ], }, @@ -107,32 +107,32 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { fallbackChain: [ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["zai-coding-plan"], model: "glm-4.7" }, ], }, ultrabrain: { fallbackChain: [ - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" }, + { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.3-codex", variant: "xhigh" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], }, deep: { fallbackChain: [ - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" }, + { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.3-codex", variant: "medium" }, { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, ], - requiresModel: "gpt-5.2-codex", + requiresModel: "gpt-5.3-codex", }, artistry: { fallbackChain: [ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, ], requiresModel: "gemini-3-pro", @@ -147,14 +147,14 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record = { "unspecified-low": { fallbackChain: [ { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }, - { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" }, + { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.3-codex", variant: "medium" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" }, ], }, "unspecified-high": { fallbackChain: [ { providers: ["anthropic"], model: "claude-opus-4-6", variant: "max" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, ], diff --git a/src/shared/model-resolver.test.ts b/src/shared/model-resolver.test.ts index c08a1e9ec..340f55081 100644 --- a/src/shared/model-resolver.test.ts +++ b/src/shared/model-resolver.test.ts @@ -8,7 +8,7 @@ describe("resolveModel", () => { test("returns userModel when all three are set", () => { // given const input: ModelResolutionInput = { - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", inheritedModel: "openai/gpt-5.2", systemDefault: "google/gemini-3-pro", } @@ -17,7 +17,7 @@ describe("resolveModel", () => { const result = resolveModel(input) // then - expect(result).toBe("anthropic/claude-opus-4-5") + expect(result).toBe("anthropic/claude-opus-4-6") }) test("returns inheritedModel when userModel is undefined", () => { @@ -87,7 +87,7 @@ describe("resolveModel", () => { test("same input returns same output (referential transparency)", () => { // given const input: ModelResolutionInput = { - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", inheritedModel: "openai/gpt-5.2", systemDefault: "google/gemini-3-pro", } @@ -118,11 +118,11 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { uiSelectedModel: "opencode/glm-4.7-free", - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", fallbackChain: [ - { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-5" }, + { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5", "github-copilot/claude-opus-4-5-preview"]), + availableModels: new Set(["anthropic/claude-opus-4-6", "github-copilot/claude-opus-4-6-preview"]), systemDefaultModel: "google/gemini-3-pro", } @@ -139,8 +139,8 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { uiSelectedModel: "opencode/glm-4.7-free", - userModel: "anthropic/claude-opus-4-5", - availableModels: new Set(["anthropic/claude-opus-4-5"]), + userModel: "anthropic/claude-opus-4-6", + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -156,8 +156,8 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { uiSelectedModel: " ", - userModel: "anthropic/claude-opus-4-5", - availableModels: new Set(["anthropic/claude-opus-4-5"]), + userModel: "anthropic/claude-opus-4-6", + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -165,16 +165,16 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("anthropic/claude-opus-4-5") - expect(logSpy).toHaveBeenCalledWith("Model resolved via config override", { model: "anthropic/claude-opus-4-5" }) + expect(result!.model).toBe("anthropic/claude-opus-4-6") + expect(logSpy).toHaveBeenCalledWith("Model resolved via config override", { model: "anthropic/claude-opus-4-6" }) }) test("empty string uiSelectedModel falls through to config override", () => { // given const input: ExtendedModelResolutionInput = { uiSelectedModel: "", - userModel: "anthropic/claude-opus-4-5", - availableModels: new Set(["anthropic/claude-opus-4-5"]), + userModel: "anthropic/claude-opus-4-6", + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -182,7 +182,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") }) }) @@ -190,11 +190,11 @@ describe("resolveModelWithFallback", () => { test("returns userModel with override source when userModel is provided", () => { // given const input: ExtendedModelResolutionInput = { - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", fallbackChain: [ - { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-5" }, + { providers: ["anthropic", "github-copilot"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5", "github-copilot/claude-opus-4-5-preview"]), + availableModels: new Set(["anthropic/claude-opus-4-6", "github-copilot/claude-opus-4-6-preview"]), systemDefaultModel: "google/gemini-3-pro", } @@ -202,9 +202,9 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("override") - expect(logSpy).toHaveBeenCalledWith("Model resolved via config override", { model: "anthropic/claude-opus-4-5" }) + expect(logSpy).toHaveBeenCalledWith("Model resolved via config override", { model: "anthropic/claude-opus-4-6" }) }) test("override takes priority even if model not in availableModels", () => { @@ -212,9 +212,9 @@ describe("resolveModelWithFallback", () => { const input: ExtendedModelResolutionInput = { userModel: "custom/my-model", fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -231,9 +231,9 @@ describe("resolveModelWithFallback", () => { const input: ExtendedModelResolutionInput = { userModel: " ", fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -249,9 +249,9 @@ describe("resolveModelWithFallback", () => { const input: ExtendedModelResolutionInput = { userModel: "", fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -268,9 +268,9 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["github-copilot/claude-opus-4-5-preview", "opencode/claude-opus-4-7"]), + availableModels: new Set(["github-copilot/claude-opus-4-6-preview", "opencode/claude-opus-4-7"]), systemDefaultModel: "google/gemini-3-pro", } @@ -278,12 +278,12 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("github-copilot/claude-opus-4-5-preview") + expect(result!.model).toBe("github-copilot/claude-opus-4-6-preview") expect(result!.source).toBe("provider-fallback") expect(logSpy).toHaveBeenCalledWith("Model resolved via fallback chain (availability confirmed)", { provider: "github-copilot", - model: "claude-opus-4-5", - match: "github-copilot/claude-opus-4-5-preview", + model: "claude-opus-4-6", + match: "github-copilot/claude-opus-4-6-preview", variant: undefined, }) }) @@ -294,7 +294,7 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["openai", "anthropic", "google"], model: "gpt-5.2" }, ], - availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-5", "google/gemini-3-pro"]), + availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-6", "google/gemini-3-pro"]), systemDefaultModel: "google/gemini-3-pro", } @@ -330,7 +330,7 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["anthropic", "github-copilot"], model: "claude-opus" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5", "github-copilot/claude-opus-4-5-preview"]), + availableModels: new Set(["anthropic/claude-opus-4-6", "github-copilot/claude-opus-4-6-preview"]), systemDefaultModel: "google/gemini-3-pro", } @@ -338,14 +338,14 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("provider-fallback") }) test("skips fallback chain when not provided", () => { // given const input: ExtendedModelResolutionInput = { - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -360,7 +360,7 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { fallbackChain: [], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -377,7 +377,7 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["anthropic"], model: "CLAUDE-OPUS" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -385,7 +385,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("provider-fallback") }) @@ -476,7 +476,7 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["anthropic"], model: "nonexistent-model" }, ], - availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-5"]), + availableModels: new Set(["openai/gpt-5.2", "anthropic/claude-opus-4-6"]), systemDefaultModel: "google/gemini-3-pro", } @@ -494,7 +494,7 @@ describe("resolveModelWithFallback", () => { const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(null) const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels: new Set(), systemDefaultModel: undefined, // no system default configured @@ -513,7 +513,7 @@ describe("resolveModelWithFallback", () => { const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["openai", "google"]) const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["anthropic", "openai"], model: "claude-opus-4-5" }, + { providers: ["anthropic", "openai"], model: "claude-opus-4-6" }, ], availableModels: new Set(), systemDefaultModel: "google/gemini-3-pro", @@ -523,7 +523,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - should use connected provider (openai) from fallback chain - expect(result!.model).toBe("openai/claude-opus-4-5") + expect(result!.model).toBe("openai/claude-opus-4-6") expect(result!.source).toBe("provider-fallback") cacheSpy.mockRestore() }) @@ -556,14 +556,14 @@ describe("resolveModelWithFallback", () => { { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" }, ], availableModels: new Set(), - systemDefaultModel: "quotio/claude-opus-4-5-20251101", + systemDefaultModel: "quotio/claude-opus-4-6-20251101", } // when const result = resolveModelWithFallback(input) // then - no provider in fallback is connected, fall through to system default - expect(result!.model).toBe("quotio/claude-opus-4-5-20251101") + expect(result!.model).toBe("quotio/claude-opus-4-6-20251101") expect(result!.source).toBe("system-default") cacheSpy.mockRestore() }) @@ -573,7 +573,7 @@ describe("resolveModelWithFallback", () => { const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(null) const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels: new Set(), systemDefaultModel: "google/gemini-3-pro", @@ -607,20 +607,20 @@ describe("resolveModelWithFallback", () => { describe("Multi-entry fallbackChain", () => { test("resolves to claude-opus when OpenAI unavailable but Anthropic available (oracle scenario)", () => { // given - const availableModels = new Set(["anthropic/claude-opus-4-5"]) + const availableModels = new Set(["anthropic/claude-opus-4-6"]) // when const result = resolveModelWithFallback({ fallbackChain: [ { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, - { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, + { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-6", variant: "max" }, ], availableModels, systemDefaultModel: "system/default", }) // then - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("provider-fallback") }) @@ -647,14 +647,14 @@ describe("resolveModelWithFallback", () => { // given const availableModels = new Set([ "openai/gpt-5.2", - "anthropic/claude-opus-4-5", + "anthropic/claude-opus-4-6", ]) // when const result = resolveModelWithFallback({ fallbackChain: [ { providers: ["openai"], model: "gpt-5.2" }, - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], availableModels, systemDefaultModel: "system/default", @@ -673,7 +673,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback({ fallbackChain: [ { providers: ["openai"], model: "gpt-5.2" }, - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, { providers: ["google"], model: "gemini-3-pro" }, ], availableModels, @@ -690,7 +690,7 @@ describe("resolveModelWithFallback", () => { test("result has correct ModelResolutionResult shape", () => { // given const input: ExtendedModelResolutionInput = { - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", availableModels: new Set(), systemDefaultModel: "google/gemini-3-pro", } @@ -713,7 +713,7 @@ describe("resolveModelWithFallback", () => { fallbackChain: [ { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, ], - availableModels: new Set(["google/gemini-3-pro-preview", "anthropic/claude-opus-4-5"]), + availableModels: new Set(["google/gemini-3-pro-preview", "anthropic/claude-opus-4-6"]), systemDefaultModel: "anthropic/claude-sonnet-4-5", } @@ -749,9 +749,9 @@ describe("resolveModelWithFallback", () => { const input: ExtendedModelResolutionInput = { categoryDefaultModel: "google/gemini-3-pro", fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: "system/default", } @@ -759,19 +759,19 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - should fall through to fallbackChain - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("provider-fallback") }) test("userModel takes priority over categoryDefaultModel", () => { // given - both userModel and categoryDefaultModel provided const input: ExtendedModelResolutionInput = { - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", categoryDefaultModel: "google/gemini-3-pro", fallbackChain: [ { providers: ["google"], model: "gemini-3-pro" }, ], - availableModels: new Set(["google/gemini-3-pro-preview", "anthropic/claude-opus-4-5"]), + availableModels: new Set(["google/gemini-3-pro-preview", "anthropic/claude-opus-4-6"]), systemDefaultModel: "system/default", } @@ -779,7 +779,7 @@ describe("resolveModelWithFallback", () => { const result = resolveModelWithFallback(input) // then - userModel wins - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("override") }) @@ -837,7 +837,7 @@ describe("resolveModelWithFallback", () => { test("still returns override when userModel provided even if systemDefaultModel undefined", () => { // given const input: ExtendedModelResolutionInput = { - userModel: "anthropic/claude-opus-4-5", + userModel: "anthropic/claude-opus-4-6", availableModels: new Set(), systemDefaultModel: undefined, } @@ -847,7 +847,7 @@ describe("resolveModelWithFallback", () => { // then expect(result).toBeDefined() - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("override") }) @@ -855,9 +855,9 @@ describe("resolveModelWithFallback", () => { // given const input: ExtendedModelResolutionInput = { fallbackChain: [ - { providers: ["anthropic"], model: "claude-opus-4-5" }, + { providers: ["anthropic"], model: "claude-opus-4-6" }, ], - availableModels: new Set(["anthropic/claude-opus-4-5"]), + availableModels: new Set(["anthropic/claude-opus-4-6"]), systemDefaultModel: undefined, } @@ -866,7 +866,7 @@ describe("resolveModelWithFallback", () => { // then expect(result).toBeDefined() - expect(result!.model).toBe("anthropic/claude-opus-4-5") + expect(result!.model).toBe("anthropic/claude-opus-4-6") expect(result!.source).toBe("provider-fallback") }) }) diff --git a/src/tools/delegate-task/constants.ts b/src/tools/delegate-task/constants.ts index ce0645736..ea405faef 100644 --- a/src/tools/delegate-task/constants.ts +++ b/src/tools/delegate-task/constants.ts @@ -194,12 +194,12 @@ You are NOT an interactive assistant. You are an autonomous problem-solver. export const DEFAULT_CATEGORIES: Record = { "visual-engineering": { model: "google/gemini-3-pro" }, - ultrabrain: { model: "openai/gpt-5.2-codex", variant: "xhigh" }, - deep: { model: "openai/gpt-5.2-codex", variant: "medium" }, + ultrabrain: { model: "openai/gpt-5.3-codex", variant: "xhigh" }, + deep: { model: "openai/gpt-5.3-codex", variant: "medium" }, artistry: { model: "google/gemini-3-pro", variant: "high" }, quick: { model: "anthropic/claude-haiku-4-5" }, "unspecified-low": { model: "anthropic/claude-sonnet-4-5" }, - "unspecified-high": { model: "anthropic/claude-opus-4-5", variant: "max" }, + "unspecified-high": { model: "anthropic/claude-opus-4-6", variant: "max" }, writing: { model: "google/gemini-3-flash" }, } @@ -343,11 +343,11 @@ FOR EVERY TASK, YOU MUST RECOMMEND: | Category | Best For | Model | |----------|----------|-------| | \`visual-engineering\` | Frontend, UI/UX, design, styling, animation | google/gemini-3-pro | -| \`ultrabrain\` | Complex architecture, deep logical reasoning | openai/gpt-5.2-codex | +| \`ultrabrain\` | Complex architecture, deep logical reasoning | openai/gpt-5.3-codex | | \`artistry\` | Highly creative/artistic tasks, novel ideas | google/gemini-3-pro | | \`quick\` | Trivial tasks - single file, typo fixes | anthropic/claude-haiku-4-5 | | \`unspecified-low\` | Moderate effort, doesn't fit other categories | anthropic/claude-sonnet-4-5 | -| \`unspecified-high\` | High effort, doesn't fit other categories | anthropic/claude-opus-4-5 | +| \`unspecified-high\` | High effort, doesn't fit other categories | anthropic/claude-opus-4-6 | | \`writing\` | Documentation, prose, technical writing | google/gemini-3-flash | ### AVAILABLE SKILLS (ALWAYS EVALUATE ALL) diff --git a/src/tools/delegate-task/tools.test.ts b/src/tools/delegate-task/tools.test.ts index 84ee612b5..effc0bf40 100644 --- a/src/tools/delegate-task/tools.test.ts +++ b/src/tools/delegate-task/tools.test.ts @@ -28,9 +28,9 @@ describe("sisyphus-task", () => { cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["anthropic", "google", "openai"]) providerModelsSpy = spyOn(connectedProvidersCache, "readProviderModelsCache").mockReturnValue({ models: { - anthropic: ["claude-opus-4-5", "claude-sonnet-4-5", "claude-haiku-4-5"], + anthropic: ["claude-opus-4-6", "claude-sonnet-4-5", "claude-haiku-4-5"], google: ["gemini-3-pro", "gemini-3-flash"], - openai: ["gpt-5.2", "gpt-5.2-codex"], + openai: ["gpt-5.2", "gpt-5.3-codex"], }, connected: ["anthropic", "google", "openai"], updatedAt: "2026-01-01T00:00:00.000Z", @@ -59,7 +59,7 @@ describe("sisyphus-task", () => { // when / #then expect(category).toBeDefined() - expect(category.model).toBe("openai/gpt-5.2-codex") + expect(category.model).toBe("openai/gpt-5.3-codex") expect(category.variant).toBe("xhigh") }) @@ -69,7 +69,7 @@ describe("sisyphus-task", () => { // when / #then expect(category).toBeDefined() - expect(category.model).toBe("openai/gpt-5.2-codex") + expect(category.model).toBe("openai/gpt-5.3-codex") expect(category.variant).toBe("medium") }) }) @@ -216,7 +216,7 @@ describe("sisyphus-task", () => { app: { agents: async () => ({ data: [] }) }, config: { get: async () => ({}) }, // No model configured provider: { list: async () => ({ data: { connected: ["openai"] } }) }, - model: { list: async () => ({ data: [{ provider: "openai", id: "gpt-5.2-codex" }] }) }, + model: { list: async () => ({ data: [{ provider: "openai", id: "gpt-5.3-codex" }] }) }, session: { create: async () => ({ data: { id: "test-session" } }), prompt: async () => ({ data: {} }), @@ -319,7 +319,7 @@ describe("sisyphus-task", () => { test("blocks requiresModel when availability is known and missing the required model", () => { // given const categoryName = "deep" - const availableModels = new Set(["anthropic/claude-opus-4-5"]) + const availableModels = new Set(["anthropic/claude-opus-4-6"]) // when const result = resolveCategoryConfig(categoryName, { @@ -349,9 +349,9 @@ describe("sisyphus-task", () => { test("bypasses requiresModel when explicit user config provided", () => { // #given const categoryName = "deep" - const availableModels = new Set(["anthropic/claude-opus-4-5"]) + const availableModels = new Set(["anthropic/claude-opus-4-6"]) const userCategories = { - deep: { model: "anthropic/claude-opus-4-5" }, + deep: { model: "anthropic/claude-opus-4-6" }, } // #when @@ -363,7 +363,7 @@ describe("sisyphus-task", () => { // #then expect(result).not.toBeNull() - expect(result!.config.model).toBe("anthropic/claude-opus-4-5") + expect(result!.config.model).toBe("anthropic/claude-opus-4-6") }) test("bypasses requiresModel when explicit user config provided even with empty availability", () => { @@ -371,7 +371,7 @@ describe("sisyphus-task", () => { const categoryName = "deep" const availableModels = new Set() const userCategories = { - deep: { model: "anthropic/claude-opus-4-5" }, + deep: { model: "anthropic/claude-opus-4-6" }, } // #when @@ -383,7 +383,7 @@ describe("sisyphus-task", () => { // #then expect(result).not.toBeNull() - expect(result!.config.model).toBe("anthropic/claude-opus-4-5") + expect(result!.config.model).toBe("anthropic/claude-opus-4-6") }) test("returns default model from DEFAULT_CATEGORIES for builtin category", () => { @@ -403,7 +403,7 @@ describe("sisyphus-task", () => { // given const categoryName = "visual-engineering" const userCategories = { - "visual-engineering": { model: "anthropic/claude-opus-4-5" }, + "visual-engineering": { model: "anthropic/claude-opus-4-6" }, } // when @@ -411,7 +411,7 @@ describe("sisyphus-task", () => { // then expect(result).not.toBeNull() - expect(result!.config.model).toBe("anthropic/claude-opus-4-5") + expect(result!.config.model).toBe("anthropic/claude-opus-4-6") }) test("user prompt_append is appended to default", () => { @@ -475,7 +475,7 @@ describe("sisyphus-task", () => { test("category built-in model takes precedence over inheritedModel", () => { // given - builtin category with its own model, parent model also provided const categoryName = "visual-engineering" - const inheritedModel = "cliproxy/claude-opus-4-5" + const inheritedModel = "cliproxy/claude-opus-4-6" // when const result = resolveCategoryConfig(categoryName, { inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) @@ -489,7 +489,7 @@ describe("sisyphus-task", () => { // given - custom category with no model defined const categoryName = "my-custom-no-model" const userCategories = { "my-custom-no-model": { temperature: 0.5 } } as unknown as Record - const inheritedModel = "cliproxy/claude-opus-4-5" + const inheritedModel = "cliproxy/claude-opus-4-6" // when const result = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) @@ -505,7 +505,7 @@ describe("sisyphus-task", () => { const userCategories = { "visual-engineering": { model: "my-provider/my-model" }, } - const inheritedModel = "cliproxy/claude-opus-4-5" + const inheritedModel = "cliproxy/claude-opus-4-6" // when const result = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) @@ -613,7 +613,7 @@ describe("sisyphus-task", () => { const mockClient = { app: { agents: async () => ({ data: [] }) }, config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) }, - model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-5" }] }, + model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-6" }] }, session: { create: async () => ({ data: { id: "test-session" } }), prompt: async () => ({ data: {} }), @@ -649,7 +649,7 @@ describe("sisyphus-task", () => { // then - variant MUST be "max" from DEFAULT_CATEGORIES expect(launchInput.model).toEqual({ providerID: "anthropic", - modelID: "claude-opus-4-5", + modelID: "claude-opus-4-6", variant: "max", }) }) @@ -664,7 +664,7 @@ describe("sisyphus-task", () => { const mockClient = { app: { agents: async () => ({ data: [] }) }, config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) }, - model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-5" }] }, + model: { list: async () => [{ provider: "anthropic", id: "claude-opus-4-6" }] }, session: { get: async () => ({ data: { directory: "/project" } }), create: async () => ({ data: { id: "ses_sync_default_variant" } }), @@ -707,7 +707,7 @@ describe("sisyphus-task", () => { // then - variant MUST be "max" from DEFAULT_CATEGORIES (passed as separate field) expect(promptBody.model).toEqual({ providerID: "anthropic", - modelID: "claude-opus-4-5", + modelID: "claude-opus-4-6", }) expect(promptBody.variant).toBe("max") }, { timeout: 20000 }) @@ -1754,7 +1754,7 @@ describe("sisyphus-task", () => { abort: new AbortController().signal, } - // when - using ultrabrain category (default model is openai/gpt-5.2-codex) + // when - using ultrabrain category (default model is openai/gpt-5.3-codex) await tool.execute( { description: "Override precedence test", @@ -1805,7 +1805,7 @@ describe("sisyphus-task", () => { client: mockClient, sisyphusJuniorModel: "anthropic/claude-sonnet-4-5", userCategories: { - ultrabrain: { model: "openai/gpt-5.2-codex" }, + ultrabrain: { model: "openai/gpt-5.3-codex" }, }, }) @@ -1830,7 +1830,7 @@ describe("sisyphus-task", () => { // then - explicit category model should win expect(launchInput.model.providerID).toBe("openai") - expect(launchInput.model.modelID).toBe("gpt-5.2-codex") + expect(launchInput.model.modelID).toBe("gpt-5.3-codex") }) }) @@ -2083,7 +2083,7 @@ describe("sisyphus-task", () => { // then - catalog model is used expect(resolved).not.toBeNull() - expect(resolved!.config.model).toBe("openai/gpt-5.2-codex") + expect(resolved!.config.model).toBe("openai/gpt-5.3-codex") expect(resolved!.config.variant).toBe("xhigh") }) @@ -2102,22 +2102,22 @@ describe("sisyphus-task", () => { test("category built-in model takes precedence over inheritedModel for builtin category", () => { // given - builtin ultrabrain category with its own model, inherited model also provided const categoryName = "ultrabrain" - const inheritedModel = "cliproxy/claude-opus-4-5" + const inheritedModel = "cliproxy/claude-opus-4-6" // when const resolved = resolveCategoryConfig(categoryName, { inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) - // then - category's built-in model wins (ultrabrain uses gpt-5.2-codex) + // then - category's built-in model wins (ultrabrain uses gpt-5.3-codex) expect(resolved).not.toBeNull() const actualModel = resolved!.config.model - expect(actualModel).toBe("openai/gpt-5.2-codex") + expect(actualModel).toBe("openai/gpt-5.3-codex") }) test("when user defines model - modelInfo should report user-defined regardless of inheritedModel", () => { // given const categoryName = "ultrabrain" const userCategories = { "ultrabrain": { model: "my-provider/custom-model" } } - const inheritedModel = "cliproxy/claude-opus-4-5" + const inheritedModel = "cliproxy/claude-opus-4-6" // when const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) @@ -2134,7 +2134,7 @@ describe("sisyphus-task", () => { // given - This test verifies the fix for PR #770 bug // The bug was: checking `if (inheritedModel)` instead of `if (actualModel === inheritedModel)` const categoryName = "ultrabrain" - const inheritedModel = "cliproxy/claude-opus-4-5" + const inheritedModel = "cliproxy/claude-opus-4-6" const userCategories = { "ultrabrain": { model: "user/model" } } // when - user model wins @@ -2162,14 +2162,14 @@ describe("sisyphus-task", () => { // given a builtin category with its own model, and an inherited model from parent // The CORRECT chain: userConfig?.model ?? categoryBuiltIn ?? systemDefaultModel const categoryName = "ultrabrain" - const inheritedModel = "anthropic/claude-opus-4-5" + const inheritedModel = "anthropic/claude-opus-4-6" - // when category has a built-in model (gpt-5.2-codex for ultrabrain) + // when category has a built-in model (gpt-5.3-codex for ultrabrain) const resolved = resolveCategoryConfig(categoryName, { inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) // then category's built-in model should be used, NOT inheritedModel expect(resolved).not.toBeNull() - expect(resolved!.model).toBe("openai/gpt-5.2-codex") + expect(resolved!.model).toBe("openai/gpt-5.3-codex") }) test("FIXED: systemDefaultModel is used when no userConfig.model and no inheritedModel", () => { @@ -2193,7 +2193,7 @@ describe("sisyphus-task", () => { // given userConfig.model is explicitly set const categoryName = "ultrabrain" const userCategories = { "ultrabrain": { model: "custom/user-model" } } - const inheritedModel = "anthropic/claude-opus-4-5" + const inheritedModel = "anthropic/claude-opus-4-6" const systemDefaultModel = "anthropic/claude-sonnet-4-5" // when resolveCategoryConfig is called with all sources @@ -2212,7 +2212,7 @@ describe("sisyphus-task", () => { // given userConfig.model is empty string "" for a custom category (no built-in model) const categoryName = "custom-empty-model" const userCategories = { "custom-empty-model": { model: "", temperature: 0.3 } } - const inheritedModel = "anthropic/claude-opus-4-5" + const inheritedModel = "anthropic/claude-opus-4-6" // when resolveCategoryConfig is called const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) @@ -2227,7 +2227,7 @@ describe("sisyphus-task", () => { const categoryName = "visual-engineering" // Using type assertion since we're testing fallback behavior for categories without model const userCategories = { "visual-engineering": { temperature: 0.2 } } as unknown as Record - const inheritedModel = "anthropic/claude-opus-4-5" + const inheritedModel = "anthropic/claude-opus-4-6" // when resolveCategoryConfig is called const resolved = resolveCategoryConfig(categoryName, { userCategories, inheritedModel, systemDefaultModel: SYSTEM_DEFAULT_MODEL }) @@ -2472,7 +2472,7 @@ describe("sisyphus-task", () => { app: { agents: async () => ({ data: [ - { name: "oracle", mode: "subagent", model: { providerID: "anthropic", modelID: "claude-opus-4-5" } }, + { name: "oracle", mode: "subagent", model: { providerID: "anthropic", modelID: "claude-opus-4-6" } }, ], }), }, @@ -2518,7 +2518,7 @@ describe("sisyphus-task", () => { // then - matched agent's model should be passed to session.prompt expect(promptBody.model).toEqual({ providerID: "anthropic", - modelID: "claude-opus-4-5", + modelID: "claude-opus-4-6", }) }, { timeout: 20000 })