From 2d0eb6c41ed208e296b36059c728ad75ae743638 Mon Sep 17 00:00:00 2001 From: roboomp Date: Fri, 14 Aug 2026 06:17:34 +0000 Subject: [PATCH] fix(catalog): grant low/high/max to OpenRouter deepseek-v4-pro-0813 The OpenRouter non-Flash DeepSeek V4 effort override forced HIGH_ONLY for every id, so getModelDefinedEfforts clamped deepseek-v4-pro-0813 to high even though OpenRouter's /models advertises reasoning.supported_efforts [low,high,max] and the route accepts them. Carve out the dated SKU to the wire-exact low/high/max ladder while keeping the undated deepseek-v4-pro route high-only. Fixes #8517 --- packages/ai/test/remote-auth-store.test.ts | 2 +- packages/catalog/CHANGELOG.md | 4 +++ packages/catalog/src/model-thinking.ts | 13 ++++++--- packages/catalog/test/model-thinking.test.ts | 28 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/ai/test/remote-auth-store.test.ts b/packages/ai/test/remote-auth-store.test.ts index 56b203664..d730efce7 100644 --- a/packages/ai/test/remote-auth-store.test.ts +++ b/packages/ai/test/remote-auth-store.test.ts @@ -1110,7 +1110,7 @@ describe("RemoteAuthCredentialStore + AuthStorage integration", () => { test("broker invalidation drops server-side last-good usage reports", async () => { const credential = serverStore!.listAuthCredentials("anthropic")[0]; - if (!credential || credential.credential.type !== "oauth") throw new Error("expected OAuth credential"); + if (credential?.credential.type !== "oauth") throw new Error("expected OAuth credential"); serverStore!.updateAuthCredential(credential.id, { ...credential.credential, expires: Date.now() + 3_600_000, diff --git a/packages/catalog/CHANGELOG.md b/packages/catalog/CHANGELOG.md index 8cde7ddb0..952f7188c 100644 --- a/packages/catalog/CHANGELOG.md +++ b/packages/catalog/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed the OpenRouter `deepseek/deepseek-v4-pro-0813` route silently clamping the reasoning effort to `high`: the dated SKU advertises (and accepts) the wire-exact `low`/`high`/`max` ladder, so its effort override no longer collapses to `high`-only. The undated `deepseek/deepseek-v4-pro` OpenRouter route stays `high`-only. ([#8517](https://github.com/can1357/oh-my-pi/issues/8517)) + ## [17.3.2] - 2026-08-13 ### Added diff --git a/packages/catalog/src/model-thinking.ts b/packages/catalog/src/model-thinking.ts index f83237574..be0ba1151 100644 --- a/packages/catalog/src/model-thinking.ts +++ b/packages/catalog/src/model-thinking.ts @@ -374,13 +374,20 @@ function getModelDefinedEfforts( // on every first-party/aggregator host — the direct API, aggregators, and // Ollama Cloud alike (medium/xhigh fold into high, max is a real wire // tier). See https://api-docs.deepseek.com/api/create-chat-completion. - // OpenRouter's non-Flash V4 route still exposes only high; the older - // reasoners (V3.x, R1, deepseek-reasoner) top out at high/max. + // OpenRouter's non-Flash V4 route exposes only high, except the dated + // `deepseek-v4-pro-0813` SKU: its /models metadata advertises (and the + // route accepts) the full low/high/max ladder like every other host. + // The older reasoners (V3.x, R1, deepseek-reasoner) top out at high/max. if (isDeepseekV4FlashModelId(spec.id)) { return LOW_HIGH_MAX_REASONING_EFFORTS; } if (bareModelId(spec.id).toLowerCase().includes("deepseek-v4")) { - return isOpenRouterThinkingFormat(compat) ? HIGH_ONLY_REASONING_EFFORTS : LOW_HIGH_MAX_REASONING_EFFORTS; + if (!isOpenRouterThinkingFormat(compat)) { + return LOW_HIGH_MAX_REASONING_EFFORTS; + } + return bareModelId(spec.id).toLowerCase() === "deepseek-v4-pro-0813" + ? LOW_HIGH_MAX_REASONING_EFFORTS + : HIGH_ONLY_REASONING_EFFORTS; } return isOpenRouterThinkingFormat(compat) ? HIGH_ONLY_REASONING_EFFORTS : HIGH_MAX_REASONING_EFFORTS; } diff --git a/packages/catalog/test/model-thinking.test.ts b/packages/catalog/test/model-thinking.test.ts index 908bd2c36..e05ec9865 100644 --- a/packages/catalog/test/model-thinking.test.ts +++ b/packages/catalog/test/model-thinking.test.ts @@ -314,6 +314,34 @@ describe("model thinking derivation", () => { expect(getSupportedEfforts(v32)).toEqual([Effort.High, Effort.Max]); }); + it("grants the low/high/max ladder to OpenRouter deepseek-v4-pro-0813 but not the undated route (issue #8517)", () => { + // OpenRouter's /models advertises reasoning.supported_efforts + // [low, high, max] for the dated SKU; the discovered ladder is baked + // into thinking.efforts. + const discovered = { mode: "effort" as const, efforts: [Effort.Low, Effort.High, Effort.Max] }; + const dated = createModel({ + id: "deepseek/deepseek-v4-pro-0813", + api: "openrouter", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + thinking: discovered, + }); + const bare = createModel({ + id: "deepseek/deepseek-v4-pro", + api: "openrouter", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + thinking: discovered, + }); + + // The dated SKU keeps its advertised ladder; :max no longer clamps. + expect(getSupportedEfforts(dated)).toEqual([Effort.Low, Effort.High, Effort.Max]); + expect(clampThinkingLevelForModel(dated, Effort.Max)).toBe(Effort.Max); + // The undated OpenRouter route stays high-only. + expect(getSupportedEfforts(bare)).toEqual([Effort.High]); + expect(clampThinkingLevelForModel(bare, Effort.Max)).toBe(Effort.High); + }); + it("encodes the Gemini 3 Pro effort gap and mandatory reasoning in metadata", () => { const model = createModel({ id: "gemini-3-pro-preview",