Skip to content

Render all usage windows dynamically from the new limits[] API (per-model / Fable, spend)#7

Open
amalakhovsky wants to merge 2 commits into
dvdstelt:mainfrom
amalakhovsky:feature/dynamic-limits
Open

Render all usage windows dynamically from the new limits[] API (per-model / Fable, spend)#7
amalakhovsky wants to merge 2 commits into
dvdstelt:mainfrom
amalakhovsky:feature/dynamic-limits

Conversation

@amalakhovsky

Copy link
Copy Markdown

Summary

Anthropic's usage endpoint (GET /api/oauth/usage) has moved its per-window data out of the flat top-level keys (five_hour, seven_day, seven_day_<model> — now returned as null) and into a self-describing limits[] array. Each entry carries its own kind (session / weekly_all / weekly_scoped), group, percent, severity (normal / warning / critical), resets_at, is_active, and an optional scope.model.display_name naming a per-model window (e.g. a weekly Fable limit). Money likewise moved to a structured spend object.

The current code only knows the flat keys, so per-model windows — and any future window type — are silently dropped. In practice a maxed-out scoped limit (e.g. Fable at 100% / critical) is completely invisible.

This PR reads the new shape and renders every window the API reports, dynamically, while keeping the legacy keys as a fallback for older responses.

What changed

  • New src/lib/usageModel.js — a pure, GI-free, unit-testable module that turns the payload into an ordered list of windows (normalizeWindows, preferring limits[] and falling back to the legacy keys) and normalises the extra-usage money block (normalizeSpend).
  • Dynamic meters — the popup now renders one meter per reported window, reusing meters by a stable key and tearing them down only when the API stops reporting that window. Per-model windows like Fable now appear automatically.
  • Severity floored at the API's — the existing burn-consequence coloring is preserved, but a window the API flags warning/critical never reads calmer than that.
  • Structured spend — the extra-usage line now uses spend (authoritative amount / limit / percent / severity), falling back to extra_usage and scaling by the API's own decimal_places instead of assuming cents. It tints amber/red with the spend severity.
  • New "Worst active limit" panel option — so the top-bar gauge can surface whichever limit is most severe right now; a maxed-out per-model window reaches the panel even when the 5-hour and 7-day totals are calm.
  • Docs: refreshed the AGENTS.md data-source notes and the changelog; tools/poll.js now prints the normalised windows + spend.

Testing

  • node tools/test-usageModel.mjs — new pure-node unit tests (10, all passing) covering the new limits[] shape, the legacy fallback, unknown/future scoped models, and the spend/extra_usage normalisation.
  • Validated normalizeWindows / normalizeSpend against a real live payload: renders 5-hour 8%, 7-day (all models) 64%, 7-day Fable 100% (critical, active), and Extra usage: USD 416.54 / USD 500.00 (83%).
  • glib-compile-schemas and ./build.sh both succeed; the bundle includes the new module.

Note: I couldn't get a live gjs -m tools/poll.js run on my machine (libsoup throws Gio.TlsError reaching api.anthropic.com, though curl works), so the model was validated against a captured real payload via node rather than end-to-end through the shell. A second pair of eyes on the live popup would be welcome.

The usage endpoint moved its per-window data out of the flat top-level
keys (five_hour, seven_day, seven_day_<model>, which are now null) and
into a self-describing `limits[]` array. Each entry carries its own
kind/group/percent/severity/resets_at plus an optional scope naming a
per-model window — e.g. a weekly Fable limit. The old code only knew the
flat keys, so scoped-model windows (and any future window type) were
silently dropped.

- Add src/lib/usageModel.js: pure, unit-testable data-shaping
  (normalizeWindows / normalizeSpend) that prefers limits[] and falls
  back to the legacy keys. Covered by tools/test-usageModel.mjs.
- Render one meter per reported window dynamically, reusing meters by a
  stable key and dropping windows the API stops reporting.
- Floor each gauge's computed burn-consequence color at the API's own
  severity, so a window flagged warning/critical never reads calmer.
- Use the structured `spend` object for the extra-usage line (with
  extra_usage as fallback), scaled by the API's decimal places, tinted
  by its severity.
- Add a "Worst active limit" panel-window option so a maxed-out
  per-model window reaches the top-bar gauge.
- Update poll.js to print the normalised windows + spend; refresh
  AGENTS.md data-source notes and the changelog.
These doc updates belong with the previous commit (they describe the new
limits[]/spend shape and usageModel.js) but missed its staging.
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.

1 participant