Repository navigation
Conversation
|
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:
📝 WalkthroughWalkthroughThe PR adds independent Antigravity quota fetching from a local language server. It parses startup logs, maps session and weekly quota buckets, and probes loopback HTTP or HTTPS endpoints with response-size and timeout limits. The rate-limit service now fetches Antigravity as a seventh provider result instead of mirroring Gemini data. The renderer uses Priority: ➖ Normal Severity of issue fixed: Medium 🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
Full details: Description checkExplanation The description includes the required sections and linked issue, but it claims OAuth fallback, credential discovery, CSRF handling, and focus-aware polling that are not supported by the current changeset. It also does not provide the required visual proof format for a status-bar behavior change. Resolution Update the description and testing claims to match the current implementation, or add the missing OAuth, discovery, CSRF, and live-poll functionality. Replace the Visual Proof section with the required before/after attachments, or write exactly Full details: Linked Issues checkExplanation Issue Resolution Add the agy OAuth credential fallback after loopback discovery fails. Fetch and map Antigravity quota through that fallback without Gemini CLI credentials. Add automated tests for credential discovery, fallback quota fetching, and operation without a local Gemini CLI installation.
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: 8
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: 90a60cba-b5b9-4a12-9516-c1a3ed18bd27
📥 Commits
Reviewing files that changed from the base of the PR and between 615b137 and ea32520930c46c06ddb35b9678c9795b0caeb2d0.
📒 Files selected for processing (30)
src/main/rate-limits/antigravity-language-server-probe.tssrc/main/rate-limits/antigravity-language-server-process.test.tssrc/main/rate-limits/antigravity-language-server-process.tssrc/main/rate-limits/antigravity-loopback-request.tssrc/main/rate-limits/antigravity-oauth-credentials.tssrc/main/rate-limits/antigravity-oauth-quota.tssrc/main/rate-limits/antigravity-quota-summary.test.tssrc/main/rate-limits/antigravity-quota-summary.tssrc/main/rate-limits/antigravity-usage-fetcher.test.tssrc/main/rate-limits/antigravity-usage-fetcher.tssrc/main/rate-limits/antigravity-usage-mirror.test.tssrc/main/rate-limits/antigravity-usage-mirror.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.tssrc/main/rate-limits/service/service-polling.tssrc/main/rate-limits/service/service-state.tssrc/main/rate-limits/service/service-types.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/usage-provider-settings-target.test.tssrc/renderer/src/components/status-bar/usage-provider-settings-target.tssrc/renderer/src/components/status-bar/use-status-bar-controller.ts
💤 Files with no reviewable changes (3)
- src/renderer/src/components/status-bar/use-status-bar-controller.ts
- src/main/rate-limits/antigravity-usage-mirror.test.ts
- src/main/rate-limits/antigravity-usage-mirror.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
There was a problem hiding this comment.
Important
The loopback probe and OAuth fallback are wired up correctly, but two background-path defects should be fixed before merge: a rejected live poll becomes an unhandled rejection on every 45s tick when a probe binary is missing, and Linux keyring lookups throw before the documented file fallback runs. Several parser and request gaps against the reference Antigravity clients can also silently drop quota buckets or mis-remedy a 403.
Reviewed changes
- Independent Antigravity fetch — deletes
antigravity-usage-mirror.ts/deriveAntigravityRateLimitsand adds a seventh fetcher: a loopback language-server probe (app →agy→ IDE) with a keyring/file OAuth fallback. - Quota mapping —
antigravity-quota-summary.tsmaps grouped and flatRetrieveUserQuotaSummarybuckets onto the session + weekly meters, tightest remaining wins. - Service wiring — a 45s focused-window live poll that writes only the
antigravityslot, plus the full-cycle fetch, state fields, and cycle result slot. - Status-bar visibility — Antigravity no longer requires Gemini CLI OAuth; the checked item + detected CLI is the durable signal, and clicking no longer jumps to Gemini Accounts.
- Tests — parser, process-table, loopback, fetcher, service, and visibility suites added/updated.
ℹ️ The setup CTA is now suppressed by a default-on item plus agy on PATH
antigravity is in DEFAULT_STATUS_BAR_ITEMS, and antigravityUsageConfigured is just "item checked AND agent on PATH". Combined with the new hasUsageProviderSettings term, any user who happens to have agy installed now reports configured usage, which hides the "set up usage tracking" empty-state CTA and renders a -- Antigravity chip even when no language server is running and Gemini OAuth is off. That reads as intended from the tests and the PR description; flagging it only because it is a user-visible change for people who configured nothing.
Technical details
# Default-on Antigravity item is now a durable "configured" signal
## Affected sites
- `src/shared/status-bar-defaults.ts:7` — `antigravity` ships checked by default.
- `src/renderer/src/components/status-bar/use-status-bar-controller.ts:106-108` — `antigravityUsageConfigured = statusBarItems.includes('antigravity') && isStatusBarItemAvailable(...)`.
- `src/renderer/src/components/status-bar/status-bar-provider-visibility.ts:76,102-104` — both `hasUsageProviderSettings` and `hasUsageProviderSettingsForProvider('antigravity')` now key on that flag alone.
- `src/renderer/src/components/status-bar/StatusBarProviderSegment.tsx:210-216` — `unavailable` renders `Icon --`.
## Required outcome
Confirm the trade-off is intended: a machine with `agy` on PATH and nothing else configured will now show an Antigravity `--` chip permanently and lose the one-time setup CTA. If not intended, gate the durable signal on something that implies a usable Antigravity session (e.g. a recent successful probe) rather than bare PATH detection.
## Open questions for the human
- Should a never-configured user with `agy` installed still be taught the usage-tracking setup?ℹ️ Nitpicks
antigravity-language-server-probe.ts:48— pass-wwtops; procps honors an inheritedCOLUMNSeven when stdout is a pipe, so a long--csrf_tokencommand line can be clipped and the candidate silently dropped (kind !== 'cli' && !csrfToken).antigravity-quota-summary.ts:160-178—tightestWindow('session')falls back to all buckets when none classify as session, so a weekly-only response renders the weekly value in the 5h slot withwindowMinutes: 10080.antigravity-quota-summary.ts:36-38vs:114—remainingFractionOftoleratesusedup to1.5 * limit, butbucketFromUnknownrejectsremaining < 0, so an over-quota bucket is dropped entirely and theMath.min(100, …)clamp at:128is unreachable. Over-quota users get "unavailable" instead of 100%.antigravity-oauth-quota.ts:94-102— a non-2xx, non-401/403 response (e.g. 500) is reported withfailureKind: 'parse';server/networkwould be more truthful and drives the stale-policy threshold.antigravity-language-server-probe.ts:99— every language-server result is labelledsource: 'cli', including anapp/idecandidate.antigravity-quota-summary.ts:117-121— bucket id falls back toraw.name/groupName; the reference parser also acceptsraw.id.antigravity-quota-summary.ts:79-107— the response payload aliassummary(alongsideresponse) and theremainingproto-oneof spelling{ case: 'remainingFraction', value }are not consumed; both appear in the reference client's decoder, so those buckets drop silently.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Live-poll containment — a rejected 45s Antigravity probe is now caught and applied as a contained
errorsnapshot instead of escaping thesetIntervalas an unhandled rejection. - Generation guard — a monotonic
antigravityLiveGeneration(bumped bystopAntigravityLiveTimerand every full-cycle apply) invalidates an in-flight probe, so a stale reading cannot overwrite a newer snapshot after blur, stop, or a full cycle. - Windows port discovery —
netstatdrops-p TCPso IPv6 listeners appear while the parser keeps filtering toLISTENING; process-command parsing now handles quoted Windows paths containing spaces. - Loopback probe — tries
httpas well ashttpson every discovered port (not just--extension_server_port) and guards the response stream against destroy/abort with a composed timeout signal. - OAuth fallback — 403 is split from 401 into a distinct
ANTIGRAVITY_QUOTA_FORBIDDENresult, a missingsecret-tool/securityno longer aborts the file fallback, an expired credential no longer masks a valid file token, and the caller signal composes with the API timeout. - Quota mapping —
disabledbuckets are dropped, over-quota remaining clamps to 100% used instead of dropping the bucket, and the session slot no longer falls back to a classified weekly bucket. - Tests — new loopback-request, credentials, and OAuth-quota suites plus service generation/rejection coverage; the Antigravity suites pass locally (37 tests).
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
…erver Stop copying Gemini usage onto Antigravity. Refresh now discovers the current Agy LanguageServer from its CLI log, POSTs RetrieveUserQuotaSummary on loopback, and maps native session/weekly buckets into ProviderRateLimits. If no local LanguageServer is running, Antigravity usage is unavailable. Gemini results and failures never populate Antigravity. The status bar shows a checked Antigravity item without Gemini OAuth and no longer routes clicks to Gemini Accounts. Fixes stablyai#9122
11089d4 to
47aaf44
Compare
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: 04cb6ab1-1b31-4a8d-9fef-7556a2c931ae
📥 Commits
Reviewing files that changed from the base of the PR and between 11089d4376f61bfaf1be52a23025d658a621f390 and 47aaf44.
📒 Files selected for processing (6)
src/main/rate-limits/antigravity-usage-fetcher.test.tssrc/main/rate-limits/antigravity-usage-fetcher.tssrc/main/rate-limits/service-antigravity-usage.test.tssrc/main/rate-limits/service/service-full-cycle-preparation.tssrc/renderer/src/components/status-bar/status-bar-provider-visibility.test.tssrc/renderer/src/components/status-bar/usage-provider-settings-target.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
| const request = transport.request(requestOptions, (response) => { | ||
| const chunks: Buffer[] = [] | ||
| response.on('data', (chunk) => { | ||
| chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
sed -n '202,299p' src/main/rate-limits/antigravity-usage-fetcher.ts
sed -n '130,225p' src/main/rate-limits/service/service-full-cycle-preparation.ts
rg -n 'prepareFetchAllCycle|runFetchAllCycle|postLoopbackQuota|setTimeout|timeout' src/main/rate-limitsRepository: stablyai/orca
Length of output: 19656
🏁 Script executed:
sed -n '1,120p' src/main/rate-limits/antigravity-usage-fetcher.ts
sed -n '1,120p' src/main/rate-limits/service/service-full-cycle-preparation.ts
sed -n '1,240p' src/main/rate-limits/service/service-fetch-queue.ts
sed -n '1,80p' src/main/rate-limits/service/service-full-cycle-application.ts
rg -n 'REQUEST_TIMEOUT_MS|fetchAntigravityRateLimits|Promise.allSettled|prepareFetchAllCycle|runFetchAllCycle|cycle' src/main/rate-limits/service src/main/rate-limits/antigravity-usage-fetcher.tsRepository: stablyai/orca
Length of output: 24400
Bound the loopback response body and total request duration.
postLoopbackQuota stores every response chunk in chunks until end. The node:http and node:https request timeout detects inactivity, not total duration. A response that continuously sends data can keep this promise pending while memory grows without an application-level limit. fetchAntigravityRateLimits() is one of seven promises in the service's Promise.allSettled cycle, so the cycle can remain pending.
Reject responses after a fixed byte limit and enforce an absolute deadline that does not reset when data arrives.
| return mapped | ||
| } | ||
| } | ||
| return unavailable(now()) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🔎 Supported by static analysis
🏁 Script executed:
sed -n '1,330p' src/main/rate-limits/antigravity-usage-fetcher.ts
rg -n -i 'antigravity|agy|oauth|credential|refresh.?token|access.?token' src/main/rate-limits src/main | head -n 240Repository: stablyai/orca
Length of output: 37044
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- candidate files ---'
git ls-files | rg -i 'antigravity|agy|gemini.*(auth|credential)|credential.*gemini|oauth'
printf '%s\n' '--- exact symbols and contract terms ---'
rg -n -i 'fetchAntigravityRateLimits|AntigravityUsageFetchDeps|no-language-server|language.?server|agy (stopped|running)|antigravity.*(oauth|credential|fallback)|oauth.*antigravity|credential.*fallback' --glob '!node_modules' --glob '!dist' .
printf '%s\n' '--- recent file structure ---'
ast-grep outline src/main/rate-limits/antigravity-usage-fetcher.tsRepository: stablyai/orca
Length of output: 50371
🏁 Script executed:
#!/bin/bash
set -eu
for f in \
src/main/rate-limits/antigravity-usage-fetcher.test.ts \
src/main/rate-limits/gemini-cli-oauth-extractor.ts \
src/main/rate-limits/gemini-oauth-sources.ts \
docs/reference/antigravity-readiness-evidence.md
do
printf '\n--- %s ---\n' "$f"
wc -l "$f"
done
printf '\n--- Antigravity test ---\n'
cat -n src/main/rate-limits/antigravity-usage-fetcher.test.ts
printf '\n--- Gemini OAuth extractor ---\n'
cat -n src/main/rate-limits/gemini-cli-oauth-extractor.ts
printf '\n--- Gemini OAuth sources ---\n'
cat -n src/main/rate-limits/gemini-oauth-sources.tsRepository: stablyai/orca
Length of output: 22541
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- credential consumers in rate-limit code ---'
rg -n 'readGeminiCredentials|refreshAccessToken|loadProjectId|tryRefreshTokenFromBundle|extractOAuthClientCredentials|oauth_creds|cloudaicompanionProject|GEMINI_CLI' src/main/rate-limits --glob '*.ts'
printf '%s\n' '--- Antigravity references outside bundled guides ---'
rg -n -i 'antigravity|agy' src/main/rate-limits src/main/ai-vault docs/reference/antigravity-readiness-evidence.md --glob '*.ts' --glob '*.md'
printf '%s\n' '--- worktree and recent commit shape ---'
git status --short
git diff --stat
git diff --name-only
git show --stat --oneline --no-renames HEADRepository: stablyai/orca
Length of output: 42098
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- deleted mirror implementation at parent ---'
git show HEAD^:src/main/rate-limits/antigravity-usage-mirror.ts | cat -n
printf '%s\n' '--- deleted mirror tests at parent ---'
git show HEAD^:src/main/rate-limits/antigravity-usage-mirror.test.ts | cat -n
printf '%s\n' '--- Gemini fetcher imports and control flow ---'
cat -n src/main/rate-limits/gemini-usage-fetcher.ts | sed -n '1,280p'Repository: stablyai/orca
Length of output: 14411
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- commit diff for Antigravity service wiring ---'
git show --format=fuller --no-ext-diff -- \
src/main/rate-limits/service/service-full-cycle-preparation.ts \
src/main/rate-limits/service/service-full-cycle-application.ts \
src/main/rate-limits/service-antigravity-usage.test.ts \
src/main/rate-limits/antigravity-usage-fetcher.ts \
src/main/rate-limits/antigravity-usage-fetcher.test.ts | sed -n '1,520p'
printf '%s\n' '--- current service preparation call site ---'
cat -n src/main/rate-limits/service/service-full-cycle-preparation.ts | sed -n '100,235p'
printf '%s\n' '--- current service application Antigravity handling ---'
cat -n src/main/rate-limits/service/service-full-cycle-application.ts | sed -n '20,110p'Repository: stablyai/orca
Length of output: 25429
Use the independent Antigravity OAuth fallback on both unavailable paths.
fetchAntigravityRateLimits returns unavailable when endpoint discovery returns null. probeQuota returns unavailable after both loopback probes fail. Neither path invokes an Antigravity OAuth credential helper, so valid credentials cannot provide quota when agy is stopped or probing fails.
Keep the LanguageServer path first. Run the independent OAuth fallback before either unavailable return. Extend the no-language-server test and add a probe-failure test to cover usable credentials.
There was a problem hiding this comment.
ℹ️ No critical issues — a few verification and robustness suggestions inline.
Reviewed changes
This run re-reviews 47aaf44, which replaced the branch's earlier multi-file implementation with a single new fetcher, so the delta is the whole current implementation.
- Rewrote discovery around a log-file probe —
antigravity-usage-fetcher.tsnow finds the language server by reading~/.gemini/antigravity-cli/log/cli-*.loginstead of walking the process table withps/lsof/netstat. - Dropped the OAuth fallback — the keyring /
oauth_creds.jsonpath and itscloudcode-parequest are gone; the local language server is the only source. - Moved Antigravity into the full refresh cycle — the 45s focused-window live poll is removed, so Antigravity is now a plain member of the cycle's
Promise.allSettled. - Simplified the renderer gate — visibility keys on the checked status-bar item alone, and clicking no longer targets Gemini Accounts.
ℹ️ The PR description describes a materially larger change than the branch contains
The description's "What Changed", "Testing", and "Review" sections still describe the deleted implementation: the OAuth keyring fallback, the X-Codeium-Csrf-Token header, the 1MB response cap, app/IDE process discovery, the 45s focused live poll, and automated tests for --print//usage and localOnly. None of that code is on the branch, and readers of the linked issue will use the description to judge cross-platform and security coverage, so it is worth rewriting to match 47aaf44.
Technical details
# Stale PR description after the rewrite
## Affected sites
- PR body sections: "What Changed", "Testing", "Review".
- Current code: `src/main/rate-limits/antigravity-usage-fetcher.ts` is the only source; there is no OAuth module, no CSRF header, no response cap, and no live poll in the diff.
## Required outcome
The description should describe the branch as shipped: log-based discovery of `~/.gemini/antigravity-cli/log/cli-*.log`, a `forceRefresh` POST to the loopback language server, and no OAuth path. If the removed capabilities are intended to return in a follow-up, say so explicitly rather than leaving them stated as present.DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| resolve(null) | ||
| }) | ||
| request.on('error', () => resolve(null)) | ||
| request.end('{"forceRefresh":true}') |
There was a problem hiding this comment.
Question on the request contract: published clients that hit this RPC send {"metadata":{"ideName":"antigravity",...}} or an empty body, and none documents a forceRefresh field. If the server's Connect/JSON codec rejects unknown fields, every call fails and the provider is permanently unavailable. Worth confirming against the live server that this exact body returns a response.groups payload (and that the field is load-bearing rather than an accidental omission of metadata).
Technical details
# Unverified request body
## Affected sites
- `src/main/rate-limits/antigravity-usage-fetcher.ts:259` — `request.end('{"forceRefresh":true}')`.
## Required outcome
A recorded request/response from a live language server proving this body is accepted and returns populated `groups`, or a body aligned with the reference clients.| const LIVE_LOG = [ | ||
| 'Starting language server process with pid 4242', | ||
| 'listening on random port at 4312 for HTTP', | ||
| 'listening on random port at 4313 for HTTPS (gRPC)' | ||
| ].join('\n') |
There was a problem hiding this comment.
LIVE_LOG is written to match the parser's own regexes, so this test passes whichever banner the real agy prints. docs/reference/antigravity-readiness-evidence.md documents five Antigravity detectors that each tuned to a hand-typed fixture and then failed on captured output. A real ~/.gemini/antigravity-cli/log/cli-*.log head (scrubbed) would let this test fail if the path, filename shape, or banner text differ.
Technical details
# Log discovery has no captured evidence
## Affected sites
- `src/main/rate-limits/antigravity-usage-fetcher.test.ts:50-54` — `LIVE_LOG` mirrors the parser's assumptions.
- `src/main/rate-limits/antigravity-usage-fetcher.ts:167-200` — `discoverCurrentEndpoint` reads `~/.gemini/antigravity-cli/log` and files named `cli-*.log`; neither the `log/` directory nor that filename shape appears anywhere else in the repo (only `.gemini/antigravity-cli/brain` and `history.jsonl` do).
## Required outcome
One committed fixture captured from a live `agy` — the log head carrying the pid and port lines — replayed through `parseAntigravityLanguageServerLog`, so the regex is exercised against real output rather than itself. A captured `RetrieveUserQuotaSummary` response would pin the bucket schema at the same time.There was a problem hiding this comment.
ℹ️ No new issues — this delta hardens the loopback probe and fixes test isolation in the shared harness.
Reviewed changes
This run re-reviews e31d6dc, the probe-hardening commit on top of 47aaf44.
- Extracted the loopback transport into
src/main/rate-limits/antigravity-loopback-quota.ts, which validates the URL (scheme and127.0.0.1host), accepts the self-signed cert only on loopback, and settles every path through one guardedfinish(). - Bounded the probe with a wall-clock deadline (replacing the socket
timeoutoption) and a 1MB response cap, tearing the request down on overflow, timeout,error, andaborted. - Split the failure taxonomy so a discovered-but-unresponsive LanguageServer returns
errorwithANTIGRAVITY_USAGE_PROBE_FAILEDandfailureKind: 'network', distinct from the no-endpointunavailable"Start agy" case. - Fixed test isolation by stubbing
fetchAntigravityRateLimitsin both shared harness helpers andvi.mock-ing the module in the six sibling service suites that use them. - Added tests for the response cap and the injected wall-clock deadline; the full rate-limits suite is green (45 files / 479 tests).
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
|
Reviewed current head P2: 12 newer exited sessions hide an older active session.
ELI5: the usage meter forgets a session that is still open after enough newer sessions leave log files behind. The file/response bounds are useful and should stay; discovering active server ownership needs a strategy that does not equate “outside the newest 12 logs” with “not running.” Simply making the scan unbounded is not a good fix. The reproduction compiles both modules unchanged, substitutes only The PR description also needs to match this head. It currently claims app/CLI/IDE process discovery, keyring/file OAuth fallback, CSRF headers, and a 45-second focus-aware live poll. The current fetcher instead reads CLI logs, probes their loopback ports, and returns unavailable when discovery fails. Its request sends content-type/protocol headers only, and the diff contains no described live-poll integration. Please rewrite the description and verification claims around the actual implementation so reviewers can assess it accurately. Bounded inspection of the 12 latest installed-agy logs here confirmed the PID and port banners fit inside the first 8 KiB, so I did not reproduce a log-prefix parsing problem. No account credentials were inspected. I’m not adopting this candidate over the currently verified native |
Co-authored-by: Filipe Moreira <lippdev@users.noreply.github.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟠 Major · Verify the process identity before selecting the endpoint. · antigravity-usage-fetcher.ts:201-202
src/main/rate-limits/antigravity-usage-fetcher.ts:201-202
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftVerify the process identity before selecting the endpoint.
The unlimited historical scan can select a stale log whose PID was reused by an unrelated active process. Discovery then returns its obsolete port and
probeQuotastops after that request fails. A real older LanguageServer is not reached, and the result becomesANTIGRAVITY_USAGE_PROBE_FAILED.Verify the process command and start time, or probe ordered endpoint candidates until one returns a mapped quota response. Add a PID-reuse test that places the real live session after the false-positive log.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Advanced
Run ID: 81a34f95-74b8-47fb-b3fa-3c063eb56816
📒 Files selected for processing (2)
src/main/rate-limits/antigravity-usage-fetcher.test.tssrc/main/rate-limits/antigravity-usage-fetcher.ts
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.
There was a problem hiding this comment.
ℹ️ No critical issues — one minor suggestion inline.
Reviewed changes
This run re-reviews 641a6b92, a discoverability follow-up to e31d6dc.
- Removed the 12-log cap in
discoverCurrentEndpoint— discovery now scanscli-*.lognewest-first with no fixed bound and returns the first entry whose pid is alive, so an older live LanguageServer behind newer exited logs is still found. - Injected a
homedirdependency for tests and added a regression test (12 newer exited logs plus one older live session) that fails when the cap is restored.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
| .filter((name) => name.startsWith('cli-') && name.endsWith('.log')) | ||
| .sort() | ||
| .toReversed() | ||
| for (const name of names) { |
There was a problem hiding this comment.
This scan is now unbounded and runs synchronously on the main process — it previously stopped after 12 logs. When agy is not running, every refresh reads all cli-*.log files in the directory (up to the 5-minute activation debounce), so a log directory that accumulates sessions adds main-thread I/O to each poll. Consider async reads, or a bounded newest-first candidate list that is probed until one returns a mapped summary.
Technical details
# Unbounded synchronous log scan
## Affected sites
- `src/main/rate-limits/antigravity-usage-fetcher.ts:192` — `discoverCurrentEndpoint` iterates every `cli-*.log`, reading 8KB from each with `openSync`/`readSync`/`closeSync`.
- `src/main/rate-limits/service/service-full-cycle-preparation.ts:185` — discovery runs on the main process inside every full refresh cycle.
## Required outcome
Discovery should not block the main process for an unbounded number of files. Either make the reads asynchronous (`node:fs/promises`) or return a bounded newest-first candidate list and probe each until one yields a mapped quota summary; the latter also avoids a stale log shadowing the live server when its pid has been reused.
## Open questions for the human
- How many `cli-*.log` files does `agy` retain, and does it prune them? If the directory stays small, this is informational only.|
Review update: this head is superseded by the current native agy quota stack #21654 → #21678, which uses the supported This PR’s loopback language-server protocol is not independently live-verified on the current installed agy profile, and its status is Scoped verdict: do not merge this head unless the language-server path is deliberately retained as a separate, freshly verified fallback. |
|
Thanks for the work on this, and for your patience. Orca now reads Antigravity quota from the agy CLI (#24073), has native Antigravity Accounts (#24691), and short pool labels in the status bar (#31007), which covers what this PR set out to do. Closing as superseded; your effort here helped shape the problem, so thank you. |

ELI5
The Antigravity meter on the status bar used to copy Gemini CLI quota. That showed the wrong pools and broke for anyone who uses
agywithout Gemini CLI installed. This PR reads Antigravity's own quota instead: first from the local language server on127.0.0.1, then from agy's OAuth token if the language server is not running.What Changed
deriveAntigravityRateLimits). Antigravity is now a seventh independent fetch in the rate-limit cycle.agy, then IDE) on loopback only. POSTRetrieveUserQuotaSummarywithforceRefresh: true. Desktop servers sendX-Codeium-Csrf-Token; CLI is tokenless.gemini/antigravity, includinggo-keyring-base64:) and~/.gemini/antigravity{,-cli}/oauth_creds.json, thendaily-cloudcode-pa/cloudcode-paretrieveUserQuotaSummary. Never spawnsagy. Never shells out to PowerShell or CredRead.stop()is dropped.agyon PATH plus the existing toggle. Clicking it does not jump to Gemini Accounts.Why
Fixes the two failures in #9122: wrong Gemini CLI buckets on the Antigravity segment, and "Token refresh failed" whenever token refresh needed a local
@google/gemini-cliinstall. The language-server path is the same source Codenotch/CodexBar use for near-real-time quota; OAuth is only the fallback when no LS is listening.Linked Issue
Fixes #9122
Related: #7809 (visibility contract), #19561 (Usage unavailable). This does not add an Antigravity Accounts sign-in surface (#19587).
Visual Proof
No new chrome or tokens — the existing compact Antigravity status-bar slot now fills with Antigravity's own session/weekly percents.
Before: segment copied Gemini CLI buckets, stayed hidden unless Gemini CLI OAuth was enabled, or showed Gemini refresh errors / "Usage unavailable".
After: independent Antigravity percents when
agyis on PATH and the status-bar item is checked. Gemini OAuth is not required. Clicking the segment does not open Gemini Accounts.Manually verified on macOS with Orca-dev against a live Antigravity language server. Screenshot not attached (no binary in the PR).
Testing
macOS: Orca-dev, Antigravity language server running — status bar showed independent session/weekly usage and updated on the live poll.
Automated: parser / process-table / loopback URL / fetcher (LS before OAuth,
localOnlyskips Google, never--print//usage) / service independence + live poll + drop-after-blur / status-bar visibility without Gemini OAuth.Linux / Windows: not run on-device. Process listing uses
ps+lsof(macOS/Linux) andreadWindowsProcessTable+netstat.exeviawindowsSystem32Binary(Windows). Windows OAuth is file-based only (no CredRead/PowerShell); live quota is the loopback LS.SSH: probes
127.0.0.1on the machine running Orca's main process. It does not inspect an SSH execution host.AI Disclosure
Implementation assisted by Cursor Grok 4.6.
Review
Security: HTTPS to the language server skips TLS verify only after the hostname is confirmed
127.0.0.1/::1. Response bodies are capped at 1MB. CSRF is required for app/IDE processes. Live poll does not call Google.Cross-platform: see Testing. Path separators go through Node
path. No hardcodedmetaKey.Remote SSH: local-host only, as above.
Mobile: unused.
Backwards compatibility: mixed client/host is fine; this is a local main-process fetch, not a wire opcode.
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
Ensure no issues in: Security, Cross-platoform support (Linux, Windows, Mac), Remote SSH, Mobile, general backwards compatibility, performance
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)Local: targeted vitest,
pnpm tc:node,pnpm run check:code-quality:changed, oxlint + oxfmt on the touched files. Fullpnpm lint/pnpm buildleft to CI.Made with Cursor