fix(server): tone usage bars by how full they are (#2322)

A usage bar in Settings -> Usage stayed green all the way to 100%, so
the one moment the meter matters was the moment it said nothing.

The client already computes this. `window-bar.tsx` reads
`window.tone ?? deriveTone(usedPct)`, and `deriveTone` escalates past
70% and 90%. But `usage.ts` only assigns `window.tone` when a provider
sends one, so any provider that sends a tone opts out of the thresholds
entirely. Claude and Kimi hardcoded `tone: "ok"`, and Codex escalated to
`warning` past 70% but could never reach `danger`.

Providers now derive tone from the percentage they already have, through
one shared `toneFromUsedPct` whose thresholds match the client's.
Claude, Codex and Kimi windows all escalate correctly.

Balances had the same gap by a different route: `balance-bar.tsx` has no
`deriveTone` fallback, and `balanceToneFromRemaining` only escalates
once a balance is completely spent, so a credits bar at 99% was green.
Cursor and Grok know their limit, so they now tone by used percentage.
Codex credits report only a remaining balance with no limit, so they
keep the remaining-based tone, documented as the no-limit case.

MiniMax is unchanged: it maps a status its own API supplies rather than
hardcoding a tone.

Verified against the live Anthropic API with a session window at 83%,
which now reports `warning` where it previously reported `ok`.

Closes #2320

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Christoph Leiter
2026-07-23 03:30:44 +08:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 10da5ca169
commit de69b2a2af
8 changed files with 181 additions and 13 deletions
@@ -12,6 +12,7 @@ import type { ProviderApiFetch, ProviderUsageFetcher } from "../provider.js";
import {
ApiNumberSchema,
balanceToneFromRemaining,
toneFromUsedPct,
fetchProviderApi,
unavailableUsage,
windowFromUsedPct,
@@ -143,7 +144,7 @@ export class CodexQuotaProvider implements ProviderUsageFetcher {
label: "Session",
utilizationPct: session.usedPct,
resetsAt: session.resetsAt,
tone: "ok",
tone: toneFromUsedPct(session.usedPct),
}),
);
}
@@ -154,7 +155,7 @@ export class CodexQuotaProvider implements ProviderUsageFetcher {
label: "Weekly",
utilizationPct: weekly.usedPct,
resetsAt: weekly.resetsAt,
tone: weekly.usedPct >= 70 ? "warning" : "ok",
tone: toneFromUsedPct(weekly.usedPct),
}),
);
}
@@ -165,7 +166,7 @@ export class CodexQuotaProvider implements ProviderUsageFetcher {
label: "Code review",
utilizationPct: codeReview.usedPct,
resetsAt: codeReview.resetsAt,
tone: codeReview.usedPct >= 70 ? "warning" : "ok",
tone: toneFromUsedPct(codeReview.usedPct),
}),
);
}