Fix Codex Responses session continuity - #249
Conversation
|
CI note: the full test matrix passes on Ubuntu 22/24 and Windows 22/24, and version-guard also passes. The build-artifact job built and packed the package successfully, then failed only at npm publish because NODE_AUTH_TOKEN is empty for this fork PR (ENEEDAUTH). |
Why the
|
|
哎,真的是,让Codex说点屁事,最后就是长篇大论。 就是我自己的Codex一直在跟我说什么,删掉可能会导致Codex以外的客户端无法判断Agent身份,所以他认为不应该删。
也就是说,这段逻辑纯粹是旧 Codex workaround,不是为通用 Responses 客户端设计的。现在我们换了更合理的方法判断codex subagent身份(也就是用thread-id区分),那么旧逻辑自然没有任何理由要保留。 现在剩下的唯一一个可能要考虑的一点就是,除非有人在用旧版的Codex,然后运行这个bili,没法用我们的新逻辑,反而必须要依赖于旧逻辑。 |
Why this change is needed
Codex on ChatGPT exercises the Responses API differently from the API-key clients this proxy was primarily tracking.
In an observed long-running Codex task, one stable Codex task label was split across seven internal billion-context sessions. Compression completed in one shard, but a later request landed in a fresh shard with no token baseline or compression blocks. That request grew to roughly 240k input tokens, Codex emitted a native compaction_trigger, and billion-context then appended an ACP nudge after it. The upstream rejected the request because compaction_trigger must be the final input item.
There are three interacting causes:
Why the fix is shaped this way
Stable account identity, narrowly scoped
For chatgpt.com upstreams, prefer chatgpt-account-id over the rotating bearer when deriving the proxy session id. This keeps a task stable across OAuth refreshes while preserving account isolation.
Other upstreams retain the existing credential-based behavior. This avoids changing API-key and custom-endpoint semantics.
Stable Codex agent identity with compatibility fallback
When Codex thread metadata is present, use its stable agent identity to isolate per-agent compression state. This keeps dynamic instruction tails from fragmenting one agent into multiple proxy sessions, while still separating named agents in the same task.
If the metadata is absent, keep the legacy full-instructions namespace. Existing Responses clients therefore retain their previous behavior instead of being collapsed into a new shared namespace.
Native compaction is a protocol boundary
If the final input item is compaction_trigger, pass that request through without ACP projection, prompt injection, tool injection, or history folding. Input id sanitization still runs, so the earlier over-length-id recovery remains active.
The session is marked for rebase only after the upstream compaction succeeds. A failed native compaction therefore does not discard local compression state.
This is deliberately a whole-request bypass rather than only suppressing the final nudge: native compaction has special ordering and state semantics, and preserving the request shape is safer than partially applying the normal ACP pipeline.
Compatibility notes
Validation