mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-07 07:42:13 +03:00
fix(executor): normalize max effort for openai shape providers
This commit is contained in:
@@ -221,7 +221,8 @@ function hasActiveClaudeThinking(body: Record<string, unknown>): boolean {
|
||||
* through unchanged, and Claude models default to xhigh support unless marked
|
||||
* as legacy unsupported entries. max support is Claude/CC-compatible only and
|
||||
* intentionally separate: older Opus/Sonnet models may support max even when
|
||||
* they do not support xhigh.
|
||||
* they do not support xhigh. For OpenAI-shape providers, normalize max to
|
||||
* xhigh when that top tier is allowed; otherwise downgrade to high.
|
||||
*/
|
||||
const MISTRAL_NO_REASONING_EFFORT_PATTERN = /devstral/i;
|
||||
const GITHUB_NO_REASONING_EFFORT_PATTERN = /(claude|haiku|oswe)/i;
|
||||
@@ -251,9 +252,27 @@ export function sanitizeReasoningEffortForProvider(
|
||||
const effortStr = typeof effort === "string" ? effort.toLowerCase() : "";
|
||||
const modelStr = model || "";
|
||||
|
||||
const shouldDowngradeXHigh = effortStr === "xhigh" && !supportsXHighEffort(provider, modelStr);
|
||||
const supportsXHigh = supportsXHighEffort(provider, modelStr);
|
||||
const shouldDowngradeXHigh = effortStr === "xhigh" && !supportsXHigh;
|
||||
const shouldNormalizeMaxToXHigh =
|
||||
effortStr === "max" && !supportsMaxEffortForProvider(provider, modelStr) && supportsXHigh;
|
||||
const shouldDowngradeMax =
|
||||
effortStr === "max" && !supportsMaxEffortForProvider(provider, modelStr);
|
||||
effortStr === "max" && !supportsMaxEffortForProvider(provider, modelStr) && !supportsXHigh;
|
||||
|
||||
if (shouldNormalizeMaxToXHigh) {
|
||||
log?.info?.(
|
||||
"REASONING_SANITIZE",
|
||||
`${provider}/${modelStr}: normalized reasoning_effort max → xhigh`
|
||||
);
|
||||
const next: Record<string, unknown> = { ...b };
|
||||
if (hasTopLevelReasoningEffort) {
|
||||
next.reasoning_effort = "xhigh";
|
||||
}
|
||||
if (reasoning) {
|
||||
next.reasoning = { ...reasoning, effort: "xhigh" };
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
if (shouldDowngradeXHigh || shouldDowngradeMax) {
|
||||
log?.info?.(
|
||||
@@ -797,7 +816,10 @@ export class BaseExecutor {
|
||||
delete (tb.output_config as Record<string, unknown>).effort;
|
||||
}
|
||||
appliedEffort = "off";
|
||||
} else if (headerEffort && ["low", "medium", "high", "xhigh", "max"].includes(headerEffort)) {
|
||||
} else if (
|
||||
headerEffort &&
|
||||
["low", "medium", "high", "xhigh", "max"].includes(headerEffort)
|
||||
) {
|
||||
const oc =
|
||||
tb.output_config && typeof tb.output_config === "object"
|
||||
? (tb.output_config as Record<string, unknown>)
|
||||
|
||||
@@ -43,6 +43,44 @@ test("sanitizeReasoningEffortForProvider: xiaomi-mimo downgrades max → high",
|
||||
);
|
||||
});
|
||||
|
||||
test("sanitizeReasoningEffortForProvider: OpenAI-compatible Gemini normalizes max → xhigh", () => {
|
||||
const log = makeLog();
|
||||
const body = {
|
||||
model: "gemini-3.1-pro-preview",
|
||||
reasoning_effort: "max",
|
||||
messages: [{ role: "user", content: "hi" }],
|
||||
};
|
||||
const result = sanitizeReasoningEffortForProvider(
|
||||
body,
|
||||
"openai-compatible-free1",
|
||||
"gemini-3.1-pro-preview",
|
||||
log
|
||||
);
|
||||
assert.notEqual(result, body, "must return a new object when mutating");
|
||||
assert.equal((result as any).reasoning_effort, "xhigh");
|
||||
assert.ok(
|
||||
log.messages.some(([tag, m]) => tag === "REASONING_SANITIZE" && /max → xhigh/.test(m)),
|
||||
"logs the normalization"
|
||||
);
|
||||
});
|
||||
|
||||
test("sanitizeReasoningEffortForProvider: nested OpenAI reasoning max normalizes to xhigh", () => {
|
||||
const body = {
|
||||
model: "gemini-3.1-pro-preview",
|
||||
reasoning: { effort: "max", summary: "auto" },
|
||||
input: [],
|
||||
};
|
||||
const result = sanitizeReasoningEffortForProvider(
|
||||
body,
|
||||
"openai-compatible-free1",
|
||||
"gemini-3.1-pro-preview",
|
||||
null
|
||||
);
|
||||
assert.equal((result as any).reasoning.effort, "xhigh");
|
||||
assert.equal((result as any).reasoning.summary, "auto", "other reasoning fields preserved");
|
||||
assert.equal((result as any).reasoning_effort, undefined);
|
||||
});
|
||||
|
||||
test("sanitizeReasoningEffortForProvider: claude preserves max for Opus/Sonnet and downgrades Haiku", () => {
|
||||
const sonnetBody = {
|
||||
model: "claude-sonnet-4-6",
|
||||
|
||||
Reference in New Issue
Block a user