diff --git a/src/tools/delegate-task/category-resolver.test.ts b/src/tools/delegate-task/category-resolver.test.ts index dacad7cd3..d48407dba 100644 --- a/src/tools/delegate-task/category-resolver.test.ts +++ b/src/tools/delegate-task/category-resolver.test.ts @@ -169,6 +169,42 @@ describe("resolveCategoryExecution", () => { agentsSpy.mockRestore() }) + test("preserves inline variant from category model string when no explicit variant is configured", 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: "openai/gpt-5.4 high", + }, + } + + //#when + const result = await resolveCategoryExecution(args, executorCtx, undefined, "anthropic/claude-sonnet-4-6") + + //#then + expect(result.error).toBeUndefined() + expect(result.actualModel).toBeDefined() + expect(result.categoryModel).toBeDefined() + if (!result.actualModel || !result.categoryModel) { + throw new Error("Expected resolved model and category model") + } + expect(result.actualModel).toBe("openai/gpt-5.4 high") + expect(result.categoryModel).toEqual({ + providerID: "openai", + modelID: "gpt-5.4", + variant: "high", + }) + }) + test("does not apply object-style fallback settings when the configured primary model matches directly", async () => { //#given const cacheSpy = spyOn(connectedProvidersCache, "readProviderModelsCache").mockReturnValue({ diff --git a/src/tools/delegate-task/category-resolver.ts b/src/tools/delegate-task/category-resolver.ts index e7099c604..5651f509d 100644 --- a/src/tools/delegate-task/category-resolver.ts +++ b/src/tools/delegate-task/category-resolver.ts @@ -131,7 +131,7 @@ Available categories: ${allCategoryNames}`, const parsedModel = parseModelString(actualModel) const variantToUse = userCategories?.[args.category!]?.variant ?? resolved.config.variant categoryModel = parsedModel - ? applyCategoryParams({ ...parsedModel, variant: variantToUse }, resolved.config) + ? applyCategoryParams({ ...parsedModel, variant: variantToUse ?? parsedModel.variant }, resolved.config) : undefined } } else { @@ -153,7 +153,7 @@ Available categories: ${allCategoryNames}`, const parsedModel = parseModelString(actualModel) const variantToUse = userCategories?.[args.category!]?.variant ?? resolved.config.variant categoryModel = parsedModel - ? applyCategoryParams({ ...parsedModel, variant: variantToUse }, resolved.config) + ? applyCategoryParams({ ...parsedModel, variant: variantToUse ?? parsedModel.variant }, resolved.config) : undefined modelInfo = { model: actualModel, type: "user-defined", source: "override" } } @@ -200,7 +200,7 @@ Available categories: ${allCategoryNames}`, const parsedModel = parseModelString(actualModel) const variantToUse = userCategories?.[args.category!]?.variant ?? resolvedVariant ?? resolved.config.variant categoryModel = parsedModel - ? applyCategoryParams({ ...parsedModel, variant: variantToUse }, resolved.config) + ? applyCategoryParams({ ...parsedModel, variant: variantToUse ?? parsedModel.variant }, resolved.config) : undefined } }