feat: add Antigravity usage meter to the status bar#7952
feat: add Antigravity usage meter to the status bar#7952andrecristodev wants to merge 7 commits into
Conversation
Add a detection-gated Antigravity (agy) subscription usage meter, reusing the existing Gemini / Google Code Assist OAuth plumbing. Source the Google OAuth token from ~/.gemini/oauth_creds.json, falling back to the OS credential store where the agy CLI keeps it (Windows Credential Manager `gemini:antigravity`; macOS/Linux keyring). Read-only: never writes or refreshes either store. Phase 1 is single-account. - antigravity-fetcher.ts: loadCodeAssist (ANTIGRAVITY ideType) -> fetchAvailableModels, falling back to retrieveUserQuota; maps remainingFraction/resetTime via the shared Gemini bucket formatters. - antigravity-keyring.ts: read-only OS credential-store reader (PowerShell CredRead on Windows; security/secret-tool best-effort on macOS/Linux), normalized to the oauth_creds shape. - Wire through types, service dispatch, status bar, tooltip, provider visibility, detection gating, store slices + default-add migration, and settings search. Icon reuses the agy agent-catalog icon. - Split appearance-status-bar-search into provider/system entry modules to stay under the max-lines cap. - Tests for the fetcher and keyring reader; extend visibility/type fixtures. Cross-platform: PowerShell path guarded to win32; file path works everywhere; macOS/Linux keyring identifiers are best-effort. No secrets logged or persisted; tests use synthetic tokens only.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
📝 WalkthroughWalkthroughThis change adds Antigravity across main-process rate-limit fetching, account storage, IPC, shared types, renderer state, status-bar UI, settings search entries, and localized copy. It introduces Antigravity credential reading and writing plus quota retrieval with fallback and retry behavior, adds Antigravity account management, and updates status-bar visibility and rendering to show the new provider. Tests were added and updated for keyring parsing, account storage, fetch behavior, and visibility logic. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/renderer/src/components/settings/appearance-status-bar-search-entries.ts (1)
200-233: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAntigravity i18n keys deviate from the SHA1 auto-key convention used by every sibling entry.
All other entries in this catalog use SHA1-hash keys (e.g.
9dc15020d7,51b0ccd6a2) generated by the localization sync tooling, but the new antigravity entries use hand-written keys (antigravityTitle,antigravityDescription,antigravityKeyword,antigravityGoogleKeyword). This could confusepnpm run sync:localization-catalog(e.g. failing to detect that "google" already has key51b0ccd6a2, resulting in a duplicate string with a different key).Consider running the sync tool to auto-key these entries like the rest of the catalog, and reuse the existing
51b0ccd6a2("google") key instead of introducingantigravityGoogleKeyword.Source: Learnings
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: ea1b2fed-cb1d-47a1-b56b-068b6fc200a8
📒 Files selected for processing (27)
src/main/rate-limits/antigravity-fetcher.test.tssrc/main/rate-limits/antigravity-fetcher.tssrc/main/rate-limits/antigravity-keyring.test.tssrc/main/rate-limits/antigravity-keyring.tssrc/main/rate-limits/service.tssrc/main/runtime/rpc/methods/client-ui.tssrc/renderer/src/components/settings/appearance-status-bar-search-entries.tssrc/renderer/src/components/settings/appearance-status-bar-search.tssrc/renderer/src/components/settings/appearance-status-bar-system-entries.tssrc/renderer/src/components/status-bar/StatusBar.tsxsrc/renderer/src/components/status-bar/status-bar-agent-gating.tssrc/renderer/src/components/status-bar/status-bar-provider-visibility.test.tssrc/renderer/src/components/status-bar/status-bar-provider-visibility.tssrc/renderer/src/components/status-bar/tooltip.tsxsrc/renderer/src/components/status-bar/usage-error-copy.tssrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.jsonsrc/renderer/src/store/slices/rate-limits.tssrc/renderer/src/store/slices/ui.tssrc/renderer/src/web/web-preload-api.tssrc/shared/rate-limit-types.test.tssrc/shared/rate-limit-types.tssrc/shared/status-bar-defaults.tssrc/shared/types.ts
- i18n: replace the hand-written localization keys with SHA1 auto-keys matching the catalog convention, and reuse the existing shared "google" keyword key (51b0ccd6a2) instead of a duplicate. - docs: add JSDoc docstrings to the antigravity fetcher and keyring helpers to meet the docstring-coverage threshold.
097f6d7 to
2f4a497
Compare
Phase 2 of the Antigravity meter.
- Multi-account: a self-contained account store persists each Google
account signed into via agy, with credentials encrypted at rest via
Electron safeStorage (only id/email kept in clear). Accounts are
auto-captured from the agy keyring/file token, keyed by email.
- Switcher: the Antigravity popover lists stored accounts with per-account
usage and switches the active account, also rewriting the
gemini:antigravity keyring entry on Windows so agy follows the switch.
- Usage view: mirror the Antigravity app's grouping — collapse the ~20
per-model quotas into the two families it shows ("Gemini Models" and
"Claude and GPT models"), each on its most-constrained limit. The
status-bar segment now renders a progress bar + "NN% 5h" like the other
providers instead of a bucket name.
- Wire through shared types, the rate-limit service + state push, a
keyring writer, IPC + preload, the store slice, and the status-bar UI.
Tests for the account store and family grouping.
The weekly window agy shows is computed locally by its own quota manager
and is not returned by the Code Assist API (confirmed via agy's request
log and against CodexBar), so only the 5-hour limit is surfaced.
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/main/rate-limits/service.ts (1)
1310-1349: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy liftGate Antigravity account seeding behind CLI detection
refreshAntigravityAccounts()runs on every poll and still reads~/.gemini/oauth_creds.json, calls Google userinfo, and rewritesantigravity-accountseven when Antigravity is hidden becauseagyisn’t on PATH. Plumb the same detection state into the service and skip this refresh unless Antigravity is actually available.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f1751ee2-d229-4b18-a117-b3e537998b02
📒 Files selected for processing (19)
src/main/ipc/rate-limits.tssrc/main/rate-limits/antigravity-account-store.test.tssrc/main/rate-limits/antigravity-account-store.tssrc/main/rate-limits/antigravity-fetcher.test.tssrc/main/rate-limits/antigravity-fetcher.tssrc/main/rate-limits/antigravity-keyring.tssrc/main/rate-limits/service.tssrc/preload/api-types.tssrc/preload/index.tssrc/renderer/src/components/status-bar/StatusBar.tsxsrc/renderer/src/i18n/locales/en.jsonsrc/renderer/src/i18n/locales/es.jsonsrc/renderer/src/i18n/locales/ja.jsonsrc/renderer/src/i18n/locales/ko.jsonsrc/renderer/src/i18n/locales/zh.jsonsrc/renderer/src/store/slices/rate-limits.tssrc/renderer/src/web/web-preload-api.tssrc/shared/rate-limit-types.test.tssrc/shared/rate-limit-types.ts
✅ Files skipped from review due to trivial changes (1)
- src/renderer/src/i18n/locales/zh.json
🚧 Files skipped from review as they are similar to previous changes (5)
- src/renderer/src/store/slices/rate-limits.ts
- src/renderer/src/i18n/locales/ko.json
- src/renderer/src/i18n/locales/en.json
- src/renderer/src/i18n/locales/es.json
- src/renderer/src/i18n/locales/ja.json
- keyring: build the CredWrite blob inside the guarded try so a bad (NaN) expiry_date resolves to `false` instead of throwing out of writeAntigravityKeyringCredentials (and rejecting the switch IPC). - StatusBar: the account-switcher `run` helper now catches and logs failed actions so a rejected switch/refresh can't become an unhandled rejection. Adds keyring write tests for the NaN-expiry and non-Windows paths.
Signing into a new Google account in agy only surfaced in Orca after the 15-minute poll. Now opening the Antigravity popover triggers an immediate capture of the account agy is currently signed into (agy keeps a single account in the OS keyring, so Orca captures whichever is active), so a new login appears as soon as the user opens the menu instead of on the next poll. Adds rateLimits.refreshAntigravityAccounts IPC + preload surface and a mount effect in the account switcher.
Adds a "Manage accounts" toggle to the Antigravity account switcher so users can remove/disconnect a stored account, like the Claude/Codex account flows. In manage mode each row becomes a remove action. Removal rebuilds the switcher WITHOUT the auto-follow capture, so a removed account is not immediately re-added; the account agy is currently signed into reappears on the next capture until the user also signs out of it in agy (surfaced in an inline hint).
✅ Action performedReview finished.
|
Raise docstring coverage: document ProviderSegment, the account-switcher memo/callback/effect helpers, the added preload rateLimits methods, the IPC registrar, and the web preload stub. Extract the switcher's inline onSelect logic into documented handleAccountAction / toggleManageMode callbacks instead of anonymous inline arrows. No behavior change.
|
@coderabbitai review |
✅ Action performedReview finished.
|
Summary
Adds an Antigravity (
agy) subscription usage meter to the status bar, bringing it to parity with the existing Claude, Codex, Gemini, OpenCode Go, Kimi, and MiniMax meters. Antigravity is already a first-class launchable agent (src/shared/tui-agent-config.ts) with managed hooks, but its remaining quota and reset window were the only ones missing from the bar.The PR now covers both phases: the read-only usage meter, and a multi-account switcher.
What it does (user-visible)
agybinary is detected onPATH, a detection-gated Antigravity usage segment appears in the status bar with a progress bar and reset window, plus a toggle in the status-bar context menu and settings search. Users withoutagyinstalled see no change.agy, each with its own usage, and lets them switch the active account. Switching also rewrites theagykeyring entry on Windows soagyfollows the switch.Phase 2 — multi-account switcher
userData/antigravity-accounts/, with credentials encrypted at rest via ElectronsafeStorage(onlyid/emailkept in clear). Accounts are auto-captured from the currentagytoken, keyed by the Google email (resolved via the OpenID userinfo endpoint).gemini:antigravitykeyring entry (Windows) so the CLI itself switches.agy's own quota manager and is not returned by the Code Assist API (verified againstagy's request log — it only callsloadCodeAssist+fetchAvailableModels— and against CodexBar, which has the same limitation). Only the 5-hour limit the API exposes is surfaced; the per-family layout is ready to accept a second window if the API ever exposes one.How it works
Antigravity authenticates the same Google account the Gemini CLI uses and serves its quota from Google's Code Assist backend (
cloudcode-pa.googleapis.com) — the same backend Orca's Gemini meter already talks to — under theANTIGRAVITYideType, which returns Antigravity's own per-model quota. The implementation reuses the existing Gemini OAuth and bucket-formatting plumbing.Credential sourcing (read-only). The Google OAuth token is read from, in order:
~/.gemini/oauth_creds.json(written by a Gemini CLI login), thenagyCLI keeps its token — it does not write an on-disk file. On Windows this is the Credential Manager Generic entrygemini:antigravity; macOS Keychain / Linux libsecret use the same identifiers.Most Antigravity users only have (2), so the keyring fallback is what makes the meter light up for a real
agylogin. Neither source is ever written or refreshed on disk — theagy/ Gemini CLIs own their credential lifecycles.Usage.
loadCodeAssist(ANTIGRAVITY ideType) resolves the Code Assist project, thenfetchAvailableModelsreturns per-modelquotaInfo { remainingFraction, resetTime }(falling back toretrieveUserQuota). Values are mapped through the shared Gemini bucket formatters (usedPercent = (1 - remainingFraction) * 100,resetsAt = Date.parse(resetTime)).Files of note
src/main/rate-limits/antigravity-fetcher.ts— the fetcher (Code Assist calls + mapping).src/main/rate-limits/antigravity-keyring.ts— read-only OS credential-store reader (PowerShellCredReadon Windows via the establishedexecFileSync('powershell', …)pattern frombrowser-cookie-import.ts;security/secret-toolbest-effort on macOS/Linux).agyagent-catalog icon (no new asset).appearance-status-bar-search.tswas split into provider/system entry modules to stay under themax-linescap.Testing
pnpm typecheck,pnpm test(new suites for the fetcher and keyring reader, plus extended visibility/type fixtures), andpnpm buildall pass locally.agykeyring entry with no~/.gemini/oauth_creds.jsonpresent.Review summary
CredReadpath is guarded towin32; the file path works on all platforms; macOS/Linux keyring identifiers are best-effort and documented as such. Windows was verified; macOS/Linux keyring reads should be validated by a maintainer with those setups.execFileSync(mirroringbrowser-cookie-import.ts); happy to convert it to async if preferred.formatWindowLabel, and agent icon — no new tokens, colors, or layout.-EncodedCommandwith a constant target name (no interpolation of untrusted input). Tests use synthetic placeholder tokens only.Screenshots
Antigravity meter in the status bar, populated from a live
agylogin sourced from the OS credential store (Windows Credential Manager entrygemini:antigravity, with no~/.gemini/oauth_creds.jsonpresent):NN% 5hwith the Antigravity icon.Security Audit
~/.gemini/oauth_creds.jsonor the OS credential store (gemini:antigravity); background polling never writes, rewrites, or refreshes either store.safeStorage(OS-backed); only the accountidandemailare stored in clear. The store file is written0600.gemini:antigravitykeyring entry (Windows only, guarded towin32) soagyfollows the switch; it is never called from background polling. Both theCredReadandCredWritePowerShell scripts are passed via-EncodedCommandwith constant target names, and the token blob is sent on stdin (never on the command line) — no interpolation of external data.ya29.test-access,a@gmail.com); the full diff was scanned for real access/refresh tokens, project ids, and emails prior to commit — none are present.Notes
_antigravityStatusBarDefaultAddedmigration.agyis single-account and keyring-backed — would require Orca to manage its own account snapshots rather than reuse the CLI-login-capture flow used for Claude/Codex.X handle: (add yours here for a shout-out)