Files
zerogravity/docs/mitm.md
Nikketryhard 3d87c04d20 docs: overhaul docs, add architecture and traces, update README/GEMINI
- Add docs/architecture.md with 4 mermaid diagrams
- Add docs/mitm.md with 3 mermaid diagrams (replaces mitm-interception-status)
- Add docs/traces.md documenting per-call trace system
- Rewrite README.md to be concise with mermaid and doc refs
- Rewrite GEMINI.md for core philosophy and agent usage
- Clean extension-server-analysis.md (remove stale debug sections)
- Delete temp docs: standalone-ls-todo, panel-stream-investigation,
  endpoint-gap-analysis, request-comparison
2026-02-18 01:31:18 -06:00

6.1 KiB

MITM Proxy

Overview

The built-in MITM proxy intercepts all traffic between the standalone LS and Google's API. It decrypts TLS, parses SSE responses, captures real token usage, and modifies requests to inject tools, parameters, and images.

sequenceDiagram
    participant LS as Standalone LS
    participant IPT as iptables
    participant MITM as MITM Proxy :8742
    participant Store as MitmStore
    participant G as Google API

    LS->>IPT: HTTPS :443
    IPT->>MITM: REDIRECT (UID-scoped)
    MITM->>MITM: TLS terminate (dynamic cert)
    MITM->>Store: Match request by cascade_id
    Store-->>MITM: RequestContext (tools, params, image)
    MITM->>MITM: modify_request()
    MITM->>G: Forward modified request
    G-->>MITM: SSE stream
    MITM->>MITM: Parse SSE, extract usage
    MITM->>Store: Dispatch events (TextDelta, Usage, etc.)
    MITM-->>LS: Forward original response

Components

graph TD
    subgraph "MITM Module"
        proxy["proxy.rs\nTLS termination\nSNI-based routing"]
        h2["h2_handler.rs\nHTTP/2 frame handling"]
        intercept["intercept.rs\nSSE parser\nUsage extraction"]
        modify["modify.rs\nRequest injection\n(tools, params, images)"]
        store["store.rs\nMitmStore\nEvent channels"]
        proto["proto.rs\nProtobuf codec"]
        ca["ca.rs\nCA + dynamic certs"]
    end

    proxy --> h2
    h2 --> intercept
    h2 --> modify
    modify --> store
    intercept --> store
    proxy --> ca
    modify --> proto

    style store fill:#dc2626,color:#fff
    style proxy fill:#ea580c,color:#fff
File Purpose
proxy.rs Accepts iptables-redirected connections, terminates TLS via SNI, manages connection lifecycle
h2_handler.rs HTTP/2 frame-level handling for CONNECT-style proxying
intercept.rs Parses Google's SSE data: lines, extracts usageMetadata, detects finishReason
modify.rs Injects tools, generation params, images, tool results, Google Search grounding into requests
store.rs Central state — RequestContext registry, event channels (MitmEvent), usage accumulation
proto.rs Protobuf encode/decode for intercepted request/response bodies
ca.rs Generates CA certificate and per-domain leaf certs for TLS termination

Request Modification

When the MITM proxy intercepts an outgoing request from the LS, it applies modifications from the RequestContext stored by the API handler:

flowchart TD
    A["Original LS Request"] --> B{"Has tools?"}
    B -- Yes --> C["Inject tool definitions\n+ toolConfig"]
    B -- No --> D{"Has generation params?"}
    C --> D
    D -- Yes --> E["Inject temperature, top_p,\nmax_output_tokens, stop_sequences,\nfrequency/presence_penalty"]
    D -- No --> F{"Has image?"}
    E --> F
    F -- Yes --> G["Inject inlineData\n(base64) into user parts"]
    F -- No --> H{"Has tool results?"}
    G --> H
    H -- Yes --> I["Inject functionResponse\nparts"]
    H -- No --> J{"Google Search?"}
    I --> J
    J -- Yes --> K["Enable Google Search\ngrounding tool"]
    J -- No --> L["Replace user text\nwith real input"]
    K --> L
    L --> M["Update Content-Length"]
    M --> N["Forward to Google"]

    style A fill:#2563eb,color:#fff
    style N fill:#059669,color:#fff

SSE Response Format

Google's API returns SSE events:

data: {"response": {"candidates": [{"content": {"role": "model", "parts": [{"text": "..."}]}}],
       "usageMetadata": {"promptTokenCount": 1514, "candidatesTokenCount": 25,
                         "totalTokenCount": 1539, "thoughtsTokenCount": 52},
       "modelVersion": "gemini-3-flash"}, "traceId": "...", "metadata": {}}

The last event includes "finishReason": "STOP" in the candidate.


MitmEvent Channel

Events dispatched through tokio::sync::mpsc channels from MITM → API handlers:

Event Source Data
TextDelta(String) intercept.rs Incremental text from model
ThinkingDelta(String) intercept.rs Thinking/reasoning text
Usage(ApiUsage) intercept.rs Token counts (input, output, thinking, cache)
FunctionCall(Vec) intercept.rs Tool calls from model
Grounding(Value) intercept.rs Google Search grounding metadata
ResponseComplete intercept.rs Stream finished
UpstreamError(Value) intercept.rs Google API error (400, 429, 500)

Setup

UID-Scoped iptables (Classic Mode)

# One-time setup — creates antigravity-ls user + iptables rule
sudo ./scripts/mitm-redirect.sh install

# Run proxy (standalone LS + MITM both enabled by default)
RUST_LOG=info ./target/release/antigravity-proxy

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

# Cleanup
sudo ./scripts/mitm-redirect.sh uninstall

Headless Mode

No iptables or sudo needed. The LS connects through HTTPS_PROXY instead:

RUST_LOG=info ./target/release/antigravity-proxy --headless

Intercepted Endpoints

Endpoint Type Content
streamGenerateContent SSE/JSON LLM responses (parsed)
fetchUserInfo Protobuf User info
loadCodeAssist Protobuf Extension config
fetchAvailableModels Protobuf Model catalog
recordCodeAssistMetrics Protobuf Telemetry (ignored)
recordTrajectoryAnalytics Protobuf Telemetry (ignored)