feat: initial commit — antigravity proxy with MITM, standalone LS, and snapshot tooling
This commit is contained in:
239
README.md
Normal file
239
README.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# Antigravity 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
|
||||
# First message
|
||||
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"}'`
|
||||
|
||||
## 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
|
||||
- **Version detection**: Auto-detects Antigravity/Chrome/Electron versions from installed app
|
||||
|
||||
## MITM Proxy
|
||||
|
||||
Built-in TLS-intercepting proxy captures real token usage from LS ↔ Google/Anthropic traffic. Disabled with `--no-mitm`.
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# 1. Start proxy (generates CA cert automatically)
|
||||
RUST_LOG=info ./target/release/antigravity-proxy
|
||||
|
||||
# 2. Install wrapper (patches LS binary to route through MITM)
|
||||
sudo ./scripts/mitm-wrapper.sh install
|
||||
|
||||
# 3. Restart Antigravity — done!
|
||||
|
||||
# Check status
|
||||
./scripts/mitm-wrapper.sh status
|
||||
|
||||
# Uninstall
|
||||
sudo ./scripts/mitm-wrapper.sh uninstall
|
||||
```
|
||||
|
||||
### Usage Stats
|
||||
|
||||
```bash
|
||||
curl -s http://localhost:8741/v1/usage | jq .
|
||||
```
|
||||
|
||||
## Standalone Language Server
|
||||
|
||||
Launch an isolated LS instance for experimentation:
|
||||
|
||||
```bash
|
||||
# Basic test (starts, checks quota, exits)
|
||||
./scripts/standalone-ls.sh
|
||||
|
||||
# Foreground mode (stays alive)
|
||||
./scripts/standalone-ls.sh --fg
|
||||
|
||||
# With MITM traffic interception
|
||||
./scripts/standalone-ls.sh --mitm
|
||||
|
||||
# Capture a clean traffic snapshot
|
||||
./scripts/standalone-ls.sh --snapshot
|
||||
|
||||
# Snapshot with custom prompt
|
||||
./scripts/standalone-ls.sh --snapshot --prompt "Explain quantum computing"
|
||||
```
|
||||
|
||||
The standalone LS shares the main Antigravity app's OAuth (via its extension server) but has its own port, data directory, and cascades.
|
||||
|
||||
### Traffic Snapshots
|
||||
|
||||
The `--snapshot` flag captures all HTTP/2 traffic and formats it into a clean, color-coded report:
|
||||
|
||||
```
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
STANDALONE LS TRAFFIC SNAPSHOT
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
|
||||
▸ Outbound Connections
|
||||
→ antigravity-unleash.goog (Feature Flags)
|
||||
→ play.googleapis.com (Telemetry)
|
||||
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
antigravity-unleash.goog — Feature Flags
|
||||
══════════════════════════════════════════════════════════════════════
|
||||
|
||||
→ POST /api/client/register
|
||||
authorization: *:production.e4455...
|
||||
unleash-appname: codeium-language-server
|
||||
Body (561 bytes, JSON):
|
||||
{"appName":"codeium-language-server","instanceId":"..."}
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Your App<br/>OpenAI SDK] -->|HTTP| B[Proxy<br/>:8741]
|
||||
B -->|gRPC| C[Language<br/>Server]
|
||||
C -->|HTTPS| D[Google /<br/>Anthropic]
|
||||
E[MITM Proxy<br/>:8742] -.->|intercept| D
|
||||
C -.->|routed via| E
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.rs # Entry point, CLI args, lifecycle
|
||||
├── backend.rs # LS discovery and RPC communication
|
||||
├── constants.rs # Version detection + stealth constants
|
||||
├── proto.rs # Hand-rolled protobuf encoder
|
||||
├── quota.rs # LS quota polling and caching
|
||||
├── session.rs # Multi-turn session management
|
||||
├── warmup.rs # Startup warmup (mimics real webview)
|
||||
├── api/
|
||||
│ └── mod.rs # Axum API server + route handlers
|
||||
└── mitm/
|
||||
├── mod.rs # MITM module root
|
||||
├── ca.rs # Dynamic CA cert generation
|
||||
├── proxy.rs # TLS-intercepting proxy server
|
||||
├── intercept.rs # API response parser (usage extraction)
|
||||
└── store.rs # Token usage aggregation store
|
||||
|
||||
scripts/
|
||||
├── mitm-wrapper.sh # Install/uninstall MITM wrapper on LS binary
|
||||
├── standalone-ls.sh # Launch isolated LS instance
|
||||
└── parse-snapshot.py # HTTP/2 traffic snapshot parser
|
||||
```
|
||||
|
||||
## CLI Flags
|
||||
|
||||
```
|
||||
antigravity-proxy [OPTIONS]
|
||||
|
||||
Options:
|
||||
--port <PORT> API server port (default: 8741)
|
||||
--no-mitm Disable MITM proxy
|
||||
--mitm-port <PORT> Override MITM proxy port (default: auto)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Private. Do not distribute.
|
||||
Reference in New Issue
Block a user