From 9a6288466d0ad8b5e9333eece3288aaaffe4bcd6 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 10 Feb 2026 09:44:02 -0500 Subject: [PATCH 1/2] refactor: clean up dialog-model.tsx per code review - Extract duplicated favorite/recent option builder into toOptions helper - Simplify showExtra memo to single boolean expression - Simplify title memo with optional chaining - Remove dead ref signal and unused DialogSelectRef import - Inline intermediate variables (q, value aliases) - Use implicit returns in map callbacks --- .../cli/cmd/tui/component/dialog-model.tsx | 175 ++++++------------ 1 file changed, 53 insertions(+), 122 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx index 4ad92eeb839..883a276c74e 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx @@ -2,7 +2,7 @@ import { createMemo, createSignal } from "solid-js" import { useLocal } from "@tui/context/local" import { useSync } from "@tui/context/sync" import { map, pipe, flatMap, entries, filter, sortBy, take } from "remeda" -import { DialogSelect, type DialogSelectRef } from "@tui/ui/dialog-select" +import { DialogSelect } from "@tui/ui/dialog-select" import { useDialog } from "@tui/ui/dialog" import { createDialogProviderOptions, DialogProvider } from "./dialog-provider" import { useKeybind } from "../context/keybind" @@ -20,21 +20,15 @@ export function DialogModel(props: { providerID?: string }) { const sync = useSync() const dialog = useDialog() const keybind = useKeybind() - const [ref, setRef] = createSignal>() const [query, setQuery] = createSignal("") const connected = useConnected() const providers = createDialogProviderOptions() - const showExtra = createMemo(() => { - if (!connected()) return false - if (props.providerID) return false - return true - }) + const showExtra = createMemo(() => connected() && !props.providerID) const options = createMemo(() => { - const q = query() - const needle = q.trim() + const needle = query().trim() const showSections = showExtra() && needle.length === 0 const favorites = connected() ? local.model.favorite() : [] const recents = local.model.recent() @@ -45,71 +39,33 @@ export function DialogModel(props: { providerID?: string }) { ) : [] - const favoriteOptions = showSections - ? favorites.flatMap((item) => { - const provider = sync.data.provider.find((x) => x.id === item.providerID) - if (!provider) return [] - const model = provider.models[item.modelID] - if (!model) return [] - return [ - { - key: item, - value: { - providerID: provider.id, - modelID: model.id, - }, - title: model.name ?? item.modelID, - description: provider.name, - category: "Favorites", - disabled: provider.id === "opencode" && model.id.includes("-nano"), - footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined, - onSelect: () => { - dialog.clear() - local.model.set( - { - providerID: provider.id, - modelID: model.id, - }, - { recent: true }, - ) - }, + function toOptions(items: typeof favorites, category: string) { + if (!showSections) return [] + return items.flatMap((item) => { + const provider = sync.data.provider.find((x) => x.id === item.providerID) + if (!provider) return [] + const model = provider.models[item.modelID] + if (!model) return [] + return [ + { + key: item, + value: { providerID: provider.id, modelID: model.id }, + title: model.name ?? item.modelID, + description: provider.name, + category, + disabled: provider.id === "opencode" && model.id.includes("-nano"), + footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined, + onSelect: () => { + dialog.clear() + local.model.set({ providerID: provider.id, modelID: model.id }, { recent: true }) }, - ] - }) - : [] + }, + ] + }) + } - const recentOptions = showSections - ? recentList.flatMap((item) => { - const provider = sync.data.provider.find((x) => x.id === item.providerID) - if (!provider) return [] - const model = provider.models[item.modelID] - if (!model) return [] - return [ - { - key: item, - value: { - providerID: provider.id, - modelID: model.id, - }, - title: model.name ?? item.modelID, - description: provider.name, - category: "Recent", - disabled: provider.id === "opencode" && model.id.includes("-nano"), - footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined, - onSelect: () => { - dialog.clear() - local.model.set( - { - providerID: provider.id, - modelID: model.id, - }, - { recent: true }, - ) - }, - }, - ] - }) - : [] + const favoriteOptions = toOptions(favorites, "Favorites") + const recentOptions = toOptions(recentList, "Recent") const providerOptions = pipe( sync.data.provider, @@ -123,45 +79,26 @@ export function DialogModel(props: { providerID?: string }) { entries(), filter(([_, info]) => info.status !== "deprecated"), filter(([_, info]) => (props.providerID ? info.providerID === props.providerID : true)), - map(([model, info]) => { - const value = { - providerID: provider.id, - modelID: model, - } - return { - value, - title: info.name ?? model, - description: favorites.some( - (item) => item.providerID === value.providerID && item.modelID === value.modelID, - ) - ? "(Favorite)" - : undefined, - category: connected() ? provider.name : undefined, - disabled: provider.id === "opencode" && model.includes("-nano"), - footer: info.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined, - onSelect() { - dialog.clear() - local.model.set( - { - providerID: provider.id, - modelID: model, - }, - { recent: true }, - ) - }, - } - }), + map(([model, info]) => ({ + value: { providerID: provider.id, modelID: model }, + title: info.name ?? model, + description: favorites.some((item) => item.providerID === provider.id && item.modelID === model) + ? "(Favorite)" + : undefined, + category: connected() ? provider.name : undefined, + disabled: provider.id === "opencode" && model.includes("-nano"), + footer: info.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined, + onSelect() { + dialog.clear() + local.model.set({ providerID: provider.id, modelID: model }, { recent: true }) + }, + })), filter((x) => { if (!showSections) return true - const value = x.value - const inFavorites = favorites.some( - (item) => item.providerID === value.providerID && item.modelID === value.modelID, - ) - if (inFavorites) return false - const inRecents = recents.some( - (item) => item.providerID === value.providerID && item.modelID === value.modelID, - ) - if (inRecents) return false + if (favorites.some((item) => item.providerID === x.value.providerID && item.modelID === x.value.modelID)) + return false + if (recents.some((item) => item.providerID === x.value.providerID && item.modelID === x.value.modelID)) + return false return true }), sortBy( @@ -175,12 +112,10 @@ export function DialogModel(props: { providerID?: string }) { const popularProviders = !connected() ? pipe( providers(), - map((option) => { - return { - ...option, - category: "Popular providers", - } - }), + map((option) => ({ + ...option, + category: "Popular providers", + })), take(6), ) : [] @@ -199,13 +134,11 @@ export function DialogModel(props: { providerID?: string }) { props.providerID ? sync.data.provider.find((x) => x.id === props.providerID) : null, ) - const title = createMemo(() => { - if (provider()) return provider()!.name - return "Select model" - }) + const title = createMemo(() => provider()?.name ?? "Select model") return ( - [number]["value"]> + options={options()} keybind={[ { keybind: keybind.all.model_provider_list?.[0], @@ -223,12 +156,10 @@ export function DialogModel(props: { providerID?: string }) { }, }, ]} - ref={setRef} onFilter={setQuery} skipFilter={true} title={title()} current={local.model.current()} - options={options()} /> ) } From 6481f6736503e834b9d5d4d53bc16334aa8cac98 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 10 Feb 2026 09:59:31 -0500 Subject: [PATCH 2/2] tui: flatten model selection list during search to show more results --- .../cli/cmd/tui/component/dialog-model.tsx | 22 +++++++++---------- .../src/cli/cmd/tui/ui/dialog-select.tsx | 20 ++++++++++++----- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx index 883a276c74e..c30b8d12a93 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx @@ -33,12 +33,6 @@ export function DialogModel(props: { providerID?: string }) { const favorites = connected() ? local.model.favorite() : [] const recents = local.model.recent() - const recentList = showSections - ? recents.filter( - (item) => !favorites.some((fav) => fav.providerID === item.providerID && fav.modelID === item.modelID), - ) - : [] - function toOptions(items: typeof favorites, category: string) { if (!showSections) return [] return items.flatMap((item) => { @@ -65,7 +59,12 @@ export function DialogModel(props: { providerID?: string }) { } const favoriteOptions = toOptions(favorites, "Favorites") - const recentOptions = toOptions(recentList, "Recent") + const recentOptions = toOptions( + recents.filter( + (item) => !favorites.some((fav) => fav.providerID === item.providerID && fav.modelID === item.modelID), + ), + "Recent", + ) const providerOptions = pipe( sync.data.provider, @@ -120,11 +119,11 @@ export function DialogModel(props: { providerID?: string }) { ) : [] - // Search shows a single merged list (favorites inline) if (needle) { - const filteredProviders = fuzzysort.go(needle, providerOptions, { keys: ["title", "category"] }).map((x) => x.obj) - const filteredPopular = fuzzysort.go(needle, popularProviders, { keys: ["title"] }).map((x) => x.obj) - return [...filteredProviders, ...filteredPopular] + return [ + ...fuzzysort.go(needle, providerOptions, { keys: ["title", "category"] }).map((x) => x.obj), + ...fuzzysort.go(needle, popularProviders, { keys: ["title"] }).map((x) => x.obj), + ] } return [...favoriteOptions, ...recentOptions, ...providerOptions, ...popularProviders] @@ -157,6 +156,7 @@ export function DialogModel(props: { providerID?: string }) { }, ]} onFilter={setQuery} + flat={true} skipFilter={true} title={title()} current={local.model.current()} diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 490a100721d..151f73cf7c0 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -15,6 +15,7 @@ export interface DialogSelectProps { title: string placeholder?: string options: DialogSelectOption[] + flat?: boolean ref?: (ref: DialogSelectRef) => void onMove?: (option: DialogSelectOption) => void onFilter?: (query: string) => void @@ -100,7 +101,10 @@ export function DialogSelect(props: DialogSelectProps) { setStore("input", "keyboard") }) - const grouped = createMemo(() => { + const flatten = createMemo(() => props.flat && store.filter.length > 0) + + const grouped = createMemo<[string, DialogSelectOption[]][]>(() => { + if (flatten()) return [["", filtered()]] const result = pipe( filtered(), groupBy((x) => x.category ?? ""), @@ -117,10 +121,16 @@ export function DialogSelect(props: DialogSelectProps) { ) }) + const rows = createMemo(() => { + const headers = grouped().reduce((acc, [category], i) => { + if (!category) return acc + return acc + (i > 0 ? 2 : 1) + }, 0) + return flat().length + headers + }) + const dimensions = useTerminalDimensions() - const height = createMemo(() => - Math.min(flat().length + grouped().length * 2 - 1, Math.floor(dimensions().height / 2) - 6), - ) + const height = createMemo(() => Math.min(rows(), Math.floor(dimensions().height / 2) - 6)) const selected = createMemo(() => flat()[store.selected]) @@ -311,7 +321,7 @@ export function DialogSelect(props: DialogSelectProps) { >