Copilot account settings and quota
Copilot model choices and usage snapshots are scoped to the signed-in account that owns them. The Preferences surface keeps account identity, model choices, and usage data together so switching accounts cannot reuse another account's selection or quota.
Behavior
Each account is identified by its numeric account id and API endpoint. Model lists, selected models, and quota snapshots use that same key. A model choice for commit-message generation or conflict resolution is written only to the selected account's map. If an account is removed, its in-flight data cannot restore itself later. Re-authentication starts a new request generation, so an older response cannot replace newer data.
Refreshes run in bounded batches of two accounts and settle independently. One slow or unavailable account therefore does not hold another account's refresh hostage. SDK startup and quota requests have bounded deadlines, and a timeout retains the last valid snapshot as stale data or reports an unavailable state when no prior snapshot exists.
The usage card reports the values returned by the provider: used requests, available requests when the provider supplies a finite entitlement, reset date, the reported or computed remaining percentage, and the local refresh timestamp. Unlimited quotas use an accessible "No usage limit" value. The card also reports loading, available, stale, unavailable, and error states. Missing data is never represented as a guessed zero or as another account's data.
Counts and percentages use the shared number-format preference, with a bounded maximum fraction setting. Zero-fraction values omit the decimal separator, so the card never displays a dangling separator beside a quota fact.
Persistence and migration
Account-scoped model selections are stored under
selected-copilot-models-by-account. The value is a bounded
object whose keys are account cache keys and whose values contain
feature-to-model selections. The legacy global selection is copied to
every known account only when that account has no explicit override.
After migration, the legacy keys are removed and repeated migration is
idempotent. Provider and model removal scrubs stale selections before
they are saved.
Selection changes go through the existing profile settings history
path. The registered setting is
selected-copilot-models-by-account, so changing a model
creates a normal local settings-history entry without storing account
tokens or provider secrets.
Failure and recovery
An account without Copilot SDK eligibility reports unavailable. A
known account whose scoped map contains null remains
loading or unavailable, rather than falling back to the first account. A
refresh failure retains the last valid snapshot and marks it stale. A
failure without a prior snapshot reports an error with no fabricated
values. A response received after sign-out or after a newer request is
ignored for cache and state mutation.
Security and privacy
The cache key contains only the account id and endpoint. Account tokens, provider credentials, and raw provider responses are not placed in model selection storage, settings history, UI labels, exports, or diagnostics. Quota values are treated as provider facts and are rendered only after the account identity and request generation have been checked.
Verification
Desktop completeness inventory
| Surface | Implementation | Search or route | Focused checks | Capture state |
|---|---|---|---|---|
| Account overview | app/src/ui/preferences/snapshot-card.tsx |
settingsCopilotAccountOverview |
account identity and sign-out isolation | Packaged capture pending |
| Quota details | app/src/ui/preferences/snapshot-card.tsx |
settingsCopilotQuota |
used/available/reset, status and progress semantics | Packaged capture pending |
| Configure models | app/src/ui/preferences/copilot.tsx |
settingsCopilotConfigureModels |
per-account selection and model restoration | Packaged capture pending |
The inventory is intentionally hand-written. It does not infer coverage from the entries already discovered by a test. Its negative evidence is the focused red proof that replaces the used value with the entitlement value and requires the UI check to turn red; restoring the provider-reported used value turns it green again.
Each account card uses a stable sanitized account suffix for its overview, quota, and model-configuration targets. This keeps palette and settings search navigation account-specific without exposing credentials or unsafe selector characters.
Focused checks cover two-account model isolation, migration overrides, storage round trips, idempotence, sign-out, re-authentication races, stale quota responses, no invented quota values, accessible account and progress semantics, localized English and Cantonese copy, funny-level framing, and settings search and command-palette reachability. The focused command is:
node script/test.mjs app/test/unit/stores/copilot-store-test.ts app/test/unit/ui/copilot-preferences-test.tsx app/test/unit/settings-search-test.ts app/test/unit/format-number-test.ts
The command-palette suite retains one unrelated pre-existing failure
in palette:set-attention-focus; the Copilot registration
and selector checks remain green.