Merge PR #8519: fix(catalog): grant low/high/max to OpenRouter deepseek-v4-pro-0813 (@roboomp)

This commit is contained in:
can1357
2026-08-14 14:11:38 +02:00
3 changed files with 39 additions and 3 deletions
+1
View File
@@ -5,6 +5,7 @@
### Fixed
- Fixed raw `COPILOT_GITHUB_TOKEN` credentials skipping plan-specific endpoint discovery, which routed GitHub Copilot Business model requests to the personal endpoint and returned HTTP 403. The GitHub Copilot model cache is now scoped per credential, so switching the token no longer serves another account's stale endpoint for the cache TTL ([#8507](https://github.com/can1357/oh-my-pi/issues/8507)).
- 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
+10 -3
View File
@@ -374,13 +374,20 @@ function getModelDefinedEfforts<TApi extends Api>(
// 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;
}
@@ -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",