Skip to content

feat(codex): add tool-excluded active Tok/s metrics - #805

Open
ihearttokyo wants to merge 4 commits into
getagentseal:mainfrom
ihearttokyo:agent/fix-daily-history-scan
Open

feat(codex): add tool-excluded active Tok/s metrics#805
ihearttokyo wants to merge 4 commits into
getagentseal:mainfrom
ihearttokyo:agent/fix-daily-history-scan

Conversation

@ihearttokyo

Copy link
Copy Markdown
Contributor

Summary

This contribution adds a low-CPU, retrospective throughput view for Codex rollouts. CodeBurn now reports generated tokens per second (Tok/s) from persisted JSONL timing while excluding recorded tool wait, so the estimate reflects active model work more closely than wall-clock turn duration.

What changed

  • Added codeburn codex-tps with one-shot text output, --json, bounded --limit, and incremental --watch mode.
  • Added bounded 64 KiB JSONL reading so large MCP arguments/results do not require loading an entire rollout into memory.
  • Preserved native MCP, function/custom-tool, fork-replay, and task timing semantics; nested argument/result duration fields are not mistaken for the payload duration.
  • Propagated active duration, generated-token, and tool-wait fields through parsing, caching, session summaries, and model breakdowns.
  • Added Tok/s immediately after 1-shot in the TUI’s By Model panel, with a concise explanation of the active-time denominator and excluded tool wait.
  • Stacked the report panels below 130 columns so the new metric remains readable in ordinary terminals.

Presentation

The repository’s generic dashboard image shows the existing CodeBurn visual language and is included here as a neutral reference:

Generic CodeBurn dashboard

This is an offline JSONL estimate—not live decoder speed. Server, prompt, and other unrecorded latency can still be included when the rollout does not expose a more precise interval.

Validation

  • 121 focused tests pass, including 29 Codex-provider cases, 6 throughput cases, 3 CLI validation cases, 21 dashboard cases, and the existing cache/session suites.
  • npx tsc --noEmit passes.
  • npm run build:cli passes.
  • npm run build passes for the CLI and dashboard; Vite reports its existing large-chunk advisory only.
  • CLI/TUI smoke checks pass for one-shot throughput, invalid limits, missing rollouts, and 120/80-column layouts.
  • Final find-bugs and code-reviewer passes at GPT-5.6 Sol High approved the staged tree, including 5 MiB MCP argument/result collision fixtures for object and string durations.

The unrelated full repository renderer harness remains environment-limited because its current setup lacks the Testing Library Chai matchers and has teardown noise; the feature-focused suite is green. npm audit --omit=dev --audit-level=high still reports the repository’s existing transitive advisories; npm audit fix --force would require a breaking MCP SDK change and was not applied.

Thank you for maintaining CodeBurn and for making room for focused contributions like this—your project made it possible to diagnose the gap from real rollout data.

@ihearttokyo

Copy link
Copy Markdown
Contributor Author

During code review, model found more and more discrepancies. This might be too big a merge but these models get really out of hand and I'm not expert enough to know what I should or should not include. Perhaps just have a model review the changes. The tok/s column is really useful and if you dont want to incorporate these bugfixes then feel free to just reimplement the tok/s column and dump my PR. I worked about an hour on it manually and the code review / bug bash lasted an hour and 8 minutes haha

iamtoruk added 2 commits July 27, 2026 11:36
…hboard width

Review fixes on top of getagentseal#805.

Discovery: getCachedCodexProject short-circuits again without opening the
file. The PR read the first line of every rollout to collect session_id,
which cost +129ms on an 827-file session directory with a warm cache.
Archived duplicates are now filtered by basename, which needs no file I/O.

Timing: on oversized mcp_tool_call_end lines a `duration_ms` key inside
invocation.arguments outranked the payload-level duration, inflating tool
wait. The depth-aware payload value wins; the naive scan stays as the
fallback for task_complete.

Layout: MIN_WIDE goes back to 90 so 90-129 column terminals keep the
two-column dashboard. The By Model panel drops the Tok/s column (and its
footnote) when the panel has fewer than 61 inner columns or when no model
recorded active timing, so narrow terminals do not truncate and non-Codex
users get no dead column.
Active/tool-wait timing used to be back-patched onto calls that had
already been appended to the result list. Buffer the calls decoded since
the last task_started instead, stamp them in place on task_complete, and
append them at the next task_started or at end of stream, so a task is
only emitted once its timing is final. Single-pass and split decodes then
agree instead of depending on where a decode boundary falls.

Output is unchanged: parsing 827 real rollouts (4.2 GB, 51224 calls) with
and without this change produces byte-identical results. The buffer holds
one task's calls; the deepest observed over that corpus was 924 against a
result list of 8196.

Attribution still spans everything since the last task_started, which
matters when a mid-file session_meta re-arms the fork-replay cutoff and
swallows a task_started while its task_complete lands past the cutoff.
The added test pins that case.
@iamtoruk

Copy link
Copy Markdown
Member

Thanks for this contribution — the throughput model held up well under a deep review (the active-time arithmetic verified end-to-end on real rollouts, the bounded reader is sound, and the cache versioning discipline was exactly right).

I've pushed two maintainer commits on top rather than round-tripping review comments, since the fixes were small and surgical:

fad84662 — three review blockers:

  • Restored the getCachedCodexProject discovery fast path (isValidCodexSession ran unconditionally, costing a measured +129ms on every invocation at ~830 rollouts; the archived-copy dedup your test pins now works via basename comparison, which needs no file I/O — back to +0.3ms).
  • Fixed duration_ms precedence at the oversized-payload site: the naive first-match scan outranked the depth-aware guard, so an MCP tool with duration_ms in its arguments corrupted timing (reproduced: toolWaitMs 5000 vs the correct 3000 — a 40% Tok/s error). Added a fixture that fails without the fix.
  • Reverted MIN_WIDE to 90 and made the Tok/s column width-conditional instead — raising the global threshold cost every 90–129-column user the two-column layout. The column now drops below the measured 61-char minimum and when no row has timing data (render-verified at 89/120/130/160 cols).

7fe43209 — restructured the timing attribution to buffer a task's calls until task_complete instead of back-patching emitted results. This matters for a planned engine refactor where decode output must be identical under any record split. While proving byte-identity over a 4.24GB corpus we found a real edge your original handles but the naive buffering didn't: a mid-file session_meta (fork/resume) can suppress a task_started, producing consecutive task_completes — now pinned by a regression test.

Also added the CHANGELOG entry, including disclosure of the parse-behavior corrections riding along (fork-replay double-count fix, exec→Bash mapping, custom_tool_call handling, exact tokens for oversized token_count lines — which reprices such sessions from exact counts; ordinary sessions verified cost-identical to the cent across 51,224 real calls).

Full suite green (2,480 passed; the 24 app/renderer file failures are a pre-existing local-env dep gap, untouched by this PR). Review from here should be quick.

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.

2 participants