fix(delegate-task): trust user-configured category models without fuzzy validation (fixes #2740)

This commit is contained in:
MoerAI
2026-03-23 20:39:47 +09:00
parent 331f7ec52b
commit c41d6fd912
4 changed files with 24 additions and 1 deletions

View File

@@ -2,6 +2,7 @@ import type { CategoryConfig, CategoriesConfig } from "../../config/schema"
import { DEFAULT_CATEGORIES, CATEGORY_PROMPT_APPENDS } from "./constants"
import { resolveModel } from "../../shared/model-resolver"
import { isModelAvailable } from "../../shared/model-availability"
import { normalizeModel } from "../../shared/model-normalization"
import { CATEGORY_MODEL_REQUIREMENTS } from "../../shared/model-requirements"
import { log } from "../../shared/logger"
@@ -16,6 +17,7 @@ export interface ResolveCategoryConfigResult {
config: CategoryConfig
promptAppend: string
model: string | undefined
isUserConfiguredModel: boolean
}
/**
@@ -56,6 +58,7 @@ export function resolveCategoryConfig(
inheritedModel: defaultConfig?.model, // Category's built-in model takes precedence over system default
systemDefault: systemDefaultModel,
})
const isUserConfiguredModel = normalizeModel(userConfig?.model) !== undefined
const config: CategoryConfig = {
...defaultConfig,
...userConfig,
@@ -70,5 +73,5 @@ export function resolveCategoryConfig(
: userConfig.prompt_append
}
return { config, promptAppend, model }
return { config, promptAppend, model, isUserConfiguredModel }
}

View File

@@ -110,6 +110,7 @@ Available categories: ${allCategoryNames}`,
userModel: explicitCategoryModel ?? overrideModel,
userFallbackModels: normalizedConfiguredFallbackModels,
categoryDefaultModel: resolved.model,
isUserConfiguredCategoryModel: resolved.isUserConfiguredModel,
fallbackChain: requirement.fallbackChain,
availableModels,
systemDefaultModel,

View File

@@ -102,6 +102,16 @@ describe("resolveModelForDelegateTask", () => {
expect(result).toEqual({ model: "anthropic/claude-sonnet-4-6" })
})
test("#then trusts user-configured category model without fuzzy validation", () => {
const result = resolveModelForDelegateTask({
categoryDefaultModel: "new-api-openai/gpt-5.4-high",
isUserConfiguredCategoryModel: true,
availableModels: new Set(["openai/gpt-5.4"]),
})
expect(result).toEqual({ model: "new-api-openai/gpt-5.4-high" })
})
})
describe("#when user fallback models include variant syntax", () => {

View File

@@ -3,6 +3,7 @@ import { normalizeModel } from "../../shared/model-normalization"
import { fuzzyMatchModel } from "../../shared/model-availability"
import { transformModelForProvider } from "../../shared/provider-model-id-transform"
import { hasConnectedProvidersCache, hasProviderModelsCache } from "../../shared/connected-providers-cache"
import { log } from "../../shared/logger"
import { parseModelString, parseVariantFromModelID } from "./model-string-parser"
function isExplicitHighModel(model: string): boolean {
@@ -48,6 +49,7 @@ export function resolveModelForDelegateTask(input: {
userModel?: string
userFallbackModels?: string[]
categoryDefaultModel?: string
isUserConfiguredCategoryModel?: boolean
fallbackChain?: FallbackEntry[]
availableModels: Set<string>
systemDefaultModel?: string
@@ -67,6 +69,13 @@ export function resolveModelForDelegateTask(input: {
const explicitHighBaseModel = categoryDefault ? getExplicitHighBaseModel(categoryDefault) : null
const explicitHighModel = explicitHighBaseModel ? categoryDefault : undefined
if (categoryDefault) {
if (input.isUserConfiguredCategoryModel) {
log("[resolveModelForDelegateTask] using user-configured category model (bypass validation)", {
categoryDefaultModel: categoryDefault,
})
return { model: categoryDefault }
}
if (input.availableModels.size === 0) {
return { model: categoryDefault }
}