fix(ai): preserve DeepSeek V4 effort metadata

closes #9485
This commit is contained in:
Vegard Stikbakke 2026-09-18 10:43:20 +02:00
parent 13784598d2
commit bb0f4aa602
3 changed files with 24 additions and 5 deletions

View file

@ -8,6 +8,7 @@
### Fixed
- Fixed DeepSeek V4.1 thinking levels on OpenRouter and OpenCode Go preserving provider effort metadata ([#9485](https://github.com/earendil-works/pi/issues/9485)).
- Fixed Vercel AI Gateway replaying unsigned thinking as assistant text ([#9676](https://github.com/earendil-works/pi/issues/9676)).
- Fixed Google Generative AI and Vertex AI using unsupported thinking levels when reasoning is omitted or when model capabilities differ within a Gemini family ([#9455](https://github.com/earendil-works/pi/issues/9455)).
- Fixed Anthropic-compatible relays breaking signed thinking replay when they report a different response model, while preserving fallback pricing ([#9188](https://github.com/earendil-works/pi/issues/9188)).

View file

@ -1024,7 +1024,11 @@ function applyThinkingLevelMetadata(model: Model<any>): void {
if (model.api === "anthropic-messages" && isAnthropicTemperatureUnsupportedModel(model.id)) {
mergeAnthropicMessagesCompat(model, { supportsTemperature: false });
}
if (model.api === "openai-completions" && model.id.includes("deepseek-v4")) {
if (
model.api === "openai-completions" &&
model.id.includes("deepseek-v4") &&
model.thinkingLevelMap === undefined
) {
mergeThinkingLevelMap(
model,
model.provider === "openrouter"
@ -2181,10 +2185,12 @@ async function loadModelsDevData(): Promise<Model<any>[]> {
}
}
const thinkingLevelMap =
api === "google-generative-ai"
? getGoogleThinkingLevelMap(modelId, m.reasoning_options ?? [])
: undefined;
let thinkingLevelMap: NonNullable<Model<Api>["thinkingLevelMap"]> | undefined;
if (api === "google-generative-ai") {
thinkingLevelMap = getGoogleThinkingLevelMap(modelId, m.reasoning_options ?? []);
} else if (variant.provider === "opencode-go" && modelId === "deepseek-v4.1-flash") {
thinkingLevelMap = getEffortThinkingLevelMap(m.reasoning_options ?? []);
}
models.push({
id: modelId,
name: m.name || modelId,

View file

@ -94,6 +94,18 @@ describe("getSupportedThinkingLevels", () => {
expect(getSupportedThinkingLevels(model!)).toEqual(["off", "low", "high", "max"]);
});
it("preserves low/high/max metadata for DeepSeek V4.1 Flash on OpenRouter", () => {
const model = getModel("openrouter", "deepseek/deepseek-v4.1-flash");
expect(model).toBeDefined();
expect(getSupportedThinkingLevels(model!)).toEqual(["off", "low", "high", "max"]);
});
it("preserves low/high/max metadata for DeepSeek V4.1 Flash on opencode-go", () => {
const model = getModel("opencode-go", "deepseek-v4.1-flash");
expect(model).toBeDefined();
expect(getSupportedThinkingLevels(model!)).toEqual(["low", "high", "max"]);
});
it("includes only high plus off for OpenCode Go Kimi K2.6", () => {
const model = getModel("opencode-go", "kimi-k2.6");
expect(model).toBeDefined();