feat(codex): accept parenthesized GPT-5.6 effort overrides (#9208)

Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates — only pre-existing audit.test.ts flake).
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-08-05 22:39:59 -03:00
committed by GitHub
parent fed64abc2e
commit e317385ba8
4 changed files with 74 additions and 32 deletions

View File

@@ -0,0 +1 @@
- **feat(codex):** accept parenthesized GPT-5.6 reasoning overrides. (thanks @seakleangnhak)

View File

@@ -48,6 +48,12 @@ export {
getCodexDualWindowCooldownMs,
} from "./codex/quota.ts";
import { isCodexFreePlan, normalizeCodexTools } from "./codex/tools.ts";
import {
CODEX_EFFORT_ORDER as EFFORT_ORDER,
GPT_5_6_ULTRA_ALIAS_MODELS,
splitCodexReasoningSuffix,
type CodexEffortLevel as EffortLevel,
} from "./codex/reasoningSuffix.ts";
// Re-exported for external importers (tests + provider services).
export { isCodexFreePlan, normalizeCodexTools } from "./codex/tools.ts";
@@ -117,12 +123,6 @@ function codexWebSocketUnavailableResponse(): Response {
// Ref: sub2api PR #1129 (feat(openai): split codex spark rate limiting from codex)
export { getCodexModelScope, getCodexRateLimitKey, type CodexQuotaScope };
// Ordered list of effort levels from lowest to highest
const EFFORT_ORDER = ["none", "low", "medium", "high", "xhigh", "max", "ultra"] as const;
type EffortLevel = (typeof EFFORT_ORDER)[number];
const STANDARD_EFFORT_SUFFIXES = ["none", "low", "medium", "high", "xhigh"] as const;
const GPT_5_6_MAX_ALIAS_MODELS = new Set(["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]);
const GPT_5_6_ULTRA_ALIAS_MODELS = new Set(["gpt-5.6-sol", "gpt-5.6-terra"]);
const CODEX_FAST_WIRE_VALUE = "priority";
const CODEX_RESPONSES_WS_URL = "wss://chatgpt.com/backend-api/codex/responses";
const CODEX_RESPONSES_LITE_HEADER = "x-openai-internal-codex-responses-lite";
@@ -185,32 +185,6 @@ function enforceCodexResponsesLiteParallelToolCalls(
return { ...body, parallel_tool_calls: false };
}
function splitCodexReasoningSuffix(model: unknown): {
baseModel: string;
effort: EffortLevel | null;
} {
const modelId = typeof model === "string" ? model : "";
const gpt56AliasMatch = /^(gpt-5\.6-(?:sol|terra|luna))-(max|ultra)$/.exec(modelId);
if (gpt56AliasMatch) {
const [, baseModel, alias] = gpt56AliasMatch;
const supportedModels =
alias === "ultra" ? GPT_5_6_ULTRA_ALIAS_MODELS : GPT_5_6_MAX_ALIAS_MODELS;
if (supportedModels.has(baseModel)) {
return { baseModel, effort: alias as EffortLevel };
}
}
for (const level of STANDARD_EFFORT_SUFFIXES) {
if (modelId.endsWith(`-${level}`)) {
return {
baseModel: modelId.slice(0, -`-${level}`.length),
effort: level,
};
}
}
return { baseModel: modelId, effort: null };
}
export function getCodexUpstreamModel(model: unknown): string {
return splitCodexReasoningSuffix(model).baseModel;
}

View File

@@ -0,0 +1,41 @@
export const CODEX_EFFORT_ORDER = [
"none",
"low",
"medium",
"high",
"xhigh",
"max",
"ultra",
] as const;
export type CodexEffortLevel = (typeof CODEX_EFFORT_ORDER)[number];
export const GPT_5_6_MAX_ALIAS_MODELS = new Set(["gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"]);
export const GPT_5_6_ULTRA_ALIAS_MODELS = new Set(["gpt-5.6-sol", "gpt-5.6-terra"]);
export function splitCodexReasoningSuffix(model: unknown): {
baseModel: string;
effort: CodexEffortLevel | null;
} {
const modelId = typeof model === "string" ? model : "";
const gpt56Match = /^(gpt-5\.6-(?:sol|terra|luna))(?:-(max|ultra)|\((max|ultra)\))$/.exec(
modelId
);
if (gpt56Match) {
const [, baseModel, hyphenEffort, parenthesizedEffort] = gpt56Match;
const effort = hyphenEffort ?? parenthesizedEffort;
const supportedModels = parenthesizedEffort
? GPT_5_6_MAX_ALIAS_MODELS
: effort === "ultra"
? GPT_5_6_ULTRA_ALIAS_MODELS
: GPT_5_6_MAX_ALIAS_MODELS;
if (supportedModels.has(baseModel)) {
return { baseModel, effort: effort as CodexEffortLevel };
}
}
for (const effort of ["none", "low", "medium", "high", "xhigh"] as const) {
if (modelId.endsWith(`-${effort}`)) {
return { baseModel: modelId.slice(0, -`-${effort}`.length), effort };
}
}
return { baseModel: modelId, effort: null };
}

View File

@@ -82,6 +82,32 @@ test("CodexExecutor.transformRequest clamps Luna ultra requests to its max effor
assert.equal(result.reasoning.effort, "max");
});
test("CodexExecutor.transformRequest accepts parenthesized GPT-5.6 effort overrides", () => {
const executor = new CodexExecutor();
const cases = [
{ model: "gpt-5.6-sol(ultra)", expectedModel: "gpt-5.6-sol", expectedEffort: "max" },
{ model: "gpt-5.6-terra(max)", expectedModel: "gpt-5.6-terra", expectedEffort: "max" },
{ model: "gpt-5.6-luna(ultra)", expectedModel: "gpt-5.6-luna", expectedEffort: "max" },
];
for (const { model, expectedModel, expectedEffort } of cases) {
const result = executor.transformRequest(
model,
{
model,
input: [],
reasoning: { effort: "low", summary: "detailed" },
},
false,
{ requestEndpointPath: "/responses" }
);
assert.equal(result.model, expectedModel);
assert.equal(result.reasoning.effort, expectedEffort);
assert.equal(result.reasoning.summary, "detailed");
}
});
test("CodexExecutor.execute disables parallel tool calls for Responses Lite markers", async () => {
const executor = new CodexExecutor();
const originalFetch = globalThis.fetch;