diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 3cb383be48..3e4d0b4270 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -581,10 +581,22 @@ function App(props: { onSnapshot?: () => Promise }) { }, }, { - title: "Switch model variant", + title: "Variant cycle", value: "variant.cycle", keybind: "variant_cycle", category: "Agent", + onSelect: () => { + local.model.variant.cycle() + }, + }, + { + title: "Switch model variant", + value: "variant.list", + category: "Agent", + hidden: local.model.variant.list().length === 0, + slash: { + name: "variants", + }, onSelect: () => { dialog.replace(() => ) }, 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 ee9fa225ed..549165f51a 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-model.tsx @@ -136,7 +136,13 @@ export function DialogModel(props: { providerID?: string }) { function onSelect(providerID: string, modelID: string) { local.model.set({ providerID, modelID }, { recent: true }) - if (local.model.variant.list().length > 0) { + const list = local.model.variant.list() + const cur = local.model.variant.selected() + if (cur === "default" || (cur && list.includes(cur))) { + dialog.clear() + return + } + if (list.length > 0) { dialog.replace(() => ) return } diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-variant.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-variant.tsx index 872092d23e..28ee1b2825 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-variant.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-variant.tsx @@ -8,21 +8,31 @@ export function DialogVariant() { const dialog = useDialog() const options = createMemo(() => { - return local.model.variant.list().map((variant) => ({ - value: variant, - title: variant, - onSelect: () => { - dialog.clear() - local.model.variant.set(variant) + return [ + { + value: "default", + title: "Default", + onSelect: () => { + dialog.clear() + local.model.variant.set(undefined) + }, }, - })) + ...local.model.variant.list().map((variant) => ({ + value: variant, + title: variant, + onSelect: () => { + dialog.clear() + local.model.variant.set(variant) + }, + })), + ] }) return ( options={options()} title={"Select variant"} - current={local.model.variant.current()} + current={local.model.variant.selected()} flat={true} /> ) diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index d93079f12a..e131df358f 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -321,12 +321,18 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ }) }, variant: { - current() { + selected() { const m = currentModel() if (!m) return undefined const key = `${m.providerID}/${m.modelID}` return modelStore.variant[key] }, + current() { + const v = this.selected() + if (!v) return undefined + if (!this.list().includes(v)) return undefined + return v + }, list() { const m = currentModel() if (!m) return [] @@ -339,7 +345,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const m = currentModel() if (!m) return const key = `${m.providerID}/${m.modelID}` - setModelStore("variant", key, value) + setModelStore("variant", key, value ?? "default") save() }, cycle() {