Skip to content

fix(rate-limits): read Antigravity quota from local runtime - #14571

Closed
leomleao wants to merge 15 commits into
stablyai:mainfrom
leomleao:leomleao/fix-antigravity-usage-v2
Closed

leomleao wants to merge 15 commits into
stablyai:mainfrom
leomleao:leomleao/fix-antigravity-usage-v2

Conversation

@leomleao

@leomleao leomleao commented Aug 14, 2026 •

Copy link
Copy Markdown

ELI5

Antigravity already knows the real quota for the account it is running. Orca was showing a copy of Gemini usage instead. This change asks the already-running, host-local Antigravity service for its own quota and displays the four real 5-hour/weekly buckets in both Compact and Detailed views—without taking ownership of Antigravity credentials.

What Changed

  • Stream the CLI log directory while retaining only the 12 newest candidates, then read bounded whole-file or head+tail excerpts to discover the newest responsive CLI or desktop language server.
  • Query its fixed loopback quota endpoint over HTTP or HTTPS and parse all four identities: Gemini 5h, Gemini wk, Claude/GPT 5h, and Claude/GPT wk.
  • Refresh Antigravity independently from Gemini OAuth and preserve the existing Gemini usage provider.
  • Show every bucket in Detailed view and the tightest bucket plus reset countdown in Compact view, including the existing Used/Left preference.
  • Bound every filesystem wait, log read, candidate set, endpoint attempt, response size, per-request socket inactivity/wall-clock time, and the total discovery operation.
  • Fall past partial or timed-out responses while treating a completed response as authoritative for account selection.
  • Handle rotating/disappearing logs, late-open resource cleanup, stale runtimes, malformed/truncated responses, cancellation, duplicate buckets, and self-signed loopback HTTPS.
  • Keep desktop-only Antigravity usage visible when the runtime is healthy even if agy is not installed on PATH, while still hiding the item after discovery confirms no runtime exists.
  • Integrate current main and migrate coverage into the new split rate-limit test architecture.

Why

The running Antigravity language server is the quota authority for the active account. Reading that host-local runtime fixes the incorrect Gemini mirror while keeping the change focused: Orca does not read, refresh, or write OAuth/keychain credentials, inspect process command lines, or replace the current Gemini usage backend.

Removing Gemini usage is intentionally separable migration work: it spans persisted settings, telemetry, localization, mobile/web projections, and compatibility behavior. Preserving it here keeps the correctness fix bounded and avoids forcing that broader migration on existing users.

This is the focused successor to #8735. It retains that PR's loopback-first architecture, updated for the current Compact/Detailed usage UI and narrowed to bounded runtime discovery.

Current main added a temporary Gemini-to-Antigravity mirror while this PR was open. This integration deliberately replaces that compatibility mirror with the native host-local authority and adapts its regression coverage so Gemini failures, successes, and cached snapshots can no longer overwrite Antigravity state.

The headless agy -p /usage output reported for Agy 1.1.18 is a promising future fallback, but adopting it safely also requires cross-platform executable resolution and subprocess deadline policy. It is not required for desktop-only installs here: a healthy desktop runtime snapshot now exposes the item without requiring agy on PATH.

Related implementations

