fix(codex): honor Pro reasoning effort contracts (#101484)

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
xingzhou
2026-07-07 18:13:50 +08:00
committed by GitHub
parent 6e792f08f8
commit f14eb97ae7
4 changed files with 76 additions and 15 deletions

View File

@@ -1409,13 +1409,23 @@ describe("resolveReasoningEffort (#71946)", () => {
expect(resolveReasoningEffort("minimal", " gpt-5.4-mini ")).toBe("low");
});
it.each(["gpt-5.5-pro", "gpt-5.4-pro"] as const)(
"uses the %s minimum effort when metadata is unavailable",
(modelId) => {
expect(resolveReasoningEffort("minimal", modelId)).toBe("medium");
expect(resolveReasoningEffort("low", modelId)).toBe("medium");
expect(resolveReasoningEffort("medium", modelId)).toBe("medium");
expect(resolveReasoningEffort("max", modelId)).toBe("xhigh");
},
);
it("honors stricter app-server reasoning metadata", () => {
const supported = ["medium", "high", "xhigh"];
expect(resolveReasoningEffort("minimal", "gpt-5.4-pro", supported)).toBe("medium");
expect(resolveReasoningEffort("low", "gpt-5.4-pro", supported)).toBe("medium");
expect(resolveReasoningEffort("medium", "gpt-5.4-pro", supported)).toBe("medium");
expect(resolveReasoningEffort("max", "gpt-5.4-pro", supported)).toBe("xhigh");
expect(resolveReasoningEffort("minimal", "gpt-5.5-pro", supported)).toBe("medium");
expect(resolveReasoningEffort("low", "gpt-5.5-pro", supported)).toBe("medium");
expect(resolveReasoningEffort("medium", "gpt-5.5-pro", supported)).toBe("medium");
expect(resolveReasoningEffort("max", "gpt-5.5-pro", supported)).toBe("xhigh");
});
});

View File

@@ -14,6 +14,7 @@ import {
isMaxReasoningCodexModel,
isModernCodexModel,
readCodexSupportedReasoningEfforts,
resolveCodexFallbackReasoningEfforts,
resolveCodexSupportedReasoningEffort,
type CodexReasoningEffort,
} from "../../provider.js";
@@ -1868,13 +1869,10 @@ export function resolveCodexAppServerModelProvider(params: {
return normalizedLower === "openai" ? "openai" : normalized;
}
// Modern Codex models (gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex-spark) use the
// none/low/medium/high/xhigh effort enum and reject "minimal". The CLI
// defaults thinkLevel to "minimal", so without translation EVERY agent turn
// on those models pays a wasted first request + retry-with-low fallback in
// embedded-agent-runner. Map "minimal" -> "low" upfront for modern models so the
// first request is accepted. Older Codex models still accept "minimal"
// directly. (#71946)
// Modern Codex models reject the legacy CLI `minimal` default. Prefer
// app-server metadata, then use the provider-owned fallback effort contract
// for Pro models whose minimum supported effort is `medium`.
// Other modern models translate `minimal` to `low`. (#71946)
// Exported for unit-test coverage of the model-aware translation path.
export function resolveReasoningEffort(
thinkLevel: EmbeddedRunAttemptParams["thinkLevel"],
@@ -1892,6 +1890,15 @@ export function resolveReasoningEffort(
}) ?? null
);
}
const fallbackReasoningEfforts = resolveCodexFallbackReasoningEfforts(modelId);
if (fallbackReasoningEfforts) {
return (
resolveCodexSupportedReasoningEffort({
requested: thinkLevel,
supportedReasoningEfforts: fallbackReasoningEfforts,
}) ?? null
);
}
if (thinkLevel === "minimal") {
return isModernCodexModel(modelId) ? "low" : "minimal";
}