From fd0b639613a2cad682f703c838580e1637015a05 Mon Sep 17 00:00:00 2001 From: marius-kilocode Date: Fri, 21 Aug 2026 13:18:24 +0200 Subject: [PATCH] fix(model-selector): match colon-prefixed names --- .changeset/model-selector-provider-prefix.md | 5 +++++ .../tests/unit/model-selector-utils.test.ts | 5 +++++ .../components/shared/model-selector-utils.ts | 8 +++++--- .../tui/test/kilocode/model-picker.test.ts | 20 +++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 .changeset/model-selector-provider-prefix.md diff --git a/.changeset/model-selector-provider-prefix.md b/.changeset/model-selector-provider-prefix.md new file mode 100644 index 00000000000..f5f98f39610 --- /dev/null +++ b/.changeset/model-selector-provider-prefix.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Allow model selector searches to match provider prefixes in colon-separated model names. diff --git a/packages/kilo-vscode/tests/unit/model-selector-utils.test.ts b/packages/kilo-vscode/tests/unit/model-selector-utils.test.ts index 2f204ed9a16..ee444202f54 100644 --- a/packages/kilo-vscode/tests/unit/model-selector-utils.test.ts +++ b/packages/kilo-vscode/tests/unit/model-selector-utils.test.ts @@ -197,9 +197,14 @@ const SEARCH_MODELS: EnrichedModel[] = [ { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", providerID: "openai", providerName: "OpenAI" }, { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", providerID: "kilo", providerName: "Kilo" }, { id: "gpt-5.6", name: "GPT-5.6", providerID: "anthropic", providerName: "Anthropic" }, + { id: "xai/grok-4.20", name: "SpaceXAI: Grok 4.20", providerID: "kilo", providerName: "Kilo Gateway" }, ] describe("rankModelSearch", () => { + it("matches colon-separated prefixes in model display names", () => { + expect(rankModelSearch(SEARCH_MODELS, "SpaceX").map((model) => model.name)).toEqual(["SpaceXAI: Grok 4.20"]) + }) + it("prefers an exact model token over a longer prefix match", () => { expect( rankModelSearch(SEARCH_MODELS, "sol") diff --git a/packages/kilo-vscode/webview-ui/src/components/shared/model-selector-utils.ts b/packages/kilo-vscode/webview-ui/src/components/shared/model-selector-utils.ts index 36d09cf68cb..67b80dc06fd 100644 --- a/packages/kilo-vscode/webview-ui/src/components/shared/model-selector-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/components/shared/model-selector-utils.ts @@ -89,12 +89,13 @@ function tokenScore(token: string, value: string): number { } function matchScore(model: EnrichedModel, query: string): number | undefined { - const name = stripSubProviderPrefix(sanitizeName(model.name)) + const raw = sanitizeName(model.name) + const name = stripSubProviderPrefix(raw) const tokens = words(query) if (tokens.length === 0) return 0 const scores = tokens.map((token) => { - const modelScore = Math.max(tokenScore(token, name), tokenScore(token, model.id)) + const modelScore = Math.max(tokenScore(token, name), tokenScore(token, raw), tokenScore(token, model.id)) const providerScore = modelScore < 0 ? tokenScore(token, model.providerName) : -1 return { modelScore, providerScore } }) @@ -102,7 +103,8 @@ function matchScore(model: EnrichedModel, query: string): number | undefined { const modelScore = scores.reduce((sum, score) => sum + Math.max(score.modelScore, 0), 0) const providerScore = scores.reduce((sum, score) => sum + Math.max(score.providerScore, 0), 0) - const exact = collapse(query) === collapse(name) || collapse(query) === collapse(model.id) + const exact = + collapse(query) === collapse(name) || collapse(query) === collapse(raw) || collapse(query) === collapse(model.id) return modelScore + Math.floor(providerScore / 10) + (exact ? 5000 : 0) } diff --git a/packages/tui/test/kilocode/model-picker.test.ts b/packages/tui/test/kilocode/model-picker.test.ts index 7f24cc54853..b282c739b77 100644 --- a/packages/tui/test/kilocode/model-picker.test.ts +++ b/packages/tui/test/kilocode/model-picker.test.ts @@ -64,6 +64,26 @@ const inCategory = (options: ReturnType, category: string) => options.filter((option) => option.category === category).map((option) => option.modelID) describe("model picker options", () => { + test("matches colon-separated prefixes in model display names", () => { + const options = buildModelPickerOptions({ + providers: [ + { + id: "kilo", + name: "Kilo Gateway", + models: { + "xai/grok-4.20": { + id: "xai/grok-4.20", + name: "SpaceXAI: Grok 4.20", + }, + }, + }, + ], + query: "SpaceX", + }) + + expect(options.map((option) => option.modelID)).toEqual(["xai/grok-4.20"]) + }) + test("keeps recommended Kilo models in their section after they are used", () => { const options = build({ recents: [sonnet45] })