PR Authority and scope Difference from this PR
This PR (#14571) Active host-local runtime; all four Antigravity buckets Preserves Gemini usage; bounded whole/head+tail log discovery; HTTP/HTTPS and desktop fallback; no credentials or process-command inspection
#15876 (merged) Gemini-derived compatibility state Correctly stops a failed Gemini read from surfacing as an Antigravity error, but still has no Antigravity fetch and mirrors successful Gemini usage even when the active accounts differ
#11536 Active local runtime; all four Antigravity buckets Broader migration that removes the Gemini usage provider and discovers runtime data through logs plus lsof/ps, including command-line CSRF; HTTP path only
#12095 Credential/keychain-backed cloud quota APIs Owns token lookup and OAuth refresh instead of treating the running local service as the authority

Gemini CLI compatibility: Unlike #11536, this PR intentionally preserves Gemini CLI support. Even as Google transitions the consumer-facing workflow to agy, Gemini CLI remains documented for organization/Enterprise accounts, Gemini API-key users, and Vertex AI users. The consumer migration therefore does not justify removing a still-supported provider from Orca. See the current Gemini CLI authentication guide and enterprise guide.

As of the validation below, #11536 is 116 commits behind current main and changes 72 files; #12095 is 673 commits behind, conflicting, and has three unresolved review threads. This PR is current with main, mergeable, changes 33 files, and has no unresolved review threads.

Linked Issue

Fixes #9122
Fixes #7809

Visual Proof

Before — broken bottom icon

Antigravity status bar icon before the fix

Before — broken popup

Antigravity usage popup before the fix

After — Compact view

Working Antigravity Compact usage view

After — Detailed view, Used

Working Antigravity Detailed usage view showing used quota

After — Detailed view, Left

Working Antigravity Detailed usage view showing remaining quota

Testing

  • I manually tested these changes locally on macOS: Compact, Detailed Used, and Detailed Left.
  • Automated tests added/updated, including service isolation and rotating-log regression coverage.

Validation on current main (94e7586665c2), at PR head 05ea85005:

  • Changed Antigravity/rate-limit/status-bar suite: 18 files, 216 tests passed.
  • Agent detection/title compatibility suite: 4 files, 120 tests passed.
  • pnpm lint: passed, including reliability, max-lines, runtime, bundled-skill, and localization gates.
  • pnpm tc: passed.
  • Relay builds for Linux/macOS/Windows, CLI, Electron/Vite, built-skills verification, and web projection: passed.
  • Changed-code quality, type-aware quality, and React Doctor: zero new findings across 31 changed source files.
  • pnpm format: passed.
  • git diff --check: passed.

The exhaustive full-repository run reported 12 failures across six files untouched by this PR: four current-main Codex PTY assertions supplemented their mocks from this machine's real ~/.codex/auth.json, one shell ZDOTDIR assertion is environment-dependent, two palette performance budgets missed under load, and five remote-terminal timers missed under load. The palette suite passed 3/3 and the remote-terminal suites passed 37/37 in isolation. The shell and Codex failures reproduce in isolation on this checkout and are absent from the PR diff. No changed-path test failed.

AI Disclosure

OpenAI Codex was used for implementation assistance, conflict resolution, test expansion, and adversarial review. Google Antigravity (agy) was used for additional repository analysis and adversarial checks. The behavior shown above was manually exercised, and repository validation was run after integrating current main.

Review

  • Security: Requests are fixed to 127.0.0.1; the self-signed HTTPS exception cannot apply to network hosts. The fetcher uses a fixed RPC path, validates ports and Antigravity page identity, caps responses at 1 MiB, reads at most 256 KiB per log, and never accesses credentials/keychains.
  • Cross-platform: Paths use Node path APIs and desktop log locations are selected at runtime for macOS vs. Windows/Linux. Discovery does not depend on platform-specific lsof/ps commands. macOS is the platform manually exercised; CI covers the remaining supported platforms.
  • SSH/remote: Discovery intentionally stays with the desktop host running Orca; an SSH worktree does not redirect loopback requests to an unrelated remote host.
  • Performance: Directory entries are streamed with only 12 candidates retained; at most 8 unique endpoints, 256 KiB per log excerpt, 1.25 seconds per request, and 6 seconds total are allowed. Cancellation covers filesystem waits and loopback requests, including the final-read boundary, and late-open resources are closed.
  • Backwards compatibility: Gemini usage remains intact. Antigravity failure is provider-isolated and returns structured unavailable/error state without affecting other providers.
  • Mobile: No mobile surface or protocol shape changes; Antigravity adds optional buckets to the existing shared rate-limit payload.

Checklist

  • This PR is small and focused
  • I explained what changed and why (including ELI5)
  • Before/after screenshots attached for UI changes
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered
  • pnpm lint and the expanded affected suite pass
  • Aggregate typecheck and all production build stages pass
  • Current-main full-suite exceptions are isolated and documented above

Author

  • X / Twitter: N/A

@coderabbitai

coderabbitai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a999a5e0-08f0-46e1-a1e8-adfd162ef6d3

📥 Commits

Reviewing files that changed from the base of the PR and between 7ae6aed and 135f742.

📒 Files selected for processing (26)
  • config/tsconfig.node.json
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/main/rate-limits/antigravity-loopback-client.ts
  • src/main/rate-limits/antigravity-loopback-request-close.test.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/main/rate-limits/antigravity-usage-fetcher.ts
  • src/main/rate-limits/antigravity-usage-log-rotation.test.ts
  • src/main/rate-limits/rate-limit-service-test-harness.ts
  • src/main/rate-limits/service-account-target-selection.test.ts
  • src/main/rate-limits/service-inactive-account-previews.test.ts
  • src/main/rate-limits/service-live-claude-usage.test.ts
  • src/main/rate-limits/service-minimax-usage.test.ts
  • src/main/rate-limits/service-refresh-orchestration.test.ts
  • src/main/rate-limits/service-window-activation.test.ts
  • src/main/rate-limits/service.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/shared/rate-limit-types.ts
🚧 Files skipped from review as they are similar to previous changes (25)
  • src/main/rate-limits/service-window-activation.test.ts
  • src/main/rate-limits/antigravity-loopback-request-close.test.ts
  • src/main/rate-limits/service-minimax-usage.test.ts
  • src/main/rate-limits/service-account-target-selection.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/main/rate-limits/antigravity-usage-log-rotation.test.ts
  • src/main/rate-limits/rate-limit-service-test-harness.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/main/rate-limits/service.ts
  • config/tsconfig.node.json
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/shared/rate-limit-types.ts
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/main/rate-limits/service-inactive-account-previews.test.ts
  • src/main/rate-limits/service-refresh-orchestration.test.ts
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/main/rate-limits/service-live-claude-usage.test.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/main/rate-limits/antigravity-usage-fetcher.ts

Included review availability: Your plan includes up to 10 reviews per rolling hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Added Antigravity quota parsing, bounded HTTP/HTTPS loopback requests, CLI and desktop discovery, CSRF handling, timeout and cancellation support, and structured unavailable states. Integrated Antigravity into independent rate-limit refreshes. Updated status-bar visibility, bucket rendering, compact and detailed views, tooltip sections, and related tests.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation independently fetches Antigravity quota from local runtimes, separates quota pools, removes Gemini dependencies, and preserves independent visibility.
Out of Scope Changes check ✅ Passed The code and tests remain focused on Antigravity quota discovery, parsing, service integration, and status-bar presentation.
Title check ✅ Passed The title clearly and concisely describes the main change: reading Antigravity quota from the local runtime.
Description check ✅ Passed The description is complete and directly addresses the template. It includes the ELI5 explanation, scope, rationale, linked issues, visual proof, testing, AI disclosure, security and compatibility rev…
Full details: Description check

Explanation

The description is complete and directly addresses the template. It includes the ELI5 explanation, scope, rationale, linked issues, visual proof, testing, AI disclosure, security and compatibility review, and checklist status. The missing standalone Agent skill upstream boundary and Notes headings are non-critical because the relevant scope considerations are covered elsewhere.

  • Fix all pre-merge checks with AI

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/main/rate-limits/antigravity-loopback-client.ts (1)

75-90: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Relax the __APP_CONFIG__ terminator match.

The pattern requires };</script> with no characters between. Antigravity can emit whitespace, a newline, or additional statements before the closing tag. In that case the match fails, parseAntigravityAppConfig returns null, and desktop CSRF negotiation degrades silently to an unauthenticated retry.

