[Bug] OpenCode Go: rolling 5-hour usage shows 100% / "Exhausted Weekly" when opencode.ai reports 1%
Repo: nesszer/Win-CodexBar
Version: v0.46.0 (built 2026-07-30, Windows)
Provider: OpenCode Go (opencodego)
Severity: Medium — false "quota exhausted" state; actual usage is fine
Summary
When the OpenCode Go rolling (5-hour) usage is at exactly 1%, the menu bar shows the 5-hour bar at 100%, labels the provider "Exhausted Weekly", and the Pace widget reports "Far ahead (+79.6%) / Runs out in 0m" — even though the opencode.ai dashboard and the provider's own API both report 1%.
Weekly (15%) and monthly (4%) rows display correctly and match the server exactly, so the web fetch and cookie path are fine. Only the rolling window is wrong.
Expected vs actual
| Window |
opencode.ai dashboard |
CodexBar (Win fork) |
| Rolling (5h) |
1% |
100% ❌ |
| Weekly |
15% |
15% ✅ |
| Monthly |
4% |
4% ✅ |
| Pace |
— |
"Far ahead (+79.6%)", "Runs out in 0m" ❌ (derived from bogus 100%) |
Reproduction
- Have an OpenCode Go subscription whose rolling 5-hour usage is exactly 1% (any value ≤ 1.0 in the API response).
- Run CodexBar v0.46.0 with the OpenCode Go provider enabled (web/Auto mode with a valid opencode.ai cookie).
- Observe the 5-hour bar at 100% red + "Exhausted Weekly" while opencode.ai shows 1%.
Evidence — live server payload
Authenticated fetch of https://opencode.ai/workspace/{wrk_id}/go (the exact URL the provider scrapes) returns:
rollingUsage:$R[34]={status:"ok",resetInSec:13631,usagePercent:1},
weeklyUsage:$R[35]={status:"ok",resetInSec:53863,usagePercent:15},
monthlyUsage:$R[36]={status:"ok",resetInSec:2334517,usagePercent:4}
usagePercent here is an integer percent (1 = 1%), matching the dashboard. The reset values also match the dashboard countdowns (3h47m / 14h58m / 27d0h at fetch time).
Root cause
rust/src/providers/opencodego/mod.rs, OpenCodeGoProvider::extract_window() (around lines 180–229):
let percent = super::extract_number(&percent_pattern, text);
if let Some(p) = percent {
let reset = ...;
// Regex path only matches direct percent field names — fraction
// heuristic is safe here (upstream #2331). used/limit computed
// percents must not use this path without a separate gate.
let p = if (0.0..=1.0).contains(&p) {
p * 100.0
} else {
p
};
return Some((p.clamp(0.0, 100.0), reset.max(0)));
}
The <= 1.0 → *100 "fraction heuristic" is applied to the direct usagePercent field on the regex path. The real server sends integer percent (usagePercent: 1 = 1%). The heuristic interprets 1 as the fraction 0.01 and multiplies by 100 → 100%.
- Weekly
15 and monthly 4 are > 1.0, so they pass through untouched — which is exactly why only the rolling bar is wrong.
- The Pace widget and "Exhausted Weekly" label are downstream artifacts of the fake 100% rolling value.
Upstream comparison (why this is a Win-fork regression)
In upstream steipete/CodexBar (Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoUsageFetcher.swift):
- Regex path (
parseSubscription, lines ~437–471): extracts usagePercent directly with no <= 1 scaling. Correctly shows 1%.
- JSON path (
parseWindow, line ~779): applies if percentIsDirect, resolvedPercent <= 1.0 { resolvedPercent *= 100 } — where fractions genuinely occur in the JSON shape (upstream tests use usagePercent: 0.25 → 25%).
The Win fork ported the JSON-path heuristic onto the regex path, where the server's serialized $R[...] payload sends integer percent. That mismatch is the bug.
Suggested fix
In extract_window() (regex path), do not scale a direct usagePercent-style field by the <= 1.0 heuristic — mirror upstream's regex path, which treats the value as-is. Keep the heuristic only for fields where the server actually sends fractions, or drop it entirely on this path since the observed $R[...] serialization always uses integer percent (0–100).
Minimal change sketch:
let p = p; // remove: let p = if (0.0..=1.0).contains(&p) { p * 100.0 } else { p };
(Keep the existing clamp to 0..100.)
Related issues (different failure modes, do not close)
This issue is distinct: the web path works, but a sub-1% integer rolling value is mis-scaled to 100%, producing a false "exhausted" state. PR #215 ("fix sub-1% usage units") fixed the computed used/limit branch but left the direct-field heuristic, so this survives in v0.46.0.
[Bug] OpenCode Go: rolling 5-hour usage shows 100% / "Exhausted Weekly" when opencode.ai reports 1%
Repo: nesszer/Win-CodexBar
Version: v0.46.0 (built 2026-07-30, Windows)
Provider: OpenCode Go (
opencodego)Severity: Medium — false "quota exhausted" state; actual usage is fine
Summary
When the OpenCode Go rolling (5-hour) usage is at exactly 1%, the menu bar shows the 5-hour bar at 100%, labels the provider "Exhausted Weekly", and the Pace widget reports "Far ahead (+79.6%) / Runs out in 0m" — even though the opencode.ai dashboard and the provider's own API both report 1%.
Weekly (15%) and monthly (4%) rows display correctly and match the server exactly, so the web fetch and cookie path are fine. Only the rolling window is wrong.
Expected vs actual
Reproduction
Evidence — live server payload
Authenticated fetch of
https://opencode.ai/workspace/{wrk_id}/go(the exact URL the provider scrapes) returns:usagePercenthere is an integer percent (1= 1%), matching the dashboard. The reset values also match the dashboard countdowns (3h47m / 14h58m / 27d0h at fetch time).Root cause
rust/src/providers/opencodego/mod.rs,OpenCodeGoProvider::extract_window()(around lines 180–229):The
<= 1.0 → *100"fraction heuristic" is applied to the directusagePercentfield on the regex path. The real server sends integer percent (usagePercent: 1= 1%). The heuristic interprets1as the fraction0.01and multiplies by 100 → 100%.15and monthly4are> 1.0, so they pass through untouched — which is exactly why only the rolling bar is wrong.Upstream comparison (why this is a Win-fork regression)
In upstream
steipete/CodexBar(Sources/CodexBarCore/Providers/OpenCodeGo/OpenCodeGoUsageFetcher.swift):parseSubscription, lines ~437–471): extractsusagePercentdirectly with no<= 1scaling. Correctly shows 1%.parseWindow, line ~779): appliesif percentIsDirect, resolvedPercent <= 1.0 { resolvedPercent *= 100 }— where fractions genuinely occur in the JSON shape (upstream tests useusagePercent: 0.25→ 25%).The Win fork ported the JSON-path heuristic onto the regex path, where the server's serialized
$R[...]payload sends integer percent. That mismatch is the bug.Suggested fix
In
extract_window()(regex path), do not scale a directusagePercent-style field by the<= 1.0heuristic — mirror upstream's regex path, which treats the value as-is. Keep the heuristic only for fields where the server actually sends fractions, or drop it entirely on this path since the observed$R[...]serialization always uses integer percent (0–100).Minimal change sketch:
(Keep the existing clamp to 0..100.)
Related issues (different failure modes, do not close)
This issue is distinct: the web path works, but a sub-1% integer rolling value is mis-scaled to 100%, producing a false "exhausted" state. PR #215 ("fix sub-1% usage units") fixed the computed
used/limitbranch but left the direct-field heuristic, so this survives in v0.46.0.