diff --git a/src/agents/builtin-agents/atlas-agent.ts b/src/agents/builtin-agents/atlas-agent.ts index bea50480b..50cfc2cf3 100644 --- a/src/agents/builtin-agents/atlas-agent.ts +++ b/src/agents/builtin-agents/atlas-agent.ts @@ -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 diff --git a/src/agents/utils.test.ts b/src/agents/utils.test.ts index d4038f9bf..0df4ef602 100644 --- a/src/agents/utils.test.ts +++ b/src/agents/utils.test.ts @@ -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"