fix(agents): honor user atlas model when resolution returns undefined (#4255)

Atlas was the only agent that bailed early (returning undefined) when
applyModelResolution returned undefined, even if the user had explicitly
configured agents.atlas.model. The general-agents.ts path already handled
this case by falling back to the user's override; sisyphus has its own
explicit-config check. Atlas had neither, so under edge cases (cold
provider cache, no system default, empty availableModels) Atlas was
silently dropped and OpenCode used its built-in default — surfaced as
the hardcoded claude-sonnet-4-6 in the reported bug.

This aligns atlas-agent.ts with the same defensive pattern used in
general-agents.ts: when resolution fails but the user has an explicit
model override, honor it directly instead of dropping the agent.

Adds a regression test covering the scenario where availableModels is
empty AND systemDefaultModel is undefined AND no provider cache exists.
This commit is contained in:
bellman
2026-05-24 00:38:42 +09:00
committed by YeonGyu-Kim
parent c0a6c667e6
commit 7d444eed5e
2 changed files with 31 additions and 1 deletions
+7 -1
View File
@@ -38,7 +38,7 @@ export function maybeCreateAtlasConfig(input: {
const orchestratorOverride = agentOverrides["atlas"]
const atlasRequirement = AGENT_MODEL_REQUIREMENTS["atlas"]
const atlasResolution = applyModelResolution({
let atlasResolution = applyModelResolution({
uiSelectedModel: orchestratorOverride?.model !== undefined ? undefined : uiSelectedModel,
userModel: orchestratorOverride?.model,
requirement: atlasRequirement,
@@ -46,6 +46,12 @@ export function maybeCreateAtlasConfig(input: {
systemDefaultModel,
})
if (!atlasResolution && orchestratorOverride?.model) {
// User explicitly configured a model but resolution failed (e.g., cold cache, no system default).
// Honor the user's choice directly instead of dropping Atlas entirely.
atlasResolution = { model: orchestratorOverride.model, provenance: "override" as const }
}
if (!atlasResolution) return undefined
const { model: atlasModel, variant: atlasResolvedVariant } = atlasResolution
+24
View File
@@ -170,6 +170,30 @@ describe("createBuiltinAgents with model overrides", () => {
}
})
test("atlas honors user config model when resolution fails (no available models, no system default)", async () => {
// #given - regression for #4255: user sets agents.atlas.model but availableModels is empty
// and systemDefaultModel is undefined, so applyModelResolution returns undefined.
// Previous behavior: atlas was silently dropped, OpenCode used its built-in default.
// Expected behavior: honor the user's explicit model override.
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(null)
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(new Set())
const overrides = {
atlas: { model: "minimax-cn-coding-plan/MiniMax-M2.5-highspeed" },
}
try {
// #when - no systemDefaultModel, no availableModels, no cache
const agents = await createBuiltinAgents([], overrides, undefined, undefined)
// #then
expect(agents.atlas).toBeDefined()
expect(agents.atlas.model).toBe("minimax-cn-coding-plan/MiniMax-M2.5-highspeed")
} finally {
cacheSpy.mockRestore()
fetchSpy.mockRestore()
}
})
test("Sisyphus is created on first run when no availableModels or cache exist", async () => {
// #given
const systemDefaultModel = "anthropic/claude-opus-4-7"