Skip to content

feat(admin): one reset model for Codex and Claude, with honest results - #175

Merged
rexdotsh merged 4 commits into
feat/codex-reset-guardfrom
feat/reset-states-ui
Oct 22, 2026
Merged

rexdotsh merged 4 commits into
feat/codex-reset-guardfrom
feat/reset-states-ui

Conversation

@rexdotsh

@rexdotsh rexdotsh commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Stack 3/4 · resets UX redo. Admin UI.

One reset model for both providers

Every account's resets are in one of three states. They show on one line under the limits (label, balance, state, what they refill) instead of a cramped sub-line under a window.

State Codex Claude Line Action
Usable now Credits, unless cached limits show nothing to reset (#174). Unknown limits also count, and Codex decides Server offer present 3 credits · refills 5h + 7d windows Use
Usable now, early n/a: Codex has no early use Offer with use_requires_limit: false and no limit hit 2 resets · usable early · refills 5h and 7d limits Use, with the existing early-use warning in the confirmation
Usable once a limit is hit codexResets.unavailable = requires_limit requires_limit 3 credits · usable once a limit is hit · … none
Unavailable, with a reason none left paused, cooling down after a recent reset, unavailable right now, can't confirm what it refills 1 reset · cooling down after a recent reset · … Settings link
Unavailable, replacing the count waiting for sync, claude.ai only, not eligible label + description Settings where useful

The Use button, the row menu item and the U shortcut only appear when a reset is usable now. Codex confirmations never show an early-use warning.

Results and toasts

Result Toast
Codex reset Limits reset · 1 credit used · N credits left
Codex nothing_to_reset Nothing to reset yet: Codex only uses a credit once you hit a limit. No credit was spent.
Codex no_credit That credit is no longer available. No credit was spent.
Codex already_redeemed This credit already reset your limits · nothing more was used · N credits left
Codex, any other code Codex answered "…" · the next limits check shows whether a credit was used
Claude reset Refilled the 5h and 7d limits · 1 reset used · N left
Claude not_limited Nothing to reset yet: no limit this reset refills is hit. No reset was spent.
Claude already_used That reset was already used · nothing more was spent
Claude cooldown Another reset was used recently · try again later. No reset was spent.
Claude ineligible This reset can't be used on this account any more. No reset was spent.
Claude unavailable Couldn't confirm the reset · the next limits check shows whether it was used
Claude, any result with reason reset_unconfirmed / stamp_indeterminate Reset not confirmed yet · the next limits check shows whether it was used (no balance change, no updating state)
Refusals and conflicts (409/502) The server's message, for example the #174 guard

Updating limits after a real reset

Kleis never shows limits the upstream hasn't reported. After a real reset (Codex reset/already_redeemed, or a confirmed Claude reset), the account's limits stay as they are, dimmed, with a small pulsing dot and Updating limits… in the row's Resets column (and phone line) and in the detail footer.

  • Starts: right after the successful spend's answer, before any reload, so a slow or hanging /admin/accounts (or /usage) can't delay it or its timers. The consume route now returns respondedAt (server time).
  • Ends when: /admin/accounts returns a quota whose fetchedAt is newer than respondedAt. Codex's immediate reload is older than that, so the state waits for the confirming read. The page re-reads about 6s after the reset, after the server's confirming read from fix(resets): confirm a reset with one limits read a few seconds later #173 lands.
  • Timeout: at about 20s the state re-renders at once and the page re-reads once more. If nothing newer has arrived, the latest data shows with a quiet Couldn't confirm yet tag and "couldn't confirm the new limits yet" in the footer, which stay until a newer read arrives. Even if every reload fails, it never spins forever.
  • No state on: nothing_to_reset, not_limited, unconfirmed claims, refusals or errors.
  • Both re-reads hit Kleis's cache only, with no upstream calls. Reduced motion stops the pulse.

Cold load: codexResets from /admin/accounts/quotas is now merged like the limits, so an account first loaded without a quota doesn't offer Use (or the menu item, or U) when the follow-up says requires_limit. I checked this in the preview: before the fix, Use showed; after it, there's none.

Screenshots

Fake data from a local preview server with mocked upstreams.

Codex: usable once a limit is hit (the reported case: 6% / 12%, 3 credits)

Codex at-limit desktop
Codex at-limit phone

Codex: usable now (5h at 100%)

Codex usable desktop
Codex usable phone
Codex confirmation desktop
Codex confirmation phone
Codex reset toast desktop
Codex reset toast phone

Codex: limits unknown, so Use is offered and Codex answers nothing_to_reset

Codex unknown desktop
Codex unknown phone
Codex nothing_to_reset toast desktop
Codex nothing_to_reset toast phone

Claude: usable now

Claude usable desktop
Claude usable phone

Updating limits… (Codex, right after a reset)

Codex updating desktop
Codex updating phone
Codex settled desktop

Updating limits… (Claude): row and detail, then the confirmed limits

Claude updating detail desktop
Claude updating row desktop
Claude updating detail phone
Claude updating row phone
Claude confirmed desktop
Claude confirmed phone

Couldn't confirm yet (the confirming read got a 429)

Timed out desktop
Timed out phone

Timeout when every reload fails

Checked in the preview: the 6s and 20s /admin/accounts reloads are aborted. Before the fix it was still spinning at 23s; now it shows the latest data with the hint.
Reloads failing desktop
Reloads failing phone

Updating starts even while account usage hangs

Checked in the preview: /admin/accounts/usage is held pending. Before the fix there was no updating state; now it shows at once.
Usage pending desktop
Usage pending phone

Unconfirmed Claude claim

Unconfirmed claim desktop
Unconfirmed claim phone

Claude: usable once a limit is hit

Claude at-limit desktop
Claude at-limit phone

Claude: usable early

Claude early desktop
Claude early phone

Claude: unavailable (cooldown)

Claude cooldown desktop
Claude cooldown phone

bun lint, bun typecheck, bun test (318 pass, 12 skip, 0 fail; also --randomize) and bun run build pass. There are no UI tests, per AGENTS.md; the behavior that matters is covered on the server in #173/#174.

@rexdotsh
rexdotsh added this pull request to stack #177 October 22, 2026 12:45
@rexdotsh rexdotsh changed the title feat/reset states ui feat(admin): one reset model for Codex and Claude, with honest results Oct 22, 2026
Each account's resets are usable now, usable once a limit is hit, or unavailable with a reason, shown on one line under the limits. Use only appears when a reset can be used now; Claude keeps early use with its warning, Codex has none. Every Codex and Claude result says what happened and whether anything was spent.
…ives

After a real reset the account's limits dim, with 'Updating limits…', until /admin/accounts returns a newer limits read. After about 20s the latest data shows with a quiet 'couldn't confirm yet'. Cold loads now merge codexResets from the quotas response, and an unconfirmed Claude claim says so instead of reporting a reset used.
@rexdotsh
rexdotsh force-pushed the feat/reset-states-ui branch from 489ff66 to 1a00944 Compare October 22, 2026 13:32
… it on timeout

The consume route returns respondedAt, and the wait starts right after the spend's answer, with both re-reads on timers that no reload can block. Limits read after respondedAt end it. The 20s timeout re-renders, so the spinner gives way to 'Couldn't confirm yet' even when every reload fails.
@rexdotsh rexdotsh closed this Oct 22, 2026
@rexdotsh rexdotsh reopened this Oct 22, 2026
@rexdotsh
rexdotsh merged commit c4ffde5 into main Oct 22, 2026
9 of 10 checks passed
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