Skip to content

web: model tooltip always shows "No reasoning" because capabilities.reasoning is hard-coded false #54472

Closed as duplicate

Description

@oopp0101

Summary

In the Web UI, the model picker tooltip reports "No reasoning" for every model, even ones that clearly expose reasoning. Reasoning detection is driven by capabilities.reasoning, which the client hard-codes to false (and which the V2 model payload never populates) instead of being derived from the model's variants (thinking / effort). Result: users believe no model supports reasoning.

Environment

  • opencode version: 2.0.26
  • OS: Linux VM-0-3-ubuntu 7.0.0-38-generic overhaul #38-Ubuntu SMP PREEMPT_DYNAMIC Fri Sep 4 09:10:14 UTC 2026 x86_64 GNU/Linux
  • Terminal: Web UI in a browser (client served by opencode serve --service on :port); shell TERM=xterm-256color
  • Shell: /bin/bash
  • Install/channel: latest installer, /home/ubuntu/.opencode/bin/opencode
  • Active plugins: none found in config

Reproduction

  1. /connect → select the built-in OpenCode Console provider and enter an API key (provider id opencode).
  2. Start/serve the Web UI (opencode serve; in our case the shared background service at http://<host>:<port>).
  3. Open the model picker and hover/inspect a model that supports reasoning, e.g. Claude Haiku 5.5 (opencode/claude-haiku-5-5).
  4. The tooltip's Reasoning row shows "No reasoning".

The same happens for every model in the provider, e.g. opencode/gpt-5.5, opencode/claude-opus-5-5, opencode/glm-5.3.

Expected Behavior

A model that exposes reasoning variants should show "Allows reasoning" (and offer the corresponding variants).

Actual Behavior

Every model shows "No reasoning", regardless of its actual capabilities. No error is raised.

Additional Context

Server truth contradicts the tooltip. opencode api get /api/model returns reasoning variants for opencode/claude-haiku-5-5:

{
  "id": "claude-haiku-5-5",
  "providerID": "opencode",
  "package": "@opencode/ai/providers/anthropic",
  "capabilities": { "tools": true, "input": ["text","image","pdf"], "output": ["text"] },
  "variants": [
    { "id": "none",    "settings": { "thinking": { "type": "disabled" } } },
    { "id": "low",     "settings": { "thinking": { "type": "adaptive", "display": "summarized" }, "effort": "low" } },
    { "id": "medium",  "settings": { "thinking": { "type": "adaptive", "display": "summarized" }, "effort": "medium" } },
    { "id": "high",    "settings": { "thinking": { "type": "adaptive", "display": "summarized" }, "effort": "high" } },
    { "id": "xhigh",   "settings": { "thinking": { "type": "adaptive", "display": "summarized" }, "effort": "xhigh" } },
    { "id": "max",     "settings": { "thinking": { "type": "adaptive", "display": "summarized" }, "effort": "max" } }
  ]
}

The V2 OpenAPI Model.Capabilities schema only defines { tools, input, output } — there is no reasoning field. Reasoning is expressed through variants (settings.thinking / settings.effort) and compatibility.reasoningField.

Client hard-codes the flag. In the served client bundle (_assets/runtime-*.js), server models are mapped into a models.dev-shaped object with reasoning forced to false:

t.models[e.id] = {
  id: e.id,
  providerID: e.providerID,
  api: { id: e.modelID, url: ``, npm: e.package ?? t.id },
  name: e.name,
  family: e.family,
  capabilities: {
    temperature: false,
    reasoning: false,          // <-- hard-coded; never derived from e.variants
    attachment: e.capabilities.input.some(x => x !== `text`),
    toolcall: e.capabilities.tools,
    input:  { text: ..., audio: ..., image: ..., video: ..., pdf: ... },
    output: { text: ..., audio: ..., image: ..., video: ..., pdf: ... },
    interleaved: false,
  },
  ...
  variants: Object.fromEntries(e.variants.map(e => [e.id, e.settings ?? {}])),
}

The tooltip then chooses its label from this flag (i18n keys in the client bundle):

"model.tooltip.reasoning":         "Reasoning"
"model.tooltip.reasoning.allowed": "Allows reasoning"
"model.tooltip.reasoning.none":    "No reasoning" 

Because capabilities.reasoning is always false, the none label is always selected.

Impact: display-only. Selecting a reasoning variant (e.g. #high) still works, but the UI misleads users into thinking reasoning is unsupported. Suggested fix: derive reasoning from whether the model exposes reasoning variants (e.g. any variant carrying settings.thinking), or from a dedicated capability on the model payload.

Frequency: reproducible consistently on every load.

Activity

  1. opencode-agent commented on Oct 11, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report and root-cause analysis! I think this is a duplicate of #50257. It's the same "No reasoning" tooltip on every V2 model, with the same cause: the app's model mapper (packages/app/src/runtime/server/global-sync/utils.ts) hard-codes capabilities.reasoning: false, and the V2 Model.Capabilities has no reasoning field. The web UI and the desktop app share that code, so it shows up in both.

    Possible duplicates and related issues, ordered from most to least likely:

    Your suggestion to derive the flag from variants (e.g. settings.thinking / settings.effort) would be useful to add on #50257.

    The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.

  2. opencode-agent commented on Oct 12, 2026

    @opencode-agent
    Contributor

    We haven't heard back, so I'm closing this as a duplicate of #50257. That issue covers the same bug: every V2 model's tooltip shows "No reasoning" because the app's model mapper hard-codes capabilities.reasoning: false. The web UI and the desktop app share that mapper. Please follow #50257 for updates and add a 👍 there. Your idea of deriving the flag from variants (settings.thinking / settings.effort) would be a useful addition on that issue. If your problem turns out to be different, reply here and we can reopen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions