110 lines
3.4 KiB
Markdown
110 lines
3.4 KiB
Markdown
# Cockpit Token Extraction & Proxy Setup
|
|
|
|
## Extracting Working Tokens from Cockpit
|
|
|
|
Cockpit stores OpenAI OAuth tokens in its filesystem. These tokens work against `api.openai.com` and can be used to build a free proxy.
|
|
|
|
### Source 1: Backup (may be stale, but readable)
|
|
```python
|
|
import json
|
|
|
|
backup = Path.home() / ".antigravity_cockpit/backups/cockpit_auto_backup_full_*.json"
|
|
# Find latest backup
|
|
with open(backup) as f:
|
|
data = json.load(f)
|
|
|
|
exported = data["accounts"]["platforms"]["codex"]["exported_data"]
|
|
tokens = []
|
|
for acc in exported:
|
|
tokens.append({
|
|
"email": acc["email"],
|
|
"planType": acc["plan_type"],
|
|
"accessToken": acc["tokens"]["access_token"],
|
|
"refreshToken": acc["tokens"]["refresh_token"],
|
|
})
|
|
```
|
|
|
|
### Source 2: Live auths file (locked by cockpit-cliproxy)
|
|
```python
|
|
# Path: ~/.antigravity_cockpit/codex_local_access_sidecar/auths
|
|
# This file is locked with exclusive access while cockpit-cliproxy is running
|
|
# Use Windows API with FILE_SHARE_READ to read it:
|
|
import ctypes
|
|
GENERIC_READ = 0x80000000
|
|
FILE_SHARE_READ = 1 | 2 | 4 # Read + Write + Delete
|
|
handle = kernel32.CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, None, 3, 0, None)
|
|
# Read, parse JSON, extract accessToken from each entry
|
|
```
|
|
|
|
### Source 3: Cockpit codex_accounts.json
|
|
```python
|
|
# Path: ~/.antigravity_cockpit/codex_accounts.json
|
|
# Lists account IDs and emails, but NOT tokens
|
|
# Use to map account IDs to emails
|
|
```
|
|
|
|
## Cockpit API Key Discovery
|
|
|
|
The cockpit-cliproxy API key is stored in:
|
|
```
|
|
~/.antigravity_cockpit/codex_local_access.json
|
|
# → {"apiKey": "agt_codex_..."}
|
|
```
|
|
|
|
Or in backups:
|
|
```
|
|
codex_local_access.json → apiKey field
|
|
```
|
|
|
|
## Cockpit-CliProxy Architecture
|
|
|
|
```
|
|
cockpit-cliproxy (port 64873)
|
|
└─ Reads tokens from codex_local_access_sidecar/auths
|
|
└─ Accepts OpenAI-compatible API requests
|
|
└─ Requires API key in Authorization header
|
|
└─ Models: gpt-5.5, gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, etc.
|
|
```
|
|
|
|
## Building a Passthrough Proxy
|
|
|
|
FastAPI proxy that forwards to cockpit-cliproxy with model name mapping:
|
|
|
|
```python
|
|
COCKPIT_URL = "http://127.0.0.1:64873"
|
|
COCKPIT_KEY = "agt_codex_..." # From codex_local_access.json
|
|
|
|
MODEL_MAP = {
|
|
"gpt-4o": "gpt-5.5",
|
|
"gpt-4": "gpt-5.4",
|
|
"gpt-4o-mini": "gpt-5.4-mini",
|
|
"gpt-3.5-turbo": "gpt-5.4-mini",
|
|
}
|
|
|
|
@app.post("/v1/chat/completions")
|
|
async def chat_completions(request: Request):
|
|
body = await request.json()
|
|
cockpit_model = MODEL_MAP.get(body["model"], body["model"])
|
|
|
|
r = await http_client.post(
|
|
f"{COCKPIT_URL}/v1/chat/completions",
|
|
headers={"Authorization": f"Bearer {COCKPIT_KEY}"},
|
|
json={**body, "model": cockpit_model},
|
|
)
|
|
return Response(r.content, status_code=r.status_code, headers=dict(r.headers))
|
|
```
|
|
|
|
**Important:** The proxy should pass through streaming responses as-is (no buffering). Cockpit-cliproxy handles round-robin token selection automatically.
|
|
|
|
## Token Characteristics
|
|
|
|
- **Format:** JWT (eyJhbG...), ~2000-2128 chars
|
|
- **Provider:** `openai_builtin` (OAuth tokens from auth.openai.com)
|
|
- **Lifetime:** ~1 hour (access token), refreshed by cockpit-cliproxy
|
|
- **Plan types:** k12 (workspace), team, free
|
|
- **Rate limits:** ~40-80 requests per 3 hours per account for GPT-4 class models
|
|
|
|
## Proxy Template
|
|
|
|
Full working proxy at: `C:/Users/User/codex_proxy/proxy.py`
|
|
Pool file at: `C:/Users/User/Desktop/chatgpt_token_pool.json` |