feat(providers): add Antigravity provider for unified Claude/Gemini access
Some checks failed
Semantic Release / release (push) Has been cancelled

Implements a new provider that uses Google's Antigravity unified gateway API to access Claude, Gemini, and other models through a single OAuth2-authenticated endpoint.

Features:
- OAuth2 token management with automatic refresh
- Multi-account rotation for rate limit distribution
- Support for Claude Opus/Sonnet 4.5 (with/without thinking)
- Support for Gemini 2.5/3 models (Pro/Flash variants)
- Thinking mode support with configurable tokens
- Image processing support
- Dual quota pool tracking (antigravity vs gemini-cli)
- Gemini-style API request format

Authentication:
- Reads from ANTIGRAVITY_REFRESH_TOKEN env var (priority)
- Falls back to ~/.config/opencode/antigravity-accounts.json
- Automatic token refresh with retry logic
- Rate limit tracking per account and quota pool

Files added:
- providers/antigravity.py - Main provider implementation
- providers/antigravity_auth.py - OAuth token manager
- providers/registries/antigravity.py - Model registry
- conf/antigravity_models.json - Model definitions (11 models)
- docs/antigravity_provider.md - Setup and usage docs
- tests/test_antigravity_provider.py - Unit tests (14 pass)

Integration:
- Added to provider priority order after ZEN
- Registered in server.py with auto-detection
- ToS warning logged on first use
This commit is contained in:
2026-02-01 17:55:26 +01:00
parent c71a535f16
commit 5add230d4c
10 changed files with 1612 additions and 1 deletions

View File

@@ -41,6 +41,7 @@ class ModelProviderRegistry:
ProviderType.AZURE, # Azure-hosted OpenAI deployments
ProviderType.XAI, # Direct X.AI GROK access
ProviderType.ZEN, # OpenCode Zen curated models
ProviderType.ANTIGRAVITY, # Antigravity unified gateway (Claude/Gemini via Google OAuth)
ProviderType.DIAL, # DIAL unified API access
ProviderType.CUSTOM, # Local/self-hosted models
ProviderType.OPENROUTER, # Catch-all for cloud models
@@ -140,6 +141,19 @@ class ModelProviderRegistry:
azure_endpoint=azure_endpoint,
api_version=azure_version,
)
elif provider_type == ProviderType.ANTIGRAVITY:
# Antigravity uses OAuth tokens from file or env var
# The provider handles token loading internally
from pathlib import Path
# Check if refresh token is available from env or accounts file
accounts_file = Path.home() / ".config" / "opencode" / "antigravity-accounts.json"
if not api_key and not accounts_file.exists():
logging.debug("Antigravity: No refresh token in env and no accounts file found")
return None
# Initialize provider (it will load tokens internally)
provider = provider_class(api_key=api_key or "")
else:
if not api_key:
return None
@@ -341,6 +355,7 @@ class ModelProviderRegistry:
ProviderType.OPENROUTER: "OPENROUTER_API_KEY",
ProviderType.CUSTOM: "CUSTOM_API_KEY", # Can be empty for providers that don't need auth
ProviderType.DIAL: "DIAL_API_KEY",
ProviderType.ANTIGRAVITY: "ANTIGRAVITY_REFRESH_TOKEN", # Uses OAuth refresh token, not API key
}
env_var = key_mapping.get(provider_type)