Skip to content

fix: Codex preflight summary compatibility (max_output_tokens + responses-lite header) - #665

Open
ranxianglei wants to merge 2 commits into
masterfrom
2026-09-09_preflight-max-output-tokens
Open

fix: Codex preflight summary compatibility (max_output_tokens + responses-lite header)#665
ranxianglei wants to merge 2 commits into
masterfrom
2026-09-09_preflight-max-output-tokens

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Fixes #663

Two related fixes so Codex (ChatGPT-login) preflight summaries work end-to-end. Both live in requestSummary (src/preflight.ts) and only affect the independently-built summary call — the original model request is untouched.

1. Learn to drop max_output_tokens when the upstream rejects it

The ChatGPT codex backend rejects the Responses max_output_tokens parameter outright (400 {"detail":"Unsupported parameter: max_output_tokens"}), which killed preflight summaries with a 502 after the #626 stream fix. The proxy now detects that rejection, retries the summarization without the optional parameter, and remembers it per session+upstream+model — so a model/provider that accepts the limit keeps the existing 8192 output cap. Both rejection orders (stream-first, param-first) recover, and the retries are bounded (each capability is learned at most once).

2. Drop the Codex Lite header from the summary call only

requestSummary copied ALL main-request headers into its independently-built summary body. The main Codex request carries x-openai-internal-codex-responses-lite (its body has reasoning.context: all_turns), but the summary body has no reasoning field — so the backend rejected the summary with 400 "…requires reasoning.context to be all_turns". The fix strips that one request-shape-specific header from the summary call only; the original model request keeps the header and its reasoning fields. Auth and routing headers are preserved. The strip is keyed on the Codex header name, so it is a no-op for Anthropic/OpenAI.

Tests

tests/preflight-max-output-tokens.test.ts — 6 e2e tests:

  • order A (stream-first) + order B (param-first): both rejection orders learn and recover; second request first-shot compatible
  • standard provider: 8192 cap retained, no capability learned
  • model scoping: rejection learned for model A keeps model B's cap
  • codex lite header: summary drops the Lite header, main request keeps it; auth preserved
  • anthropic: header strip is a no-op — summary keeps auth, fold + forward OK

Pre-flight

  • npm run typecheck
  • npm test ✓ (1252/1252)
  • npm run build

Validated against the real backend by the reporter: an over-window Lite-mode request now completes after preflight folds the ranges, preserving the canary.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

📦 Built Package Artifact

Branch: 2026-09-09_preflight-max-output-tokens (128f9d3)

Option A — Install from npm PR tag (recommended)

npm install -g billion-context@pr-665

Each push to this PR publishes a new version under the pr-665 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr665.tgz
npm install -g package

This comment is automatically updated on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Review in progress — verifying #663 repro evidence, checking the diff against the #626 capability-learning pattern, and running typecheck/tests/build on the PR branch. Will report findings here.

@ranxianglei ranxianglei changed the title fix: preflight learns to drop max_output_tokens when the upstream rejects it fix: Codex preflight summary compatibility (max_output_tokens + responses-lite header) Sep 9, 2026
ework-agent added 2 commits September 10, 2026 02:57
…ects it

Responses-API preflight summaries unconditionally sent
max_output_tokens: 8192. The Codex backend
(chatgpt.com/backend-api/codex/responses) rejects that parameter with
400 {"detail":"Unsupported parameter: max_output_tokens"}, so every
over-window request died with a 502 that no client retry could recover.

Follows the existing #626 stream-required capability-learning pattern:
only an explicit HTTP 400 naming max_output_tokens causes Responses
summaries to omit it. Learning is scoped to session + upstream URL +
model, so standard Responses providers keep the 8192 output limit.
Both rejection orders (stream-first / param-first) are covered and
compatibility retries are bounded (each capability learned at most
once, <=3 attempts per range).

Adds tests/preflight-max-output-tokens.test.ts: both rejection orders
against a mock Codex-like backend (summary generation + recovery +
forwarding + second-request first-shot compatibility), a standard
provider that retains the cap, and model-scoped learning.
The independently built Responses summary body has no reasoning field, but
requestSummary copied ALL main-request headers into it — including
x-openai-internal-codex-responses-lite, which the backend only accepts when
the body carries reasoning.context: all_turns. The summary call was rejected
with 400 "…requires `reasoning.context` to be `all_turns`", killing
preflight right after the max_output_tokens fix.

Strip that one request-shape-specific header from the summary call only; the
original model request keeps the header and its reasoning fields. Auth and
routing headers are preserved. The strip is keyed on the Codex header name, so
it is a no-op for Anthropic/OpenAI.

Fixes #663
@ranxianglei
ranxianglei force-pushed the 2026-09-09_preflight-max-output-tokens branch from 3c35be1 to 128f9d3 Compare September 10, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: Codex preflight summaries fail with unsupported max_output_tokens

1 participant