Skip to content

fix(codex): restore o200k token estimates - #90

Merged
raine merged 1 commit into
raine:mainfrom
mulfyx:fix/codex-count-tokens
Jul 31, 2026
Merged

fix(codex): restore o200k token estimates#90
raine merged 1 commit into
raine:mainfrom
mulfyx:fix/codex-count-tokens

Conversation

@mulfyx

@mulfyx mulfyx commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • restore o200k_base text tokenization for Codex /v1/messages/count_tokens
  • keep image, encrypted-reasoning, and protocol-framing costs as explicit local estimates
  • use the same tokenizer for standalone-search truncation so its token budget remains valid
  • document which provider counters are tokenizer-backed and which remain heuristic

Problem

The Rust implementation currently treats each uninterrupted run of letters, digits, _, or - as one token. Long identifiers, CJK text without whitespace, and base64-like text can therefore collapse to a single estimated token. The endpoint then severely under-reports request size.

This is also a regression from the proxy's original TypeScript implementation, which encoded text with gpt-tokenizer/model/gpt-4o. The current documentation continued to describe the Codex path as o200k_base-backed even though the Rust implementation had become a word-run heuristic.

Measured end to end against Codex terminal usage for the same translated requests:

Fixture Previous /count_tokens Actual input tokens Error
English prose 976 978 -0.2%
Long identifier 17 531 -96.8% (31.2x undercount)
Minified code 2,224 1,649 +34.9%
CJK text 17 2,705 -99.4% (159.1x undercount)
Base64-like text 17 2,257 -99.2% (132.8x undercount)

With this change:

Fixture New /count_tokens Actual input tokens Error
English prose 984 978 +0.6%
Long identifier 537 531 +1.1%
Minified code 1,655 1,649 +0.4%
CJK text 2,711 2,705 +0.2%
Base64-like text 2,263 2,257 +0.3%

The remaining six-token offset is the proxy's protocol-framing estimate. /count_tokens remains a local preflight estimate, not an upstream billing total.

Implementation

  • add tiktoken-rs with default features disabled
  • count ordinary Codex text with the shared o200k_base tokenizer
  • preserve the existing explicit estimates for images, encrypted reasoning, and request framing
  • truncate standalone-search content by encoded-token prefixes while backing up to a valid UTF-8 boundary
  • add regression coverage for long identifiers, CJK, base64-like text, minified code, and UTF-8-safe token-budget truncation
  • correct the HTTP API and architecture documentation

Why this is a bug

Validation

  • cargo fmt --all -- --check
  • cargo check --all-targets
  • cargo test --all-targets
  • cargo clippy --all-targets -- -D warnings
  • live /count_tokens calls and matching terminal Codex requests across all fixtures above
  • verified that /count_tokens remains local and does not make an upstream request

@raine
raine merged commit ef95d57 into raine:main Jul 31, 2026
2 checks passed
@raine

raine commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Seems to make sense. Thanks again

bp0lr pushed a commit to bp0lr/claude-code-proxy that referenced this pull request Aug 29, 2026
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