From f7cba50cb76eb89ea04bee2650c2f5d00bc94aa7 Mon Sep 17 00:00:00 2001 From: Jorge Delgado Date: Thu, 20 Aug 2026 05:30:01 -0400 Subject: [PATCH] fix(analytics): treat Claude Code (`claude`/`cc`) as a flat-rate subscription provider (#10773) (#10774) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution! --- changelog.d/fixes/10774-claude-code-flat-rate.md | 1 + src/lib/usage/flatRateProviders.ts | 7 +++++-- tests/unit/flat-rate-cost-5552.test.ts | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 changelog.d/fixes/10774-claude-code-flat-rate.md diff --git a/changelog.d/fixes/10774-claude-code-flat-rate.md b/changelog.d/fixes/10774-claude-code-flat-rate.md new file mode 100644 index 0000000000..ea09e2b208 --- /dev/null +++ b/changelog.d/fixes/10774-claude-code-flat-rate.md @@ -0,0 +1 @@ +- **fix(analytics):** Claude Code (`claude`/`cc`) is a flat-rate subscription, so cost analytics reports `$0` for it instead of estimating Anthropic list prices — the metered `anthropic` API keeps its real cost, and budget/quota/routing still estimate as before ([#10774](https://github.com/diegosouzapw/OmniRoute/pull/10774)) — thanks @electrumguy diff --git a/src/lib/usage/flatRateProviders.ts b/src/lib/usage/flatRateProviders.ts index e24df131a1..8d3eec2c5d 100644 --- a/src/lib/usage/flatRateProviders.ts +++ b/src/lib/usage/flatRateProviders.ts @@ -31,8 +31,9 @@ import { WEB_COOKIE_PROVIDERS } from "@/shared/constants/providers/web-cookie"; * its analytics cost is intentional, not an artifact), `byteplus` (BytePlus * ModelArk is a metered inference host, billed per token — zeroing it would hide * real cost), `minimax-cn` (the metered Minimax China API, distinct from the - * `minimax` "Minimax Coding" plan), and `glm-thinking` (metered tier, distinct - * from the `glm` Coding plan). + * `minimax` "Minimax Coding" plan), `glm-thinking` (metered tier, distinct + * from the `glm` Coding plan), and `anthropic` (the metered Anthropic API, + * distinct from the `claude`/`cc` Claude Code plan below). */ const FLAT_RATE_SUBSCRIPTION_PROVIDER_IDS: ReadonlySet = new Set([ "minimax", // "Minimax Coding" plan @@ -43,6 +44,8 @@ const FLAT_RATE_SUBSCRIPTION_PROVIDER_IDS: ReadonlySet = new Set([ "qwen-cloud-token-plan", // Qwen Cloud Token Plan "glm", // GLM Coding plan "glm-cn", // GLM Coding (China) plan + "claude", // Claude Code plan (OAuth-only — a Claude Pro/Max subscription) + "cc", // Claude Code plan (alias id — same connection, shares the `cc` pricing rows) ]); /** diff --git a/tests/unit/flat-rate-cost-5552.test.ts b/tests/unit/flat-rate-cost-5552.test.ts index e467024e9b..2df378ee3e 100644 --- a/tests/unit/flat-rate-cost-5552.test.ts +++ b/tests/unit/flat-rate-cost-5552.test.ts @@ -23,6 +23,8 @@ test("isFlatRateProvider: dedicated subscription / coding-plan providers are fla "qwen-cloud-token-plan", "glm", "glm-cn", + "claude", + "cc", ]) { assert.equal(isFlatRateProvider(id), true, `${id} should be flat-rate`); } @@ -36,7 +38,8 @@ test("isFlatRateProvider: case-insensitive + trimmed", () => { test("isFlatRateProvider: metered / cost-tracked providers are NOT flat-rate (no hidden cost)", () => { // codex/cx = OmniRoute actively tracks Codex token cost (Fast-tier multipliers, // GPT-5.x pricing) and Codex can be a metered account; byteplus = metered ModelArk; - // minimax-cn = metered China API; glm-thinking = metered tier. + // minimax-cn = metered China API; glm-thinking = metered tier; anthropic = the + // metered Anthropic API, distinct from the `claude`/`cc` Claude Code plan. for (const id of [ "openai", "anthropic", @@ -68,6 +71,11 @@ test("computeCostFromPricing: flat-rate provider with flatRateAsZero → $0", () computeCostFromPricing(PRICING, TOKENS, { provider: "minimax", flatRateAsZero: true }), 0 ); + // Claude Code is billed by the Pro/Max subscription, never per token. + assert.equal( + computeCostFromPricing(PRICING, TOKENS, { provider: "claude", flatRateAsZero: true }), + 0 + ); }); test("computeCostFromPricing: opt-in only — flat-rate provider WITHOUT the flag still estimates", () => { @@ -85,4 +93,9 @@ test("computeCostFromPricing: metered provider with the flag still estimates", ( computeCostFromPricing(PRICING, TOKENS, { provider: "byteplus", flatRateAsZero: true }), 3 ); + // The metered Anthropic API keeps its real cost — only the Claude Code plan is flat-rate. + assert.equal( + computeCostFromPricing(PRICING, TOKENS, { provider: "anthropic", flatRateAsZero: true }), + 3 + ); });