fix: respect user-configured category model over fallbackChain defaults

When a user configures a custom model for a category (e.g. quick.model),
the hardcoded CATEGORY_MODEL_REQUIREMENTS fallbackChain was overriding it.
This caused the user's model to be ignored and replaced with the default
(e.g. openai/gpt-5.4-mini).

Fix:
- Use userModelOverride directly instead of potentially stale actualModel
- Suppress hardcoded fallbackChain when explicitCategoryModel is provided
- Add regression test verifying user category model takes precedence

Closes #3040
This commit is contained in:
YeonGyu-Kim
2026-04-03 18:27:26 +09:00
parent ed06428ba3
commit 8f449e1627
2 changed files with 35 additions and 3 deletions
@@ -452,4 +452,36 @@ describe("resolveCategoryExecution", () => {
cacheSpy.mockRestore()
agentsSpy.mockRestore()
})
test("does not inherit hardcoded fallbackChain when user configures a category model [regression #3040]", async () => {
//#given
const args = {
category: "quick",
prompt: "test prompt",
description: "Test task",
run_in_background: false,
load_skills: [],
blockedBy: undefined,
enableSkillTools: false,
}
const executorCtx = createMockExecutorContext()
executorCtx.userCategories = {
quick: {
model: "animal-gateway-xai/grok-4-fast-non-reasoning",
},
}
//#when
const result = await resolveCategoryExecution(args, executorCtx, undefined, "anthropic/claude-sonnet-4-6")
//#then
expect(result.error).toBeUndefined()
expect(result.actualModel).toBe("animal-gateway-xai/grok-4-fast-non-reasoning")
expect(result.categoryModel).toEqual({
providerID: "animal-gateway-xai",
modelID: "grok-4-fast-non-reasoning",
variant: undefined,
})
expect(result.fallbackChain).toBeUndefined()
})
})
+3 -3
View File
@@ -150,12 +150,12 @@ Available categories: ${allCategoryNames}`,
const userModelOverride = explicitCategoryModel ?? overrideModel
if (userModelOverride) {
actualModel = userModelOverride
const parsedModel = parseModelString(actualModel)
const parsedModel = parseModelString(userModelOverride)
const variantToUse = userCategories?.[args.category!]?.variant ?? resolved.config.variant
categoryModel = parsedModel
? applyCategoryParams({ ...parsedModel, variant: variantToUse ?? parsedModel.variant }, resolved.config)
: undefined
modelInfo = { model: actualModel, type: "user-defined", source: "override" }
modelInfo = { model: userModelOverride, type: "user-defined", source: "override" }
}
} else if (resolution) {
const {
@@ -275,6 +275,6 @@ Available categories: ${categoryNames.join(", ")}`,
actualModel,
isUnstableAgent,
// Don't use hardcoded fallback chain when resolution was skipped (cold cache)
fallbackChain: configuredFallbackChain ?? (isModelResolutionSkipped ? undefined : requirement?.fallbackChain),
fallbackChain: configuredFallbackChain ?? ((isModelResolutionSkipped || explicitCategoryModel) ? undefined : requirement?.fallbackChain),
}
}