From c5e89f1eea2a7cdd9ba17b2dbb013b0b0dc570a8 Mon Sep 17 00:00:00 2001 From: acamq <179265037+acamq@users.noreply.github.com> Date: Sun, 10 May 2026 10:11:55 -0600 Subject: [PATCH 1/3] fix(model-settings): support family reasoning aliases --- src/shared/model-capability-heuristics.ts | 1 + src/shared/model-settings-compatibility.ts | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/shared/model-capability-heuristics.ts b/src/shared/model-capability-heuristics.ts index 882fe81ec..fd0b9e7a8 100644 --- a/src/shared/model-capability-heuristics.ts +++ b/src/shared/model-capability-heuristics.ts @@ -6,6 +6,7 @@ export type HeuristicModelFamilyDefinition = { pattern?: RegExp variants?: string[] reasoningEfforts?: string[] + reasoningEffortAliases?: Record supportsThinking?: boolean } diff --git a/src/shared/model-settings-compatibility.ts b/src/shared/model-settings-compatibility.ts index c2354038e..76f20bf09 100644 --- a/src/shared/model-settings-compatibility.ts +++ b/src/shared/model-settings-compatibility.ts @@ -86,6 +86,7 @@ function resolveField( ladder: string[], familyKnown: boolean, metadataOverride?: string[], + familyAliases?: Record, ): FieldResolution { if (metadataOverride) { if (metadataOverride.includes(normalized)) return { value: normalized } @@ -97,6 +98,10 @@ function resolveField( if (familyCaps) { if (familyCaps.includes(normalized)) return { value: normalized } + const aliased = familyAliases?.[normalized] + if (aliased && familyCaps.includes(aliased)) { + return { value: aliased, reason: "unsupported-by-model-family" } + } return { value: downgradeWithinLadder(normalized, familyCaps, ladder), reason: "unsupported-by-model-family", @@ -132,7 +137,14 @@ export function resolveCompatibleModelSettings( let reasoningEffort = input.desired.reasoningEffort if (reasoningEffort !== undefined) { const normalized = reasoningEffort.toLowerCase() - const resolved = resolveField(normalized, family?.reasoningEfforts, REASONING_LADDER, familyKnown, metadataReasoningEfforts) + const resolved = resolveField( + normalized, + family?.reasoningEfforts, + REASONING_LADDER, + familyKnown, + metadataReasoningEfforts, + family?.reasoningEffortAliases, + ) if (resolved.value !== normalized && resolved.reason) { changes.push({ field: "reasoningEffort", from: reasoningEffort, to: resolved.value, reason: resolved.reason }) } From fd670a81694aa899ba1e5b4cc2b6924a0ad96b9c Mon Sep 17 00:00:00 2001 From: acamq <179265037+acamq@users.noreply.github.com> Date: Sun, 10 May 2026 10:12:22 -0600 Subject: [PATCH 2/3] fix(model-settings): enable DeepSeek reasoning effort --- src/shared/model-capability-heuristics.ts | 6 +++ .../model-settings-compatibility.test.ts | 41 ++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/shared/model-capability-heuristics.ts b/src/shared/model-capability-heuristics.ts index fd0b9e7a8..61d9e5cbc 100644 --- a/src/shared/model-capability-heuristics.ts +++ b/src/shared/model-capability-heuristics.ts @@ -73,6 +73,12 @@ export const HEURISTIC_MODEL_FAMILY_REGISTRY: ReadonlyArray { { name: "Kimi (k2)", modelID: "k2-v2", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, { name: "GLM", modelID: "glm-5", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, { name: "Minimax", modelID: "minimax-m2.5", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, - { name: "DeepSeek", modelID: "deepseek-r2", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, + { name: "DeepSeek", modelID: "deepseek-r2", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: true }, { name: "Mistral", modelID: "mistral-large-next", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, { name: "Codestral → Mistral", modelID: "codestral-2506", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, { name: "Llama", modelID: "llama-4-maverick", expectedVariants: ["low", "medium", "high"], hasReasoningEffort: false }, @@ -320,6 +320,45 @@ describe("resolveCompatibleModelSettings", () => { }) }) + test("DeepSeek keeps canonical high and max reasoningEffort values", () => { + for (const reasoningEffort of ["high", "max"]) { + const result = resolveCompatibleModelSettings({ + providerID: "openai-compatible", + modelID: "deepseek-v4-pro", + desired: { reasoningEffort }, + }) + + expect(result.reasoningEffort).toBe(reasoningEffort) + expect(result.changes).toEqual([]) + } + }) + + test("DeepSeek maps generic reasoningEffort levels to canonical API values", () => { + const cases = [ + { requested: "low", expected: "high" }, + { requested: "medium", expected: "high" }, + { requested: "xhigh", expected: "max" }, + ] + + for (const { requested, expected } of cases) { + const result = resolveCompatibleModelSettings({ + providerID: "openai-compatible", + modelID: "deepseek-v4-pro", + desired: { reasoningEffort: requested }, + }) + + expect(result.reasoningEffort).toBe(expected) + expect(result.changes).toEqual([ + { + field: "reasoningEffort", + from: requested, + to: expected, + reason: "unsupported-by-model-family", + }, + ]) + } + }) + test("GPT-5 downgrades unsupported max variant to xhigh", () => { const result = resolveCompatibleModelSettings({ providerID: "openai", From 5259bdfd20d69d0176f3744c743b2f455152f7f8 Mon Sep 17 00:00:00 2001 From: acamq <179265037+acamq@users.noreply.github.com> Date: Sun, 10 May 2026 10:19:34 -0600 Subject: [PATCH 3/3] fix(model-settings): apply reasoning aliases with capabilities --- .../model-settings-compatibility.test.ts | 23 +++++++++++++++++++ src/shared/model-settings-compatibility.ts | 9 ++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/shared/model-settings-compatibility.test.ts b/src/shared/model-settings-compatibility.test.ts index 134bb9e71..9d92b2c7d 100644 --- a/src/shared/model-settings-compatibility.test.ts +++ b/src/shared/model-settings-compatibility.test.ts @@ -359,6 +359,29 @@ describe("resolveCompatibleModelSettings", () => { } }) + test("DeepSeek maps generic reasoningEffort levels when capabilities come from heuristics", () => { + const capabilities = getModelCapabilities({ + providerID: "openai-compatible", + modelID: "deepseek-v4-pro", + }) + const result = resolveCompatibleModelSettings({ + providerID: "openai-compatible", + modelID: "deepseek-v4-pro", + desired: { reasoningEffort: "xhigh" }, + capabilities, + }) + + expect(result.reasoningEffort).toBe("max") + expect(result.changes).toEqual([ + { + field: "reasoningEffort", + from: "xhigh", + to: "max", + reason: "unsupported-by-model-family", + }, + ]) + }) + test("GPT-5 downgrades unsupported max variant to xhigh", () => { const result = resolveCompatibleModelSettings({ providerID: "openai", diff --git a/src/shared/model-settings-compatibility.ts b/src/shared/model-settings-compatibility.ts index 76f20bf09..414638fef 100644 --- a/src/shared/model-settings-compatibility.ts +++ b/src/shared/model-settings-compatibility.ts @@ -88,6 +88,11 @@ function resolveField( metadataOverride?: string[], familyAliases?: Record, ): FieldResolution { + const aliased = familyAliases?.[normalized] + if (aliased && (metadataOverride?.includes(aliased) || familyCaps?.includes(aliased))) { + return { value: aliased, reason: "unsupported-by-model-family" } + } + if (metadataOverride) { if (metadataOverride.includes(normalized)) return { value: normalized } return { @@ -98,10 +103,6 @@ function resolveField( if (familyCaps) { if (familyCaps.includes(normalized)) return { value: normalized } - const aliased = familyAliases?.[normalized] - if (aliased && familyCaps.includes(aliased)) { - return { value: aliased, reason: "unsupported-by-model-family" } - } return { value: downgradeWithinLadder(normalized, familyCaps, ladder), reason: "unsupported-by-model-family",