Skip to content

Fix OpenAI usage percent normalization for low values#178

Open
ktmyname wants to merge 1 commit into
1jehuang:masterfrom
ktmyname:fix/openai-usage-normalize-ratio
Open

Fix OpenAI usage percent normalization for low values#178
ktmyname wants to merge 1 commit into
1jehuang:masterfrom
ktmyname:fix/openai-usage-normalize-ratio

Conversation

@ktmyname
Copy link
Copy Markdown

@ktmyname ktmyname commented May 8, 2026

Summary

jcode usage (and the inline /usage overlay) shows ChatGPT subscriptions
as fully rate-limited (100% used, exhausted bar) even when the live
wham/usage endpoint reports only a few percent consumed. The Codex
desktop app, which reads the same endpoint with the same OAuth token,
correctly shows the actual remaining quota.

Root cause

Both src/usage/openai_helpers.rs and src/usage_openai.rs define a
normalize_ratio helper:

pub(super) fn normalize_ratio(raw: f32) -> f32 {
    if !raw.is_finite() { return 0.0; }
    if raw > 1.0 {
        (raw / 100.0).clamp(0.0, 1.0)
    } else {
        raw.clamp(0.0, 1.0)
    }
}

It tries to auto-detect whether the input is a ratio (0..=1) or a
percent (0..=100) using raw > 1.0. The OpenAI wham/usage endpoint
unambiguously returns used_percent in [0, 100]. A real production
payload with a barely-touched weekly bucket looks like:

{
  "rate_limit": {
    "primary_window":  { "used_percent": 5, ... },
    "secondary_window":{ "used_percent": 1, ... }
  }
}

used_percent: 1 (1% used) hits the else branch, clamps to 1.0,
and is rendered as 100% used / fully exhausted — even though the
user has 99% of their weekly Codex quota remaining.

The existing tests only exercise values like 25.0, 50.0, 75.0,
100.0, so the bug never surfaced in CI.

Fix

The wham/usage and OpenAI account-usage endpoints always report
percentages in [0, 100]. Drop the heuristic and just divide:

pub(super) fn normalize_ratio(raw: f32) -> f32 {
    if !raw.is_finite() { return 0.0; }
    (raw / 100.0).clamp(0.0, 1.0)
}

Applied to both src/usage/openai_helpers.rs and the legacy
src/usage_openai.rs.

Tests

Added two tests in src/usage/tests.rs:

  1. test_normalize_ratio_treats_low_integer_values_as_percent — direct
    unit coverage of the helper across 0, 1, 5, 50, 100, plus
    >100, negative, and NaN inputs.
  2. test_parse_openai_usage_payload_reports_low_percentages_correctly
    regression test built from a real wham/usage payload with
    used_percent: 1 in the secondary window. Asserts the parser
    returns 1.0, not 100.0.

All 33 usage::tests::* pass on cargo test --release --lib.

Verification (live API)

Before patch:

OpenAI (ChatGPT) (k***9@gmail.com)
----------------------------------
5-hour window: █░░░░░░░░░░░░░░ 5% (resets in 3h 0m)
7-day window:  ███████████████ 100% (resets in 6d 22h)
GPT-5.3-Codex-Spark (5h): █░░░░░░░░░░░░░░ 5%
GPT-5.3-Codex-Spark (7d): ███████████████ 100%

After patch (same account, same wham/usage response, ~10 minutes later):

OpenAI (ChatGPT) (k***9@gmail.com)
----------------------------------
5-hour window: █░░░░░░░░░░░░░░ 5% (resets in 2h 26m)
7-day window:  ░░░░░░░░░░░░░░░ 1% (resets in 6d 21h)
GPT-5.3-Codex-Spark (5h): █░░░░░░░░░░░░░░ 5%
GPT-5.3-Codex-Spark (7d): ░░░░░░░░░░░░░░░ 1%

This now matches what the Codex desktop app shows for the same account.

Impact

  • jcode usage, the /usage overlay, and the info-widget compact usage
    bar all consume normalize_ratio via parse_wham_window, so all three
    now report correctly.
  • Cross-provider failover heuristics that key off usage_ratio /
    seven_day_ratio previously assumed users were exhausted at 1% real
    usage; they now see the true value and stop spuriously failing over.

View in Codesmith
Need help on this PR? Tag @codesmith with what you need.

  • Let Codesmith autofix CI failures and bot reviews

The wham/usage endpoint and OpenAI account-usage helpers report
'used_percent' as a value in [0, 100]. The previous heuristic in
'normalize_ratio' tried to auto-detect ratio-vs-percent by checking
'raw > 1.0', which incorrectly mapped legitimate API responses like
'used_percent: 1' (1% used) to a ratio of 1.0, displayed as a fully
exhausted '100%' bar.

This made 'jcode usage' (and the inline /usage overlay) show
ChatGPT subscriptions as completely rate-limited even when only ~1%
of the weekly bucket had been consumed. The Codex desktop app, which
reads the same endpoint, correctly showed the actual remaining quota.

Treat the API value as a percent unconditionally and clamp to [0, 1].
Also add direct unit tests and a regression test that mirrors a real
production payload from the wham/usage endpoint with single-digit
'used_percent' values.
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