fix(model-availability): prefer exact model ID match in fuzzyMatchModel (#1460)
* fix(model-availability): prefer exact model ID match in fuzzyMatchModel * fix(model-availability): use filter+shortest for multi-provider tie-break - Change Priority 2 from find() to filter()+reduce() - Preserves shortest-match tie-break when multiple providers share model ID - Add test for multi-provider same model ID case - Addresses Oracle review feedback
This commit is contained in:
parent
c57c0a6bcb
commit
faae3d0f32
@ -277,6 +277,42 @@ describe("fuzzyMatchModel", () => {
|
|||||||
expect(result).toBe("anthropic/claude-opus-4-5")
|
expect(result).toBe("anthropic/claude-opus-4-5")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// given available models with similar model IDs (e.g., glm-4.7 and glm-4.7-free)
|
||||||
|
// when searching for the longer variant (glm-4.7-free)
|
||||||
|
// then return exact model ID match, not the shorter one
|
||||||
|
it("should prefer exact model ID match over shorter substring match", () => {
|
||||||
|
const available = new Set([
|
||||||
|
"zai-coding-plan/glm-4.7",
|
||||||
|
"zai-coding-plan/glm-4.7-free",
|
||||||
|
])
|
||||||
|
const result = fuzzyMatchModel("glm-4.7-free", available)
|
||||||
|
expect(result).toBe("zai-coding-plan/glm-4.7-free")
|
||||||
|
})
|
||||||
|
|
||||||
|
// given available models with similar model IDs
|
||||||
|
// when searching for the shorter variant
|
||||||
|
// then return the shorter match (existing behavior preserved)
|
||||||
|
it("should still prefer shorter match when searching for shorter variant", () => {
|
||||||
|
const available = new Set([
|
||||||
|
"zai-coding-plan/glm-4.7",
|
||||||
|
"zai-coding-plan/glm-4.7-free",
|
||||||
|
])
|
||||||
|
const result = fuzzyMatchModel("glm-4.7", available)
|
||||||
|
expect(result).toBe("zai-coding-plan/glm-4.7")
|
||||||
|
})
|
||||||
|
|
||||||
|
// given same model ID from multiple providers
|
||||||
|
// when searching for exact model ID
|
||||||
|
// then return shortest full string (preserves tie-break behavior)
|
||||||
|
it("should use shortest tie-break when multiple providers have same model ID", () => {
|
||||||
|
const available = new Set([
|
||||||
|
"opencode/gpt-5.2",
|
||||||
|
"openai/gpt-5.2",
|
||||||
|
])
|
||||||
|
const result = fuzzyMatchModel("gpt-5.2", available)
|
||||||
|
expect(result).toBe("openai/gpt-5.2")
|
||||||
|
})
|
||||||
|
|
||||||
// given available models with multiple providers
|
// given available models with multiple providers
|
||||||
// when multiple providers are specified
|
// when multiple providers are specified
|
||||||
// then search all specified providers
|
// then search all specified providers
|
||||||
|
|||||||
@ -72,14 +72,29 @@ export function fuzzyMatchModel(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority 1: Exact match (normalized)
|
// Priority 1: Exact match (normalized full model string)
|
||||||
const exactMatch = matches.find((model) => normalizeModelName(model) === targetNormalized)
|
const exactMatch = matches.find((model) => normalizeModelName(model) === targetNormalized)
|
||||||
if (exactMatch) {
|
if (exactMatch) {
|
||||||
log("[fuzzyMatchModel] exact match found", { exactMatch })
|
log("[fuzzyMatchModel] exact match found", { exactMatch })
|
||||||
return exactMatch
|
return exactMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority 2: Shorter model name (more specific)
|
// Priority 2: Exact model ID match (part after provider/)
|
||||||
|
// This ensures "glm-4.7-free" matches "zai-coding-plan/glm-4.7-free" over "zai-coding-plan/glm-4.7"
|
||||||
|
// Use filter + shortest to handle multi-provider cases (e.g., openai/gpt-5.2 + opencode/gpt-5.2)
|
||||||
|
const exactModelIdMatches = matches.filter((model) => {
|
||||||
|
const modelId = model.split("/").slice(1).join("/")
|
||||||
|
return normalizeModelName(modelId) === targetNormalized
|
||||||
|
})
|
||||||
|
if (exactModelIdMatches.length > 0) {
|
||||||
|
const result = exactModelIdMatches.reduce((shortest, current) =>
|
||||||
|
current.length < shortest.length ? current : shortest,
|
||||||
|
)
|
||||||
|
log("[fuzzyMatchModel] exact model ID match found", { result, candidateCount: exactModelIdMatches.length })
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority 3: Shorter model name (more specific, fallback for partial matches)
|
||||||
const result = matches.reduce((shortest, current) =>
|
const result = matches.reduce((shortest, current) =>
|
||||||
current.length < shortest.length ? current : shortest,
|
current.length < shortest.length ? current : shortest,
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user