fix(codex): proactive context-pressure retire + handoff on app-server runtime (#36801) - #48485
fix(codex): proactive context-pressure retire + handoff on app-server runtime (#36801)#48485ahmadalzaro1 wants to merge 1 commit into
Conversation
e5a7dc6 to
1bac1f3
Compare
… runtime The Codex app-server runtime hands each turn to a persistent subprocess that owns its own conversation thread; unlike the chat-completions path it had no proactive compaction, so sessions grew unbounded until codex hard-reset and silently lost context. Add a post-turn guard: when a turn's prompt tokens reach compression.codex_retire_threshold (new, default 0.85) of the codex-reported context window, summarize Hermes' projection via the auxiliary summary model, retire the codex thread, and reseed the respawned thread with the summary on the next turn — so Goal/Discoveries/Files survive instead of a cold history=0 reset. Threshold 0 disables. Fixes NousResearch#36801.
1bac1f3 to
08c05df
Compare
|
Ready for review. This is rebased onto current The codex app-server path still has no proactive compaction, so long sessions keep growing until codex hits its hard ceiling and silently resets (#36801). This adds a post-turn guard: when prompt tokens reach 10 new unit tests; existing |
|
Thanks for the focused investigation and tests. This is now superseded by the Codex-native compaction implementation on current
This is an automated hermes-sweeper review. |
Fixes #36801.
Problem
The Codex app-server runtime (
run_codex_app_server_turn) hands each turn to a persistentcodex app-serversubprocess that owns its own conversation thread. Unlike the chat-completions path — which runs a preflight compaction check inbuild_turn_context()before every model call — the codex path had no proactive compaction. Sessions grow unbounded inside the subprocess until codex hits its hard context ceiling and silently hard-resets, losing all context. The failure is silent: the operator only notices after context is already gone (and on metered Codex seats the retained context is also a per-turn budget burn).Compressing Hermes'
messageslist (the naive fix) does not help — codex holds the real history internally;run_turn()only forwards the new user message. The only lever is to retire the thread and reseed a fresh one.Fix
A proactive, post-turn guard on the codex path:
_record_codex_app_server_usage()— where the real prompt-token count and codex-reportedmodel_context_windoware both known — computeprompt_tokens / context_window.compression.codex_retire_threshold(new config, default 0.85,0disables), build a structured handoff summary from Hermes' projectedmessagesvia the auxiliary summary model (not codex — so the summarization itself can't overflow the already-full window), then retire the codex thread (close()+ drop) and stash the summary.history=0reset.This implements the flow proposed in the issue (extract usage → proactive threshold → handoff-on-retire) plus the structured-summary handoff suggested in the thread.
Notes
compression.codex_retire_threshold(0disables).ContextCompressor.build_handoff_summary()seam.logger.warning) rather than ride an over-full window into a hard reset.Tests
New
tests/agent/transports/test_codex_proactive_compaction.py(10 cases): over/under threshold, summary-less retire, disabled (flag +threshold=0), unknown window, already-retired session, and thebuild_handoff_summaryseam (empty / delegate / error-swallow). All pass; existingtest_context_compressor.py+test_codex_app_server_session.py(154 tests) remain green.