Repository navigation
fix(usage): fetch native Antigravity quotas via Agy - #15948
mikeascendx wants to merge 1 commit into
Conversation
📝 WalkthroughWalkthroughAdded Antigravity usage parsing for four quota identities. Added Merge Risk: 🔵 Low · up to The change can display incorrect Antigravity quota percentages if the CLI returns an invalid fraction outside the expected range. This is a bounded parsing risk that is mergeable with explicit owner awareness and follow-up to reject invalid values; the remaining test suggestion is non-blocking. 🚥 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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx (1)
251-286: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the rendered percentage values.
The test checks bucket count and labels only. It does not verify the rendered
2%,9%,0%, and1%values. Add assertions for these values so incorrect quota percentage rendering fails the test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fb1007f6-0e05-4e7e-8983-9f5f642f1b64
📒 Files selected for processing (15)
src/main/rate-limits/antigravity-usage-fetcher.test.tssrc/main/rate-limits/antigravity-usage-fetcher.tssrc/main/rate-limits/rate-limit-service-test-harness.tssrc/main/rate-limits/service-account-target-selection.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.tssrc/renderer/src/components/status-bar/UsageRosterPanel.test.tsxsrc/renderer/src/components/status-bar/UsageRosterPanel.tsxsrc/renderer/src/components/status-bar/status-bar-provider-visibility.test.tssrc/renderer/src/components/status-bar/status-bar-provider-visibility.tssrc/shared/rate-limit-types.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
| if (typeof value.remaining_fraction !== 'number' || !Number.isFinite(value.remaining_fraction)) { | ||
| return null | ||
| } | ||
| return { | ||
| id: value.id as AgyBucketId, | ||
| remainingFraction: value.remaining_fraction, | ||
| resetTime: parseResetTime(value.reset_time) | ||
| } | ||
| } | ||
|
|
||
| function toRateLimitBucket(bucket: AgyUsageBucket): RateLimitBucket { | ||
| const definition = AGY_BUCKETS[bucket.id] | ||
| const remainingFraction = Math.min(1, Math.max(0, bucket.remainingFraction)) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Reject out-of-range quota fractions.
Line 46 accepts values below 0 and above 1. Line 58 then converts them into valid-looking 100% or 0% usage values. Reject these values in parseAgyBucket so malformed CLI output cannot report fabricated quota data. Add tests for negative and greater-than-one fractions.
Proposed fix
- if (typeof value.remaining_fraction !== 'number' || !Number.isFinite(value.remaining_fraction)) {
+ if (
+ typeof value.remaining_fraction !== 'number' ||
+ !Number.isFinite(value.remaining_fraction) ||
+ value.remaining_fraction < 0 ||
+ value.remaining_fraction > 1
+ ) {
return null
}
@@
- const remainingFraction = Math.min(1, Math.max(0, bucket.remainingFraction))
+ const remainingFraction = bucket.remainingFraction📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (typeof value.remaining_fraction !== 'number' || !Number.isFinite(value.remaining_fraction)) { | |
| return null | |
| } | |
| return { | |
| id: value.id as AgyBucketId, | |
| remainingFraction: value.remaining_fraction, | |
| resetTime: parseResetTime(value.reset_time) | |
| } | |
| } | |
| function toRateLimitBucket(bucket: AgyUsageBucket): RateLimitBucket { | |
| const definition = AGY_BUCKETS[bucket.id] | |
| const remainingFraction = Math.min(1, Math.max(0, bucket.remainingFraction)) | |
| if ( | |
| typeof value.remaining_fraction !== 'number' || | |
| !Number.isFinite(value.remaining_fraction) || | |
| value.remaining_fraction < 0 || | |
| value.remaining_fraction > 1 | |
| ) { | |
| return null | |
| } | |
| return { | |
| id: value.id as AgyBucketId, | |
| remainingFraction: value.remaining_fraction, | |
| resetTime: parseResetTime(value.reset_time) | |
| } | |
| } | |
| function toRateLimitBucket(bucket: AgyUsageBucket): RateLimitBucket { | |
| const definition = AGY_BUCKETS[bucket.id] | |
| const remainingFraction = bucket.remainingFraction |
ELI5
Orca currently labels a copy of Gemini CLI usage as Antigravity usage. This change asks the installed Antigravity CLI for its own quota report instead, so Orca shows the real Gemini and Claude/GPT five-hour and weekly limits without needing Gemini CLI OAuth.
What Changed
Added an Antigravity usage fetcher that runs the public Agy print-mode interface:
Strictly parses the four native Agy quota identities: Gemini 5h/weekly and Claude/GPT 5h/weekly.
Converts each
remaining_fractioninto Orca's used percentage and preserves each independent reset timestamp.Fetches Antigravity independently from Gemini in the rate-limit service.
Removes Gemini OAuth as a visibility prerequisite for the Antigravity usage row.
Keeps the existing Gemini usage integration unchanged for users who still configure it.
Uses the tightest five-hour bucket as the existing compact/session summary while Detailed mode renders all four named buckets.
Why
The current implementation copies the Gemini provider snapshot and changes only its provider ID, so the Antigravity row can show the wrong product's quotas or fail when legacy Gemini OAuth credentials are absent.
Agy 1.1.18 exposes its native usage payload through public non-interactive print mode. This is smaller and less coupled than the older open implementations in #11536, #12095, and #14571: it does not inspect credentials or keychains and does not discover or call a private local LanguageServer through logs, process tables, ports, TLS exceptions, or CSRF tokens.
The live command completed in about 6.5 seconds on Windows, reported zero input/output tokens, and did not change Agy history or create a conversation. Orca bounds it with cancellation, a 25-second process timeout, and a 1 MiB output cap.
Linked Issue
Fixes #9122
Visual Proof
N/A — no layout or interaction component changed. The existing named-bucket renderer is reused; a render regression test verifies all four Antigravity labels and percentages are present.
Testing
Validated on Windows 11 with Antigravity CLI 1.1.18:
agy -p /usage --output-format json --print-timeout 1m: success, two groups/four buckets, zero model tokens, no history/conversation mutationpnpm typecheck: passedpnpm run build:desktop: passedpnpm run build:native: passedpnpm testpreflight is unavailable on this machine because the optionalwindows-native-registrypackage requires a Visual Studio C++ toolchain. A direct aggregate Vitest attempt encountered unrelated existing Windows failures in symlink, watcher, SSH, relay, and daemon suites; the affected Antigravity suites pass.pnpm lintreaches the existing generated-skill-manifest check, which reports stale skill artifacts on currentmain; this PR does not touch skill artifacts.AI Disclosure
OpenAI Codex (GPT-5) assisted with implementation, tests, validation, and review.
Review
agythrough Orca's shared CLI resolver and starts it through the shared no-shell process wrapper, including Windows.cmd/.bathandling and hidden-console behavior.Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
Author X handle: @mikeascendx
The CLI-backed approach requires an Agy version that supports structured print-mode slash-command output. Older versions fail safely as unavailable/parse errors rather than falling back to Gemini data.
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildall pass (see Testing for passed checks and environment/baseline blockers)