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

@@ -392,6 +392,7 @@ def configure_providers():
value = get_env(key)
logger.debug(f" {key}: {'[PRESENT]' if value else '[MISSING]'}")
from providers import ModelProviderRegistry
from providers.antigravity import AntigravityProvider
from providers.azure_openai import AzureOpenAIProvider
from providers.custom import CustomProvider
from providers.dial import DIALModelProvider
@@ -490,6 +491,21 @@ def configure_providers():
else:
logger.debug("OpenCode Zen API key is placeholder value")
# Check for Antigravity OAuth accounts
antigravity_token = get_env("ANTIGRAVITY_REFRESH_TOKEN")
antigravity_accounts_file = Path.home() / ".config" / "opencode" / "antigravity-accounts.json"
has_antigravity = False
if antigravity_token:
valid_providers.append("Antigravity (OAuth)")
has_antigravity = True
logger.info("Antigravity refresh token found - Claude/Gemini models via unified gateway")
elif antigravity_accounts_file.exists():
valid_providers.append("Antigravity (OAuth)")
has_antigravity = True
logger.info("Antigravity accounts file found - Claude/Gemini models via unified gateway")
else:
logger.debug("Antigravity: No refresh token or accounts file found")
# Check for custom API endpoint (Ollama, vLLM, etc.)
custom_url = get_env("CUSTOM_API_URL")
if custom_url:
@@ -551,7 +567,13 @@ def configure_providers():
registered_providers.append(ProviderType.ZEN.value)
logger.debug(f"Registered provider: {ProviderType.ZEN.value}")
# 4. OpenRouter last (catch-all for everything else)
# 4. Antigravity (Google unified gateway for Claude/Gemini)
if has_antigravity:
ModelProviderRegistry.register_provider(ProviderType.ANTIGRAVITY, AntigravityProvider)
registered_providers.append(ProviderType.ANTIGRAVITY.value)
logger.debug(f"Registered provider: {ProviderType.ANTIGRAVITY.value}")
# 5. OpenRouter last (catch-all for everything else)
if has_openrouter:
ModelProviderRegistry.register_provider(ProviderType.OPENROUTER, OpenRouterProvider)
registered_providers.append(ProviderType.OPENROUTER.value)