Skip to content

feat(codex): opt-in end_turn mode for repeated empty completions on any request - #209

Draft
Butanium wants to merge 1 commit into
raine:mainfrom
Butanium:empty-completion-end-turn-mode
Draft

Butanium wants to merge 1 commit into
raine:mainfrom
Butanium:empty-completion-end-turn-mode

Conversation

@Butanium

Copy link
Copy Markdown

⚠️ Written by Claude (Opus 5.5) in Claude Code, with little human supervision; @Butanium asked for it to be sent and hasn't reviewed the code. We hit this in real use. Whether to AI-review, merge, adapt or close it is up to you.

Closes #208. This adds an opt-in setting, CCP_CODEX_EMPTY_COMPLETION=end_turn or codex.emptyCompletion: "end_turn", that applies the #122 rule to every Codex request. The rule is to retry an empty completion once and then return an empty end_turn. Without the setting, behavior is unchanged: the rule covers only resolved tool results, and other empty completions get the full retry loop and a 503.

Why. With Claude Code, some requests that don't end in tool results come back empty by design, for example a turn answering a Monitor event that needs no reply. Each one cost 11 full-context calls and 3–4 minutes before failing. Details and timings are in #208.

Change

  • config.rs: codex_empty_completion_end_turn() reads the env var, then codex.emptyCompletion. It accepts end_turn / end-turn or retry; anything else falls back to retry. The setting is also listed in the config summary.
  • providers/codex/mod.rs: both places that call tail_is_successful_tool_result(&body) now call empty_completion_may_end_turn(&body), which is that check OR the setting. accept_empty_completion is untouched, so the one-retry discriminator from codex: treat an empty successful completion after a tool_result tail as a valid end_turn #122 still applies.
  • Docs: a row in the configuration table and an "Empty completions" subsection in the Codex page.

Result. We ran the same change on top of v0.1.44 with #122's earlier version. Offline, against a stub upstream that always completes empty, a request costs 2 upstream calls and ~1.5 s instead of 11 calls and a 503, on both the buffered and the streaming path. Claude Code 2.1.293 accepts the empty end_turn (-p returns success, one turn, no client retries). Live with gpt-6-astra, the next 270 requests over three weeks produced no empty-completion 503.

Details for reviewers and agents: tests, scope

Tests

  • New codex_empty_completion_mode_reads_env_and_config: default off, config on, env retry overrides config, env end_turn.
  • cargo fmt --all -- --check: clean.
  • cargo clippy --all-targets --locked -- -D warnings: clean.
  • cargo test --all --locked: 1175 passed, 0 failed (on main at fe10718).

Scope

  • The setting is read per request, like the other Codex config accessors.
  • It only widens which requests may take the existing one-retry path. It doesn't change what counts as an empty completion or the retry count.

Unrelated, noticed while testing: running cargo test appends log lines to the real ~/.local/state/claude-code-proxy/proxy.log, e.g. gpt-5.5 503s at ~4 ms and ~11 s. Some test doesn't isolate the state dir. #164 has a similar leak: one of its tests wrote codex-compaction/session.json into the real state dir.


Written by Claude Opus 5.5 in Claude Code on behalf of @Butanium, with little human supervision; not reviewed by a human.

https://claude.ai/code/session_01Xmx9RE7u4ZLBzSUjpjqyBM

CCP_CODEX_EMPTY_COMPLETION=end_turn (or codex.emptyCompletion) applies the
empty-completion acceptance from raine#122 to every request: one retry, then a
valid empty end_turn instead of up to 11 full-context upstream calls and a
503. The default, retry, keeps the resolved-tool-results-only behavior.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

Codex: empty completions without a tool-result tail still run the full 11-call retry loop (Claude Code Monitor turns, end-of-turn requests)

1 participant