mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 19:05:11 +00:00
Fix model selector fuzzy search to match provider and support multi-token queries
This commit is contained in:
parent
7272eb9274
commit
3de8e0757d
3 changed files with 36 additions and 7 deletions
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Model selector fuzzy search now matches against provider name (not just model ID) and supports space-separated tokens where all tokens must match
|
||||||
|
|
||||||
## [0.21.0] - 2025-12-14
|
## [0.21.0] - 2025-12-14
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export class ModelSelectorComponent extends Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
private filterModels(query: string): void {
|
private filterModels(query: string): void {
|
||||||
this.filteredModels = fuzzyFilter(this.allModels, query, ({ id }) => id);
|
this.filteredModels = fuzzyFilter(this.allModels, query, ({ id, provider }) => `${id} ${provider}`);
|
||||||
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
||||||
this.updateList();
|
this.updateList();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,23 +61,48 @@ export function fuzzyMatch(query: string, text: string): FuzzyMatch {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter and sort items by fuzzy match quality (best matches first)
|
// Filter and sort items by fuzzy match quality (best matches first)
|
||||||
|
// Supports space-separated tokens: all tokens must match, sorted by match count then score
|
||||||
export function fuzzyFilter<T>(items: T[], query: string, getText: (item: T) => string): T[] {
|
export function fuzzyFilter<T>(items: T[], query: string, getText: (item: T) => string): T[] {
|
||||||
if (!query.trim()) {
|
if (!query.trim()) {
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
const results: { item: T; score: number }[] = [];
|
// Split query into tokens
|
||||||
|
const tokens = query
|
||||||
|
.trim()
|
||||||
|
.split(/\s+/)
|
||||||
|
.filter((t) => t.length > 0);
|
||||||
|
|
||||||
|
if (tokens.length === 0) {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
const results: { item: T; totalScore: number }[] = [];
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const text = getText(item);
|
const text = getText(item);
|
||||||
const match = fuzzyMatch(query, text);
|
let totalScore = 0;
|
||||||
if (match.matches) {
|
let allMatch = true;
|
||||||
results.push({ item, score: match.score });
|
|
||||||
|
// Check each token against the text - ALL must match
|
||||||
|
for (const token of tokens) {
|
||||||
|
const match = fuzzyMatch(token, text);
|
||||||
|
if (match.matches) {
|
||||||
|
totalScore += match.score;
|
||||||
|
} else {
|
||||||
|
allMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only include if all tokens match
|
||||||
|
if (allMatch) {
|
||||||
|
results.push({ item, totalScore });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort ascending by score (lower = better match)
|
// Sort by score (asc, lower is better)
|
||||||
results.sort((a, b) => a.score - b.score);
|
results.sort((a, b) => a.totalScore - b.totalScore);
|
||||||
|
|
||||||
return results.map((r) => r.item);
|
return results.map((r) => r.item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue