Skip to content

fix(anthropic): send adaptive thinking only to models that support it#699

Merged
ericleepi314 merged 1 commit into
mainfrom
fix/anthropic-adaptive-thinking-gate
Jul 12, 2026
Merged

fix(anthropic): send adaptive thinking only to models that support it#699
ericleepi314 merged 1 commit into
mainfrom
fix/anthropic-adaptive-thinking-gate

Conversation

@ericleepi314

Copy link
Copy Markdown
Collaborator

Summary

Testing the Claude subscription (OAuth) login flow end-to-end surfaced a pre-existing, general bug: every Anthropic request 400s with adaptive thinking is not supported on this model for any model except sonnet-4-6 / opus-4-6 / opus-4-7.

_call_model_sync (src/query/query.py) sent thinking={"type":"adaptive"} + output_config={"effort":...} to all Claude 4.x models, gated only by the broad _model_supports_extended_thinking regex. But adaptive thinking and effort are supported by only a narrow subset. This is not subscription-specific — the API-key path 400s identically — but the default model sonnet-4-6 supports adaptive, which masked it. For the subscription flow it was fatal: a Max user selecting haiku (very plausible, to conserve rate limit) or sonnet-4-5 got a hard 400 on every turn.

Fix

Ports the authoritative adaptive-vs-budget selection from the in-repo upstream Claude Code source (typescript/):

  • claude.ts:1612-1640 — the selection logic
  • utils/thinking.ts:117-169modelSupportsThinking (all Claude 4+ incl. Haiku on first-party) vs modelSupportsAdaptiveThinking (opus-4-6/4-7, sonnet-4-6 only)
  • utils/effort.ts:32-51modelSupportsEffort (opus-4-6, sonnet-4-6 only)

Two new helpers (_model_supports_adaptive_thinking, _model_supports_effort) split the single injection into three independently-gated decisions:

model thinking adaptive effort sent
sonnet-4-6, opus-4-6 {type:adaptive} + effort
opus-4-7 {type:adaptive}
sonnet-4-5, haiku-4-5, opus-4-1/4-5 {type:enabled, budget_tokens}
claude-3.x (none)

Budget models get budget_tokens = max_tokens-1 (clamped ≥1024, <max_tokens, matching claude.ts:1628-1635). Adaptive-capable models — including the default sonnet-4-6 — are unchanged, so there is no regression for the common path.

Validation

Live against api.anthropic.com with a Claude Max OAuth token (the subscription path #697 added):

  • haiku headless — previously a hard 400, now passes ✓
  • full Bash tool loop through the agent loop under subscription auth ✓
  • sonnet-4-6 default — adaptive+effort unchanged ✓

Also independently confirms the #697 subscription request path works: OAuth bearer + beta headers accepted, mcp_ tool prefixing/stripping correct, billing_mode: subscription ($0), 2-turn tool exchange.

Unit tests (tests/test_query_extended_thinking.py): updated 2 that pinned the old buggy behavior (asserted adaptive for sonnet-4-5), added the opus-4-7 adaptive-without-effort regression pin (the fix's most fragile case) and a direct allowlist matrix. Full suite: 8482 passed, 3 skipped. Critic-reviewed: APPROVE.

🤖 Generated with Claude Code

While evaluating the Claude subscription (OAuth) flow, every Anthropic
request 400'd with "adaptive thinking is not supported on this model"
for any model except sonnet-4-6 / opus-4-6 / opus-4-7. _call_model_sync
sent thinking={type:adaptive} + output_config={effort} to ALL Claude
4.x models, gated only by the broad _model_supports_extended_thinking
regex. Pre-existing + general (hits the API-key path identically); the
default model sonnet-4-6 supports adaptive, which masked it. It made
the subscription flow dead-on-arrival for a Max user picking haiku or
sonnet-4-5.

Port the authoritative selection from the in-repo upstream source
(typescript/src/services/api/claude.ts:1612-1640, utils/thinking.ts,
utils/effort.ts):
- _model_supports_adaptive_thinking: opus-4-6/4-7, sonnet-4-6 only
- _model_supports_effort: opus-4-6, sonnet-4-6 only
Thinking-capable-but-not-adaptive models now get
{type:enabled, budget_tokens: max_tokens-1} (clamped >=1024, <max_tokens);
effort is gated independently. Adaptive models (incl. the default) are
unchanged.

Validated LIVE against api.anthropic.com with a Max OAuth token: haiku
headless (previously 400) + full Bash tool loop now pass; sonnet-4-6
default unchanged. Unit: updated 2 tests that pinned the old buggy
behavior, added the opus-4-7 adaptive-without-effort pin + a direct
allowlist matrix. Full suite green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ericleepi314 ericleepi314 merged commit 50b2878 into main Jul 12, 2026
2 checks passed
@ericleepi314 ericleepi314 deleted the fix/anthropic-adaptive-thinking-gate branch July 12, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant