# Antigravity Rust Proxy OpenAI-compatible proxy that intercepts and relays requests to Google's Antigravity language server, impersonating the real Electron webview. ## Quick Start ```bash # 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 ```bash 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 ```bash 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) ```bash 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 ```bash # 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 ```bash 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 `: Override MITM proxy port (default: auto-assign)