From dbc7bfa3f36cc61a3f1a2015e47d71ae9dee5421 Mon Sep 17 00:00:00 2001 From: maria Date: Wed, 2 Sep 2026 20:27:42 -0400 Subject: [PATCH] fix(opencode): show Reasoning selector for OpenCode models (#9287) Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com> --- .../src/provider/Layers/OpenCodeProvider.ts | 36 +++++++++++++++++-- .../src/components/chat/TraitsPicker.test.ts | 2 +- apps/web/src/components/chat/TraitsPicker.tsx | 2 +- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/apps/server/src/provider/Layers/OpenCodeProvider.ts b/apps/server/src/provider/Layers/OpenCodeProvider.ts index a094fe8601a2a899f73417bccb47fad65990eaa4..7f131a54b330c26f1010607917f5a7e6d118da18 100644 --- a/apps/server/src/provider/Layers/OpenCodeProvider.ts +++ b/apps/server/src/provider/Layers/OpenCodeProvider.ts @@ -171,7 +171,30 @@ function inferDefaultAgent(agents: ReadonlyArray): string | undefined { } const DEFAULT_OPENCODE_MODEL_CAPABILITIES: ModelCapabilities = createModelCapabilities({ - optionDescriptors: [], + optionDescriptors: [ + { + id: "variant", + label: "Reasoning", + type: "select", + options: [ + { id: "low", label: "Low" }, + { id: "medium", label: "Medium", isDefault: true }, + { id: "high", label: "High" }, + { id: "xhigh", label: "Extra High" }, + ], + currentValue: "medium", + }, + { + id: "agent", + label: "Agent", + type: "select", + options: [ + { id: "build", label: "Build", isDefault: true }, + { id: "plan", label: "Plan" }, + ], + currentValue: "build", + }, + ], }); function openCodeCapabilitiesForModel(input: { @@ -179,7 +202,14 @@ function openCodeCapabilitiesForModel(input: { readonly model: ProviderListResponse["all"][number]["models"][string]; readonly agents: ReadonlyArray; }): ModelCapabilities { - const variantValues = Object.keys(input.model.variants ?? {}); + const rawVariantValues = Object.keys(input.model.variants ?? {}); + // When a model advertises no variants, synthesize the standard reasoning + // levels so the composer still offers a Reasoning selector (mirrors the + // Codex/Grok experience where reasoning is always configurable). The set + // covers the common OpenCode variant spectrum; `inferDefaultVariant` + // picks the provider-appropriate default (e.g. medium for openai/opencode). + const variantValues = + rawVariantValues.length > 0 ? rawVariantValues : ["low", "medium", "high", "xhigh"]; const defaultVariant = inferDefaultVariant(input.providerID, variantValues); const variantOptions = variantValues.map((value) => defaultVariant === value @@ -201,7 +231,7 @@ function openCodeCapabilitiesForModel(input: { ? [ { id: "variant", - label: "Variant", + label: "Reasoning", type: "select" as const, options: variantOptions, ...(defaultVariant ? { currentValue: defaultVariant } : {}), diff --git a/apps/web/src/components/chat/TraitsPicker.test.ts b/apps/web/src/components/chat/TraitsPicker.test.ts index 5e9a3cf88e232feec60992bb875acf3fc1aaa648..dbe97cdd54e0333e507ee184e93e9e8d5440c075 100644 --- a/apps/web/src/components/chat/TraitsPicker.test.ts +++ b/apps/web/src/components/chat/TraitsPicker.test.ts @@ -167,7 +167,7 @@ describe("buildUnavailableModelOptionDescriptors", () => { ).toEqual([ { id: "variant", - label: "Variant", + label: "Reasoning", type: "select", options: [{ id: "max", label: "max" }], currentValue: "max", diff --git a/apps/web/src/components/chat/TraitsPicker.tsx b/apps/web/src/components/chat/TraitsPicker.tsx index 57a0a869918129cbbfdcf451f82c40092ba1542d..6f122deb7fa2ef524c31e3d501d38ec9cc505ef8 100644 --- a/apps/web/src/components/chat/TraitsPicker.tsx +++ b/apps/web/src/components/chat/TraitsPicker.tsx @@ -40,7 +40,7 @@ const SAVED_OPTION_LABELS: Readonly> = { agent: "Agent", effort: "Effort", reasoningEffort: "Reasoning effort", - variant: "Variant", + variant: "Reasoning", }; function savedOptionLabel(id: string): string { -- 2.54.0