Summary
Add an optional reasoningEffort control for reasoning-capable remote models (Qwen3, DeepSeek-R1, OpenAI o-series/gpt-5, etc.) served through the OpenAI-compatible provider. Today GenerationOptions only exposes enableThinking (a boolean) plus temperature/topP — there is no way to ask a reasoning model to think harder or lighter per chat.
Deferred out of the DSML/tool-loop fix branch (feat/serper-search-provider) to keep that change focused.
Why it's not trivial: you can't discover which levels a model supports
Verified empirically against opencode.ai/zen: its /v1/models returns only the bare OpenAI fields per model —
{"id":"big-pickle","object":"model","created":1783094914,"owned_by":"opencode"}
No capabilities, no supported_parameters, nothing about reasoning effort. There is no standard OpenAI mechanism to enumerate supported reasoning-effort values:
reasoning_effort (minimal|low|medium|high on OpenAI o-series/gpt-5) is a request parameter, not a discoverable capability.
- The one exception in the wild is aggregators like OpenRouter, which put a
supported_parameters array on each model object (can include reasoning/reasoning_effort). Most OpenAI-compatible servers (including zen) do not.
Risk: blindly sending it can 400
Strict OpenAI-compatible servers reject unknown fields. The app already gates chat_template_kwargs to LM Studio only for exactly this reason (openAICompatibleProvider.buildRequestBody). So reasoning_effort must be opt-in and gated, not sent to every server.
Proposed design
- Add
reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high' to GenerationOptions (src/services/providers/types.ts).
- In model discovery, opportunistically read
supported_parameters when a server provides it (OpenRouter-style) and store it on the model capabilities. Absent that, treat support as unknown.
- In
buildRequestBody (src/services/providers/openAICompatibleProvider.ts), include reasoning_effort only when the user has set it and (the server advertised support or the user explicitly forced it).
- UI: a per-chat / per-server control, only shown for models where it's plausibly supported.
- Leave the tool-loop forced-final / synthesis passes with thinking disabled regardless — a reasoning model given room to think there can re-decide to keep searching, which is the loop we're trying to terminate.
Notes
- big-pickle itself reports
supportsThinking: false, so it would not use this — the feature targets genuinely reasoning-capable remotes.
Summary
Add an optional
reasoningEffortcontrol for reasoning-capable remote models (Qwen3, DeepSeek-R1, OpenAI o-series/gpt-5, etc.) served through the OpenAI-compatible provider. TodayGenerationOptionsonly exposesenableThinking(a boolean) plus temperature/topP — there is no way to ask a reasoning model to think harder or lighter per chat.Deferred out of the DSML/tool-loop fix branch (
feat/serper-search-provider) to keep that change focused.Why it's not trivial: you can't discover which levels a model supports
Verified empirically against opencode.ai/zen: its
/v1/modelsreturns only the bare OpenAI fields per model —{"id":"big-pickle","object":"model","created":1783094914,"owned_by":"opencode"}No capabilities, no
supported_parameters, nothing about reasoning effort. There is no standard OpenAI mechanism to enumerate supported reasoning-effort values:reasoning_effort(minimal|low|medium|highon OpenAI o-series/gpt-5) is a request parameter, not a discoverable capability.supported_parametersarray on each model object (can includereasoning/reasoning_effort). Most OpenAI-compatible servers (including zen) do not.Risk: blindly sending it can 400
Strict OpenAI-compatible servers reject unknown fields. The app already gates
chat_template_kwargsto LM Studio only for exactly this reason (openAICompatibleProvider.buildRequestBody). Soreasoning_effortmust be opt-in and gated, not sent to every server.Proposed design
reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high'toGenerationOptions(src/services/providers/types.ts).supported_parameterswhen a server provides it (OpenRouter-style) and store it on the model capabilities. Absent that, treat support as unknown.buildRequestBody(src/services/providers/openAICompatibleProvider.ts), includereasoning_effortonly when the user has set it and (the server advertised support or the user explicitly forced it).Notes
supportsThinking: false, so it would not use this — the feature targets genuinely reasoning-capable remotes.