From 08a679508302beef9fc2e3c654c01aeb2ac391ef Mon Sep 17 00:00:00 2001 From: Xiangzhe <32761048+xz-dev@users.noreply.github.com> Date: Sat, 20 Jun 2026 21:51:08 +0800 Subject: [PATCH] fix(codex): request reasoning summaries (#4359) Adds reasoning.summary=auto + reasoning.encrypted_content include for Codex. Thanks @xz-dev. --- open-sse/executors/codex.ts | 25 +++++++++++++++++++++++++ tests/unit/executor-codex.test.ts | 18 ++++++++---------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/open-sse/executors/codex.ts b/open-sse/executors/codex.ts index 661f380f5f..03c2769beb 100644 --- a/open-sse/executors/codex.ts +++ b/open-sse/executors/codex.ts @@ -618,6 +618,9 @@ function clampEffort(model: string, requested: string): string { return requested; } +const CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE = "reasoning.encrypted_content"; +const CODEX_DEFAULT_REASONING_SUMMARY = "auto"; + function normalizeEffortValue(value: unknown): string | undefined { if (typeof value !== "string") return undefined; const normalized = value.trim().toLowerCase(); @@ -625,6 +628,27 @@ function normalizeEffortValue(value: unknown): string | undefined { return normalized || undefined; } +function ensureCodexReasoningSummary(body: Record): void { + const reasoning = + body.reasoning && typeof body.reasoning === "object" && !Array.isArray(body.reasoning) + ? (body.reasoning as Record) + : null; + if (!reasoning || normalizeEffortValue(reasoning.effort) === "none") return; + + if (!("summary" in reasoning)) { + reasoning.summary = CODEX_DEFAULT_REASONING_SUMMARY; + } + + if (!Array.isArray(body.include)) { + body.include = [CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE]; + return; + } + + if (!body.include.includes(CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE)) { + body.include = [...body.include, CODEX_REASONING_ENCRYPTED_CONTENT_INCLUDE]; + } +} + function consumeResponsesStoreMarker(body: Record): unknown { const marker = body._omnirouteResponsesStore; delete body._omnirouteResponsesStore; @@ -1321,6 +1345,7 @@ export class CodexExecutor extends BaseExecutor { effort: clampEffort(cleanModel, rawEffort), }; } + ensureCodexReasoningSummary(body); delete body.reasoning_effort; // Remove unsupported token limit parameters BEFORE the passthrough return. diff --git a/tests/unit/executor-codex.test.ts b/tests/unit/executor-codex.test.ts index ee200316e7..673b205271 100644 --- a/tests/unit/executor-codex.test.ts +++ b/tests/unit/executor-codex.test.ts @@ -242,10 +242,10 @@ test("CodexExecutor.transformRequest injects default instructions, clamps reason requestEndpointPath: "/responses", }); - assert.equal(result.stream, true); - assert.equal(result.store, false); + assert.deepEqual([result.stream, result.store], [true, false]); assert.equal(result.instructions.length > 0, true); - assert.equal(result.reasoning.effort, "high"); + assert.deepEqual(result.reasoning, { effort: "high", summary: "auto" }); + assert.deepEqual(result.include, ["reasoning.encrypted_content"]); assert.equal(result.service_tier, "priority"); assert.equal(result.messages, undefined); assert.equal(result.prompt, undefined); @@ -736,7 +736,7 @@ test("CodexExecutor.transformRequest keeps explicit request values ahead of conn } ); - assert.equal(result.reasoning.effort, "none"); + assert.deepEqual([result.reasoning, result.include], [{ effort: "none" }, undefined]); assert.equal(result.service_tier, "standard"); }); @@ -806,7 +806,8 @@ test("CodexExecutor.transformRequest passes GPT 5.4 Mini xhigh reasoning through { model: "gpt-5.4-mini", input: [], - reasoning: { effort: "xhigh", summary: "auto" }, + reasoning: { effort: "xhigh", summary: "detailed" }, + include: ["code_interpreter_call.outputs"], }, true, { @@ -822,11 +823,8 @@ test("CodexExecutor.transformRequest passes GPT 5.4 Mini xhigh reasoning through const reasoning = getRecord(sanitized.reasoning); assert.equal(sanitized.model, "gpt-5.4-mini"); - // #3756: xhigh now passes through by default. gpt-5.4-mini has no - // supportsXHighEffort:false flag (and ships a gpt-5.4-mini-xhigh catalog - // variant), so the effort is preserved instead of downgraded to "high". - assert.equal(reasoning.effort, "xhigh"); - assert.equal(reasoning.summary, "auto"); + assert.deepEqual(reasoning, { effort: "xhigh", summary: "detailed" }); + assert.deepEqual(sanitized.include, ["code_interpreter_call.outputs", "reasoning.encrypted_content"]); assert.equal(sanitized.reasoning_effort, undefined); });