Repository navigation
Codex: count usage per notification and report the last call's context - #473
alex-clickhouse wants to merge 1 commit into
Conversation
- Take the usage baseline from the restored usage that app-server sends after thread/resume and thread/fork. start_turn drained it and receive_turn dropped it, so the first turn on a new client used total - last of its first notification. When that notification resent the previous counts, the turn counted the previous turn's last response again. - Add up the increase in total for each notification. A drop in total is a reset to 0 (ContextWindowExceeded), so the responses before the reset stay in the usage of the turn. - Count a notification in num_turns only when it increases total. Resends, usage limits and compactions are not model responses. - Report the input tokens of the last response as context_tokens. The context bar uses it instead of the mean input per call, which is too low when the context grows during the turn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Nerve PR review · ✅ Ready to merge This fixes the Codex per-turn token counts that per-turn cost is computed from. On main, the first turn after each resume (every daemon restart or client rebuild) counts the previous turn's last response a second time. A mid-turn Completeness: backend tests plus a fake app-server resume mode, and a ContextBar test. No engine test checks that Checked: full suite in an offline sandbox at |
This fixes four problems in the Codex turn usage and cleans up the tests. The codex-rs links are for 0.153.3, the version that nerve accepts.
Changes
thread/resumeandthread/fork, app-server sends the restored usage of the thread with the id of an earlier turn (thread_processor.rs#L4031-L4042).start_turndrained that notification andreceive_turndropped it. So the first turn on a new client usedtotal - lastof its first notification. When that notification resent the previous counts (a retry after a failed request, or a usage limit), the turn counted the previous turn's last response again. The client now takes the baseline from the replay. It usestotal - lastonly when there is no replay.totalfor each notification. A drop intotalis a reset to 0 onContextWindowExceeded(protocol.rs#L2291-L2304). The responses before the reset stay in the usage of the turn. On main, that turn records 0.num_turns. A notification counts as a model response only when it increasestotal. codex also sends a notification after a failed request, on a usage limit and after a compaction (session/mod.rs#L4412-L4459).num_turnsis the mean input per call. The context grows during a tool loop, so the mean is too low. For example, calls from 100k to 260k in a 272k window show 180k (66%), not 260k (96%). The Codex backend now reports the input tokens of the last response ascontext_tokens. The engine sends it in thedonemessage and stores it inlast_usage, andContextBaruses it when it is present. The Claude backend does not set it, so its context bar does not change.Tests
resume_usagemode in the fake app-server sends the replay afterthread/resume, then a resend of the restored counts, then one response. On main the turn records 5,000 fresh, 261,000 cached and 90 output tokens withnum_turns=2. The correct values are 3,000, 131,000 and 50 withnum_turns=1.ContextBartest covers both ways to get the context size.test_dropped_mid_turn_notification_self_heals, which tests a notification drop thatreceive_turncannot cause, andtest_reset_turn_accounting_clears_state, which only checks private attributes. Corrected the comment oftest_second_turn_deltas_off_first_turn_end.🤖 Generated with Claude Code