From e872bd3c8fc15914980518958a42153b2543ed55 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Sat, 1 Aug 2026 10:54:46 -0400 Subject: [PATCH] feat(tui): prioritize favorite model search results (#40049) --- packages/tui/src/component/dialog-model.tsx | 14 +++++++++---- .../test/cli/cmd/tui/model-options.test.ts | 20 ++++++++++++++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/packages/tui/src/component/dialog-model.tsx b/packages/tui/src/component/dialog-model.tsx index f998a28417..87168f6c29 100644 --- a/packages/tui/src/component/dialog-model.tsx +++ b/packages/tui/src/component/dialog-model.tsx @@ -63,15 +63,15 @@ export function DialogModel(props: { providerID?: string }) { .filter((model) => (props.providerID ? model.providerID === props.providerID : true)) .map((model) => { const provider = providers().get(model.providerID) + const favorite = favorites.some((item) => item.providerID === model.providerID && item.modelID === model.id) return { value: { providerID: model.providerID, modelID: model.id }, providerID: model.providerID, providerName: provider?.name ?? model.providerID, title: model.name, releaseDate: model.time.released, - description: favorites.some((item) => item.providerID === model.providerID && item.modelID === model.id) - ? "(Favorite)" - : undefined, + favorite, + description: favorite ? "(Favorite)" : undefined, category: connected() ? (provider?.name ?? model.providerID) : undefined, footer: free(model) ? "Free" : undefined, onSelect() { @@ -96,7 +96,9 @@ export function DialogModel(props: { providerID?: string }) { ) if (needle) { - return fuzzysort.go(needle, modelOptions, { keys: ["title", "category"] }).map((item) => item.obj) + return prioritizeFavorites( + fuzzysort.go(needle, modelOptions, { keys: ["title", "category"] }).map((item) => item.obj), + ) } return [...favoriteOptions, ...recentOptions, ...modelOptions] @@ -160,6 +162,10 @@ export function DialogModel(props: { providerID?: string }) { ) } +export function prioritizeFavorites(options: T[]) { + return options.toSorted((a, b) => Number(b.favorite) - Number(a.favorite)) +} + export function sortModelOptions< T extends { providerID?: string; providerName?: string; releaseDate: string | number; title: string }, >(options: T[]) { diff --git a/packages/tui/test/cli/cmd/tui/model-options.test.ts b/packages/tui/test/cli/cmd/tui/model-options.test.ts index 38aa2cff8a..54fd168862 100644 --- a/packages/tui/test/cli/cmd/tui/model-options.test.ts +++ b/packages/tui/test/cli/cmd/tui/model-options.test.ts @@ -1,5 +1,23 @@ import { describe, expect, test } from "bun:test" -import { sortModelOptions } from "../../../../src/component/dialog-model" +import { prioritizeFavorites, sortModelOptions } from "../../../../src/component/dialog-model" + +describe("prioritizeFavorites", () => { + test("moves favorites first while preserving fuzzy result order", () => { + const prioritized = prioritizeFavorites([ + { title: "Best match", favorite: false }, + { title: "Favorite match", favorite: true }, + { title: "Second best match", favorite: false }, + { title: "Second favorite match", favorite: true }, + ]) + + expect(prioritized.map((model) => model.title)).toEqual([ + "Favorite match", + "Second favorite match", + "Best match", + "Second best match", + ]) + }) +}) describe("sortModelOptions", () => { test("orders opencode models before other providers", () => {