Skip to main content

Module account

Module account 

Source
Expand description

Account state, health and probe scheduling.

The per-account state map every selection reads: it holds each account’s declared models, its LoadingState, its latest usage snapshot and its last probe outcome. The walk that turns that into a picked account lives in selection.rs; this module owns the state and the classification the walk and the accounts read both use.

Two-tier classification:

  1. Usable - usage is unknown, OR usage shows under 100% on both windows, OR last probe failed transiently (network / other HTTP). A session can try this account; the spawned claude either succeeds or surfaces its own rate-limit error we can react to.
  2. Unusable - usage shows 100% on at least one window, OR /api/oauth/usage returned 429, OR credentials are expired / unauthorized. Known to be either at the cap or unable to authenticate.

Saturation and probe failures are classification only - they feed the walk’s preference order and the accounts read.

Rate-limited accounts are visible in a view’s usage bars so the user can wait for the window to reset.

Re-exports§

use forge_primitives::usage::UsageSnapshot; 🔒
use forge_primitives::usage::UsageWindow; 🔒
use forge_primitives::account::LoadedAccount; 🔒

Structs§

AccountKey
Newtype wrapping the account’s display_name.
AccountState
AccountStateMap

Enums§

LoadingState
Boot-time loading state for an account. The boot wave and the cron spawn path wait for every account in the map to resolve to Ready or Bailed; the selection walk skips Loading and keeps Bailed as its last resort. A bailed account’s usage is None by construction (the loader clears it on the transition).
Unusable
Why an account is held out of the usable tier. Which reason can apply is keyed on the account’s billing kind: only a window-billed account can saturate, so on a spend row an unusable account can only be probe-blocked. A snapshot whose source is not the account backend’s is ignored here, so a cache surviving a forge.toml provider edit cannot saturate the row it landed on.
UsageFetchStatus
Classification of the latest usage-poll attempt outcome for an account. Feeds unusable_reason’s probe-blocked branch and the backoff schedule.

Constants§

BACKOFF_CAP 🔒
Ceiling shared by the exponential schedule and the server Retry-After clamp. The hold-down this caps is the sole re-probe path for a settled account, so a bogus header must not hold one down arbitrarily long.

Functions§

account_serves
true when an account declaring models serves model: it declares the name, or declares it as an alias of a model it does. The one home for the rule: the selection walk, the route’s binding gate, and the config load gate all match a request’s model here.
backoff_delay 🔒
Per-account exponential backoff schedule for usage-probe failures. Doubles each consecutive failure, capped at 10 minutes. The 60 s poll loop ticks ~once a minute; without backoff, a transient per-IP /usage 429 would persist across every cycle for as long as Anthropic kept rate-limiting, preventing any account from accumulating fresh usage data.
is_rate_limited 🔒
True when ANY window in the snapshot is currently at-or-beyond the plan cap AND its scheduled reset has not yet passed. Such an account will immediately trip the API rate limit on the next request, so it’s excluded from the “available” tier and only used as a fallback when every pinned account is rate-limited.
unusable_reason 🔒
The classification behind AccountStateMap::unusable_reason for a key already resolved to its inputs. None means usable: usage unknown, or under 100% on every window, or the last probe failed transiently (network / unknown HTTP - we just don’t know yet). Some means at the cap, or unable to authenticate.