fix(model-fallback): align OpenAI fallback resolution across CLI and runtime
Keep install-time and runtime model tables in sync, stop OpenAI-only misrouting when OpenCode Go is present, and add valid OpenAI fallbacks for atlas, metis, and sisyphus-junior. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -966,6 +966,28 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
|
||||
cacheSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
test("atlas and metis resolve to OpenAI in an OpenAI-only environment without a system default", async () => {
|
||||
// #given
|
||||
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(new Set(["openai/gpt-5.4"]))
|
||||
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(["openai"])
|
||||
|
||||
try {
|
||||
// #when
|
||||
const agents = await createBuiltinAgents([], {}, undefined, undefined, undefined, undefined, [], {})
|
||||
|
||||
// #then
|
||||
expect(agents.atlas).toBeDefined()
|
||||
expect(agents.atlas.model).toBe("openai/gpt-5.4")
|
||||
expect(agents.atlas.variant).toBe("medium")
|
||||
expect(agents.metis).toBeDefined()
|
||||
expect(agents.metis.model).toBe("openai/gpt-5.4")
|
||||
expect(agents.metis.variant).toBe("high")
|
||||
} finally {
|
||||
fetchSpy.mockRestore()
|
||||
cacheSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("buildAgent with category and skills", () => {
|
||||
|
||||
@@ -69,7 +69,7 @@ exports[`generateModelConfig single native provider uses Claude models when only
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -110,17 +110,17 @@ exports[`generateModelConfig single native provider uses Claude models when only
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "anthropic/claude-opus-4-6",
|
||||
"variant": "max",
|
||||
},
|
||||
"writing": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -131,7 +131,7 @@ exports[`generateModelConfig single native provider uses Claude models with isMa
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -176,14 +176,14 @@ exports[`generateModelConfig single native provider uses Claude models with isMa
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "anthropic/claude-opus-4-6",
|
||||
"variant": "max",
|
||||
},
|
||||
"writing": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -194,7 +194,8 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "medium",
|
||||
},
|
||||
"explore": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -209,7 +210,8 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
|
||||
"variant": "medium",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "high",
|
||||
},
|
||||
"momus": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -232,7 +234,8 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
|
||||
"variant": "medium",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "medium",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
@@ -249,7 +252,7 @@ exports[`generateModelConfig single native provider uses OpenAI models when only
|
||||
"variant": "low",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
@@ -277,7 +280,8 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "medium",
|
||||
},
|
||||
"explore": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -292,7 +296,8 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
|
||||
"variant": "medium",
|
||||
},
|
||||
"metis": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "high",
|
||||
},
|
||||
"momus": {
|
||||
"model": "openai/gpt-5.4",
|
||||
@@ -315,7 +320,8 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
|
||||
"variant": "medium",
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "medium",
|
||||
},
|
||||
},
|
||||
"categories": {
|
||||
@@ -332,7 +338,7 @@ exports[`generateModelConfig single native provider uses OpenAI models with isMa
|
||||
"variant": "low",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
@@ -480,7 +486,7 @@ exports[`generateModelConfig all native providers uses preferred models from fal
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -530,14 +536,14 @@ exports[`generateModelConfig all native providers uses preferred models from fal
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -555,7 +561,7 @@ exports[`generateModelConfig all native providers uses preferred models with isM
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -605,15 +611,15 @@ exports[`generateModelConfig all native providers uses preferred models with isM
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "high",
|
||||
"model": "anthropic/claude-opus-4-6",
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -631,7 +637,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/claude-sonnet-4-5",
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
@@ -681,14 +687,14 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models when on
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.3-codex",
|
||||
"model": "opencode/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "opencode/claude-sonnet-4-5",
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "opencode/claude-sonnet-4-5",
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "opencode/gemini-3.1-pro",
|
||||
@@ -706,7 +712,7 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "opencode/claude-sonnet-4-5",
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
@@ -756,15 +762,15 @@ exports[`generateModelConfig fallback providers uses OpenCode Zen models with is
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.3-codex",
|
||||
"model": "opencode/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "opencode/gpt-5.4",
|
||||
"variant": "high",
|
||||
"model": "opencode/claude-opus-4-6",
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "opencode/claude-sonnet-4-5",
|
||||
"model": "opencode/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "opencode/gemini-3.1-pro",
|
||||
@@ -782,11 +788,15 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "github-copilot/gpt-5-mini",
|
||||
},
|
||||
"hephaestus": {
|
||||
"model": "github-copilot/gpt-5.4",
|
||||
"variant": "medium",
|
||||
},
|
||||
"metis": {
|
||||
"model": "github-copilot/claude-opus-4.6",
|
||||
"variant": "max",
|
||||
@@ -796,7 +806,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "github-copilot/gpt-5-nano",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "github-copilot/gpt-5.4",
|
||||
@@ -827,10 +837,10 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models when
|
||||
"variant": "high",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "github-copilot/gemini-3.1-pro-preview",
|
||||
@@ -848,11 +858,15 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "github-copilot/gpt-5-mini",
|
||||
},
|
||||
"hephaestus": {
|
||||
"model": "github-copilot/gpt-5.4",
|
||||
"variant": "medium",
|
||||
},
|
||||
"metis": {
|
||||
"model": "github-copilot/claude-opus-4.6",
|
||||
"variant": "max",
|
||||
@@ -862,7 +876,7 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"multimodal-looker": {
|
||||
"model": "opencode/glm-4.7-free",
|
||||
"model": "github-copilot/gpt-5-nano",
|
||||
},
|
||||
"oracle": {
|
||||
"model": "github-copilot/gpt-5.4",
|
||||
@@ -893,11 +907,11 @@ exports[`generateModelConfig fallback providers uses GitHub Copilot models with
|
||||
"variant": "high",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "github-copilot/gpt-5.4",
|
||||
"variant": "high",
|
||||
"model": "github-copilot/claude-opus-4.6",
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "github-copilot/gemini-3.1-pro-preview",
|
||||
@@ -1031,7 +1045,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -1081,14 +1095,14 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + OpenCode Zen
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.3-codex",
|
||||
"model": "opencode/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "opencode/gemini-3.1-pro",
|
||||
@@ -1106,7 +1120,7 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "github-copilot/gpt-5-mini",
|
||||
@@ -1156,14 +1170,14 @@ exports[`generateModelConfig mixed provider scenarios uses OpenAI + Copilot comb
|
||||
"model": "github-copilot/claude-haiku-4.5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "github-copilot/gemini-3.1-pro-preview",
|
||||
@@ -1181,7 +1195,7 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -1225,16 +1239,16 @@ exports[`generateModelConfig mixed provider scenarios uses Claude + ZAI combinat
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "zai-coding-plan/glm-5",
|
||||
},
|
||||
"writing": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1245,7 +1259,7 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -1290,10 +1304,10 @@ exports[`generateModelConfig mixed provider scenarios uses Gemini + Claude combi
|
||||
"variant": "high",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -1311,7 +1325,7 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "opencode/claude-haiku-4-5",
|
||||
@@ -1364,14 +1378,14 @@ exports[`generateModelConfig mixed provider scenarios uses all fallback provider
|
||||
"model": "github-copilot/claude-haiku-4.5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "opencode/gpt-5.3-codex",
|
||||
"model": "opencode/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "github-copilot/claude-sonnet-4.5",
|
||||
"model": "github-copilot/claude-sonnet-4.6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "github-copilot/gemini-3.1-pro-preview",
|
||||
@@ -1389,7 +1403,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -1442,14 +1456,14 @@ exports[`generateModelConfig mixed provider scenarios uses all providers togethe
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
@@ -1467,7 +1481,7 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
|
||||
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
|
||||
"agents": {
|
||||
"atlas": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"explore": {
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
@@ -1520,15 +1534,15 @@ exports[`generateModelConfig mixed provider scenarios uses all providers with is
|
||||
"model": "anthropic/claude-haiku-4-5",
|
||||
},
|
||||
"ultrabrain": {
|
||||
"model": "openai/gpt-5.3-codex",
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "xhigh",
|
||||
},
|
||||
"unspecified-high": {
|
||||
"model": "openai/gpt-5.4",
|
||||
"variant": "high",
|
||||
"model": "anthropic/claude-opus-4-6",
|
||||
"variant": "max",
|
||||
},
|
||||
"unspecified-low": {
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
"model": "anthropic/claude-sonnet-4-6",
|
||||
},
|
||||
"visual-engineering": {
|
||||
"model": "google/gemini-3.1-pro-preview",
|
||||
|
||||
31
src/cli/model-fallback-requirements.test.ts
Normal file
31
src/cli/model-fallback-requirements.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
|
||||
import {
|
||||
CLI_AGENT_MODEL_REQUIREMENTS,
|
||||
CLI_CATEGORY_MODEL_REQUIREMENTS,
|
||||
} from "./model-fallback-requirements"
|
||||
import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS } from "../shared/model-requirements"
|
||||
|
||||
describe("CLI model fallback requirements", () => {
|
||||
test("agent requirements stay aligned with runtime requirements", () => {
|
||||
// #given
|
||||
const runtimeAgents = AGENT_MODEL_REQUIREMENTS
|
||||
|
||||
// #when
|
||||
const cliAgents = CLI_AGENT_MODEL_REQUIREMENTS
|
||||
|
||||
// #then
|
||||
expect(cliAgents).toEqual(runtimeAgents)
|
||||
})
|
||||
|
||||
test("category requirements stay aligned with runtime requirements", () => {
|
||||
// #given
|
||||
const runtimeCategories = CATEGORY_MODEL_REQUIREMENTS
|
||||
|
||||
// #when
|
||||
const cliCategories = CLI_CATEGORY_MODEL_REQUIREMENTS
|
||||
|
||||
// #then
|
||||
expect(cliCategories).toEqual(runtimeCategories)
|
||||
})
|
||||
})
|
||||
@@ -1,283 +1,9 @@
|
||||
import type { ModelRequirement } from "../shared/model-requirements";
|
||||
import {
|
||||
AGENT_MODEL_REQUIREMENTS,
|
||||
CATEGORY_MODEL_REQUIREMENTS,
|
||||
type ModelRequirement,
|
||||
} from "../shared/model-requirements"
|
||||
|
||||
// NOTE: These requirements are used by the CLI config generator (`generateModelConfig`).
|
||||
// They intentionally use "install-time" provider IDs (anthropic/openai/google/opencode/etc),
|
||||
// not runtime-only providers like `nvidia`.
|
||||
export const CLI_AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = AGENT_MODEL_REQUIREMENTS
|
||||
|
||||
export const CLI_AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
|
||||
sisyphus: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
{ providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4", variant: "medium" },
|
||||
{ providers: ["zai-coding-plan", "opencode"], model: "glm-5" },
|
||||
],
|
||||
requiresAnyModel: true,
|
||||
},
|
||||
hephaestus: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["openai", "opencode"],
|
||||
model: "gpt-5.3-codex",
|
||||
variant: "medium",
|
||||
},
|
||||
],
|
||||
requiresProvider: ["openai", "opencode"],
|
||||
},
|
||||
oracle: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "high",
|
||||
},
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
variant: "high",
|
||||
},
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
],
|
||||
},
|
||||
librarian: {
|
||||
fallbackChain: [
|
||||
{ providers: ["opencode-go"], model: "minimax-m2.5" },
|
||||
{ providers: ["opencode"], model: "minimax-m2.5-free" },
|
||||
{ providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
|
||||
{ providers: ["opencode"], model: "gpt-5-nano" },
|
||||
],
|
||||
},
|
||||
explore: {
|
||||
fallbackChain: [
|
||||
{ providers: ["github-copilot"], model: "grok-code-fast-1" },
|
||||
{ providers: ["opencode-go"], model: "minimax-m2.5" },
|
||||
{ providers: ["anthropic", "opencode"], model: "claude-haiku-4-5" },
|
||||
{ providers: ["opencode"], model: "gpt-5-nano" },
|
||||
],
|
||||
},
|
||||
"multimodal-looker": {
|
||||
fallbackChain: [
|
||||
{ providers: ["openai", "opencode"], model: "gpt-5.4", variant: "medium" },
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{ providers: ["zai-coding-plan"], model: "glm-4.6v" },
|
||||
{ providers: ["opencode"], model: "gpt-5-nano" },
|
||||
],
|
||||
},
|
||||
prometheus: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "high",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
},
|
||||
],
|
||||
},
|
||||
metis: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
],
|
||||
},
|
||||
momus: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "xhigh",
|
||||
},
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
variant: "high",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
],
|
||||
},
|
||||
atlas: {
|
||||
fallbackChain: [
|
||||
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-5" },
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
],
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
fallbackChain: [
|
||||
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{ providers: ["opencode"], model: "big-pickle" },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const CLI_CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
|
||||
"visual-engineering": {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
variant: "high",
|
||||
},
|
||||
{ providers: ["zai-coding-plan", "opencode"], model: "glm-5" },
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
],
|
||||
},
|
||||
ultrabrain: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["openai", "opencode"],
|
||||
model: "gpt-5.3-codex",
|
||||
variant: "xhigh",
|
||||
},
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
variant: "high",
|
||||
},
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
],
|
||||
},
|
||||
deep: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["openai", "opencode"],
|
||||
model: "gpt-5.3-codex",
|
||||
variant: "medium",
|
||||
},
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
variant: "high",
|
||||
},
|
||||
],
|
||||
requiresModel: "gpt-5.3-codex",
|
||||
},
|
||||
artistry: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3.1-pro",
|
||||
variant: "high",
|
||||
},
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
},
|
||||
],
|
||||
requiresModel: "gemini-3.1-pro",
|
||||
},
|
||||
quick: {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-haiku-4-5",
|
||||
},
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3-flash",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "minimax-m2.5" },
|
||||
{ providers: ["opencode"], model: "gpt-5-nano" },
|
||||
],
|
||||
},
|
||||
"unspecified-low": {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-sonnet-4-5",
|
||||
},
|
||||
{
|
||||
providers: ["openai", "opencode"],
|
||||
model: "gpt-5.3-codex",
|
||||
variant: "medium",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3-flash",
|
||||
},
|
||||
],
|
||||
},
|
||||
"unspecified-high": {
|
||||
fallbackChain: [
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "high",
|
||||
},
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{ providers: ["zai-coding-plan", "opencode"], model: "glm-5" },
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
{ providers: ["opencode"], model: "kimi-k2.5" },
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
],
|
||||
},
|
||||
writing: {
|
||||
fallbackChain: [
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
{
|
||||
providers: ["google", "github-copilot", "opencode"],
|
||||
model: "gemini-3-flash",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{
|
||||
providers: ["anthropic", "github-copilot", "opencode"],
|
||||
model: "claude-sonnet-4-5",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
export const CLI_CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = CATEGORY_MODEL_REQUIREMENTS
|
||||
|
||||
@@ -13,6 +13,7 @@ function createConfig(overrides: Partial<InstallConfig> = {}): InstallConfig {
|
||||
hasOpencodeZen: false,
|
||||
hasZaiCodingPlan: false,
|
||||
hasKimiForCoding: false,
|
||||
hasOpencodeGo: false,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
@@ -410,6 +411,44 @@ describe("generateModelConfig", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("OpenAI fallback coverage", () => {
|
||||
test("Atlas resolves to OpenAI when only OpenAI is available", () => {
|
||||
// #given
|
||||
const config = createConfig({ hasOpenAI: true })
|
||||
|
||||
// #when
|
||||
const result = generateModelConfig(config)
|
||||
|
||||
// #then
|
||||
expect(result.agents?.atlas?.model).toBe("openai/gpt-5.4")
|
||||
expect(result.agents?.atlas?.variant).toBe("medium")
|
||||
})
|
||||
|
||||
test("Metis resolves to OpenAI when only OpenAI is available", () => {
|
||||
// #given
|
||||
const config = createConfig({ hasOpenAI: true })
|
||||
|
||||
// #when
|
||||
const result = generateModelConfig(config)
|
||||
|
||||
// #then
|
||||
expect(result.agents?.metis?.model).toBe("openai/gpt-5.4")
|
||||
expect(result.agents?.metis?.variant).toBe("high")
|
||||
})
|
||||
|
||||
test("Sisyphus-Junior resolves to OpenAI when only OpenAI is available", () => {
|
||||
// #given
|
||||
const config = createConfig({ hasOpenAI: true })
|
||||
|
||||
// #when
|
||||
const result = generateModelConfig(config)
|
||||
|
||||
// #then
|
||||
expect(result.agents?.["sisyphus-junior"]?.model).toBe("openai/gpt-5.4")
|
||||
expect(result.agents?.["sisyphus-junior"]?.variant).toBe("medium")
|
||||
})
|
||||
})
|
||||
|
||||
describe("Hephaestus agent special cases", () => {
|
||||
test("Hephaestus is created when OpenAI is available (openai provider connected)", () => {
|
||||
// #given
|
||||
@@ -423,15 +462,18 @@ describe("generateModelConfig", () => {
|
||||
expect(result.agents?.hephaestus?.variant).toBe("medium")
|
||||
})
|
||||
|
||||
test("Hephaestus is NOT created when only Copilot is available (gpt-5.3-codex unavailable on github-copilot)", () => {
|
||||
test("Hephaestus falls back to Copilot GPT-5.4 when only Copilot is available", () => {
|
||||
// #given
|
||||
const config = createConfig({ hasCopilot: true })
|
||||
|
||||
// #when
|
||||
const result = generateModelConfig(config)
|
||||
|
||||
// #then - hephaestus is omitted because gpt-5.3-codex is not available on github-copilot
|
||||
expect(result.agents?.hephaestus).toBeUndefined()
|
||||
// #then
|
||||
expect(result.agents?.hephaestus).toEqual({
|
||||
model: "github-copilot/gpt-5.4",
|
||||
variant: "medium",
|
||||
})
|
||||
})
|
||||
|
||||
test("Hephaestus is created when OpenCode Zen is available (opencode provider connected)", () => {
|
||||
|
||||
@@ -13,6 +13,7 @@ function createConfig(overrides: Partial<InstallConfig> = {}): InstallConfig {
|
||||
hasOpencodeZen: false,
|
||||
hasZaiCodingPlan: false,
|
||||
hasKimiForCoding: false,
|
||||
hasOpencodeGo: false,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
@@ -43,4 +44,17 @@ describe("generateModelConfig OpenAI-only model catalog", () => {
|
||||
expect(result.categories?.["visual-engineering"]).toEqual({ model: "openai/gpt-5.4", variant: "high" })
|
||||
expect(result.categories?.writing).toEqual({ model: "openai/gpt-5.4", variant: "medium" })
|
||||
})
|
||||
|
||||
test("does not apply OpenAI-only overrides when OpenCode Go is also available", () => {
|
||||
// #given
|
||||
const config = createConfig({ hasOpenAI: true, hasOpencodeGo: true })
|
||||
|
||||
// #when
|
||||
const result = generateModelConfig(config)
|
||||
|
||||
// #then
|
||||
expect(result.agents?.explore).toEqual({ model: "opencode-go/minimax-m2.5" })
|
||||
expect(result.agents?.librarian).toEqual({ model: "opencode-go/minimax-m2.5" })
|
||||
expect(result.categories?.quick).toEqual({ model: "opencode-go/minimax-m2.5" })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -17,6 +17,7 @@ export function isOpenAiOnlyAvailability(availability: ProviderAvailability): bo
|
||||
availability.native.openai &&
|
||||
!availability.native.claude &&
|
||||
!availability.native.gemini &&
|
||||
!availability.opencodeGo &&
|
||||
!availability.opencodeZen &&
|
||||
!availability.copilot &&
|
||||
!availability.zai &&
|
||||
|
||||
@@ -74,6 +74,13 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
mode: "subagent",
|
||||
}
|
||||
|
||||
const builtinAtlasConfig: AgentConfig = {
|
||||
name: "atlas",
|
||||
prompt: "atlas prompt",
|
||||
mode: "all",
|
||||
model: "openai/gpt-5.4",
|
||||
}
|
||||
|
||||
const sisyphusJuniorConfig: AgentConfig = {
|
||||
name: "Sisyphus-Junior",
|
||||
prompt: "junior prompt",
|
||||
@@ -85,6 +92,7 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
sisyphus: builtinSisyphusConfig,
|
||||
oracle: builtinOracleConfig,
|
||||
"multimodal-looker": builtinMultimodalLookerConfig,
|
||||
atlas: builtinAtlasConfig,
|
||||
})
|
||||
|
||||
createSisyphusJuniorAgentSpy = spyOn(
|
||||
@@ -255,4 +263,19 @@ describe("applyAgentConfig builtin override protection", () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test("passes the resolved Atlas model to Sisyphus-Junior as its fallback default", async () => {
|
||||
// given
|
||||
|
||||
// when
|
||||
await applyAgentConfig({
|
||||
config: createBaseConfig(),
|
||||
pluginConfig: createPluginConfig(),
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginComponents: createPluginComponents(),
|
||||
})
|
||||
|
||||
// then
|
||||
expect(createSisyphusJuniorAgentSpy).toHaveBeenCalledWith(undefined, "openai/gpt-5.4", false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -158,7 +158,7 @@ export async function applyAgentConfig(params: {
|
||||
|
||||
agentConfig["sisyphus-junior"] = createSisyphusJuniorAgentWithOverrides(
|
||||
params.pluginConfig.agents?.["sisyphus-junior"],
|
||||
undefined,
|
||||
(builtinAgents.atlas as { model?: string } | undefined)?.model,
|
||||
useTaskSystem,
|
||||
);
|
||||
|
||||
|
||||
@@ -178,6 +178,13 @@ describe("AGENT_MODEL_REQUIREMENTS", () => {
|
||||
expect(primary.model).toBe("claude-opus-4-6")
|
||||
expect(primary.providers).toEqual(["anthropic", "github-copilot", "opencode"])
|
||||
expect(primary.variant).toBe("max")
|
||||
|
||||
const openAiFallback = metis.fallbackChain.find((entry) => entry.providers.includes("openai"))
|
||||
expect(openAiFallback).toEqual({
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "high",
|
||||
})
|
||||
})
|
||||
|
||||
test("momus has valid fallbackChain with gpt-5.4 as primary", () => {
|
||||
@@ -213,6 +220,32 @@ describe("AGENT_MODEL_REQUIREMENTS", () => {
|
||||
const secondary = atlas.fallbackChain[1]
|
||||
expect(secondary.model).toBe("kimi-k2.5")
|
||||
expect(secondary.providers[0]).toBe("opencode-go")
|
||||
|
||||
const tertiary = atlas.fallbackChain[2]
|
||||
expect(tertiary).toEqual({
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "medium",
|
||||
})
|
||||
})
|
||||
|
||||
test("sisyphus-junior has an OpenAI fallback before big-pickle", () => {
|
||||
// given - sisyphus-junior agent requirement
|
||||
const sisyphusJunior = AGENT_MODEL_REQUIREMENTS["sisyphus-junior"]
|
||||
|
||||
// when - locating the OpenAI fallback entry
|
||||
const openAiFallback = sisyphusJunior.fallbackChain.find((entry) => entry.providers.includes("openai"))
|
||||
const openAiFallbackIndex = sisyphusJunior.fallbackChain.findIndex((entry) => entry.providers.includes("openai"))
|
||||
const bigPickleIndex = sisyphusJunior.fallbackChain.findIndex((entry) => entry.model === "big-pickle")
|
||||
|
||||
// then
|
||||
expect(openAiFallback).toEqual({
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "medium",
|
||||
})
|
||||
expect(openAiFallbackIndex).toBeGreaterThan(-1)
|
||||
expect(bigPickleIndex).toBeGreaterThan(openAiFallbackIndex)
|
||||
})
|
||||
|
||||
test("hephaestus supports openai, github-copilot, venice, and opencode providers", () => {
|
||||
|
||||
@@ -121,6 +121,11 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
|
||||
model: "claude-opus-4-6",
|
||||
variant: "max",
|
||||
},
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "high",
|
||||
},
|
||||
{ providers: ["opencode-go"], model: "glm-5" },
|
||||
{ providers: ["kimi-for-coding"], model: "k2p5" },
|
||||
],
|
||||
@@ -149,12 +154,22 @@ export const AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = {
|
||||
fallbackChain: [
|
||||
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "medium",
|
||||
},
|
||||
],
|
||||
},
|
||||
"sisyphus-junior": {
|
||||
fallbackChain: [
|
||||
{ providers: ["anthropic", "github-copilot", "opencode"], model: "claude-sonnet-4-6" },
|
||||
{ providers: ["opencode-go"], model: "kimi-k2.5" },
|
||||
{
|
||||
providers: ["openai", "github-copilot", "opencode"],
|
||||
model: "gpt-5.4",
|
||||
variant: "medium",
|
||||
},
|
||||
{ providers: ["opencode"], model: "big-pickle" },
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user