From 01bd0d6760b1ae942c8cb28c71416c4fa5d8ba96 Mon Sep 17 00:00:00 2001 From: Randi <55005611+rdself@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:07:18 -0400 Subject: [PATCH] Add Claude Opus 4.7 to Claude Code OAuth models (#1347) Integrated into release/v3.6.7 --- README.md | 14 +++++++------- docs/USER_GUIDE.md | 16 ++++++++-------- open-sse/config/providerRegistry.ts | 1 + open-sse/executors/base.ts | 1 + open-sse/services/modelFamilyFallback.ts | 1 + src/app/api/providers/[id]/models/route.ts | 1 + src/shared/constants/modelSpecs.ts | 10 ++++++++++ src/shared/constants/pricing.ts | 7 +++++++ tests/unit/cc-compatible-model-catalog.test.ts | 1 + tests/unit/models-catalog-route.test.ts | 1 + tests/unit/provider-models-route.test.ts | 1 + tests/unit/t31-t33-t34-t38-model-specs.test.ts | 3 +++ 12 files changed, 42 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index d6f6a16a4e..7f45c559c0 100644 --- a/README.md +++ b/README.md @@ -695,7 +695,7 @@ During deep debugging, long histories with tool results quickly exceed provider ```txt Combo: "maximize-claude" - 1. cc/claude-opus-4-6 + 1. cc/claude-opus-4-7 2. glm/glm-4.7 3. if/kimi-k2-thinking @@ -719,7 +719,7 @@ Outcome: stable free coding workflow ```txt Combo: "always-on" - 1. cc/claude-opus-4-6 + 1. cc/claude-opus-4-7 2. cx/gpt-5.2-codex 3. glm/glm-4.7 4. minimax/MiniMax-M2.1 @@ -1511,7 +1511,7 @@ OmniRoute v3.6 is built as an operational platform, not just a relay proxy. ```txt Combo: "my-coding-stack" - 1. cc/claude-opus-4-6 + 1. cc/claude-opus-4-7 2. nvidia/llama-3.3-70b 3. glm/glm-4.7 4. if/kimi-k2-thinking @@ -1650,7 +1650,7 @@ Dashboard → Providers → Connect Claude Code → 5-hour + weekly quota tracking Models: - cc/claude-opus-4-6 + cc/claude-opus-4-7 cc/claude-sonnet-4-5-20250929 cc/claude-haiku-4-5-20251001 ``` @@ -1850,7 +1850,7 @@ Dashboard → Combos → Create New Name: premium-coding Models: - 1. cc/claude-opus-4-6 (Subscription primary) + 1. cc/claude-opus-4-7 (Subscription primary) 2. glm/glm-4.7 (Cheap backup, $0.6/1M) 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M) @@ -1880,7 +1880,7 @@ Cost: $0 forever! Settings → Models → Advanced: OpenAI API Base URL: http://localhost:20128/v1 OpenAI API Key: [from OmniRoute dashboard] - Model: cc/claude-opus-4-6 + Model: cc/claude-opus-4-7 ``` ### Claude Code @@ -1990,7 +1990,7 @@ opencode **Rate limiting** - Subscription quota out → Fallback to GLM/MiniMax -- Add combo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking` +- Add combo: `cc/claude-opus-4-7 → glm/glm-4.7 → if/kimi-k2-thinking` **OAuth token expired** diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index b4892aabb3..a639755c1d 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -55,7 +55,7 @@ Complete guide for configuring providers, creating combos, integrating CLI tools ``` Combo: "maximize-claude" - 1. cc/claude-opus-4-6 (use subscription fully) + 1. cc/claude-opus-4-7 (use subscription fully) 2. glm/glm-4.7 (cheap backup when quota out) 3. if/kimi-k2-thinking (free emergency fallback) @@ -83,7 +83,7 @@ Quality: Production-ready models ``` Combo: "always-on" - 1. cc/claude-opus-4-6 (best quality) + 1. cc/claude-opus-4-7 (best quality) 2. cx/gpt-5.2-codex (second subscription) 3. glm/glm-4.7 (cheap, resets daily) 4. minimax/MiniMax-M2.1 (cheapest, 5h reset) @@ -121,7 +121,7 @@ Dashboard → Providers → Connect Claude Code → 5-hour + weekly quota tracking Models: - cc/claude-opus-4-6 + cc/claude-opus-4-7 cc/claude-sonnet-4-5-20250929 cc/claude-haiku-4-5-20251001 ``` @@ -230,7 +230,7 @@ Dashboard → Combos → Create New Name: premium-coding Models: - 1. cc/claude-opus-4-6 (Subscription primary) + 1. cc/claude-opus-4-7 (Subscription primary) 2. glm/glm-4.7 (Cheap backup, $0.6/1M) 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M) @@ -259,7 +259,7 @@ Cost: $0 forever! Settings → Models → Advanced: OpenAI API Base URL: http://localhost:20128/v1 OpenAI API Key: [from omniroute dashboard] - Model: cc/claude-opus-4-6 + Model: cc/claude-opus-4-7 ``` ### Claude Code @@ -313,7 +313,7 @@ Edit `~/.openclaw/openclaw.json`: Provider: OpenAI Compatible Base URL: http://localhost:20128/v1 API Key: [from dashboard] -Model: cc/claude-opus-4-6 +Model: cc/claude-opus-4-7 ``` --- @@ -552,7 +552,7 @@ For the full environment variable reference, see the [README](../README.md).
View all available models -**Claude Code (`cc/`)** — Pro/Max: `cc/claude-opus-4-6`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001` +**Claude Code (`cc/`)** — Pro/Max: `cc/claude-opus-4-7`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001` **Codex (`cx/`)** — Plus/Pro: `cx/gpt-5.2-codex`, `cx/gpt-5.1-codex-max` @@ -745,7 +745,7 @@ Define global fallback chains that apply across all requests: ``` Chain: production-fallback - 1. cc/claude-opus-4-6 + 1. cc/claude-opus-4-7 2. gh/gpt-5.1-codex 3. glm/glm-4.7 ``` diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index 7ddaa5009c..02369d2eb5 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -277,6 +277,7 @@ export const REGISTRY: Record = { tokenUrl: "https://console.anthropic.com/v1/oauth/token", }, models: [ + { id: "claude-opus-4-7", name: "Claude Opus 4.7" }, { id: "claude-opus-4-6", name: "Claude Opus 4.6" }, { id: "claude-sonnet-4-6", name: "Claude 4.6 Sonnet" }, { id: "claude-opus-4-5-20251101", name: "Claude 4.5 Opus" }, diff --git a/open-sse/executors/base.ts b/open-sse/executors/base.ts index ee953afe10..c623802d7d 100644 --- a/open-sse/executors/base.ts +++ b/open-sse/executors/base.ts @@ -390,6 +390,7 @@ export class BaseExecutor { // Only supported for specific Claude models per Anthropic docs if (extendedContext) { const EXTENDED_CONTEXT_MODELS = [ + "claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-4-6", "claude-sonnet-4-5", diff --git a/open-sse/services/modelFamilyFallback.ts b/open-sse/services/modelFamilyFallback.ts index c75d5bd00b..b7812ca877 100644 --- a/open-sse/services/modelFamilyFallback.ts +++ b/open-sse/services/modelFamilyFallback.ts @@ -73,6 +73,7 @@ const MODEL_FAMILIES: Record = { "gemini-2.5-pro-preview-06-05": ["gemini-2.5-pro", "gemini-2.5-pro-exp-03-25"], // Claude Opus family + "claude-opus-4-7": ["claude-opus-4-6", "claude-opus-4-5-20251101", "claude-sonnet-4-6"], "claude-opus-4-6": ["claude-opus-4-6-thinking", "claude-opus-4-5-20251101", "claude-sonnet-4-6"], "claude-opus-4-6-thinking": ["claude-opus-4-6", "claude-opus-4-5-20251101"], diff --git a/src/app/api/providers/[id]/models/route.ts b/src/app/api/providers/[id]/models/route.ts index 2e75d914d9..959585fc68 100755 --- a/src/app/api/providers/[id]/models/route.ts +++ b/src/app/api/providers/[id]/models/route.ts @@ -124,6 +124,7 @@ const STATIC_MODEL_PROVIDERS: Record Array<{ id: string; name: str { id: "gpt-oss-120b-medium", name: "GPT OSS 120B Medium" }, ], claude: () => [ + { id: "claude-opus-4-7", name: "Claude Opus 4.7" }, { id: "claude-opus-4-6", name: "Claude Opus 4.6" }, { id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" }, { id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (2025-11-01)" }, diff --git a/src/shared/constants/modelSpecs.ts b/src/shared/constants/modelSpecs.ts index 6b094fe545..7d1311067e 100644 --- a/src/shared/constants/modelSpecs.ts +++ b/src/shared/constants/modelSpecs.ts @@ -66,6 +66,16 @@ export const MODEL_SPECS: Record = { supportsVision: true, }, + // ── Claude Opus 4.7 ───────────────────────────────────────────── + "claude-opus-4-7": { + maxOutputTokens: 128000, + contextWindow: 1000000, + supportsThinking: true, + supportsTools: true, + supportsVision: true, + aliases: ["claude-opus-4.7"], + }, + // Defaults __default__: { maxOutputTokens: 8192, diff --git a/src/shared/constants/pricing.ts b/src/shared/constants/pricing.ts index 01f891c58b..ce4635613e 100644 --- a/src/shared/constants/pricing.ts +++ b/src/shared/constants/pricing.ts @@ -121,6 +121,13 @@ export const DEFAULT_PRICING = { // Claude Code (cc) cc: { + "claude-opus-4-7": { + input: 5.0, + output: 25.0, + cached: 2.5, + reasoning: 25.0, + cache_creation: 5.0, + }, "claude-opus-4-6": { input: 5.0, output: 25.0, diff --git a/tests/unit/cc-compatible-model-catalog.test.ts b/tests/unit/cc-compatible-model-catalog.test.ts index 2664bb5b39..d227e17d62 100644 --- a/tests/unit/cc-compatible-model-catalog.test.ts +++ b/tests/unit/cc-compatible-model-catalog.test.ts @@ -58,6 +58,7 @@ test("v1 models exposes CC-compatible fallback models under the provider node pr const body = await response.json(); const ids = new Set(body.data.map((item) => item.id)); + assert.ok(ids.has("cm/claude-opus-4-7")); assert.ok(ids.has("cm/claude-opus-4-6")); assert.ok(ids.has("cm/claude-sonnet-4-6")); assert.equal( diff --git a/tests/unit/models-catalog-route.test.ts b/tests/unit/models-catalog-route.test.ts index 56274cc1ac..b31527151a 100644 --- a/tests/unit/models-catalog-route.test.ts +++ b/tests/unit/models-catalog-route.test.ts @@ -542,6 +542,7 @@ test("v1 models catalog adds managed fallback models for Claude-compatible provi const ids = new Set(body.data.map((item) => item.id)); assert.equal(response.status, 200); + assert.ok(ids.has("ccdemo/claude-opus-4-7")); assert.ok(ids.has("ccdemo/claude-opus-4-6")); assert.equal(ids.has("ccdemo/claude-sonnet-4-6"), false); }); diff --git a/tests/unit/provider-models-route.test.ts b/tests/unit/provider-models-route.test.ts index 82cae4cf74..23b595b94f 100644 --- a/tests/unit/provider-models-route.test.ts +++ b/tests/unit/provider-models-route.test.ts @@ -356,6 +356,7 @@ test("provider models route filters hidden models from the static Claude catalog assert.equal(response.status, 200); assert.equal(body.provider, "claude"); + assert.ok(body.models.some((model) => model.id === "claude-opus-4-7")); assert.equal( body.models.some((model) => model.id === "claude-sonnet-4-6"), false diff --git a/tests/unit/t31-t33-t34-t38-model-specs.test.ts b/tests/unit/t31-t33-t34-t38-model-specs.test.ts index 4cceada193..d39ce99fc0 100644 --- a/tests/unit/t31-t33-t34-t38-model-specs.test.ts +++ b/tests/unit/t31-t33-t34-t38-model-specs.test.ts @@ -45,6 +45,7 @@ test("T34: max output tokens are capped by model spec", () => { assert.equal(capMaxOutputTokens("gemini-3-flash", 131072), 65536); assert.equal(capMaxOutputTokens("gemini-3-flash"), 65536); assert.equal(capMaxOutputTokens("gemini-3.1-pro-high", 131072), 65535); + assert.equal(capMaxOutputTokens("claude-opus-4-7", 200000), 128000); }); test("T38: modelSpecs exposes centralized helpers with alias and prefix lookup", () => { @@ -53,6 +54,8 @@ test("T38: modelSpecs exposes centralized helpers with alias and prefix lookup", assert.equal(getModelSpec("gemini-3-flash-preview").maxOutputTokens, 65536); assert.equal(getModelSpec("gemini-3.1-pro-preview").maxOutputTokens, 65535); assert.equal(getModelSpec("gemini-3.1-pro-preview-customtools").maxOutputTokens, 65535); + assert.equal(getModelSpec("claude-opus-4-7").contextWindow, 1000000); + assert.equal(getModelSpec("claude-opus-4.7").maxOutputTokens, 128000); assert.equal(resolveModelAlias("gemini-3-pro-low"), "gemini-3.1-pro-low"); assert.equal(resolveModelAlias("gemini-3.1-pro-preview"), "gemini-3.1-pro-high"); assert.equal(resolveModelAlias("gemini-3.1-pro-preview-customtools"), "gemini-3.1-pro-high");