refactor(models): update agent/category fallback chains

- quick: replace openai fallback with opencode/grok-code
- writing: add zai-coding-plan/glm-4.7 between sonnet and gpt
- unspecified-low: gpt-5.2 → gpt-5.2-codex (medium)
- Sisyphus: add zai/glm-4.7 before openai, use gpt-5.2-codex (medium)
- Momus & Metis: add variant 'max' to gemini-3-pro
- explore: simplify to haiku (anthropic/opencode) → grok-code (opencode)
This commit is contained in:
justsisyphus 2026-01-23 15:07:58 +09:00
parent 57b10439a4
commit c6d6bd197e
6 changed files with 60 additions and 52 deletions

View File

@ -80,7 +80,7 @@ exports[`generateModelConfig single native provider uses Claude models when only
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
@ -230,17 +230,19 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2",
}, },
"quick": { "quick": {
"model": "openai/gpt-5.1-codex-mini", "model": "opencode/glm-4.7-free",
}, },
"ultrabrain": { "ultrabrain": {
"model": "openai/gpt-5.2-codex", "model": "openai/gpt-5.2-codex",
"variant": "xhigh", "variant": "xhigh",
}, },
"unspecified-high": { "unspecified-high": {
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2-codex",
"variant": "medium",
}, },
"unspecified-low": { "unspecified-low": {
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2-codex",
"variant": "medium",
}, },
"visual-engineering": { "visual-engineering": {
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2",
@ -273,8 +275,8 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
"variant": "high", "variant": "high",
}, },
"Sisyphus": { "Sisyphus": {
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2-codex",
"variant": "high", "variant": "medium",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "opencode/grok-code",
@ -295,7 +297,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2",
}, },
"quick": { "quick": {
"model": "openai/gpt-5.1-codex-mini", "model": "opencode/glm-4.7-free",
}, },
"ultrabrain": { "ultrabrain": {
"model": "openai/gpt-5.2-codex", "model": "openai/gpt-5.2-codex",
@ -306,7 +308,8 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
"variant": "high", "variant": "high",
}, },
"unspecified-low": { "unspecified-low": {
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2-codex",
"variant": "medium",
}, },
"visual-engineering": { "visual-engineering": {
"model": "openai/gpt-5.2", "model": "openai/gpt-5.2",
@ -328,9 +331,11 @@ exports[`generateModelConfig single native provider uses Gemini models when only
}, },
"Metis (Plan Consultant)": { "Metis (Plan Consultant)": {
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
"variant": "max",
}, },
"Momus (Plan Reviewer)": { "Momus (Plan Reviewer)": {
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
"variant": "max",
}, },
"Prometheus (Planner)": { "Prometheus (Planner)": {
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
@ -339,7 +344,7 @@ exports[`generateModelConfig single native provider uses Gemini models when only
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "opencode/grok-code",
}, },
"librarian": { "librarian": {
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
@ -387,9 +392,11 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa
}, },
"Metis (Plan Consultant)": { "Metis (Plan Consultant)": {
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
"variant": "max",
}, },
"Momus (Plan Reviewer)": { "Momus (Plan Reviewer)": {
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
"variant": "max",
}, },
"Prometheus (Planner)": { "Prometheus (Planner)": {
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
@ -398,7 +405,7 @@ exports[`generateModelConfig single native provider uses Gemini models with isMa
"model": "google/gemini-3-pro-preview", "model": "google/gemini-3-pro-preview",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "opencode/grok-code",
}, },
"librarian": { "librarian": {
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
@ -460,7 +467,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
@ -525,7 +532,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM
"variant": "max", "variant": "max",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
@ -590,7 +597,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on
"model": "opencode/claude-sonnet-4-5", "model": "opencode/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "opencode/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
@ -655,7 +662,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is
"variant": "max", "variant": "max",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "opencode/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
@ -879,7 +886,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian whe
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
}, },
"writing": { "writing": {
"model": "opencode/glm-4.7-free", "model": "zai-coding-plan/glm-4.7",
}, },
}, },
} }
@ -902,7 +909,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian wit
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
}, },
"Sisyphus": { "Sisyphus": {
"model": "opencode/glm-4.7-free", "model": "zai-coding-plan/glm-4.7",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "opencode/grok-code",
@ -937,7 +944,7 @@ exports[`generateModelConfig fallback providers uses ZAI model for librarian wit
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
}, },
"writing": { "writing": {
"model": "opencode/glm-4.7-free", "model": "zai-coding-plan/glm-4.7",
}, },
}, },
} }
@ -966,7 +973,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
@ -1093,7 +1100,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",
@ -1157,7 +1164,7 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
@ -1221,7 +1228,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
"model": "github-copilot/claude-sonnet-4.5", "model": "github-copilot/claude-sonnet-4.5",
}, },
"explore": { "explore": {
"model": "opencode/grok-code", "model": "opencode/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",
@ -1285,7 +1292,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",
@ -1350,7 +1357,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
"variant": "max", "variant": "max",
}, },
"explore": { "explore": {
"model": "google/gemini-3-flash-preview", "model": "anthropic/claude-haiku-4-5",
}, },
"librarian": { "librarian": {
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",

View File

@ -343,7 +343,7 @@ describe("generateOmoConfig - model fallback system", () => {
expect((result.agents as Record<string, { model: string }>).explore.model).toBe("anthropic/claude-haiku-4-5") expect((result.agents as Record<string, { model: string }>).explore.model).toBe("anthropic/claude-haiku-4-5")
}) })
test("uses grok-code for explore when not max20", () => { test("uses haiku for explore regardless of max20 flag", () => {
// #given user has Claude but not max20 // #given user has Claude but not max20
const config: InstallConfig = { const config: InstallConfig = {
hasClaude: true, hasClaude: true,
@ -358,7 +358,7 @@ describe("generateOmoConfig - model fallback system", () => {
// #when generating config // #when generating config
const result = generateOmoConfig(config) const result = generateOmoConfig(config)
// #then explore should use grok-code (preserve Claude quota) // #then explore should use haiku (isMax20 doesn't affect explore anymore)
expect((result.agents as Record<string, { model: string }>).explore.model).toBe("opencode/grok-code") expect((result.agents as Record<string, { model: string }>).explore.model).toBe("anthropic/claude-haiku-4-5")
}) })
}) })

View File

@ -310,19 +310,19 @@ describe("generateModelConfig", () => {
}) })
describe("explore agent special cases", () => { describe("explore agent special cases", () => {
test("explore uses Gemini flash when Gemini available", () => { test("explore uses grok-code when only Gemini available (no Claude)", () => {
// #given Gemini is available // #given only Gemini is available (no Claude)
const config = createConfig({ hasGemini: true }) const config = createConfig({ hasGemini: true })
// #when generateModelConfig is called // #when generateModelConfig is called
const result = generateModelConfig(config) const result = generateModelConfig(config)
// #then explore should use gemini-3-flash-preview // #then explore should use grok-code (Claude haiku not available)
expect(result.agents?.explore?.model).toBe("google/gemini-3-flash-preview") expect(result.agents?.explore?.model).toBe("opencode/grok-code")
}) })
test("explore uses Claude haiku when Claude + isMax20 but no Gemini", () => { test("explore uses Claude haiku when Claude available", () => {
// #given Claude is available with Max 20 plan but no Gemini // #given Claude is available
const config = createConfig({ hasClaude: true, isMax20: true }) const config = createConfig({ hasClaude: true, isMax20: true })
// #when generateModelConfig is called // #when generateModelConfig is called
@ -332,15 +332,15 @@ describe("generateModelConfig", () => {
expect(result.agents?.explore?.model).toBe("anthropic/claude-haiku-4-5") expect(result.agents?.explore?.model).toBe("anthropic/claude-haiku-4-5")
}) })
test("explore uses grok-code when Claude without isMax20 and no Gemini", () => { test("explore uses Claude haiku regardless of isMax20 flag", () => {
// #given Claude is available without Max 20 plan and no Gemini // #given Claude is available without Max 20 plan
const config = createConfig({ hasClaude: true, isMax20: false }) const config = createConfig({ hasClaude: true, isMax20: false })
// #when generateModelConfig is called // #when generateModelConfig is called
const result = generateModelConfig(config) const result = generateModelConfig(config)
// #then explore should use grok-code // #then explore should use claude-haiku-4-5 (isMax20 doesn't affect explore)
expect(result.agents?.explore?.model).toBe("opencode/grok-code") expect(result.agents?.explore?.model).toBe("anthropic/claude-haiku-4-5")
}) })
test("explore uses grok-code when only OpenAI available", () => { test("explore uses grok-code when only OpenAI available", () => {

View File

@ -139,12 +139,12 @@ export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig {
continue continue
} }
// Special case: explore has custom Gemini → Claude → Grok logic // Special case: explore uses Claude haiku → OpenCode grok-code
if (role === "explore") { if (role === "explore") {
if (avail.native.gemini) { if (avail.native.claude) {
agents[role] = { model: "google/gemini-3-flash-preview" }
} else if (avail.native.claude && avail.isMaxPlan) {
agents[role] = { model: "anthropic/claude-haiku-4-5" } agents[role] = { model: "anthropic/claude-haiku-4-5" }
} else if (avail.opencodeZen) {
agents[role] = { model: "opencode/claude-haiku-4-5" }
} else { } else {
agents[role] = { model: "opencode/grok-code" } agents[role] = { model: "opencode/grok-code" }
} }

View File

@ -54,19 +54,19 @@ describe("AGENT_MODEL_REQUIREMENTS", () => {
expect(primary.model).toBe("glm-4.7") expect(primary.model).toBe("glm-4.7")
}) })
test("explore has valid fallbackChain with gemini-3-flash-preview as primary", () => { test("explore has valid fallbackChain with claude-haiku-4-5 as primary", () => {
// #given - explore agent requirement // #given - explore agent requirement
const explore = AGENT_MODEL_REQUIREMENTS["explore"] const explore = AGENT_MODEL_REQUIREMENTS["explore"]
// #when - accessing explore requirement // #when - accessing explore requirement
// #then - fallbackChain exists with gemini-3-flash-preview as first entry // #then - fallbackChain exists with claude-haiku-4-5 as first entry
expect(explore).toBeDefined() expect(explore).toBeDefined()
expect(explore.fallbackChain).toBeArray() expect(explore.fallbackChain).toBeArray()
expect(explore.fallbackChain.length).toBeGreaterThan(0) expect(explore.fallbackChain.length).toBeGreaterThan(0)
const primary = explore.fallbackChain[0] const primary = explore.fallbackChain[0]
expect(primary.providers).toContain("google") expect(primary.providers).toContain("anthropic")
expect(primary.model).toBe("gemini-3-flash-preview") expect(primary.model).toBe("claude-haiku-4-5")
}) })
test("multimodal-looker has valid fallbackChain with gemini-3-flash-preview as primary", () => { test("multimodal-looker has valid fallbackChain with gemini-3-flash-preview as primary", () => {

View File

@ -13,7 +13,8 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
Sisyphus: { Sisyphus: {
fallbackChain: [ fallbackChain: [
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["zai-coding-plan"], model: "glm-4.7" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro-preview" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro-preview" },
], ],
}, },
@ -33,9 +34,8 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
}, },
explore: { explore: {
fallbackChain: [ fallbackChain: [
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" }, { providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" }, { providers: ["opencode"], model: "grok-code" },
{ providers: ["opencode", "github-copilot"], model: "grok-code" },
], ],
}, },
"multimodal-looker": { "multimodal-looker": {
@ -56,14 +56,14 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
fallbackChain: [ fallbackChain: [
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5", variant: "max" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "high" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro-preview" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro-preview", variant: "max" },
], ],
}, },
"Momus (Plan Reviewer)": { "Momus (Plan Reviewer)": {
fallbackChain: [ fallbackChain: [
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2", variant: "medium" },
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-opus-4-5" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro-preview" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro-preview", variant: "max" },
], ],
}, },
Atlas: { Atlas: {
@ -101,13 +101,13 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
fallbackChain: [ fallbackChain: [
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-haiku-4-5" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.1-codex-mini" }, { providers: ["opencode"], model: "grok-code" },
], ],
}, },
"unspecified-low": { "unspecified-low": {
fallbackChain: [ fallbackChain: [
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" },
], ],
}, },
@ -122,6 +122,7 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
fallbackChain: [ fallbackChain: [
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash-preview" },
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" }, { providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
{ providers: ["zai-coding-plan"], model: "glm-4.7" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
], ],
}, },