Summary
The management panel's Codex quota card appears to display ChatGPT/Codex used_percent backwards. The upstream Codex quota endpoint returns usage as percent used, but the UI transforms it into percent remaining (100 - used_percent) and then displays that value without saying it is remaining quota. This makes a mostly-empty quota look nearly full.
Example observed
A direct Codex usage check returned this payload for one credential:
{
"email": "foxsnow61@gmail.com",
"plan_type": "team",
"rate_limit": {
"allowed": true,
"limit_reached": false,
"primary_window": {
"used_percent": 3,
"limit_window_seconds": 18000,
"reset_after_seconds": 9132,
"reset_at": 1778075834
},
"secondary_window": {
"used_percent": 0,
"limit_window_seconds": 604800,
"reset_after_seconds": 595932,
"reset_at": 1778662634
}
}
}
Expected UI:
- 5-hour limit:
3% used
- Weekly limit:
0% used
- Progress bar nearly empty/low
Actual UI before local patch:
- 5-hour limit displayed around
97%
- Weekly limit displayed around
100%
- Progress bar looked full/high
This is confusing because the credential looks exhausted/full even though the upstream response says it is mostly unused.
Related CLIProxyAPI context
While testing router-for-me/CLIProxyAPI#3240, the backend management API correctly exposed runtime state such as quota and model_states. The incorrect display is in the management panel interpretation of the Codex quota endpoint response.
The management API response itself did not contain quota usage windows; the panel fetched Codex usage through management api-call and received the correct used_percent values.
Root cause
The Codex quota response field is named used_percent, and it already represents usage consumed.
The UI currently behaves like this:
const used = window.usedPercent
const clampedUsed = used === null ? null : Math.max(0, Math.min(100, used))
const remaining = clampedUsed === null ? null : Math.max(0, Math.min(100, 100 - clampedUsed))
const label = remaining === null ? '--' : `${Math.round(remaining)}%`
return (
<QuotaProgressBar
percent={remaining}
highThreshold={70}
mediumThreshold={30}
/>
)
That is only correct if the UI is explicitly showing remaining quota. But the UI reads like usage and color semantics imply that higher means more consumed. For Codex, it makes 3% used appear as 97%.
Suggested fix option A: display used percentage directly
This is the clearest behavior for fields named used_percent:
type QuotaWindow = {
id: string
label: string
labelKey?: string
labelParams?: Record<string, unknown>
usedPercent: number | null
resetLabel?: string
}
function clampPercent(value: number | null): number | null {
if (value === null || !Number.isFinite(value)) return null
return Math.max(0, Math.min(100, value))
}
function renderCodexQuotaWindow(
window: QuotaWindow,
t: (key: string, params?: Record<string, unknown>) => string,
styles: Record<string, string>,
QuotaProgressBar: React.ComponentType<{
percent: number | null
highThreshold: number
mediumThreshold: number
}>,
) {
const used = clampPercent(window.usedPercent)
const displayPercent = used === null ? '--' : `${Math.round(used)}% used`
const label = window.labelKey ? t(window.labelKey, window.labelParams) : window.label
return (
<div key={window.id} className={styles.quotaRow}>
<div className={styles.quotaRowHeader}>
<span className={styles.quotaModel}>{label}</span>
<div className={styles.quotaMeta}>
<span className={styles.quotaPercent}>{displayPercent}</span>
<span className={styles.quotaReset}>{window.resetLabel}</span>
</div>
</div>
<QuotaProgressBar
percent={used}
highThreshold={70}
mediumThreshold={30}
/>
</div>
)
}
Suggested fix option B: keep remaining percent, but label it clearly
If the intended UI is to show remaining quota, then labels and colors should make that clear:
const used = clampPercent(window.usedPercent)
const remaining = used === null ? null : 100 - used
const displayPercent = remaining === null ? '--' : `${Math.round(remaining)}% remaining`
<QuotaProgressBar
percent={remaining}
highThreshold={70}
mediumThreshold={30}
/>
In this mode, high percent means high remaining capacity, so the color thresholds should be reviewed to avoid implying danger when the account is actually healthy.
Local workaround tested
I patched the built panel asset locally by replacing the Codex quota render calculation from:
remaining = used === null ? null : Math.max(0, Math.min(100, 100 - used))
label = remaining === null ? `--` : `${Math.round(remaining)}%`
to:
remaining = used
label = used === null ? `--` : `${Math.round(used)}% used`
After rebuilding and serving the patched panel:
- The served
management.html contains % used labels.
- The old
100 - used_percent display path is gone.
- The same upstream response now displays low usage as low usage.
Acceptance criteria
- Given
primary_window.used_percent = 3, the UI shows 3% used or clearly shows 97% remaining.
- Given
secondary_window.used_percent = 0, the UI shows 0% used or clearly shows 100% remaining.
- The progress bar color/threshold semantics match the label semantics.
- Codex quota cards no longer visually imply that a mostly unused account is exhausted/full.
Why this matters
Operators may disable or rotate away from healthy credentials because the dashboard indicates they are full. This is especially confusing when paired with CLIProxyAPI runtime quota state because the backend may be accurate while the frontend still renders the external Codex quota backwards.
Summary
The management panel's Codex quota card appears to display ChatGPT/Codex
used_percentbackwards. The upstream Codex quota endpoint returns usage as percent used, but the UI transforms it into percent remaining (100 - used_percent) and then displays that value without saying it is remaining quota. This makes a mostly-empty quota look nearly full.Example observed
A direct Codex usage check returned this payload for one credential:
{ "email": "foxsnow61@gmail.com", "plan_type": "team", "rate_limit": { "allowed": true, "limit_reached": false, "primary_window": { "used_percent": 3, "limit_window_seconds": 18000, "reset_after_seconds": 9132, "reset_at": 1778075834 }, "secondary_window": { "used_percent": 0, "limit_window_seconds": 604800, "reset_after_seconds": 595932, "reset_at": 1778662634 } } }Expected UI:
3% used0% usedActual UI before local patch:
97%100%This is confusing because the credential looks exhausted/full even though the upstream response says it is mostly unused.
Related CLIProxyAPI context
While testing
router-for-me/CLIProxyAPI#3240, the backend management API correctly exposed runtime state such asquotaandmodel_states. The incorrect display is in the management panel interpretation of the Codex quota endpoint response.The management API response itself did not contain quota usage windows; the panel fetched Codex usage through management
api-calland received the correctused_percentvalues.Root cause
The Codex quota response field is named
used_percent, and it already represents usage consumed.The UI currently behaves like this:
That is only correct if the UI is explicitly showing remaining quota. But the UI reads like usage and color semantics imply that higher means more consumed. For Codex, it makes
3% usedappear as97%.Suggested fix option A: display used percentage directly
This is the clearest behavior for fields named
used_percent:Suggested fix option B: keep remaining percent, but label it clearly
If the intended UI is to show remaining quota, then labels and colors should make that clear:
In this mode, high percent means high remaining capacity, so the color thresholds should be reviewed to avoid implying danger when the account is actually healthy.
Local workaround tested
I patched the built panel asset locally by replacing the Codex quota render calculation from:
to:
After rebuilding and serving the patched panel:
management.htmlcontains% usedlabels.100 - used_percentdisplay path is gone.Acceptance criteria
primary_window.used_percent = 3, the UI shows3% usedor clearly shows97% remaining.secondary_window.used_percent = 0, the UI shows0% usedor clearly shows100% remaining.Why this matters
Operators may disable or rotate away from healthy credentials because the dashboard indicates they are full. This is especially confusing when paired with CLIProxyAPI runtime quota state because the backend may be accurate while the frontend still renders the external Codex quota backwards.