feat: prioritize claude-opus-4-6 over claude-opus-4-5 in anthropic fallback chains

Add claude-opus-4-6 as the first anthropic provider entry before
claude-opus-4-5 across all agent and category fallback chains.
Also add high variant mapping for think-mode switcher.
This commit is contained in:
YeonGyu-Kim 2026-02-06 03:31:55 +09:00
parent 2224183b5c
commit 11d0005eb5
9 changed files with 117 additions and 79 deletions

View File

@ -91,7 +91,7 @@ describe("createBuiltinAgents with model overrides", () => {
// #then // #then
expect(agents.sisyphus).toBeDefined() 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 { } finally {
cacheSpy.mockRestore() cacheSpy.mockRestore()
fetchSpy.mockRestore() fetchSpy.mockRestore()
@ -345,7 +345,7 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
// #then // #then
expect(agents.sisyphus).toBeDefined() 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 { } finally {
cacheSpy.mockRestore() cacheSpy.mockRestore()
fetchSpy.mockRestore() fetchSpy.mockRestore()

View File

@ -75,26 +75,26 @@ exports[`generateModelConfig single native provider uses Claude models when only
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"multimodal-looker": { "multimodal-looker": {
"model": "anthropic/claude-haiku-4-5", "model": "anthropic/claude-haiku-4-5",
}, },
"oracle": { "oracle": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -103,7 +103,7 @@ exports[`generateModelConfig single native provider uses Claude models when only
"model": "anthropic/claude-haiku-4-5", "model": "anthropic/claude-haiku-4-5",
}, },
"ultrabrain": { "ultrabrain": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"unspecified-high": { "unspecified-high": {
@ -113,7 +113,7 @@ exports[`generateModelConfig single native provider uses Claude models when only
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"visual-engineering": { "visual-engineering": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"writing": { "writing": {
@ -137,26 +137,26 @@ exports[`generateModelConfig single native provider uses Claude models with isMa
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"multimodal-looker": { "multimodal-looker": {
"model": "anthropic/claude-haiku-4-5", "model": "anthropic/claude-haiku-4-5",
}, },
"oracle": { "oracle": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -165,18 +165,18 @@ exports[`generateModelConfig single native provider uses Claude models with isMa
"model": "anthropic/claude-haiku-4-5", "model": "anthropic/claude-haiku-4-5",
}, },
"ultrabrain": { "ultrabrain": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"unspecified-high": { "unspecified-high": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"unspecified-low": { "unspecified-low": {
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"visual-engineering": { "visual-engineering": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"writing": { "writing": {
@ -458,7 +458,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
@ -473,11 +473,11 @@ exports[`generateModelConfig all native providers uses preferred models from fal
"variant": "high", "variant": "high",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -531,7 +531,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
@ -546,11 +546,11 @@ exports[`generateModelConfig all native providers uses preferred models with isM
"variant": "high", "variant": "high",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -571,7 +571,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM
"variant": "xhigh", "variant": "xhigh",
}, },
"unspecified-high": { "unspecified-high": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"unspecified-low": { "unspecified-low": {
@ -1009,7 +1009,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
"model": "opencode/glm-4.7-free", "model": "opencode/glm-4.7-free",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
@ -1024,11 +1024,11 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
"variant": "high", "variant": "high",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -1151,26 +1151,26 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"multimodal-looker": { "multimodal-looker": {
"model": "zai-coding-plan/glm-4.6v", "model": "zai-coding-plan/glm-4.6v",
}, },
"oracle": { "oracle": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -1179,7 +1179,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
"model": "anthropic/claude-haiku-4-5", "model": "anthropic/claude-haiku-4-5",
}, },
"ultrabrain": { "ultrabrain": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"unspecified-high": { "unspecified-high": {
@ -1189,7 +1189,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"visual-engineering": { "visual-engineering": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"writing": { "writing": {
@ -1213,11 +1213,11 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
"model": "anthropic/claude-sonnet-4-5", "model": "anthropic/claude-sonnet-4-5",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"multimodal-looker": { "multimodal-looker": {
@ -1228,11 +1228,11 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
"variant": "high", "variant": "high",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -1355,7 +1355,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
@ -1370,11 +1370,11 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
"variant": "high", "variant": "high",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -1428,7 +1428,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
"model": "zai-coding-plan/glm-4.7", "model": "zai-coding-plan/glm-4.7",
}, },
"metis": { "metis": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"momus": { "momus": {
@ -1443,11 +1443,11 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
"variant": "high", "variant": "high",
}, },
"prometheus": { "prometheus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"sisyphus": { "sisyphus": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
}, },
@ -1468,7 +1468,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
"variant": "xhigh", "variant": "xhigh",
}, },
"unspecified-high": { "unspecified-high": {
"model": "anthropic/claude-opus-4-5", "model": "anthropic/claude-opus-4-6",
"variant": "max", "variant": "max",
}, },
"unspecified-low": { "unspecified-low": {

View File

@ -259,7 +259,7 @@ describe("generateOmoConfig - model fallback system", () => {
// #then Sisyphus uses Claude (OR logic - at least one provider available) // #then Sisyphus uses Claude (OR logic - at least one provider available)
expect(result.$schema).toBe("https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json") expect(result.$schema).toBe("https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json")
expect(result.agents).toBeDefined() expect(result.agents).toBeDefined()
expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-5") expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-6")
}) })
test("generates native opus models when Claude max20 subscription", () => { test("generates native opus models when Claude max20 subscription", () => {
@ -279,7 +279,7 @@ describe("generateOmoConfig - model fallback system", () => {
const result = generateOmoConfig(config) const result = generateOmoConfig(config)
// #then Sisyphus uses Claude (OR logic - at least one provider available) // #then Sisyphus uses Claude (OR logic - at least one provider available)
expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-5") expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-6")
}) })
test("uses github-copilot sonnet fallback when only copilot available", () => { test("uses github-copilot sonnet fallback when only copilot available", () => {
@ -342,7 +342,7 @@ describe("generateOmoConfig - model fallback system", () => {
// #then librarian should use zai-coding-plan/glm-4.7 // #then librarian should use zai-coding-plan/glm-4.7
expect((result.agents as Record<string, { model: string }>).librarian.model).toBe("zai-coding-plan/glm-4.7") expect((result.agents as Record<string, { model: string }>).librarian.model).toBe("zai-coding-plan/glm-4.7")
// #then Sisyphus uses Claude (OR logic) // #then Sisyphus uses Claude (OR logic)
expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-5") expect((result.agents as Record<string, { model: string }>).sisyphus.model).toBe("anthropic/claude-opus-4-6")
}) })
test("uses native OpenAI models when only ChatGPT available", () => { test("uses native OpenAI models when only ChatGPT available", () => {

View File

@ -14,9 +14,8 @@ describe("model-resolution check", () => {
// then: Should have agent entries // then: Should have agent entries
const sisyphus = info.agents.find((a) => a.name === "sisyphus") const sisyphus = info.agents.find((a) => a.name === "sisyphus")
expect(sisyphus).toBeDefined() expect(sisyphus).toBeDefined()
expect(sisyphus!.requirement.fallbackChain[0]?.model).toBe("claude-opus-4-5") expect(sisyphus!.requirement.fallbackChain[0]?.model).toBe("claude-opus-4-6")
expect(sisyphus!.requirement.fallbackChain[0]?.providers).toContain("anthropic") expect(sisyphus!.requirement.fallbackChain[0]?.providers).toContain("anthropic")
expect(sisyphus!.requirement.fallbackChain[0]?.providers).toContain("github-copilot")
}) })
it("returns category requirements with provider chains", async () => { it("returns category requirements with provider chains", async () => {

View File

@ -376,7 +376,7 @@ describe("generateModelConfig", () => {
const result = generateModelConfig(config) const result = generateModelConfig(config)
// #then // #then
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-5") expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-6")
}) })
test("Sisyphus is created when multiple fallback providers are available", () => { test("Sisyphus is created when multiple fallback providers are available", () => {
@ -393,7 +393,7 @@ describe("generateModelConfig", () => {
const result = generateModelConfig(config) const result = generateModelConfig(config)
// #then // #then
expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-5") expect(result.agents?.sisyphus?.model).toBe("anthropic/claude-opus-4-6")
}) })
test("Sisyphus is omitted when no fallback provider is available (OpenAI not in chain)", () => { test("Sisyphus is omitted when no fallback provider is available (OpenAI not in chain)", () => {

View File

@ -141,6 +141,14 @@ describe("think-mode switcher", () => {
expect(variant).toBe("claude-opus-4-5-high") expect(variant).toBe("claude-opus-4-5-high")
}) })
it("should handle claude-opus-4-6 high variant", () => {
// given a Claude Opus 4.6 model ID
const variant = getHighVariant("claude-opus-4-6")
// then should return high variant
expect(variant).toBe("claude-opus-4-6-high")
})
it("should handle dots in GPT version numbers", () => { it("should handle dots in GPT version numbers", () => {
// given a GPT model ID with dot format (gpt-5.2) // given a GPT model ID with dot format (gpt-5.2)
const variant = getHighVariant("gpt-5.2") const variant = getHighVariant("gpt-5.2")

View File

@ -88,6 +88,7 @@ function resolveProvider(providerID: string, modelID: string): string {
const HIGH_VARIANT_MAP: Record<string, string> = { const HIGH_VARIANT_MAP: Record<string, string> = {
// Claude // Claude
"claude-sonnet-4-5": "claude-sonnet-4-5-high", "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", "claude-opus-4-5": "claude-opus-4-5-high",
// Gemini // Gemini
"gemini-3-pro": "gemini-3-pro-high", "gemini-3-pro": "gemini-3-pro-high",

View File

@ -23,23 +23,28 @@ describe("AGENT_MODEL_REQUIREMENTS", () => {
expect(primary.variant).toBe("high") expect(primary.variant).toBe("high")
}) })
test("sisyphus has valid fallbackChain with claude-opus-4-5 as primary and requiresAnyModel", () => { test("sisyphus has claude-opus-4-6 as primary before claude-opus-4-5 and requiresAnyModel", () => {
// #given - sisyphus agent requirement // #given - sisyphus agent requirement
const sisyphus = AGENT_MODEL_REQUIREMENTS["sisyphus"] const sisyphus = AGENT_MODEL_REQUIREMENTS["sisyphus"]
// #when - accessing Sisyphus requirement // #when - accessing Sisyphus requirement
// #then - fallbackChain exists with claude-opus-4-5 as first entry, glm-4.7-free as last // #then - fallbackChain has claude-opus-4-6 first, claude-opus-4-5 second, glm-4.7-free last
expect(sisyphus).toBeDefined() expect(sisyphus).toBeDefined()
expect(sisyphus.fallbackChain).toBeArray() expect(sisyphus.fallbackChain).toBeArray()
expect(sisyphus.fallbackChain).toHaveLength(5) expect(sisyphus.fallbackChain).toHaveLength(6)
expect(sisyphus.requiresAnyModel).toBe(true) expect(sisyphus.requiresAnyModel).toBe(true)
const primary = sisyphus.fallbackChain[0] const primary = sisyphus.fallbackChain[0]
expect(primary.providers[0]).toBe("anthropic") expect(primary.providers).toEqual(["anthropic"])
expect(primary.model).toBe("claude-opus-4-5") expect(primary.model).toBe("claude-opus-4-6")
expect(primary.variant).toBe("max") expect(primary.variant).toBe("max")
const last = sisyphus.fallbackChain[4] const secondary = sisyphus.fallbackChain[1]
expect(secondary.providers[0]).toBe("anthropic")
expect(secondary.model).toBe("claude-opus-4-5")
expect(secondary.variant).toBe("max")
const last = sisyphus.fallbackChain[5]
expect(last.providers[0]).toBe("opencode") expect(last.providers[0]).toBe("opencode")
expect(last.model).toBe("glm-4.7-free") expect(last.model).toBe("glm-4.7-free")
}) })
@ -98,36 +103,46 @@ describe("AGENT_MODEL_REQUIREMENTS", () => {
expect(primary.model).toBe("gemini-3-flash") expect(primary.model).toBe("gemini-3-flash")
}) })
test("prometheus has valid fallbackChain with claude-opus-4-5 as primary", () => { test("prometheus has claude-opus-4-6 as primary before claude-opus-4-5", () => {
// given - prometheus agent requirement // #given - prometheus agent requirement
const prometheus = AGENT_MODEL_REQUIREMENTS["prometheus"] const prometheus = AGENT_MODEL_REQUIREMENTS["prometheus"]
// when - accessing Prometheus requirement // #when - accessing Prometheus requirement
// then - fallbackChain exists with claude-opus-4-5 as first entry // #then - claude-opus-4-6 is first, claude-opus-4-5 is second
expect(prometheus).toBeDefined() expect(prometheus).toBeDefined()
expect(prometheus.fallbackChain).toBeArray() expect(prometheus.fallbackChain).toBeArray()
expect(prometheus.fallbackChain.length).toBeGreaterThan(0) expect(prometheus.fallbackChain.length).toBeGreaterThan(1)
const primary = prometheus.fallbackChain[0] const primary = prometheus.fallbackChain[0]
expect(primary.model).toBe("claude-opus-4-5") expect(primary.model).toBe("claude-opus-4-6")
expect(primary.providers[0]).toBe("anthropic") expect(primary.providers).toEqual(["anthropic"])
expect(primary.variant).toBe("max") expect(primary.variant).toBe("max")
const secondary = prometheus.fallbackChain[1]
expect(secondary.model).toBe("claude-opus-4-5")
expect(secondary.providers[0]).toBe("anthropic")
expect(secondary.variant).toBe("max")
}) })
test("metis has valid fallbackChain with claude-opus-4-5 as primary", () => { test("metis has claude-opus-4-6 as primary before claude-opus-4-5", () => {
// given - metis agent requirement // #given - metis agent requirement
const metis = AGENT_MODEL_REQUIREMENTS["metis"] const metis = AGENT_MODEL_REQUIREMENTS["metis"]
// when - accessing Metis requirement // #when - accessing Metis requirement
// then - fallbackChain exists with claude-opus-4-5 as first entry // #then - claude-opus-4-6 is first, claude-opus-4-5 is second
expect(metis).toBeDefined() expect(metis).toBeDefined()
expect(metis.fallbackChain).toBeArray() expect(metis.fallbackChain).toBeArray()
expect(metis.fallbackChain.length).toBeGreaterThan(0) expect(metis.fallbackChain.length).toBeGreaterThan(1)
const primary = metis.fallbackChain[0] const primary = metis.fallbackChain[0]
expect(primary.model).toBe("claude-opus-4-5") expect(primary.model).toBe("claude-opus-4-6")
expect(primary.providers[0]).toBe("anthropic") expect(primary.providers).toEqual(["anthropic"])
expect(primary.variant).toBe("max") expect(primary.variant).toBe("max")
const secondary = metis.fallbackChain[1]
expect(secondary.model).toBe("claude-opus-4-5")
expect(secondary.providers[0]).toBe("anthropic")
expect(secondary.variant).toBe("max")
}) })
test("momus has valid fallbackChain with gpt-5.2 as primary", () => { test("momus has valid fallbackChain with gpt-5.2 as primary", () => {
@ -285,20 +300,25 @@ describe("CATEGORY_MODEL_REQUIREMENTS", () => {
expect(primary.providers[0]).toBe("anthropic") expect(primary.providers[0]).toBe("anthropic")
}) })
test("unspecified-high has valid fallbackChain with claude-opus-4-5 as primary", () => { test("unspecified-high has claude-opus-4-6 as primary before claude-opus-4-5", () => {
// given - unspecified-high category requirement // #given - unspecified-high category requirement
const unspecifiedHigh = CATEGORY_MODEL_REQUIREMENTS["unspecified-high"] const unspecifiedHigh = CATEGORY_MODEL_REQUIREMENTS["unspecified-high"]
// when - accessing unspecified-high requirement // #when - accessing unspecified-high requirement
// then - fallbackChain exists with claude-opus-4-5 as first entry // #then - claude-opus-4-6 is first, claude-opus-4-5 is second
expect(unspecifiedHigh).toBeDefined() expect(unspecifiedHigh).toBeDefined()
expect(unspecifiedHigh.fallbackChain).toBeArray() expect(unspecifiedHigh.fallbackChain).toBeArray()
expect(unspecifiedHigh.fallbackChain.length).toBeGreaterThan(0) expect(unspecifiedHigh.fallbackChain.length).toBeGreaterThan(1)
const primary = unspecifiedHigh.fallbackChain[0] const primary = unspecifiedHigh.fallbackChain[0]
expect(primary.model).toBe("claude-opus-4-5") expect(primary.model).toBe("claude-opus-4-6")
expect(primary.variant).toBe("max") expect(primary.variant).toBe("max")
expect(primary.providers[0]).toBe("anthropic") expect(primary.providers).toEqual(["anthropic"])
const secondary = unspecifiedHigh.fallbackChain[1]
expect(secondary.model).toBe("claude-opus-4-5")
expect(secondary.variant).toBe("max")
expect(secondary.providers[0]).toBe("anthropic")
}) })
test("artistry has valid fallbackChain with gemini-3-pro as primary", () => { test("artistry has valid fallbackChain with gemini-3-pro as primary", () => {

View File

@ -14,6 +14,7 @@ export type ModelRequirement = {
export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = { export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
sisyphus: { sisyphus: {
fallbackChain: [ 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-5", variant: "max" },
{ providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["kimi-for-coding"], model: "k2p5" },
{ providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["opencode"], model: "kimi-k2.5-free" },
@ -32,6 +33,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
fallbackChain: [ fallbackChain: [
{ 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", 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-5", variant: "max" },
], ],
}, },
@ -62,6 +64,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
}, },
prometheus: { prometheus: {
fallbackChain: [ 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-5", variant: "max" },
{ providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["kimi-for-coding"], model: "k2p5" },
{ providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["opencode"], model: "kimi-k2.5-free" },
@ -71,6 +74,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
}, },
metis: { metis: {
fallbackChain: [ 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-5", variant: "max" },
{ providers: ["kimi-for-coding"], model: "k2p5" }, { providers: ["kimi-for-coding"], model: "k2p5" },
{ providers: ["opencode"], model: "kimi-k2.5-free" }, { providers: ["opencode"], model: "kimi-k2.5-free" },
@ -81,6 +85,7 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
momus: { momus: {
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"], 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-5", variant: "max" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" },
], ],
@ -100,6 +105,7 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
"visual-engineering": { "visual-engineering": {
fallbackChain: [ fallbackChain: [
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" }, { 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-5", variant: "max" },
{ providers: ["zai-coding-plan"], model: "glm-4.7" }, { providers: ["zai-coding-plan"], model: "glm-4.7" },
], ],
@ -108,12 +114,14 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
fallbackChain: [ fallbackChain: [
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "xhigh" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", 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-5", variant: "max" },
], ],
}, },
deep: { deep: {
fallbackChain: [ fallbackChain: [
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-codex", variant: "medium" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2-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-5", variant: "max" },
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", variant: "high" },
], ],
@ -122,6 +130,7 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
artistry: { artistry: {
fallbackChain: [ fallbackChain: [
{ providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro", 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-5", variant: "max" },
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" }, { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.2" },
], ],
@ -143,6 +152,7 @@ export const CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
}, },
"unspecified-high": { "unspecified-high": {
fallbackChain: [ 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-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" }, { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-pro" },