Overall: OpenCode plugin — fetch-interceptor that transforms Gemini API requests into Antigravity (Cloud Code Assist) format, with OAuth multi-account rotation, quota management, session recovery, and cross-model compatibility.
Key Characteristics:
- Single
createAntigravityPluginfactory insrc/plugin/index.tsthat returns the full OpenCode plugin surface - All outbound traffic to
generativelanguage.googleapis.comis intercepted and rewritten before it leaves the process - Two header-style routing paths:
antigravity(Electron-style UA + fingerprint) andgemini-cli(nodejs-client UA) - All state (accounts, rate-limit counters, health scores) is module-level; the plugin factory runs once per session
- Config schema is Zod-validated; environment variables always override file config
Entry Point / Composition Root:
- Purpose: Initialize shared module state, wire plugin factories, and return the OpenCode hook surface
- Location:
src/plugin/index.ts - Contains:
createAntigravityPluginfactory and subsystem wiring - Depends on: Hook, auth, tool, account-access, OAuth, and fetch factories
- Used by: OpenCode host via
@opencode-ai/plugincontract
OAuth / Credentials:
- Purpose: OAuth token exchange with Google, token refresh, access-token lifecycle
- Location:
src/antigravity/oauth.ts,src/plugin/auth.ts,src/plugin/token.ts - Contains:
authorizeAntigravity,exchangeAntigravity,refreshAccessToken,AntigravityTokenRefreshError, token expiry helpers - Depends on:
@openauthjs/openauth,src/constants.ts - Used by:
src/plugin/oauth-methods.ts,src/plugin/auth-loader.ts,src/plugin/refresh-queue.ts
Request Transform:
- Purpose: Convert OpenCode/Anthropic-format request bodies into Antigravity (Cloud Code Assist) wire format and back
- Location:
src/plugin/request.ts,src/plugin/request-helpers.ts,src/plugin/transform/ - Contains:
prepareAntigravityRequest,transformAntigravityResponse, schema cleaning, thinking-block stripping, tool-hardening injection, cross-model sanitisation, stable system-instruction ordering (prompt → tool hardening → thinking hint) for prompt caching, and streaming cache-stats tracking viaonUsageMetadatacallback - Depends on:
src/constants.ts,src/plugin/transform/,src/plugin/thinking-recovery.ts,src/plugin/cache/ - Used by:
src/plugin/fetch-interceptor.ts
Model Resolution & Per-Model Transforms:
- Purpose: Map request model names to Antigravity model IDs, choose header style (antigravity vs gemini-cli), apply model-specific config, resolve thinking tier budgets
- Location:
src/plugin/transform/model-resolver.ts,src/plugin/transform/claude.ts,src/plugin/transform/gemini.ts,src/plugin/transform/cross-model-sanitizer.ts,src/plugin/model-registry.ts - Contains:
resolveModelWithTier,resolveModelWithVariant,resolveModelForHeaderStyle,applyClaudeTransforms,applyGeminiTransforms,sanitizeCrossModelPayload,supportsThinkingTiers,extractThinkingTierFromModel - Depends on:
src/plugin/transform/types.ts - Used by:
src/plugin/request.ts
Multi-Account Management:
- Purpose: Track per-account OAuth state, rate-limit cooldowns, quota cache, fingerprints, and daily request usage; select the best account for each request; detect and repair auth storage drift; track session metrics and request rate estimation
- Location:
src/plugin/accounts.ts,src/plugin/storage.ts,src/plugin/rotation.ts,src/plugin/fingerprint.ts,src/plugin/auth-doctor.ts,src/plugin/auth-drift.ts - Contains:
AccountManager,HealthScoreTracker,TokenBucketTracker,selectHybridAccount,generateFingerprint,buildFingerprintHeaders,FingerprintVersionhistory (max 5), account storage version 4 support with migration, secure POSIX permissions,detectAuthStorageDrift,createAuthDoctorReport, self-healing repairs, per-family daily request tracking, and in-memory session summaries with hourly rate calculations - Depends on:
src/plugin/auth.ts,src/plugin/quota.ts,proper-lockfile,xdg-basedir - Used by:
src/plugin/auth-loader.ts,src/plugin/fetch-interceptor.ts,src/plugin/lifecycle.ts
Token Refresh Queue:
- Purpose: Background proactive OAuth token refresh so requests never block on expiry
- Location:
src/plugin/refresh-queue.ts - Contains:
ProactiveRefreshQueue,createProactiveRefreshQueue - Depends on:
src/plugin/accounts.ts,src/plugin/token.ts - Used by:
src/plugin/auth-loader.ts,src/plugin/lifecycle.ts
Quota:
- Purpose: Query Antigravity API for per-account quota usage; populate quota cache used by AccountManager for soft-quota gating; fetch Antigravity and Gemini CLI quotas in parallel; handle sequential endpoint fallback; track per-model quota data; manage stale-cache fail-open scenarios
- Location:
src/plugin/quota.ts - Contains:
checkAccountsQuota,QuotaGroup,QuotaGroupSummary,fetchGeminiCliQuota, parallel fetches, wider model matching (gemini-3.5-, gemini-3.1-, gemini-2.5-*),gpt-ossquota group tracking, sequential endpoint fallbacks acrossANTIGRAVITY_ENDPOINT_FALLBACKS, per-model quota tracking (cachedPerModelQuota), stale-cache fail-open (treating 0% quota asREADYwhen reset time is past or missing), and paywall detection ((unavailable)status) - Depends on: OAuth token utilities,
src/plugin/model-registry.ts - Used by:
src/plugin/fetch-interceptor.ts,src/plugin/oauth-methods.ts,src/plugin/accounts.ts
Session Recovery:
- Purpose: Detect interrupted tool executions (
tool_result_missing) and malformed thinking blocks; inject synthetic completions to restore session - Location:
src/plugin/recovery/(index.ts,types.ts,constants.ts,storage.ts),src/plugin/thinking-recovery.ts - Contains:
createSessionRecoveryHook,isRecoverableError,handleSessionRecovery,analyzeConversationState,closeToolLoopForThinking - Depends on: OpenCode session client API
- Used by:
src/plugin/event-handler.ts
Signature Cache:
- Purpose: Persist and recall Claude thinking-block signatures across requests and restarts when
keep_thinkingis enabled - Location:
src/plugin/cache/(index.ts,signature-cache.ts),src/plugin/stores/signature-store.ts - Contains:
SignatureCache,createSignatureCache,defaultSignatureStore - Depends on:
src/plugin/config/ - Used by:
src/plugin/request.ts
Streaming Core:
- Purpose: Transform SSE stream payloads line-by-line; cache signatures; inject debug annotations
- Location:
src/plugin/core/streaming/(transformer.ts,types.ts,index.ts) - Contains:
createStreamingTransformer,transformSseLine,transformStreamingPayload, andonUsageMetadatacallback to extract usage stats and log cache hit-rate at stream completion - Depends on:
src/plugin/stores/signature-store.ts - Used by:
src/plugin/request.ts
Configuration:
- Purpose: Load, merge, and validate plugin configuration from files and environment variables
- Location:
src/plugin/config/(schema.ts,loader.ts,models.ts,updater.ts,index.ts) - Contains:
AntigravityConfigSchema,loadConfig,initRuntimeConfig,AntigravityConfig, settings forthinking_warmup,max_account_switches,quota_style_fallback - Depends on:
zod - Used by:
src/plugin/index.ts, mostsrc/plugin/modules viagetKeepThinking()etc.
Auto-Update Checker Hook:
- Purpose: On
session.created, check npm for a newer plugin version and optionally auto-update the pinned version inopencode.json - Location:
src/hooks/auto-update-checker/(index.ts,checker.ts,cache.ts,logging.ts,constants.ts,types.ts) - Contains:
createAutoUpdateCheckerHook,getLatestVersion,updatePinnedVersion - Depends on: npm registry HTTP, OpenCode TUI toast API
- Used by:
src/plugin/index.ts, forwarded bysrc/plugin/event-handler.ts
Google Search Tool:
- Purpose: Expose a
google_searchOpenCode tool that runs separate Antigravity API calls with native grounding tools - Location:
src/plugin/search.ts - Contains:
executeSearch - Depends on:
src/constants.ts,src/plugin/logger.ts - Used by:
src/plugin/index.ts(registers the tool)
Logging / Debug:
- Purpose: Structured per-module logger with TUI integration; detailed debug file logging for request/response inspection
- Location:
src/plugin/logger.ts,src/plugin/debug.ts,src/plugin/logging-utils.ts - Contains:
createLogger,initLogger,initializeDebug,isDebugEnabled,logAntigravityDebugResponse - Depends on: OpenCode TUI client
- Used by: All modules
Errors:
- Purpose: Domain-specific error classes with metadata
- Location:
src/plugin/errors.ts - Contains:
EmptyResponseError, and other typed error classes - Depends on: nothing
- Used by:
src/plugin/fetch-interceptor.ts,src/plugin/request.ts
CLI / UI:
- Purpose: Interactive terminal prompts for login, account selection, project ID entry, per-model availability, and aggregate quota health display
- Location:
src/plugin/cli.ts,src/plugin/ui/(auth-menu.ts,ansi.ts,confirm.ts,select.ts,model-status.ts,quota-status.ts) - Contains:
promptLoginMode,promptAddAnotherAccount,promptProjectId,showAuthMenuwith two-line layout and status/availability breakdown per model group,getModelStatusFromAccounts,formatQuotaStatusBadge,classifyGroupStatuswith stale-cache fail-open, andbuildModelBreakdownshowing available/exhausted model counts - Depends on: Node.js readline
- Used by:
src/plugin/oauth-methods.ts,src/plugin/account-access.ts
Request Transform Pipeline:
- OpenCode calls plugin
loader()with the original request —src/plugin/auth-loader.ts isGenerativeLanguageRequest()confirms the URL matches —src/plugin/request.tsAccountManager.selectAccount()picks the best OAuth account —src/plugin/accounts.tsresolveModelWithTier()maps model name → Antigravity model ID + header style —src/plugin/transform/model-resolver.tsprepareAntigravityRequest()cleans schema, strips thinking blocks for Claude, injects tool-hardening, and appends Claude thinking hints in a strict stable ordering (original prompt → tool hardening → thinking hint) to maximize prompt cache hits —src/plugin/request.ts,src/plugin/request-helpers.tsbuildFingerprintHeaders()attaches per-account device fingerprint —src/plugin/fingerprint.tsfetch()is called against Antigravity endpoint with Bearer token —src/plugin/fetch-interceptor.tsaccountManager.recordRequest()tracks daily request usage per account and updates in-memory session request counts for rate consumption estimation —src/plugin/fetch-interceptor.ts,src/plugin/accounts.tstransformAntigravityResponse()converts SSE stream back to Gemini API format —src/plugin/request.ts- Streaming transformer processes each SSE line, caches signatures, injects debug annotations, and fires
onUsageMetadatacallback to log cache hit statistics upon stream termination —src/plugin/core/streaming/
Rate-Limit Retry Loop:
- 429 / 503 response received —
src/plugin/fetch-interceptor.ts parseRateLimitReason()classifies the error —src/plugin/accounts.ts- Retry state computes delay with deduplication —
src/plugin/fetch/retry-state.ts AccountManager.markRateLimited()records cooldown —src/plugin/accounts.ts- If other accounts available,
selectAccount()switches —src/plugin/accounts.ts - Loop retries until success or
max_rate_limit_wait_secondsexceeded
OAuth Login Flow:
- OAuth authorization invoked by OpenCode host —
src/plugin/oauth-methods.ts authorizeAntigravity()generates authorization URL —src/antigravity/oauth.ts- Local HTTP listener or manual URL paste captures callback —
src/plugin/server.ts exchangeAntigravity()exchanges code → tokens —src/antigravity/oauth.tspersistAccountPool()merges intoantigravity-accounts.json—src/plugin/persist-account-pool.ts,src/plugin/storage.ts
Session Recovery:
session.errorevent fires —src/plugin/event-handler.tsisRecoverableError()checks error type —src/plugin/recovery/handleSessionRecovery()injects synthetictool_resultblocks —src/plugin/recovery/- If
auto_resume, plugin sends a "continue" prompt viaclient.session.prompt()—src/plugin/event-handler.ts
Quota Tracking & Refresh Flow:
- Background refresh or user-triggered update invokes quota management —
src/plugin/fetch-interceptor.ts,src/plugin/oauth-methods.ts fetchAvailableModels()andfetchGeminiCliQuota()query endpoints sequentially acrossANTIGRAVITY_ENDPOINT_FALLBACKS—src/plugin/quota.ts- Quota responses map to group-level (
cachedQuota) and model-level (cachedPerModelQuota) summaries —src/plugin/quota.ts - Active storage persists the updated summaries —
src/plugin/storage.ts - The terminal UI
showAuthMenu()displays the status, treating stale cache values (0% remaining without a future reset time or reset time in the past) asREADY(fail-open) and displaying paywalled Pro models as(unavailable)—src/plugin/ui/auth-menu.ts,src/plugin/ui/quota-status.ts
AccountManager:
- Purpose: Single source of truth for all OAuth accounts, their cooldowns, health scores, quota caches, fingerprints, and daily/session request metrics
- Location:
src/plugin/accounts.ts - Pattern: Stateful class with selection algorithms (
sticky,round-robin,hybrid) delegating toHealthScoreTrackerandTokenBucketTracker; tracks in-memory session stats and persists daily request counters on disk
AntigravityConfig / AntigravityConfigSchema:
- Purpose: Zod-validated runtime configuration with environment variable overrides
- Location:
src/plugin/config/schema.ts,src/plugin/config/loader.ts - Pattern: Zod schema →
z.infer<>type, merged from project file + user file + env vars
HeaderStyle:
- Purpose: Discriminate between
antigravity(Electron UA) andgemini-cli(nodejs UA) request paths - Location:
src/constants.ts,src/plugin/transform/model-resolver.ts - Pattern: String literal union; resolved per model name suffix (
:antigravityvs no suffix)
ModelFamily:
- Purpose: Route model-specific logic (
claudevsgemini) - Location:
src/plugin/storage.ts(type),src/plugin/transform/model-resolver.ts - Pattern: Discriminated string union used by
AccountManager,quota.ts, and rate-limit key construction
ModelQuotaGroup:
- Purpose: Partition available models into four quota tracking groups (
claude,gemini-pro,gemini-flash, andgpt-oss) - Location:
src/plugin/model-registry.ts(type),src/plugin/quota.ts(tracking) - Pattern: String literal union mapping physical model IDs to logical quota partitions, allowing parallel quota fetching, aggregated health reporting, and granular per-model status rendering (
cachedPerModelQuotatracks individual models)
AuthDoctor:
- Purpose: Diagnose and self-heal storage inconsistencies and active credentials drift
- Location:
src/plugin/auth-doctor.ts,src/plugin/auth-drift.ts - Pattern: Diagnostic functional reporting (
createAuthDoctorReport) that identifies severity findings and suggests/applies target repairs (e.g., restoring active accounts, clamping indices)
SignatureStore / SignatureCache:
- Purpose: Cache Claude thinking-block signatures in memory and optionally on disk, keyed by session
- Location:
src/plugin/core/streaming/types.ts,src/plugin/cache/signature-cache.ts,src/plugin/stores/signature-store.ts - Pattern: Map-based store with TTL; disk layer uses JSON file with background flush interval
Plugin Factory:
- Location:
src/plugin/index.ts→createAntigravityPlugin(providerId) - Triggers: OpenCode loads package
index.ts, which exports the initialized plugin aliases - Responsibilities: Initialize all subsystems, register auth methods, and return the OpenCode hook surface
Root Index:
- Location:
index.ts - Triggers: OpenCode plugin host imports the package
- Responsibilities: Export only
AntigravityCLIOAuthPluginandGoogleOAuthPlugin
Auto-Update Hook:
- Location:
src/hooks/auto-update-checker/index.ts - Triggers:
session.createdevent - Responsibilities: Compare current vs latest npm version; update
opencode.jsonpin if auto-update enabled
Strategy: Defensive try/catch with graceful degradation — fallback values rather than crashes. Rate-limit and quota errors trigger account rotation, not failure. Session errors trigger recovery injection. Empty responses retry up to empty_response_max_attempts times before returning a synthetic error response. Token refresh failures throw typed AntigravityTokenRefreshError. Unknown errors are caught, logged, and surfaced as domain errors to callers. Capacity rate-limits (503/429) trigger a device fingerprint regeneration after 1 attempt per endpoint fallback.
Logging: createLogger("module-name") from src/plugin/logger.ts for structured per-module logging with dual sinks: TUI log panel (debug_tui) and debug file (debug). Per-message API request counters track request volumes for diagnostic visibility. Post-request logging outputs cached remaining quota percentages, session request rates (average requests per hour), and cache hit/miss statistics (HIT, MISS, WRITE status and hit rate percentage) computed from response usage metadata. console.log only in CLI / interactive auth flows.
Caching: In-memory signature store for thinking blocks; optional disk persistence via SignatureCache when keep_thinking is enabled. Auth tokens cached per-account in AccountManager. Quota data cached per-account with configurable TTL and background parallel refreshes. Prompt caching utilizes a strict prefix-stabilization ordering (stable system instructions first, dynamic content last) to maximize gateway-level cache hits.
Storage: Accounts persisted to antigravity-accounts.json (XDG data dir) via src/plugin/storage.ts with proper-lockfile for concurrent-write safety. Current format is version 4, featuring automatic migration from older versions (v1, v2, v3), secure POSIX permissions (0600), and legacy Windows path migration. Persists per-account daily request counters (dailyRequestCounts) and per-model granular quota data (cachedPerModelQuota). Config loaded from .opencode/antigravity.json (project) and ~/.config/opencode/antigravity.json (user).
Configuration: Two-level config file hierarchy (project overrides user) plus environment variable overrides. All config is read once at startup via loadConfig() and made available globally via initRuntimeConfig() and module-level getters. Config supports quota fallback disabling via quota_style_fallback: false, switches limit via max_account_switches: 2, and thinking warmup option thinking_warmup: false.