Skip to content

Shift+Tab thinking cycle hides the max effort tier on Opus 4.7/4.8 (and Sonnet 4.6, Fable 5) — single-top-tier gating can't express xhigh + max #3100

@aheritier

Description

@aheritier

Summary

The interactive Shift+Tab thinking-level cycle (TUI model picker) hides the max effort tier for several Claude models that actually support it — most visibly Claude Opus 4.7 / 4.8. The cycle offers off / low / medium / high / xhigh and never reaches max.

This is a gating bug only: authored thinking_budget values (e.g. adaptive/max) are still sent correctly to the API. It affects only the user-selectable Shift+Tab cycle.

Reproduction

  1. Configure an agent:
    models:
      anthropic-large:
        provider: anthropic
        model: claude-opus-4-8
        thinking_budget: adaptive/max
  2. Run the TUI; the header correctly shows thinking auto adaptive.
  3. Press Shift+Tab to cycle thinking levels.
  4. Observed: cycle is off → low → medium → high → xhigh → (wrap). max is never offered.
  5. Expected: max is offered, since Anthropic lists max as supported on Opus 4.8.

Root cause

anthropicTopEffort() in pkg/modelinfo/thinking_levels.go returns a single highest effort Level, implicitly assuming the selectable tiers form a linear ladder. For Opus 4.7+ it returns XHigh:

switch {
case minor >= 7:
    return effort.XHigh
case minor == 6:
    return effort.Max
default:
    return ""
}

thinkingLevelMap() then declares only that one tier as supported:

m := effort.LevelMap{effort.Minimal: false}
if top := anthropicTopEffort(modelID); top != "" {
    m[top] = true
}

Because Max is an explicit-only tier (explicitOnlyLevels = {XHigh, Max} in pkg/effort/effort.go) and the map only declares XHigh: true, SupportedLevels() drops Max. Net result for Opus 4.7/4.8: off / low / medium / high / xhigh.

The deeper problem: xhigh and max are independent capabilities, not a single ladder. A single returned "top tier" cannot represent a model that supports both xhigh and max (Opus 4.7/4.8, Fable 5), nor distinguish it from a model that supports max without xhigh (Opus 4.6, Sonnet 4.6).

Authoritative reference

Anthropic — Effort: https://platform.claude.com/docs/en/build-with-claude/effort

Per-level model availability, quoted from that page:

  • max — Claude Fable 5, Claude Mythos 5, Claude Opus 4.8, Claude Mythos Preview, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 4.6
  • xhigh — Claude Fable 5, Claude Mythos 5, Claude Opus 4.8, Claude Opus 4.7

Resulting capability matrix:

Model low medium high xhigh max
Opus 4.5
Sonnet 4.6
Opus 4.6
Opus 4.7
Opus 4.8
Fable 5

Affected models (cycle gating incorrect)

  • Opus 4.7, Opus 4.8max missing (cycle caps at xhigh)
  • Sonnet 4.6max missing (cycle caps at high)
  • Fable 5max missing (cycle caps at xhigh)
  • Mythos 5 / Mythos Preview — unrecognized (cycle caps at high)

Correct today: Opus 4.6 (max, no xhigh) and Opus 4.5 (high).

Not affected (scope clarification)

  • The request path in pkg/model/provider/anthropic/thinking.go sends adaptive/<effort> verbatim (e.g. effort max), so authored configs already behave correctly.
  • RejectsTokenThinking() correctly coerces Opus 4.6/4.7/4.8 onto adaptive thinking.
  • agent-schema.json already accepts max / adaptive/max.

Suggested fix

  • Replace the single-Level return of anthropicTopEffort() with independent capability flags (e.g. supportsXHigh, supportsMax), and have thinkingLevelMap() set both effort.XHigh and effort.Max in the LevelMap where applicable.
  • Add table-driven tests covering each Claude tier (Opus 4.5 / 4.6 / 4.7 / 4.8, Sonnet 4.6, Fable 5, and the Mythos variants).

Relevant files:

  • pkg/modelinfo/thinking_levels.go
  • pkg/effort/effort.go
  • pkg/runtime/model_switcher.go (consumer of SupportedThinkingLevels)

Metadata

Metadata

Assignees

Labels

area/providers/anthropicFor features/issues/fixes related to the usage of Anthropic modelsarea/tuiFor features/issues/fixes related to the TUI

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions