Files
zerogravity/GEMINI.md

6.5 KiB

Antigravity Rust Proxy

OpenAI-compatible proxy that intercepts and relays requests to Google's Antigravity language server, impersonating the real Electron webview.

Quick Start

# Build
cargo build --release

# Run (language server must be running)
RUST_LOG=info ./target/release/antigravity-proxy

# Custom port
RUST_LOG=info ./target/release/antigravity-proxy --port 9000

Default port: 8741

Endpoints

Method Path Description
POST /v1/responses Responses API (primary) — supports stream: true/false
POST /v1/chat/completions Chat Completions API (OpenAI compat shim)
GET /v1/models List available models
GET /v1/sessions List active sessions
DELETE /v1/sessions/:id Delete a session
POST /v1/token Set OAuth token at runtime
GET /v1/usage MITM-intercepted token usage stats
GET /v1/quota LS quota — credits, per-model rate limits, reset timers
GET /health Health check

Available Models

Name Label
opus-4.6 Claude Opus 4.6 (Thinking) — default
opus-4.5 Claude Opus 4.5 (Thinking)
gemini-3-pro-high Gemini 3 Pro (High)
gemini-3-pro Gemini 3 Pro (Low)
gemini-3-flash Gemini 3 Flash

Development & Testing

  • Dev/testing model: gemini-3-flash — use this for all development, debugging, and iterative testing
  • Production model: opus-4.6 — use sparingly for real-world validation only (has quota limit)
  • See docs/ls-binary-analysis.md for full reverse-engineered model catalog and proto enum mappings

Example: Responses API

Sync

curl -s http://localhost:8741/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-flash",
    "input": "Say hello in exactly 3 words",
    "stream": false,
    "timeout": 60
  }' | jq .

Streaming

curl -N http://localhost:8741/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-flash",
    "input": "Say hello in exactly 3 words",
    "stream": true,
    "timeout": 60
  }'

Multi-turn (session reuse)

curl -s http://localhost:8741/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-flash",
    "input": "What is 2+2?",
    "conversation": "my-session-1",
    "stream": false
  }' | jq .

# Follow-up in same cascade:
curl -s http://localhost:8741/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3-flash",
    "input": "Now multiply that by 10",
    "conversation": "my-session-1",
    "stream": false
  }' | jq .

Authentication

The proxy needs an OAuth token. Three ways to provide it:

  1. Environment variable: export ANTIGRAVITY_OAUTH_TOKEN=ya29.xxx
  2. Token file: echo 'ya29.xxx' > ~/.config/antigravity-proxy-token
  3. Runtime API: curl -X POST http://localhost:8741/v1/token -d '{"token":"ya29.xxx"}'

Version Detection

Version strings (Antigravity, Chrome, Electron, Client) are auto-detected at startup from the installed Antigravity app:

  • product.json → app version + client/IDE version
  • Binary → Chrome + Electron versions via strings

Falls back to hardcoded values if the app isn't installed. No manual updates needed when Antigravity updates.

Stealth Features

  • TLS fingerprint: BoringSSL with Chrome JA3/JA4 + H2 fingerprint via wreq (version auto-detected)
  • Protobuf: Hand-rolled encoder producing byte-exact match to real webview traffic
  • Warmup: Mimics real webview startup RPC calls
  • Heartbeat: Periodic keep-alive matching real webview lifecycle
  • Jitter: Randomized polling intervals to avoid automation fingerprint
  • Session reuse: Cascades are reused for multi-turn, matching real webview behavior
  • MITM proxy: TLS-intercepting proxy for real token usage capture (opt-in)

MITM Proxy

Built-in MITM proxy intercepts LS ↔ Google/Anthropic traffic to capture real token usage (input, output, cache read, cache creation). Disabled with --no-mitm.

Setup

# 1. Start proxy (generates CA cert automatically)
RUST_LOG=info ./target/release/antigravity-proxy

# 2. Patch extension to enable proxy detection (required!)
#    The LS has a protobuf field `detect_and_use_proxy` that defaults to UNSPECIFIED,
#    which means it ignores HTTPS_PROXY for LLM API calls. This patch sets it to ENABLED (1).
#    Must be re-applied after every Antigravity update.
sudo sed -i -E 's/detectAndUseProxy=[^,;)]+/detectAndUseProxy=1/g' \
  /usr/share/antigravity/resources/app/extensions/antigravity/dist/extension.js

# 3. Install wrapper (patches LS binary to route through MITM)
./scripts/mitm-wrapper.sh install

# 4. Restart Antigravity — done!

# Check status
./scripts/mitm-wrapper.sh status

# Uninstall
./scripts/mitm-wrapper.sh uninstall

Extension Patch Details

The LS uses daily-cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse for LLM API calls (regular HTTPS+SSE, NOT gRPC). The LS binary checks a protobuf field (detect_and_use_proxy, field 34 on init metadata) to decide whether to honor HTTPS_PROXY. The extension defaults this to UNSPECIFIED (ignore proxy). The sed patch above changes it to ENABLED (value 1), allowing the MITM wrapper's env vars to take effect.

Verify patch: grep -o 'detectAndUseProxy=[^;]*' /usr/share/antigravity/resources/app/extensions/antigravity/dist/extension.js should show detectAndUseProxy=1.

Model IDs (for standalone LS testing): See docs/ls-binary-analysis.md for the full proto enum mapping.

Usage Stats

curl -s http://localhost:8741/v1/usage | jq .

Returns aggregate token counts from all intercepted API calls.

CLI Flags

  • --no-mitm: Disable MITM proxy entirely
  • --mitm-port <PORT>: Override MITM proxy port (default: auto-assign)