| ... | @@ -171,7 +171,30 @@ function inferDefaultAgent(agents: ReadonlyArray<Agent>): string | undefined { | ... | @@ -171,7 +171,30 @@ function inferDefaultAgent(agents: ReadonlyArray<Agent>): string | undefined { |
| 171 | } | 171 | } |
| 172 | | 172 | |
| 173 | const DEFAULT_OPENCODE_MODEL_CAPABILITIES: ModelCapabilities = createModelCapabilities({ | 173 | const DEFAULT_OPENCODE_MODEL_CAPABILITIES: ModelCapabilities = createModelCapabilities({ |
| 174 | optionDescriptors: [], | 174 | optionDescriptors: [ |
| | 175 | { |
| | 176 | id: "variant", |
| | 177 | label: "Reasoning", |
| | 178 | type: "select", |
| | 179 | options: [ |
| | 180 | { id: "low", label: "Low" }, |
| | 181 | { id: "medium", label: "Medium", isDefault: true }, |
| | 182 | { id: "high", label: "High" }, |
| | 183 | { id: "xhigh", label: "Extra High" }, |
| | 184 | ], |
| | 185 | currentValue: "medium", |
| | 186 | }, |
| | 187 | { |
| | 188 | id: "agent", |
| | 189 | label: "Agent", |
| | 190 | type: "select", |
| | 191 | options: [ |
| | 192 | { id: "build", label: "Build", isDefault: true }, |
| | 193 | { id: "plan", label: "Plan" }, |
| | 194 | ], |
| | 195 | currentValue: "build", |
| | 196 | }, |
| | 197 | ], |
| 175 | }); | 198 | }); |
| 176 | | 199 | |
| 177 | function openCodeCapabilitiesForModel(input: { | 200 | function openCodeCapabilitiesForModel(input: { |
| ... | @@ -179,7 +202,14 @@ function openCodeCapabilitiesForModel(input: { | ... | @@ -179,7 +202,14 @@ function openCodeCapabilitiesForModel(input: { |
| 179 | readonly model: ProviderListResponse["all"][number]["models"][string]; | 202 | readonly model: ProviderListResponse["all"][number]["models"][string]; |
| 180 | readonly agents: ReadonlyArray<Agent>; | 203 | readonly agents: ReadonlyArray<Agent>; |
| 181 | }): ModelCapabilities { | 204 | }): ModelCapabilities { |
| 182 | const variantValues = Object.keys(input.model.variants ?? {}); | 205 | const rawVariantValues = Object.keys(input.model.variants ?? {}); |
| | 206 | // When a model advertises no variants, synthesize the standard reasoning |
| | 207 | // levels so the composer still offers a Reasoning selector (mirrors the |
| | 208 | // Codex/Grok experience where reasoning is always configurable). The set |
| | 209 | // covers the common OpenCode variant spectrum; `inferDefaultVariant` |
| | 210 | // picks the provider-appropriate default (e.g. medium for openai/opencode). |
| | 211 | const variantValues = |
| | 212 | rawVariantValues.length > 0 ? rawVariantValues : ["low", "medium", "high", "xhigh"]; |
| 183 | const defaultVariant = inferDefaultVariant(input.providerID, variantValues); | 213 | const defaultVariant = inferDefaultVariant(input.providerID, variantValues); |
| 184 | const variantOptions = variantValues.map((value) => | 214 | const variantOptions = variantValues.map((value) => |
| 185 | defaultVariant === value | 215 | defaultVariant === value |
| ... | @@ -201,7 +231,7 @@ function openCodeCapabilitiesForModel(input: { | ... | @@ -201,7 +231,7 @@ function openCodeCapabilitiesForModel(input: { |
| 201 | ? [ | 231 | ? [ |
| 202 | { | 232 | { |
| 203 | id: "variant", | 233 | id: "variant", |
| 204 | label: "Variant", | 234 | label: "Reasoning", |
| 205 | type: "select" as const, | 235 | type: "select" as const, |
| 206 | options: variantOptions, | 236 | options: variantOptions, |
| 207 | ...(defaultVariant ? { currentValue: defaultVariant } : {}), | 237 | ...(defaultVariant ? { currentValue: defaultVariant } : {}), |