fix(model-resolver): return variant from fallback chain, handle model name normalization

- Add variant to ModelResolutionResult return type
- Return variant from matched fallback entry
- Add normalizeModelName() for Claude model hyphen/period differences
- Add transformModelForProvider() for github-copilot model names
- Update delegate-task to use resolved variant (user config takes priority)
- Fix test expectations for new fallback behavior
This commit is contained in:
justsisyphus
2026-01-23 02:20:32 +09:00
parent 7de376e24f
commit 6e84a14f20
7 changed files with 71 additions and 46 deletions
+3 -3
View File
@@ -256,7 +256,7 @@ describe("generateOmoConfig - model fallback system", () => {
// #when generating config
const result = generateOmoConfig(config)
// #then should use github-copilot sonnet models
// #then should use github-copilot sonnet models (copilot fallback)
expect((result.agents as Record<string, { model: string }>).Sisyphus.model).toBe("github-copilot/claude-sonnet-4.5")
})
@@ -318,8 +318,8 @@ describe("generateOmoConfig - model fallback system", () => {
// #then Sisyphus should use native OpenAI (fallback within native tier)
expect((result.agents as Record<string, { model: string }>).Sisyphus.model).toBe("openai/gpt-5.2")
// #then Oracle should use native OpenAI (primary for ultrabrain)
expect((result.agents as Record<string, { model: string }>).oracle.model).toBe("openai/gpt-5.2-codex")
// #then Oracle should use native OpenAI (first fallback entry)
expect((result.agents as Record<string, { model: string }>).oracle.model).toBe("openai/gpt-5.2")
// #then multimodal-looker should use native OpenAI (fallback within native tier)
expect((result.agents as Record<string, { model: string }>)["multimodal-looker"].model).toBe("openai/gpt-5.2")
})
+13 -1
View File
@@ -65,6 +65,17 @@ function isProviderAvailable(provider: string, avail: ProviderAvailability): boo
return mapping[provider] ?? false
}
function transformModelForProvider(provider: string, model: string): string {
if (provider === "github-copilot") {
return model
.replace("claude-opus-4-5", "claude-opus-4.5")
.replace("claude-sonnet-4-5", "claude-sonnet-4.5")
.replace("claude-haiku-4-5", "claude-haiku-4.5")
.replace("claude-sonnet-4", "claude-sonnet-4")
}
return model
}
function resolveModelFromChain(
fallbackChain: FallbackEntry[],
avail: ProviderAvailability
@@ -72,8 +83,9 @@ function resolveModelFromChain(
for (const entry of fallbackChain) {
for (const provider of entry.providers) {
if (isProviderAvailable(provider, avail)) {
const transformedModel = transformModelForProvider(provider, entry.model)
return {
model: `${provider}/${entry.model}`,
model: `${provider}/${transformedModel}`,
variant: entry.variant,
}
}