Repository navigation
Conversation
…probe - Probe local Antigravity Language Server Connect-RPC endpoint to retrieve quota summary and user plan - Parse 5-hour session quota and weekly quota separately into dual-window presentation - Update Gemini usage fetcher and mirror to preserve weekly quota and clear single-model masking - Wire local probe into RateLimitService full cycle with graceful fallback to Gemini OAuth read
There was a problem hiding this comment.
Important
The probe's transport matches a verified working request, but macOS detection does not: the real IDE bundle is Antigravity IDE.app (with a space), which the executable tokenizer truncates, so the probe returns null on macOS and silently falls back to Gemini. Two smaller findings inline.
Reviewed changes
- Local probe — new
antigravity-local-probe.tslocates the language-server process, verifies listener ownership through the port scanner, queriesRetrieveUserQuotaSummary/GetUserStatus, and maps5h/weeklybuckets intosession/weekly. - Transport — new
antigravity-local-quota-request.tssends the Connect-RPC POST with the CSRF header, a 2.5s timeout, abort propagation, and a 1 MB response cap. - Service wiring — the probe joins the provider
Promise.allSettled;service-full-cycle-application.tsprefers the probe result and falls back toderiveAntigravityRateLimits(gemini). - Gemini mirror —
deriveAntigravityRateLimitsnow clears model buckets, andgemini-usage-fetcher.tsattempts to read session/weekly from the cloud response. - Tests — new probe, transport, and mirror suites, plus probe mocks added to the seven service test files that use
rate-limit-service-test-harness.
ℹ️ Nitpicks
antigravity-usage-mirror.ts:3-6still opens with "Orca never actually queries Antigravity"; the local probe now does, so that rationale no longer holds.status-bar-provider-visibility.ts:12-15and:112-116say Antigravity data is durable only withgeminiCliOAuthEnabled. A local-probeoksnapshot bypasseshasUsageProviderSettingsForProviderviaisProviderConfigured, so the comment now describes only the fallback path.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| const executable = row.command.match(/^(?:"([^"]+)"|([^\s]+))/) | ||
| const executablePath = executable?.[1] ?? executable?.[2] ?? '' | ||
| if ( | ||
| !/[\\/](?:\.?antigravity(?:-cli)?|agy)[\\/]/i.test(executablePath) || | ||
| !/[\\/]language_server[^\\/]*$/i.test(executablePath) || |
There was a problem hiding this comment.
On macOS the Antigravity IDE bundle is named Antigravity IDE.app (with a space) and ps prints the command line unquoted, so the [^\s]+ alternative captures only /Applications/Antigravity. Both path checks then run against that truncated string and fail, rejecting the real macOS process even though this PR claims macOS support and matches language_server_macos_*. Only Windows and Linux paths are covered by the new tests.
Technical details
# macOS executable tokenization drops the real Antigravity IDE path
## Affected sites
- src/main/rate-limits/antigravity-local-probe.ts:151 — `row.command.match(/^(?:"([^"]+)"|([^\s]+))/)` takes the first whitespace-delimited token when the command is unquoted.
- src/main/rate-limits/antigravity-local-probe.ts:154-155 — both the `antigravity` segment test and the `language_server…$` test then run against `/Applications/Antigravity`.
## Evidence
- macOS `ps` emits, unquoted: `88547 /Applications/Antigravity IDE.app/Contents/Resources/app/extensions/antigravity/bin/language_server_macos_arm --csrf_token=... --extension_server_port 56512 ...` (verified in https://github.com/kunchenguid/quota-axi/issues/164).
- The full path would satisfy both checks (segment `/antigravity/`, trailing `language_server_macos_arm`); only the tokenizer loses it.
## Required outcome
- A macOS language-server process whose executable path contains spaces must be recognized.
## Suggested approach
- Derive the executable from the whole command up to the first ` --` argument rather than the first whitespace token, then keep the existing `antigravity`-segment and trailing-`language_server` checks. Add a macOS `Antigravity IDE.app` case to `selectAntigravityLocalServer` tests.| ...new Set( | ||
| ports | ||
| .filter( | ||
| (p) => p.pid === pid && p.port > 0 && (p.host === '127.0.0.1' || p.host === '0.0.0.0') |
There was a problem hiding this comment.
This allowlist keeps only 127.0.0.1 and 0.0.0.0, but the scanner's macOS lsof parser reports a wildcard listener as * and IPv6 as ::/::1 (local-workspace-port-scanner.test.ts:44-49). connectHostForBindHost already normalizes exactly those values, so a wildcard-bound language server on macOS would be silently skipped. Conditional on the server binding wildcard rather than loopback.
Technical details
# macOS wildcard listener host is `*`, not `0.0.0.0`
## Affected sites
- src/main/rate-limits/antigravity-local-probe.ts:195 — host allowlist is `'127.0.0.1' || '0.0.0.0'`.
- src/main/ports/local-workspace-port-address.ts:3 — `connectHostForBindHost` maps `'*'`, `'0.0.0.0'`, `'::'` to a loopback host and exists for this normalization.
## Required outcome
- Ports the scanner attributes to the target pid but reports as a wildcard (`*`) should be probed via `127.0.0.1`, consistent with the rest of the scanner's consumers.| provider: 'gemini', | ||
| session: deriveSessionSummary(buckets), | ||
| weekly: null, | ||
| session: quotaSummary.session ?? deriveSessionSummary(buckets), |
There was a problem hiding this comment.
parseAntigravityQuotaSummary (line 68) only reads a groups array (response.groups or top-level groups), but the cloud retrieveUserQuota response is an array or { buckets: [...] } — see parseQuotaResponse and the Gemini CLI RetrieveUserQuotaResponse type. So quotaSummary is always { session: null, weekly: null } here and lines 74-75 never change behavior; the mirrored weekly stays null. If weekly from the shared quota is intended, the cloud shape needs its own parser; otherwise this call is dead.
Technical details
# Cloud quota response has no `groups`, so the new parse is a no-op
## Affected sites
- src/main/rate-limits/gemini-usage-fetcher.ts:68 — `parseAntigravityQuotaSummary(data)`.
- src/main/rate-limits/gemini-usage-fetcher.ts:74-75 — `quotaSummary.session ?? deriveSessionSummary(buckets)` / `quotaSummary.weekly ?? null`.
- src/main/rate-limits/antigravity-local-probe.ts:87 — reads `response.groups ?? groups`, both absent in the cloud payload.
## Evidence
- `RetrieveUserQuotaResponse { buckets?: BucketInfo[] }` — https://raw.githubusercontent.com/google-gemini/gemini-cli/main/packages/core/src/code_assist/types.ts
- In-repo fixtures for that endpoint only ever use an array or `{ buckets }` (`gemini-usage-fetcher.test-fixtures.ts:40-43`, `gemini-usage-fetcher.test.ts:97-108,151`).
## Open questions for the human
- Is surfacing the cloud weekly window a goal, or was this added speculatively?|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 📝 WalkthroughWalkthroughThe change adds parsing for Antigravity quota and plan responses, plus a local language-server probe that discovers an eligible process and its listening ports. The rate-limit fetch cycle now includes the probe and uses its result when fulfilled, with Gemini-derived limits as a fallback. Gemini quota parsing can provide session and weekly windows, and Antigravity mapping omits model buckets. Priority: ➖ Normal Severity of issue fixed: Medium Merge Risk: 🟡 Moderate · up to A slow local server can delay quota updates for every provider. The fallback can also show a model quota as Antigravity session usage. Bound the probe and correct the fallback before merging. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to The new local quota probe has useful process, port, and response checks, but it can accept data from an endpoint whose ownership may change between discovery and request. Quota results also lack an account-identity check before they enter shared rate-limit state. The observed exposure is local quota information, not a demonstrated remote or privileged attack path. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Warning Review coverage is incomplete: 5 files could not be fully reviewed. Findings from completed review steps are included; see review info for details. 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: Advanced
Run ID: 40a0cf22-2458-4a2e-bddc-8d29f9926a8c
📒 Files selected for processing (18)
src/main/rate-limits/antigravity-local-probe-linux.test.tssrc/main/rate-limits/antigravity-local-probe.test.tssrc/main/rate-limits/antigravity-local-probe.tssrc/main/rate-limits/antigravity-local-quota-request.test.tssrc/main/rate-limits/antigravity-local-quota-request.tssrc/main/rate-limits/antigravity-usage-mirror.test.tssrc/main/rate-limits/antigravity-usage-mirror.tssrc/main/rate-limits/gemini-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-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/service-full-cycle-application.tssrc/main/rate-limits/service/service-full-cycle-preparation.ts
Files not reviewed due to moderation or processing errors (5)
- src/main/rate-limits/antigravity-local-probe.ts
- src/main/rate-limits/antigravity-local-quota-request.ts
- src/main/rate-limits/antigravity-local-probe.test.ts
- src/main/rate-limits/antigravity-local-quota-request.test.ts
- src/main/rate-limits/antigravity-local-probe-linux.test.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
| provider: 'antigravity', | ||
| // Why: Antigravity distinguishes the 5-hour session and weekly windows cleanly, | ||
| // without masking the session window behind model-named buckets. | ||
| buckets: undefined |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
sed -n '40,95p' src/main/rate-limits/gemini-usage-fetcher.ts
sed -n '1,105p' src/main/rate-limits/gemini-bucket-formatting.ts
sed -n '1,95p' src/main/rate-limits/antigravity-usage-mirror.ts
sed -n '70,100p' src/main/rate-limits/service/service-full-cycle-application.tsRepository: stablyai/orca
Length of output: 7469
🏁 Script executed:
printf '%s\n' '--- Gemini parser and fetcher ---'
sed -n '1,65p' src/main/rate-limits/gemini-usage-fetcher.ts
printf '%s\n' '--- Shared rate-limit types ---'
cat -n src/shared/rate-limit-types.ts
printf '%s\n' '--- Session/window consumers and Antigravity labels ---'
rg -n -C 3 "windowMinutes|\.session|session.*5.hour|5.hour.*session|Antigravity" src
printf '%s\n' '--- PR change summary ---'
git diff --stat 646e9a5b02514795af5139961ccca225dfa01b12 7ac0f0cbfd0362787ec1091de461f5c5129e7433 -- src/main/rate-limits/antigravity-usage-mirror.tsRepository: stablyai/orca
Length of output: 45659
🏁 Script executed:
printf '%s\n' '--- Quota summary parser ---'
rg -n -C 12 'parseAntigravityQuotaSummary|session:|weekly:' src/main/rate-limits/antigravity-local-probe.ts
printf '%s\n' '--- Rate-limit UI files ---'
git ls-files 'src/renderer/*' 'src/shared/*' | rg 'rate.?limit|usage'
printf '%s\n' '--- Focused duration and session display references ---'
rg -n -C 3 'windowMinutes|rateLimits\.session|\.session\?.*usedPercent|session.*label|Session' src/renderer --glob '*rate*' --glob '*usage*' --glob '*.tsx' | head -n 450Repository: stablyai/orca
Length of output: 40912
🏁 Script executed:
printf '%s\n' '--- Recognized quota groups and duration construction ---'
sed -n '54,125p' src/main/rate-limits/antigravity-local-probe.ts
printf '%s\n' '--- Duration consumers ---'
rg -n -C 3 'windowMinutes' src/renderer/src src/shared
printf '%s\n' '--- Rate-limit session property consumers ---'
rg -n -C 2 'rateLimits\??\.session|rateLimits\.session|\.session\?\.usedPercent|session\.usedPercent' src/renderer/src/components src/renderer/src/libRepository: stablyai/orca
Length of output: 35972
Do not mirror a model bucket as Antigravity’s session.
When Gemini has only model buckets, deriveSessionSummary creates a 60-minute window. deriveAntigravityRateLimits preserves that window in session while removing buckets. The session contract requires a 5-hour window. Preserve the session only when windowMinutes === 300; otherwise set it to null.
🐛 Suggested fix
...gemini,
provider: 'antigravity',
+ session: gemini.session?.windowMinutes === 300 ? gemini.session : null,
// Why: Antigravity distinguishes the 5-hour session and weekly windows cleanly,
// without masking the session window behind model-named buckets.
buckets: undefined| apiKey: miniMaxApiKey | ||
| }) | ||
| }), | ||
| probeLocalAntigravityLanguageServer({ signal }) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Do not make every provider wait for the local probe.
If an eligible local server accepts a connection but delays a quota or user-status response, Promise.allSettled cannot finish until that request settles. The probe can repeat this wait across ports and protocols. Claude, Codex, and the other completed results therefore remain in fetching instead of updating. Give the whole probe a short deadline, or apply the other provider results independently of it.
Known Limitation / Defect SupplementObserved during manual testing on Windows 11: When the user exits the Antigravity desktop application (\Antigravity.exe), the operating system terminates its child process tree, including the background \language_server.exe\ process.
Unlike Claude Code and Codex (which run as standalone CLI tools without external GUI app dependencies), Antigravity currently requires the desktop app to remain running in the background. This follow-up defect and potential UX improvements (stale quota state caching, graceful exit messaging, headless daemon exploration) have been filed for tracking in #23008. |
Replaces the fork's local language-server probe (superseded, stablyai#22862 closed) with the agy CLI /usage fetcher, so quota shows without the Antigravity app running. Keeps the fork's Cursor mocks and win32 test expectations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

