fix: respect user-configured agent models over system defaults
When user explicitly configures an agent model in oh-my-opencode.json, that model should take priority over the active model in OpenCode's config (which may just be the system default, not a deliberate UI selection). This fixes the issue where user-configured models from plugin providers (e.g., google/antigravity-*) were being overridden by the fallback chain because config.model was being passed as uiSelectedModel regardless of whether the user had an explicit config. The fix: - Only pass uiSelectedModel when there's no explicit userModel config - If user has configured a model, let resolveModelPipeline use it directly Fixes #1573
This commit is contained in:
committed by
YeonGyu-Kim
parent
368ac310a1
commit
dbf584af95
@@ -79,6 +79,72 @@ describe("createBuiltinAgents with model overrides", () => {
|
||||
}
|
||||
})
|
||||
|
||||
test("user config model takes priority over uiSelectedModel for sisyphus", async () => {
|
||||
// #given
|
||||
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
|
||||
new Set(["openai/gpt-5.2", "anthropic/claude-sonnet-4-5"])
|
||||
)
|
||||
const uiSelectedModel = "openai/gpt-5.2"
|
||||
const overrides = {
|
||||
sisyphus: { model: "google/antigravity-claude-opus-4-5-thinking" },
|
||||
}
|
||||
|
||||
try {
|
||||
// #when
|
||||
const agents = await createBuiltinAgents(
|
||||
[],
|
||||
overrides,
|
||||
undefined,
|
||||
TEST_DEFAULT_MODEL,
|
||||
undefined,
|
||||
undefined,
|
||||
[],
|
||||
undefined,
|
||||
undefined,
|
||||
uiSelectedModel
|
||||
)
|
||||
|
||||
// #then
|
||||
expect(agents.sisyphus).toBeDefined()
|
||||
expect(agents.sisyphus.model).toBe("google/antigravity-claude-opus-4-5-thinking")
|
||||
} finally {
|
||||
fetchSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
test("user config model takes priority over uiSelectedModel for atlas", async () => {
|
||||
// #given
|
||||
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
|
||||
new Set(["openai/gpt-5.2", "anthropic/claude-sonnet-4-5"])
|
||||
)
|
||||
const uiSelectedModel = "openai/gpt-5.2"
|
||||
const overrides = {
|
||||
atlas: { model: "google/antigravity-claude-opus-4-5-thinking" },
|
||||
}
|
||||
|
||||
try {
|
||||
// #when
|
||||
const agents = await createBuiltinAgents(
|
||||
[],
|
||||
overrides,
|
||||
undefined,
|
||||
TEST_DEFAULT_MODEL,
|
||||
undefined,
|
||||
undefined,
|
||||
[],
|
||||
undefined,
|
||||
undefined,
|
||||
uiSelectedModel
|
||||
)
|
||||
|
||||
// #then
|
||||
expect(agents.atlas).toBeDefined()
|
||||
expect(agents.atlas.model).toBe("google/antigravity-claude-opus-4-5-thinking")
|
||||
} finally {
|
||||
fetchSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
test("Sisyphus is created on first run when no availableModels or cache exist", async () => {
|
||||
// #given
|
||||
const systemDefaultModel = "anthropic/claude-opus-4-6"
|
||||
@@ -422,6 +488,58 @@ describe("createBuiltinAgents with requiresAnyModel gating (sisyphus)", () => {
|
||||
cacheSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
test("sisyphus uses user-configured plugin model even when not in cache or fallback chain", async () => {
|
||||
// #given - user configures a model from a plugin provider (like antigravity)
|
||||
// that is NOT in the availableModels cache and NOT in the fallback chain
|
||||
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
|
||||
new Set(["openai/gpt-5.2"])
|
||||
)
|
||||
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(
|
||||
["openai"]
|
||||
)
|
||||
const overrides = {
|
||||
sisyphus: { model: "google/antigravity-claude-opus-4-5-thinking" },
|
||||
}
|
||||
|
||||
try {
|
||||
// #when
|
||||
const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], {})
|
||||
|
||||
// #then
|
||||
expect(agents.sisyphus).toBeDefined()
|
||||
expect(agents.sisyphus.model).toBe("google/antigravity-claude-opus-4-5-thinking")
|
||||
} finally {
|
||||
fetchSpy.mockRestore()
|
||||
cacheSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
test("sisyphus uses user-configured plugin model when availableModels is empty but cache exists", async () => {
|
||||
// #given - connected providers cache exists but models cache is empty
|
||||
// This reproduces the exact scenario where provider-models.json has models: {}
|
||||
const fetchSpy = spyOn(shared, "fetchAvailableModels").mockResolvedValue(
|
||||
new Set()
|
||||
)
|
||||
const cacheSpy = spyOn(connectedProvidersCache, "readConnectedProvidersCache").mockReturnValue(
|
||||
["google", "openai", "opencode"]
|
||||
)
|
||||
const overrides = {
|
||||
sisyphus: { model: "google/antigravity-claude-opus-4-5-thinking" },
|
||||
}
|
||||
|
||||
try {
|
||||
// #when
|
||||
const agents = await createBuiltinAgents([], overrides, undefined, TEST_DEFAULT_MODEL, undefined, undefined, [], {})
|
||||
|
||||
// #then
|
||||
expect(agents.sisyphus).toBeDefined()
|
||||
expect(agents.sisyphus.model).toBe("google/antigravity-claude-opus-4-5-thinking")
|
||||
} finally {
|
||||
fetchSpy.mockRestore()
|
||||
cacheSpy.mockRestore()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("buildAgent with category and skills", () => {
|
||||
|
||||
@@ -304,7 +304,7 @@ export async function createBuiltinAgents(
|
||||
const isPrimaryAgent = isFactory(source) && source.mode === "primary"
|
||||
|
||||
const resolution = applyModelResolution({
|
||||
uiSelectedModel: isPrimaryAgent ? uiSelectedModel : undefined,
|
||||
uiSelectedModel: (isPrimaryAgent && !override?.model) ? uiSelectedModel : undefined,
|
||||
userModel: override?.model,
|
||||
requirement,
|
||||
availableModels,
|
||||
@@ -356,7 +356,7 @@ export async function createBuiltinAgents(
|
||||
|
||||
if (!disabledAgents.includes("sisyphus") && meetsSisyphusAnyModelRequirement) {
|
||||
let sisyphusResolution = applyModelResolution({
|
||||
uiSelectedModel,
|
||||
uiSelectedModel: sisyphusOverride?.model ? undefined : uiSelectedModel,
|
||||
userModel: sisyphusOverride?.model,
|
||||
requirement: sisyphusRequirement,
|
||||
availableModels,
|
||||
@@ -454,7 +454,7 @@ export async function createBuiltinAgents(
|
||||
const atlasRequirement = AGENT_MODEL_REQUIREMENTS["atlas"]
|
||||
|
||||
const atlasResolution = applyModelResolution({
|
||||
uiSelectedModel,
|
||||
uiSelectedModel: orchestratorOverride?.model ? undefined : uiSelectedModel,
|
||||
userModel: orchestratorOverride?.model,
|
||||
requirement: atlasRequirement,
|
||||
availableModels,
|
||||
|
||||
Reference in New Issue
Block a user