171 lines
6.4 KiB
Markdown
171 lines
6.4 KiB
Markdown
# 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 |
|
|
|
|
## 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 142 JA3/JA4 + H2 fingerprint via `wreq`
|
|
- **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 's/detectAndUseProxy=pe.UNSPECIFIED/detectAndUseProxy=1/' \
|
|
/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): `MODEL_PLACEHOLDER_M18` = Gemini 3 Flash, `MODEL_PLACEHOLDER_M8` = Gemini 3 Pro (High), `MODEL_PLACEHOLDER_M7` = Gemini 3 Pro (Low), `MODEL_PLACEHOLDER_M26` = Claude Opus 4.6, `MODEL_PLACEHOLDER_M12` = Claude Opus 4.5, `MODEL_CLAUDE_4_5_SONNET` = Claude Sonnet 4.5.
|
|
|
|
### 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 <PORT>`: Override MITM proxy port (default: auto-assign)
|