ELI5
Orca can now read Antigravity quota (both 5-hour rolling session and weekly limits) directly from the local Antigravity Language Server on the user's machine, falling back to shared Google Code Assist quota when Antigravity is not running.
What Changed
/exa.language_server_pb.LanguageServerService/RetrieveUserQuotaSummaryandGetUserStatus) to obtain 5-hour session and weekly quota. If the local probe is unavailable, it gracefully mirrors shared Gemini quota as before.language_server_windows_x64.exe,language_server_linux_x64,language_server_macos_*).5h,300) and weekly buckets (weekly,10080), populating bothsessionandweeklyrate-limit windows.RateLimitServiceFullCyclePreparationandRateLimitServiceFullCycleApplicationwith fail-closed fallback toderiveAntigravityRateLimits(gemini).Why
Addresses #16704. Antigravity users frequently work without Gemini CLI OAuth configured, or experience divergent quotas between local Antigravity sessions and shared cloud endpoints. Direct local probing provides real-time, accurate quota metrics without requiring external API tokens or browser logins.
Linked Issue
Fixes #16704
CC @nwparker as discussed in #20469.
Visual Proof
Live evidence captured directly from the status bar and flyout on Windows 11 Pro, demonstrating both single-window and dual-window Antigravity rate limit indicators (5h rolling session and weekly limits) and the
· Proplan badge:Single-window mode
Dual-window mode (5h session + weekly)
Testing
src/main/rate-limits/antigravity-local-probe.test.ts(port detection, process matching, CSRF authentication, error handling)src/main/rate-limits/antigravity-local-probe-linux.test.ts(Linux socket inode resolution)src/main/rate-limits/antigravity-local-quota-request.test.ts(Connect-RPC transport framing and abort signal handling)src/main/rate-limits/antigravity-usage-mirror.test.ts(weekly and 5h session mirror formatting)src/main/rate-limits/service-antigravity-usage.test.ts(full refresh cycle, probe precedence, and fallback)pnpm tc:nodeandpnpm run check:code-quality:changed.AI Disclosure
Antigravity 2.0 was used to refine the local probe implementation, test coverage, and service test harness mocks.
Review
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.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)