From f186b3cd5be37a642ab70053fdcd450e12331cd4 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:25:28 +1000 Subject: [PATCH 1/3] fix: make variant modal less annoying --- packages/opencode/src/cli/cmd/tui/app.tsx | 14 +++++++++- .../cli/cmd/tui/component/dialog-model.tsx | 8 +++++- .../cli/cmd/tui/component/dialog-variant.tsx | 26 +++++++++++++------ .../cli/cmd/tui/component/prompt/index.tsx | 2 +- .../src/cli/cmd/tui/context/local.tsx | 16 ++++++++---- 5 files changed, 50 insertions(+), 16 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 3cb383be48db..3e4d0b42707f 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 ee9fa225ed0c..549165f51a0d 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 872092d23e26..28ee1b28250b 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/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index 96563b884ede..510d5f2b6640 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -632,7 +632,7 @@ export function Prompt(props: PromptProps) { // Capture mode before it gets reset const currentMode = store.mode - const variant = local.model.variant.current() + const variant = local.model.variant.selected() if (store.mode === "shell") { sdk.client.session.shell({ diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index d93079f12a42..dbda08d33e29 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,18 +345,18 @@ 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() { const variants = this.list() if (variants.length === 0) return - const current = this.current() - if (!current) { + const cur = this.current() + if (!cur) { this.set(variants[0]) return } - const index = variants.indexOf(current) + const index = variants.indexOf(cur) if (index === -1 || index === variants.length - 1) { this.set(undefined) return From 32fd860fd01983ec2944525b99dd55583e49098b Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:30:59 +1000 Subject: [PATCH 2/3] fix: send resolved variant to server, not raw sentinel --- packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index 510d5f2b6640..96563b884ede 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -632,7 +632,7 @@ export function Prompt(props: PromptProps) { // Capture mode before it gets reset const currentMode = store.mode - const variant = local.model.variant.selected() + const variant = local.model.variant.current() if (store.mode === "shell") { sdk.client.session.shell({ From 37952c508754eb25231a13996ab5ca6a1f96bf3d Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Mon, 30 Mar 2026 15:34:46 +1000 Subject: [PATCH 3/3] fix: revert unnecessary variable rename in cycle() --- packages/opencode/src/cli/cmd/tui/context/local.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/context/local.tsx b/packages/opencode/src/cli/cmd/tui/context/local.tsx index dbda08d33e29..e131df358fb0 100644 --- a/packages/opencode/src/cli/cmd/tui/context/local.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/local.tsx @@ -351,12 +351,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ cycle() { const variants = this.list() if (variants.length === 0) return - const cur = this.current() - if (!cur) { + const current = this.current() + if (!current) { this.set(variants[0]) return } - const index = variants.indexOf(cur) + const index = variants.indexOf(current) if (index === -1 || index === variants.length - 1) { this.set(undefined) return