Repository navigation
Read Antigravity usage from the agy CLI - #16653
baioccheg-bit wants to merge 4 commits into
Conversation
Antigravity usage was derived from a successful Gemini CLI read, on the assumption that both share Google Code Assist quota. Google stopped serving Gemini Code Assist for individual accounts on 2026-06-18 and pointed those users at Antigravity, so the mirror now has nothing to copy: the meter sits at 0% forever and the error blames a Gemini sign-in that can no longer exist. Ask the Antigravity CLI instead. `agy -p "/usage"` works in print mode and prints one tab-separated row per model family and window, which is the only supported way to read a token the CLI keeps in the OS keyring. The Gemini mirror stays as the fallback so machines without `agy` keep their current behaviour. A CLI that is installed but signed out answers for itself, because pointing that user back at Gemini would send them to a dead product. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds Antigravity CLI rate-limit support for host and WSL runtimes. The implementation resolves executable candidates, runs the CLI with timeout and abort-signal support, parses session and weekly quotas, and returns localized unavailable results with failure metadata. Provider refreshes resolve the local runtime target and use CLI results unless the CLI is unavailable. Vitest coverage validates quota mapping, percentage conversion, model precedence, named buckets, unavailable states, and metadata. Merge Risk: 🟡 Moderate · up to The PR adds Antigravity quota reporting, but SSH workspaces may show quota from the wrong machine, and rejected CLI requests may incorrectly display Gemini data instead. These bounded correctness issues should be addressed or explicitly accepted before merging. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Description checkExplanation The description is complete and follows the repository template. It explains the problem, implementation, linked issue, testing, platform coverage, limitations, and checklist status. The missing full test and build runs are explicitly explained. Full details: Linked Issues checkExplanation The implementation addresses issue Full details: Out of Scope Changes checkExplanation The changes remain within scope for issue
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.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: e31a03ca-0868-4b68-87e4-16f3864b0319
📒 Files selected for processing (3)
src/main/rate-limits/antigravity-cli-usage.test.tssrc/main/rate-limits/antigravity-cli-usage.tssrc/main/rate-limits/service.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
Review feedback on the first commit. Antigravity plans bill two independent pools with their own reset times, so collapsing them to the Gemini numbers threw away half the data stablyai#9122 asks for. Both pools now survive as named buckets; the headline session and weekly windows still come from the Gemini pool. Binary resolution now checks X_OK instead of mere existence, so a leftover file from an older install cannot shadow a working `agy` found later in the list, and every `where`/`which` hit is considered rather than only the first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0a49b6e3-ba9e-4b3f-ba48-9da8167fa377
📒 Files selected for processing (2)
src/main/rate-limits/antigravity-cli-usage.test.tssrc/main/rate-limits/antigravity-cli-usage.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.
|
Thanks — going through the three findings. 1. Fallback executable check — fixed in 2. Run I had argued parity with the Where I am stuck is the plumbing, and I would rather ask than guess:
That is a design decision about a shared service rather than a detail of this fix, so I did not want to invent it unilaterally. Two options, happy with either:
Worth noting for scope: whichever way this goes, the segment is currently broken for every individual-tier user since Google's 2026-06-18 shutdown, and this PR fixes that on local sessions regardless. 3. Localize the availability errors — I do not think this applies here, but tell me if I am reading the convention wrong. These strings land in Across If main-process provider errors are meant to be localized going forward, I am glad to do it — but that reads like a directory-wide change rather than something to start in this PR, and I did not want to half-apply a convention. |
Three corrections after reading AGENTS.md properly. The fetcher spawned `node:child_process` directly, which the repo forbids and a ratchet test fails on. It now goes through `runProcess`, and resolves system binaries with `windowsSystem32Binary` rather than trusting the child's PATH. `agy` signs in per runtime and keeps the token in that runtime's keyring, so a WSL target must be asked inside WSL — the host copy answers for a different account. The service now takes a runtime target resolver, wired from settings the way Kimi's home resolver is (stablyai#12370). WSL argv is built with buildWslExecArgs and fenced with buildWslCapturedLoginShellCommand, because the login shell prints the distro banner to the stdout this parses. User-facing availability strings go through translateMain with intent-named ids. SSH remains unhandled: RateLimitService has no execution-host vocabulary at all, so honouring ssh-execution-boundary.md there is a service-wide change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Reworked in Localization — you were right, I was wrong. I argued the convention from raw Two things I broke that review had not reached yet:
Execution host — partly addressed. SSH is still not honoured, and I did not want to fake it. Verification: 16 tests pass (my 7, the 5 pre-existing mirror tests, and Unchanged from before: I still cannot produce a running-app capture, because |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 08399914-dc25-4f5c-b0a7-391e63d4d356
📒 Files selected for processing (3)
src/main/index.tssrc/main/rate-limits/antigravity-cli-usage.tssrc/main/rate-limits/service.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.
…stop the fetch leaking into tests Two problems, both found by running the whole rate-limits suite rather than only the files this change adds. A runtime switch while `agy` is running left the old runtime's answer on screen until the next full refresh. The target is now captured before the fetch and compared after it, matching how the Codex and Claude targets are guarded; a stale answer keeps the previous reading instead. Adding a seventh provider to the parallel batch also meant every service test that exercises refresh() ran the real fetcher, spawning `where`/`agy` on the test machine. That broke 11 tests and took the suite from 8s to 83s, and it made results depend on whether the machine happened to have Antigravity installed. The fetcher is now mocked alongside the other providers, defaulting to the no-CLI case so the Gemini mirror stays under test. Suite is back to the base commit's 9 pre-existing failures in 7.6s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Discard results after a runtime switch — fixed. The target is captured before the fetch and compared after it, following the The bigger one, which review had not reached: my fetcher was leaking into every service test. Adding a seventh provider to the
Mocked alongside the other providers, with Before/after on
The 9 remaining failures are identical by name to the base commit's — New coverage in
Still open: SSH. Unchanged from my last comment — |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1bcbe681-04a8-4d42-abc2-737521cf6121
📒 Files selected for processing (9)
src/main/rate-limits/rate-limit-service-test-harness.tssrc/main/rate-limits/service-account-target-selection.test.tssrc/main/rate-limits/service-antigravity-usage.test.tssrc/main/rate-limits/service-inactive-account-previews.test.tssrc/main/rate-limits/service-live-claude-usage.test.tssrc/main/rate-limits/service-minimax-usage.test.tssrc/main/rate-limits/service-refresh-orchestration.test.tssrc/main/rate-limits/service-window-activation.test.tssrc/main/rate-limits/service.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.
| fetchAntigravityRateLimits({ | ||
| target: antigravityTarget, | ||
| signal | ||
| }) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Run agy on the SSH execution host. LocalAccountRuntimeTarget cannot represent SSH, so this call can show local quota for an SSH workspace; add execution-host plumbing or publish an unverifiable result. As per coding guidelines: “the execution host owns everything that touches execution.”
Source: Coding guidelines
| const antigravityCli = | ||
| !antigravityTargetStale && antigravityResult.status === 'fulfilled' | ||
| ? antigravityResult.value | ||
| : null | ||
| const antigravity = antigravityTargetStale | ||
| ? (previousState.antigravity ?? deriveAntigravityRateLimits(gemini)) | ||
| : antigravityCli && antigravityCli.usageMetadata?.failureKind !== 'cli-unavailable' | ||
| ? antigravityCli | ||
| : deriveAntigravityRateLimits(gemini) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Do not mirror a rejected CLI call. A rejected fetchAntigravityRateLimits produces null, so Line 1814 uses Gemini data even though only cli-unavailable should use that fallback; map rejection to an Antigravity error result and add a regression test.
ELI5
Orca's Antigravity meter was showing Gemini's numbers, because it assumed both share one quota. Google turned Gemini Code Assist off for individuals, so there is nothing left to copy and the meter reads
0%forever. This asks the Antigravity CLI for its own numbers instead.What Changed
fetchAntigravityRateLimitsrunsagy -p "/usage"and parses its tab-separated rows.Promise.allSettledbatch inservice.ts, so it costs no extra wall-clock.deriveAntigravityRateLimitsstays as the fallback, so machines withoutagykeep today's behaviour byte for byte.No renderer changes: the Antigravity status-bar toggle and label already exist and simply never received real data.
Why
deriveAntigravityRateLimitsderives the meter from a successful Gemini CLI read. Google stopped serving Gemini Code Assist for individual accounts on 2026-06-18 and directed those users to Antigravity, so that read now always fails:The existing code comment already names the constraint —
agykeeps its token in the OS keyring, so no file the Gemini fetcher reads can ever describe it. #9122 reaches the same conclusion and suggests exactly this approach ("or by shelling out toagy— CodexBar takes this approach and reliably reports both Antigravity pools"), including the detail that the two pools have independent resets.agy -p "/usage"on Windows, verbatim:Five Hour→session(300 min),Weekly→weekly(10080 min). The CLI reports what is left, so it is converted to used percentage like every other provider.Linked Issue
Fixes #9122
Visual Proof
N/A— I could not produce a before/after of the status-bar segment.pnpm installresolves, but thepostinstallnative rebuild ofnode-ptyneeds a Visual Studio C++ toolchain I do not have, so I cannot run a local Electron build. The change only populatesProviderRateLimitsfor an existing segment and touches no renderer code. Happy to add captures if a maintainer can point me at a build that skips the native step.Testing
vitest run src/main/rate-limits/antigravity-cli-usage.test.ts src/main/rate-limits/antigravity-usage-mirror.test.ts→ 12 passed. The pre-existing mirror tests are unchanged and still pass.tsc --noEmit -p config/tsconfig.node.json→ clean.oxfmt+oxlinton the touched files → clean.agy -p "/usage"output from Windows 11 withagy1.1.21.Platforms actually exercised: Windows 11 (CLI output and binary resolution). macOS/Linux paths are code-reviewed only, not run.
Not checking the manual box: the parser and CLI invocation are verified on Windows, but I have not seen the segment render in a running Orca for the build reason above.
AI Disclosure
Written with Claude Opus 5 via Claude Code. Every command, test run and the
agyoutput quoted above were executed on a real machine; nothing here is model recollection.Review
Automated review flagged two things on the first commit; both are addressed in
0ab6a06:X_OKrather than mere existence, and considers everywhere/whichhit instead of only the first.fetchGeminiRateLimits, which this replaces, takes no runtime target and reads local credentials only (zero occurrences ofwsl/runtimeTarget/executionHostin that file), so the mirror was always local-scoped too. Making both providers runtime-aware is a genuine gap; it needs a resolver wired throughRateLimitServicelike Codex/Kimi have, which is a larger change than this fix and better scoped separately. I documented the boundary in a docstring rather than leaving it implicit. Glad to take it on as a follow-up if you want it.Agent skill upstream boundary
Notes
execFile, neverexec, so no shell interpolation, andwindowsHidestays effective.where.exe/which; fallbacks are the documented install prefixes per platform. Windows is the only one I ran.agyinstalled, behaviour is identical to today via the retained mirror.execFileinside the existing parallel batch, with the CLI's own 30s print timeout and the caller'sAbortSignal.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)Last box unchecked deliberately: targeted
vitest,typecheck:node,oxfmtandoxlintpass locally, but the fullpnpm testandpnpm buildneed the native rebuild I cannot complete on this machine. Leaving that to CI.🤖 Generated with Claude Code