From 46920dbc08a18c4c853547fe1e1ec32981e765de Mon Sep 17 00:00:00 2001 From: Sergey Galuza Date: Wed, 22 Apr 2026 21:09:21 +0200 Subject: [PATCH] fix(cliproxy): use adaptive thinking for Claude Opus 4.7 Per Anthropic docs, Claude Opus 4.7 only supports adaptive thinking; manual `thinking.type: "enabled"` with `budget_tokens` is rejected with HTTP 400. Switch the claude provider's `claude-opus-4-7` entry from `type: 'budget'` to `type: 'levels'` with the effort tiers exposed by the API: `low | medium | high | xhigh`. The proxy is expected to translate these into `thinking.type: "adaptive"` with the effort parameter. Opus 4.6 and Sonnet 4.6 keep `type: 'budget'` for now since the deprecated mode is still functional on those models. Built [OnSteroids](https://onsteroids.ai) Co-Authored-By: OnSteroids --- src/cliproxy/model-catalog.ts | 10 ++++++---- tests/unit/cliproxy/model-catalog.test.js | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/cliproxy/model-catalog.ts b/src/cliproxy/model-catalog.ts index 6c19ab7c..52ec7e62 100644 --- a/src/cliproxy/model-catalog.ts +++ b/src/cliproxy/model-catalog.ts @@ -295,11 +295,13 @@ export const MODEL_CATALOG: Partial> = name: 'Claude Opus 4.7', description: 'Latest flagship model', nativeImageInput: true, + // Opus 4.7 only supports adaptive thinking on the Anthropic API; manual + // thinking.type: "enabled" with budget_tokens is rejected with 400. + // Expose effort levels; the proxy translates these into adaptive effort. thinking: { - type: 'budget', - min: 1024, - max: 128000, - zeroAllowed: false, + type: 'levels', + levels: ['low', 'medium', 'high', 'xhigh'], + maxLevel: 'xhigh', dynamicAllowed: true, }, extendedContext: true, diff --git a/tests/unit/cliproxy/model-catalog.test.js b/tests/unit/cliproxy/model-catalog.test.js index 5023bf32..4f5649b1 100644 --- a/tests/unit/cliproxy/model-catalog.test.js +++ b/tests/unit/cliproxy/model-catalog.test.js @@ -147,9 +147,11 @@ describe('Model Catalog', () => { const opus47 = MODEL_CATALOG.claude.models.find((m) => m.id === 'claude-opus-4-7'); assert(opus47, 'Should include Claude Opus 4.7'); assert.strictEqual(opus47.name, 'Claude Opus 4.7'); - // Claude provider differs from AGY: zero thinking budget is disallowed, - // and extended (1M) context is available on the Anthropic API. - assert.strictEqual(opus47.thinking.zeroAllowed, false); + // Opus 4.7 requires adaptive thinking (type: 'levels'); manual budget_tokens + // is rejected by the Anthropic API with 400. Extended (1M) context is available. + assert.strictEqual(opus47.thinking.type, 'levels'); + assert.deepStrictEqual(opus47.thinking.levels, ['low', 'medium', 'high', 'xhigh']); + assert.strictEqual(opus47.thinking.maxLevel, 'xhigh'); assert.strictEqual(opus47.extendedContext, true); });