Allow optional whitespace and stop at the first </script>.

♻️ Proposed relaxation
-  const configJson = html.match(/window\.__APP_CONFIG__\s*=\s*(\{.*?\});<\/script>/s)?.[1]
+  const configJson = html.match(/window\.__APP_CONFIG__\s*=\s*(\{.*?\})\s*;?\s*(?:<\/script>|$)/s)?.[1]
src/main/rate-limits/antigravity-usage-fetcher.ts (1)

58-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Compute the log directory once.

getAntigravityCliLogDirectory(homePath) is called at Line 61 and again at Line 65 with the same argument. Hoist it above the readdir call.

♻️ Proposed cleanup
 async function fetchFromCliLogs(homePath: string, signal: AbortSignal): Promise<FetchAttempt> {
+  const logDirectory = getAntigravityCliLogDirectory(homePath)
   let entries: Dirent[]
   try {
-    entries = await readdir(getAntigravityCliLogDirectory(homePath), { withFileTypes: true })
+    entries = await readdir(logDirectory, { withFileTypes: true })
   } catch {
     return { discovered: false, answered: false, limits: null }
   }
-  const logDirectory = getAntigravityCliLogDirectory(homePath)
   const logNames = entries
src/main/rate-limits/antigravity-usage-fetcher.test.ts (1)

33-51: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated loopback test-server setup across the two Antigravity test files. Six tests repeat the same sequence: create a server, listen(0, '127.0.0.1'), narrow server.address(), throw when the address is not a TCP object, and close the server in finally. The shared root cause is the absence of one loopback test fixture that returns the bound port and handles teardown.

  • src/main/rate-limits/antigravity-usage-fetcher.test.ts#L33-L51: replace the four inline setup and teardown blocks in this file with the shared fixture, and keep the HTTPS variant as an option of that fixture.
  • src/main/rate-limits/antigravity-loopback-client.test.ts#L53-L93: replace the two inline setup and teardown blocks with the same fixture.

Give the fixture a concrete domain name such as antigravity-loopback-test-server.ts. Do not name it helpers or utils. This is optional cleanup; the current assertions are correct. As per coding guidelines: "Do not use vague names such as helpers, utils, common, misc, or shared-stuff for files, folders, or modules; use concrete domain-oriented names instead."

Source: Coding guidelines

src/main/rate-limits/service.test.ts (1)

2139-2153: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a test that pins Antigravity independence from Gemini.

The failure-isolation test now covers an Antigravity rejection. It does not cover the specific regression this PR fixes: Antigravity state must not mirror Gemini state. Add a case where fetchGeminiRateLimits rejects or reports unavailable while fetchAntigravityRateLimits resolves, then assert state.antigravity?.status is 'ok' and its usage does not equal the Gemini values. That assertion prevents a future refactor from reintroducing the mirroring described in the linked issue.

Also consider asserting the 'unavailable' plus failureKind: 'cli-unavailable' result reaches state, because the status bar renders that case differently from 'error'.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c7e5489-cf33-48f1-9c80-6228b13c046c

📥 Commits

Reviewing files that changed from the base of the PR and between 266b5ae and 1f94715.

📒 Files selected for processing (18)
  • config/tsconfig.node.json
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/main/rate-limits/antigravity-loopback-client.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/main/rate-limits/antigravity-usage-fetcher.ts
  • src/main/rate-limits/service.test.ts
  • src/main/rate-limits/service.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/shared/rate-limit-types.ts

Comment thread src/main/rate-limits/antigravity-usage-fetcher.ts
@leomleao

Copy link
Copy Markdown
Author

Addressed the CodeRabbit feedback in 0badf4460:

  • reports the internal discovery deadline as Antigravity usage lookup timed out, with a regression test
  • parses formatted/nested __APP_CONFIG__ JSON independently of whitespace, semicolon placement, or following script statements while retaining the Antigravity identity check
  • resolves the CLI log directory once
  • explicitly verifies that Antigravity remains healthy when Gemini usage is unavailable
  • documents the non-obvious compatibility, trust-boundary, and normalization contracts for the new functions

I left the suggested shared test-server fixture out because it was marked optional and would add structural churn without changing coverage.

Validation after the changes:

  • focused: 4 files, 95 tests passed
  • full suite: 4,866 files passed, 19 skipped; 52,252 tests passed, 119 skipped
  • typecheck, lint, reliability gates, max-lines ratchet, and changed-code quality all passed

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@leomleao

Copy link
Copy Markdown
Author

Integrated current main in cfc34b5ed and resolved the rate-limit test split without restoring the deleted monolith. This update also adds a rotating-log regression so a vanished newest AGY log cannot mask an older live runtime.

Fresh validation on the rebased head:

  • full suite: 5,637 files / 52,833 tests passed
  • focused Antigravity + status-bar suite: 13 files / 187 tests passed
  • lint, typecheck, production build, changed-code quality, React Doctor, and diff checks passed
  • zero new changed-code or React Doctor findings

The two Actions workflows currently show action_required because this fork commit needs maintainer approval to start; there is no reported CI test failure.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Your plan includes PR reviews subject to rate limits. Reviews are available now.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/main/rate-limits/antigravity-loopback-client.ts (2)

75-119: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Compute the script boundary during the scan, not before it.

end is fixed at the first </script> match after start. If a JSON string value contains the text </script>, the scan stops inside the object and parseAntigravityAppConfig returns null. The brace matcher already tracks string state, so the bound is redundant: an unterminated object ends the loop at html.length anyway.

♻️ Proposed simplification
-  const scriptEndPattern = /<\/script\s*>/gi
-  scriptEndPattern.lastIndex = start
-  const end = scriptEndPattern.exec(html)?.index ?? html.length
   let depth = 0
   let escaped = false
   let inString = false
 
-  for (let index = start; index < end; index += 1) {
+  for (let index = start; index < html.length; index += 1) {

139-233: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Confirm the promise settles when the request closes without an error event.

The promise resolves on end and rejects on error or timeout. A socket that closes after headers but before end, or an external req.destroy() with no error argument, leaves the promise pending. A close guard removes that risk.

🛡️ Proposed guard
     req.on('error', (error) => {
@@
       reject(error)
     })
+    req.on('close', () =>
+      reject(new AntigravityLoopbackResponseError('Antigravity quota request closed early'))
+    )
     req.end(body)

The extra reject after a settled promise is a no-op.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bd7437b5-611e-4c55-b6c1-74cbd26eea18

📥 Commits

Reviewing files that changed from the base of the PR and between 931cb03 and cfc34b5.

📒 Files selected for processing (25)
  • config/tsconfig.node.json
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/main/rate-limits/antigravity-loopback-client.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/main/rate-limits/antigravity-usage-fetcher.ts
  • src/main/rate-limits/antigravity-usage-log-rotation.test.ts
  • src/main/rate-limits/rate-limit-service-test-harness.ts
  • src/main/rate-limits/service-account-target-selection.test.ts
  • src/main/rate-limits/service-inactive-account-previews.test.ts
  • src/main/rate-limits/service-live-claude-usage.test.ts
  • src/main/rate-limits/service-minimax-usage.test.ts
  • src/main/rate-limits/service-refresh-orchestration.test.ts
  • src/main/rate-limits/service-window-activation.test.ts
  • src/main/rate-limits/service.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/shared/rate-limit-types.ts
🚧 Files skipped from review as they are similar to previous changes (15)
  • config/tsconfig.node.json
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/shared/rate-limit-types.ts
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/main/rate-limits/service.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts

@leomleao

Copy link
Copy Markdown
Author

Addressed the two nitpicks from the full review in f47d07f57:

  1. Early request close: implemented the defensive close settlement guard and added an isolated regression that emits close without a response or error event. The request now rejects with a structured AntigravityLoopbackResponseError instead of being able to remain pending.
  2. Closing script boundary: intentionally retained the boundary rather than scanning through the rest of the HTML. A literal </script> terminates an HTML script element even when it appears inside JavaScript string syntax; scanning beyond it could accept JSON assembled across a markup boundary. Added a regression that pins rejection when the CSRF value crosses a closing script tag.

Validation on the pushed commit:

  • affected Antigravity/status-bar suites: 15 files, 190 tests passed
  • full suite: 5,638 files / 52,835 tests passed
  • lint and typecheck passed
  • changed-code quality and React Doctor: zero new findings across 25 source files
  • diff checks passed

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== HEAD AND TARGET COMMIT ==='
git rev-parse --short HEAD
git show --no-ext-diff --format=fuller --stat f47d07f57

echo '=== TARGET COMMIT DIFF ==='
git diff --no-ext-diff --unified=80 f47d07f57^ f47d07f57 -- \
  src/main/rate-limits/antigravity-loopback-client.ts \
  src/main/rate-limits/antigravity-loopback-client.test.ts

echo '=== SOURCE OUTLINE ==='
ast-grep outline src/main/rate-limits/antigravity-loopback-client.ts --items all --view expanded

echo '=== TEST OUTLINE ==='
ast-grep outline src/main/rate-limits/antigravity-loopback-client.test.ts --items all --view expanded

echo '=== REQUEST AND APP-CONFIG REFERENCES ==='
rg -n -C 8 --glob 'antigravity-loopback-client*.ts' \
  'requestAntigravityLoopbackPage|parseAntigravityAppConfig|\.on\(.close.|\.once\(.close.|</script>|__APP_CONFIG__|AntigravityLoopbackResponseError' \
  src/main/rate-limits

Length of output: 38472


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== CLOSE-EVENT TEST OUTLINE AND CONTENT ==='
ast-grep outline src/main/rate-limits/antigravity-loopback-request-close.test.ts --items all --view expanded
cat -n src/main/rate-limits/antigravity-loopback-request-close.test.ts

echo '=== PR MERGE BASE AND CHANGED FILES ==='
base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
printf 'merge-base: %s\n' "$base"
git diff --no-ext-diff --name-status "$base"...HEAD

echo '=== COMPLETE PR DIFF STAT ==='
git diff --no-ext-diff --stat "$base"...HEAD

echo '=== COMPLETE PR DIFF (COMPACT) ==='
git diff --no-ext-diff --unified=12 "$base"...HEAD -- \
  src/main/rate-limits \
  src/renderer/src/components/status-bar \
  src/shared/rate-limit-types.ts \
  config/tsconfig.node.json

Length of output: 105444


@leomleao The targeted verification confirms both fixes.

The request now settles when it closes before response completion. The isolated regression verifies the structured AntigravityLoopbackResponseError.

The parser stops at the closing </script> boundary. The regression verifies that it rejects configuration that crosses this boundary.

I will now run the updated PR review.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@leomleao

Copy link
Copy Markdown
Author

Updated this branch to current main (7ae6aedc02db) in 135f74210.

The only merge conflict was in the shared provider refresh orchestration. The resolution preserves main's new Codex skip-state gating while keeping Antigravity as an independent, host-local quota fetch, so a Codex account transition cannot block or misroute Antigravity discovery.

Fresh validation after the merge:

  • Full suite: 5,843 files / 54,612 tests passed, zero failures
  • Focused Antigravity/status-bar suite: 15 files / 196 tests passed
  • All rate-limit service regressions: 6 files / 82 tests passed
  • pnpm lint, pnpm typecheck, and pnpm build: passed
  • Changed-code quality, type-aware quality, and React Doctor: zero findings across 25 source files
  • Branch is 0 commits behind current main and conflict-free locally

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '=== MERGE COMMIT ==='
git show --no-ext-diff --format=fuller --stat 135f74210
git show --no-ext-diff --format= --cc --unified=50 135f74210 -- src/main/rate-limits/service.ts

echo '=== SERVICE MODULE OUTLINE ==='
ast-grep outline src/main/rate-limits/service.ts --items all --view expanded

echo '=== ORCHESTRATION REFERENCES ==='
rg -n -C 10 --type ts \
  'fetchAntigravityRateLimits|fetchCodexRateLimits|codex|antigravity|skip' \
  src/main/rate-limits/service.ts \
  src/main/rate-limits/service-refresh-orchestration.test.ts \
  src/main/rate-limits/service-window-activation.test.ts \
  src/main/rate-limits/service-account-target-selection.test.ts

echo '=== PR CHANGED SERVICE-RELATED FILES ==='
base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
git diff --no-ext-diff --name-status "$base"...HEAD -- src/main/rate-limits

Length of output: 201409


🏁 Script executed:

#!/bin/bash
set -euo pipefail

parents=($(git show -s --format=%P 135f74210))
printf 'parents: %s\n' "${parents[*]}"

echo '=== SERVICE: FIRST PARENT TO MERGE ==='
git diff --no-ext-diff --unified=25 "${parents[0]}" 135f74210 -- src/main/rate-limits/service.ts

echo '=== SERVICE: SECOND PARENT TO MERGE ==='
git diff --no-ext-diff --unified=25 "${parents[1]}" 135f74210 -- src/main/rate-limits/service.ts

echo '=== FULL-REFRESH IMPLEMENTATION ==='
sed -n '1600,1910p' src/main/rate-limits/service.ts

echo '=== TARGETED ORCHESTRATION TESTS ==='
rg -n -A45 -B8 --type ts \
  'keeps Antigravity usage when Gemini usage is unavailable|fetches Gemini, Antigravity, and OpenCode Go|skip|gated Codex|Codex.*skip' \
  src/main/rate-limits/service-refresh-orchestration.test.ts \
  src/main/rate-limits/service-account-target-selection.test.ts

Length of output: 74517


@leomleao I found no actionable issue in merge commit 135f74210.

The merge preserves the Codex skip-state gate in src/main/rate-limits/service.ts.

A skipped Codex home gates only the Codex fetch slot. It does not return from the full refresh cycle.

fetchAntigravityRateLimits({ signal }) remains an independent operation in the same Promise.allSettled call. Its result has separate error handling, failure tracking, and state updates.

The reviewed tests cover Codex skip handling and Antigravity health when Gemini is unavailable. The merge does not restore Gemini-mirrored Antigravity usage.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 06d2a238-580c-4d84-86ff-91188b6c9a6c

📥 Commits

Reviewing files that changed from the base of the PR and between 7ae6aed and 135f742.

📒 Files selected for processing (26)
  • config/tsconfig.node.json
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/main/rate-limits/antigravity-loopback-client.ts
  • src/main/rate-limits/antigravity-loopback-request-close.test.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/main/rate-limits/antigravity-usage-fetcher.ts
  • src/main/rate-limits/antigravity-usage-log-rotation.test.ts
  • src/main/rate-limits/rate-limit-service-test-harness.ts
  • src/main/rate-limits/service-account-target-selection.test.ts
  • src/main/rate-limits/service-inactive-account-previews.test.ts
  • src/main/rate-limits/service-live-claude-usage.test.ts
  • src/main/rate-limits/service-minimax-usage.test.ts
  • src/main/rate-limits/service-refresh-orchestration.test.ts
  • src/main/rate-limits/service-window-activation.test.ts
  • src/main/rate-limits/service.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/shared/rate-limit-types.ts
🚧 Files skipped from review as they are similar to previous changes (24)
  • src/renderer/src/components/status-bar/tooltip.tsx
  • src/main/rate-limits/service-live-claude-usage.test.ts
  • src/main/rate-limits/service-account-target-selection.test.ts
  • src/main/rate-limits/service-window-activation.test.ts
  • src/main/rate-limits/service-minimax-usage.test.ts
  • src/shared/rate-limit-types.ts
  • src/renderer/src/components/status-bar/UsageRosterPanel.tsx
  • src/main/rate-limits/antigravity-loopback-request-close.test.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.ts
  • src/renderer/src/components/status-bar/status-bar-provider-visibility.test.ts
  • src/main/rate-limits/service-inactive-account-previews.test.ts
  • src/renderer/src/components/status-bar/tooltip.test.ts
  • config/tsconfig.node.json
  • src/renderer/src/components/status-bar/UsageRosterPanel.test.tsx
  • src/main/rate-limits/antigravity-quota-parser.ts
  • src/main/rate-limits/antigravity-quota-parser.test.ts
  • src/main/rate-limits/antigravity-loopback-client.test.ts
  • src/main/rate-limits/antigravity-usage-fetcher.test.ts
  • src/renderer/src/components/status-bar/provider-segment-monthly-window.test.tsx
  • src/main/rate-limits/service-refresh-orchestration.test.ts
  • src/main/rate-limits/service.ts
  • src/main/rate-limits/rate-limit-service-test-harness.ts
  • src/main/rate-limits/antigravity-usage-fetcher.ts
  • src/renderer/src/components/status-bar/StatusBar.tsx

Included review availability: Your plan includes up to 10 reviews per rolling hour; 9 remain after this review.

Comment thread src/main/rate-limits/antigravity-loopback-client.ts
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@leomleao

Copy link
Copy Markdown
Author

Addressed the latest full-review finding and updated this branch to current main (fc8b92e507af) in d7b8e174f.

The loopback client now enforces both socket-inactivity and fixed wall-clock request deadlines. The wall-clock timer is cleared on completion/error/close, and regression coverage verifies a trickling response cannot keep the request alive, early close cancels the timer, and the independent six-second discovery deadline remains effective across multiple silent endpoints. The CodeRabbit thread has been replied to and resolved.

Fresh validation:

  • Full suite: 5,945 files / 55,890 tests passed, zero failures
  • Expanded rate-limit/status-bar suite: 48 files / 546 tests passed
  • pnpm lint: passed
  • Changed-code quality, type-aware quality, and React Doctor: zero findings across 25 source files
  • Node and CLI typecheck scopes: passed
  • Relay, CLI, Electron/Vite, built-skills, web projection, and native production build stages: passed
  • Branch is 0 commits behind current main and conflict-free locally

The aggregate web typecheck currently stops in an untouched current-main tab-bar test fixture introduced by 7a695c70f (occupantAgent is missing). That file is byte-identical to main; the PR description records this baseline exception explicitly.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Your plan includes PR reviews subject to rate limits. Reviews are available now.

@nwparker nwparker removed the P1 label Aug 19, 2026
@leomleao

Copy link
Copy Markdown
Author

Updated #14571 to current main (3e079debec65) in 0b930eb5e. The 87 upstream commits merged without conflicts or overlap with the PR's 26-file diff.

I also re-audited the two related implementations. This PR remains the bounded provider-preserving option: newest-responsive log-tail discovery, HTTP/HTTPS plus desktop fallback, fixed endpoint/response/time limits, no credential or process-command inspection, and explicit stale-runtime/race coverage. The PR description now also links #7809, whose pending/visibility acceptance criteria this implementation covers.

Fresh validation:

  • Expanded rate-limit/status-bar suite: 84 files / 736 tests passed
  • Full suite: 6,031 files / 56,745 tests passed
  • pnpm lint: passed, including reliability, max-lines, bundled-skill, and localization gates
  • Aggregate pnpm typecheck: passed
  • Changed-code quality, type-aware quality, and React Doctor: zero findings across 25 source files
  • Relay, CLI, Electron/Vite, built-skills, web projection, and native production build stages: passed
  • Branch is 0 commits behind current main and conflict-free

The full run had three environment-dependent assertions in two new, untouched current-main files. shell-startup-feature-channel.test.ts passes 12/12 with Orca's inherited wrapper-only ORCA_ORIG_ZDOTDIR removed; wsl-exec-mode-separator.test.ts passes 4/4 when the concurrently generated E2E release checkout is outside its source scan. No PR file or affected test failed.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Your plan includes PR reviews subject to rate limits. Reviews are available now.

@leomleao

Copy link
Copy Markdown
Author

Updated #14571 to current main (59892a2f134f) in af7a99c2d, then landed the adversarial hardening in 4e7b62b1a.

The additional hardening:

  • streams arbitrarily large CLI log directories while retaining only the 12 newest candidates;
  • races every filesystem wait against the six-second discovery deadline and cleans up resources that open after cancellation;
  • distinguishes complete service replies from partial/trickling responses, so a stalled newest runtime no longer hides an older healthy one;
  • adds regression coverage for 10,000-entry discovery, incomplete-response fallback, total-deadline enforcement, and late-open cleanup.

Fresh validation on the pushed head:

  • 0 commits behind current main; merge preview/integration completed without conflicts or direct changed-path overlap;
  • focused Antigravity/status-bar suite: 10 files, 137 tests passed;
  • pnpm lint, aggregate typecheck, changed-code quality/React Doctor, and git diff --check: passed with zero new findings;
  • Linux/macOS/Windows relay targets, CLI, Electron/Vite, built-skills verification, and web projection: passed;
  • aggregate suite: 6,037 files / 56,836 tests passed; all 11 failures from nine untouched performance/environment-sensitive files passed in serial or clean-environment reruns;
  • CodeRabbit-style adversarial review plus a final read-only agy review: no remaining actionable findings.

The PR description now includes the refreshed evidence and a current comparison with #11536 and #12095.

@plaonn

plaonn commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

I found one reproducible edge case in the bounded CLI-log discovery.

readAntigravityLogTail() currently keeps only the final 128 KiB. With a synthetic ~280 KiB cli-*.log where the Language server listening ... announcement is near the beginning, the listener falls outside that window: discovery returns cli-unavailable and makes zero loopback quota requests.

I tested a bounded fix that:

  • reads the whole file when it is <= 256 KiB;
  • otherwise reads the first 128 KiB + final 128 KiB, in chronological order.

This preserves the bounded I/O/cancellation and late-open cleanup behavior while retaining both startup listener announcements and later log content. I also added a regression with the listener near the start followed by >128 KiB of filler.

Validation of the patched #14571 code:

  • 28 focused Antigravity tests
  • 82 related rate-limit service tests
  • 40 UI/store tests
  • Node typecheck
  • full lint
  • changed-code quality checks
  • Electron E2E build
  • diff checks

I also validated it against a real host-local Antigravity runtime. The quota RPC returned all four buckets, and Orca rendered them correctly in both Detailed and Compact usage views across refreshes. I additionally checked the desktop UI directly against Antigravity CLI quota output; the values/reset windows were consistent.

I did not have a naturally occurring >256 KiB Antigravity log locally (largest CLI log was ~31 KiB), so that exact real-world long-log condition is covered synthetically rather than by a natural runtime sample.

The local validation commit is 6e9a1c8d71df623a2580a0379e88b7690a0ac6b7; the relevant change is the bounded head+tail read plus the long-log regression described above.

@mikeascendx

Copy link
Copy Markdown

Windows validation from a current install:

  • Windows 11
  • Orca 1.4.188
  • Antigravity CLI 1.1.18

The existing Orca release still mirrors Gemini usage and fails when the legacy ~/.gemini/oauth_creds.json is absent. Agy 1.1.18 now also exposes the native quota payload headlessly through:

agy -p /usage --output-format json --print-timeout 1m

That returns structured command.data.groups[].buckets[] data for all four native identities:

  • Gemini weekly
  • Gemini 5h
  • Claude/GPT weekly
  • Claude/GPT 5h

Each bucket includes remaining_fraction and reset_time, and the command reported zero input/output tokens in this test. I wired that payload into the installed Orca provider locally and confirmed the Usage popover renders a single Antigravity row with all four independently calculated buckets, with no Gemini OAuth credential involved.

This does not replace the loopback implementation in this PR, but it may be a useful Windows fallback or future simplification because print mode works without a PTY in Agy 1.1.18. No credentials or account identifiers are involved in the output parsing.

Preserve native Antigravity quota authority, adapt upstream mirror regressions, and retain bounded head/tail log discovery.
Keep desktop-only Antigravity usage visible without requiring agy on PATH, preserve absent-runtime gating, and stop parsing when cancellation lands after the final log read.
@leomleao

Copy link
Copy Markdown
Author

Updated #14571 to current main (afd76a4df939) in ef4b35529, then landed the final adversarial hardening in c27d2e9f0.

Thanks @plaonn — the long-log edge case is now covered by a bounded read of the whole file up to 256 KiB, or the first and final 128 KiB for larger logs. Regression coverage places the listener announcement at both the beginning and end of a >256 KiB log, and the read now observes cancellation at the final-read boundary.

Thanks @mikeascendx — I also fixed the desktop-only visibility gap: a healthy Antigravity Desktop runtime can expose the usage item even when agy is not on PATH, while a confirmed absent runtime remains hidden. I evaluated the new headless agy -p /usage path as an optional fallback; it is kept as follow-up work because adopting it safely adds executable discovery and subprocess lifecycle/deadline policy, while this loopback implementation already covers desktop-only installs without requiring the CLI.

The current-main integration also supersedes the temporary Gemini-to-Antigravity mirror with the native provider and adapts its regression tests so Gemini state cannot overwrite Antigravity state.

Fresh validation on the pushed head:

  • 0 commits behind current main, mergeable, and no unresolved review threads;
  • affected rate-limit/status-bar suite: 87 files / 749 tests passed;
  • full suite: 6,136 files / 57,715 tests passed; the two failures were in untouched environment/timing-sensitive tests and both passed in isolated or clean-environment reruns (12/12 and 28/28);
  • pnpm lint, aggregate typecheck, changed-code quality, type-aware quality, React Doctor, runtime/max-lines/reliability gates, and git diff --check: passed;
  • Linux/macOS/Windows relay targets, CLI, Electron/Vite, built-skills verification, and web projection: passed;
  • two independent final adversarial reviews found no remaining high- or medium-severity production issue.

The PR description now contains the refreshed comparison with #11536 and #12095 plus the exact validation/disclosure details.

@leomleao

Copy link
Copy Markdown
Author

Refreshed this branch onto current main (94e7586665c2) and pushed 05ea85005.

The integration was conflict-free. A completed adversarial review found two current-main edge cases, both now fixed with regression coverage:

  • stale Antigravity listener logs now settle to unavailable instead of pinning a stopped runtime as a persistent error;
  • Settings > Appearance now receives the Antigravity runtime snapshot, so desktop-only users retain the same toggle visibility as the status-bar menu;
  • the HTTPS test now reuses current main's canonical local certificate fixture after its upstream move.

Final adversarial review through agy in an Orca-managed terminal reported no remaining actionable PR-introduced findings.

Validation:

  • changed Antigravity/rate-limit/status-bar tests: 18 files, 216 tests passed;
  • agent detection/title compatibility: 4 files, 120 tests passed;
  • pnpm tc, pnpm lint, pnpm format, pnpm build:desktop, changed-code quality, type-aware quality, React Doctor, and git diff --check: passed;
  • zero unresolved review threads at the time of refresh.

The exhaustive repository run also completed. Its failures were limited to six unchanged current-main/environment-sensitive files; no changed-path test failed. The remote-terminal and palette failures passed in isolation, while the shell and Codex failures reproduce independently of this PR on this local checkout.

@leomleao

leomleao commented Oct 4, 2026

Copy link
Copy Markdown
Author

Closing this PR as superseded by #24073 and its status-bar follow-up #24074, both now merged into main. Together they address the native Antigravity quota and model-group display problem this PR targeted.

The merged implementation reads quota through agy /usage, while this PR queried the running host-local Antigravity service. #24073 references this PR among the alternative approaches considered. With the fix now upstream, this PR is no longer needed.

@leomleao leomleao closed this Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants