### Install Project Dependencies (Bash) Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md This bash script outlines the steps to set up the project locally. It includes cloning the repository, navigating into the project directory, and installing dependencies using 'bun install'. ```bash git clone https://github.com/shekohex/opencode-google-antigravity-auth.git cd opencode-google-antigravity-auth bun install ``` -------------------------------- ### Testing Opencode Antigravity Integration with Gemini Models Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md This sequence of commands outlines the process for testing the Opencode Antigravity authentication and model integration. It covers installing the plugin, logging in with Antigravity, and then running sample requests to Gemini models to verify successful responses and the absence of API key prompts. ```bash opencode auth login # Pick Antigravity and complete browser flow or copy/paste if headless. ``` ```bash opencode run -m google/gemini-2.5-flash -p "hello" ``` ```bash opencode run -m google/gemini-3-pro-high -p "solve this" ``` -------------------------------- ### Start Local OAuth Callback Server (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt This function starts a local HTTP server to capture OAuth redirects during the authentication flow. It listens on port 36742, extracts the authorization code and state, and displays a success page. Dependencies include the 'opencode-google-antigravity-auth/src/plugin/server' module and functions like 'authorizeAntigravity', 'openBrowser', and 'exchangeAntigravity'. ```typescript import { startOAuthListener } from "opencode-google-antigravity-auth/src/plugin/server"; // Start the callback listener before initiating OAuth const listener = await startOAuthListener({ timeoutMs: 5 * 60 * 1000 }); // 5 min timeout // Generate authorization URL and open in browser const authorization = await authorizeAntigravity(); console.log(`Opening browser: ${authorization.url}`); await openBrowser(authorization.url); try { // Wait for callback (blocks until user completes auth or timeout) const callbackUrl = await listener.waitForCallback(); // callbackUrl = URL { http://localhost:36742/oauth-callback?code=...&state=... } const code = callbackUrl.searchParams.get("code"); const state = callbackUrl.searchParams.get("state"); // Exchange code for tokens const result = await exchangeAntigravity(code, state); console.log(`Authenticated: ${result.email}`); } catch (error) { if (error.message === "Timed out waiting for OAuth callback") { console.log("Authentication timed out. Please try again."); } else { console.error("OAuth callback failed:", error); } } finally { // Clean up server await listener.close(); } // The server displays a styled success page with: // - "You're connected to Opencode" message // - "Close window" button // - Instructions for reconnecting later ``` -------------------------------- ### Example Opencode Configuration with Google Provider and Models Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md This JSON configuration defines the opencode plugin and specifies the Google provider with various Gemini models. It includes details like model IDs, names, release dates, reasoning capabilities, context and output limits, cost information, supported modalities, and different variant options for reasoning levels. ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["opencode-google-antigravity-auth"], "provider": { "google": { "npm": "@ai-sdk/google", "models": { "gemini-3-pro-preview": { "id": "gemini-3-pro-preview", "name": "Gemini 3 Pro", "release_date": "2025-11-18", "reasoning": true, "limit": { "context": 1000000, "output": 64000 }, "cost": { "input": 2, "output": 12, "cache_read": 0.2 }, "modalities": { "input": ["text", "image", "video", "audio", "pdf"], "output": ["text"] }, "variants": { "low": { "options": { "thinkingConfig": { "thinkingLevel": "low", "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingLevel": "medium", "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingLevel": "high", "includeThoughts": true } } } } }, "gemini-3-flash": { "id": "gemini-3-flash", "name": "Gemini 3 Flash", "release_date": "2025-12-17", "reasoning": true, "limit": { "context": 1048576, "output": 65536 }, "cost": { "input": 0.5, "output": 3, "cache_read": 0.05 }, "modalities": { "input": ["text", "image", "video", "audio", "pdf"], "output": ["text"] }, "variants": { "minimal": { "options": { "thinkingConfig": { "thinkingLevel": "minimal", "includeThoughts": true } } }, "low": { "options": { "thinkingConfig": { "thinkingLevel": "low", "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingLevel": "medium", "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingLevel": "high", "includeThoughts": true } } } } }, "gemini-2.5-flash-lite": { "id": "gemini-2.5-flash-lite", "name": "Gemini 2.5 Flash Lite", "reasoning": false }, "gemini-claude-sonnet-4-5-thinking": { "id": "gemini-claude-sonnet-4-5-thinking", "name": "Claude Sonnet 4.5", "reasoning": true, "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, "variants": { "none": { "reasoning": false, "options": { "thinkingConfig": { "includeThoughts": false } } }, "low": { "options": { "thinkingConfig": { "thinkingBudget": 4000, "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingBudget": 16000, "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingBudget": 32000, "includeThoughts": true } } } } }, "gemini-claude-opus-4-5-thinking": { "id": "gemini-claude-opus-4-5-thinking", "name": "Claude Opus 4.5", "release_date": "2025-11-24", "reasoning": true, "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, "variants": { "low": { "options": { "thinkingConfig": { "thinkingBudget": 4000, "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingBudget": 16000, "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingBudget": 32000, "includeThoughts": true } } } } } } } } } ``` -------------------------------- ### Register Antigravity OAuth Plugin in Opencode Configuration (JSON) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt This JSON configuration snippet demonstrates how to register the Antigravity OAuth Plugin within your Opencode setup. It specifies the plugin to be loaded and configures the Google provider with model details, including limits, modalities, and variants for different thinking levels. ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["opencode-google-antigravity-auth"], "provider": { "google": { "npm": "@ai-sdk/google", "models": { "gemini-3-pro-preview": { "id": "gemini-3-pro-preview", "name": "Gemini 3 Pro", "limit": { "context": 1000000, "output": 64000 }, "modalities": { "input": ["text", "image", "video", "audio", "pdf"], "output": ["text"] }, "variants": { "low": { "options": { "thinkingConfig": { "thinkingLevel": "low", "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingLevel": "medium", "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingLevel": "high", "includeThoughts": true } } } } }, "gemini-claude-sonnet-4-5-thinking": { "id": "gemini-claude-sonnet-4-5-thinking", "name": "Claude Sonnet 4.5", "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, "variants": { "low": { "options": { "thinkingConfig": { "thinkingBudget": 4000, "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingBudget": 16000, "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingBudget": 32000, "includeThoughts": true } } } } } } } } } ``` -------------------------------- ### Debugging Antigravity Requests with Opencode CLI Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md These bash commands demonstrate how to enable detailed logging for Antigravity requests using the Opencode command-line interface. This is crucial for diagnosing issues by setting the log level to DEBUG and either printing logs directly or directing them to log files. ```bash opencode --log-level DEBUG --print-logs ``` ```bash opencode --log-level DEBUG ``` -------------------------------- ### Manage Account Storage with TypeScript Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt This snippet demonstrates how to use the storage module to load and save account metadata and rate limit state. It handles automatic migration from older storage formats to v3 and shows how to access account details and rate limit information. The storage path is automatically determined based on the operating system. ```typescript import { loadAccounts, saveAccounts, getStoragePath } from "opencode-google-antigravity-auth/src/plugin/storage"; // Storage location const storagePath = getStoragePath(); // Linux/Mac: ~/.local/share/opencode/antigravity-accounts.json // Windows: %APPDATA%/opencode/antigravity-accounts.json // Load existing accounts (auto-migrates from v1/v2 to v3) const storage = await loadAccounts(); if (storage) { console.log(`Version: ${storage.version}`); // Always 3 after loading console.log(`Active account: ${storage.activeIndex}`); for (const account of storage.accounts) { console.log(`- ${account.email || "Unknown"}`); console.log(` Tier: ${account.tier || "unknown"}`); console.log(` Project: ${account.projectId}`); console.log(` Last used: ${new Date(account.lastUsed)}`); // Per-model rate limits if (account.rateLimitResetTimes) { if (account.rateLimitResetTimes.claude) { console.log(` Claude rate-limited until: ${new Date(account.rateLimitResetTimes.claude)}`); } if (account.rateLimitResetTimes["gemini-flash"]) { console.log(` Gemini Flash limited until: ${new Date(account.rateLimitResetTimes["gemini-flash"])}`); } } } } // Save updated account state await saveAccounts({ version: 3, accounts: [ { email: "user@gmail.com", tier: "paid", refreshToken: "refresh_token_here", projectId: "my-project", addedAt: Date.now(), lastUsed: Date.now(), lastSwitchReason: "initial", rateLimitResetTimes: { "gemini-flash": Date.now() + 60000 // Rate-limited for 60s } } ], activeIndex: 0 }); ``` -------------------------------- ### Update Opencode Plugin Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md These bash commands demonstrate how to update the 'opencode-google-antigravity-auth' plugin. First, remove the cached plugin directory, then run 'opencode' to trigger a reinstallation. If issues persist, remove the dependency from the package.json file. ```bash rm -rf ~/.cache/opencode/node_modules/opencode-google-antigravity-auth opencode ``` -------------------------------- ### Configure Gemini Thinking Options (JSON) Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md This JSON configuration demonstrates how to set 'thinkingConfig' for different Gemini models. It includes 'thinkingLevel' for Gemini 3 models and 'thinkingBudget' for Gemini 2.5 models, along with 'includeThoughts' to enable thought generation. ```json { "provider": { "google": { "models": { "gemini-3-pro-preview": { "variants": { "high": { "options": { "thinkingConfig": { "thinkingLevel": "high", "includeThoughts": true } } } } }, "gemini-3-flash": { "variants": { "medium": { "options": { "thinkingConfig": { "thinkingLevel": "medium", "includeThoughts": true } } } } }, "gemini-claude-sonnet-4-5-thinking": { "variants": { "high": { "options": { "thinkingConfig": { "thinkingBudget": 32000, "includeThoughts": true } } } } } } } } } ``` -------------------------------- ### Configure Opencode Plugin Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md This JSON snippet shows how to add the 'opencode-google-antigravity-auth' plugin to your Opencode configuration file. Ensure the '$schema' property points to the correct Opencode schema URL. ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["opencode-google-antigravity-auth"] } ``` -------------------------------- ### Google Search Tool Execution (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt Executes real-time web searches using Gemini's native search capabilities. It makes separate API calls to Gemini with `googleSearch` and `urlContext` tools enabled, returning formatted markdown results with source citations. This works around Gemini API limitations. Dependencies include 'opencode-google-antigravity-auth/src/plugin/search'. ```typescript // The google_search tool is automatically available to models via the plugin // Example tool call from a model: // Tool definition exposed by the plugin: const googleSearchTool = { name: "google_search", description: "Search the web using Google Search and analyze URLs...", args: { query: "string - The search query or question", urls: "string[] - Optional URLs to fetch and analyze", thinking: "boolean - Enable deep thinking (default: true)" } }; // Example usage in a conversation: // User: "What are the latest developments in AI?" // Model calls: google_search({ query: "latest AI developments 2024", thinking: true }) // Internal execution via executeSearch: import { executeSearch } from "opencode-google-antigravity-auth/src/plugin/search"; const result = await executeSearch( { query: "latest AI developments", urls: ["https://example.com/ai-news"], thinking: true // Uses 16384 thinking budget }, "access_token_here", "project-id", AbortSignal.timeout(60000) ); // Returns formatted markdown: // ## Search Results // // [Summary of findings from web search...] // // ### Sources // - [AI News Today](https://example.com/ai-news) // - [Tech Report](https://techreport.com/ai) // // ### URLs Retrieved // - ✓ https://example.com/ai-news // // ### Search Queries Used // - "latest AI developments" ``` -------------------------------- ### Load Local Opencode Plugin (JSON) Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md This JSON configuration snippet shows how to load a local checkout of the opencode-google-antigravity-auth plugin into Opencode. It requires the absolute path to the plugin directory. ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["file:///absolute/path/to/opencode-google-antigravity-auth"] } ``` -------------------------------- ### Configure Image Input for Antigravity Models in OpenCode Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md To enable image input for Antigravity models in OpenCode, you must add the `modalities` configuration to your model definitions in `opencode.json`. The `input` array must include `"image"` for the model to accept image inputs. ```json { "provider": { "google": { "models": { "gemini-3-pro-preview": { "modalities": { "input": ["text", "image"], "output": ["text"] } }, "gemini-claude-sonnet-4-5-thinking": { "modalities": { "input": ["text", "image"], "output": ["text"] } } } } } } ``` -------------------------------- ### Create Antigravity Fetch Wrapper (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt The `createAntigravityFetch` function provides a custom fetch wrapper for Google's generative language API. It handles authentication, endpoint fallback, rate limiting with exponential backoff, and automatic rotation between endpoints and accounts. This simplifies API interactions by abstracting complex retry and fallback logic. ```typescript import { createAntigravityFetch } from "opencode-google-antigravity-auth/src/plugin/fetch-wrapper"; // Create the authenticated fetch wrapper const antigravityFetch = createAntigravityFetch(getAuth, client); // Use like regular fetch - automatically handles: // - Adding Authorization header // - Transforming request body for Antigravity API // - Trying fallback endpoints (daily → autopush → prod) // - Rate limit handling with exponential backoff // - Multi-account rotation on 429 errors // - Response transformation const response = await antigravityFetch( "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ contents: [{ role: "user", parts: [{ text: "Hello!" }] }], generationConfig: { thinkingConfig: { thinkingBudget: 8192, includeThoughts: true } } }) } ); // Rate limit handling behavior: // - Single account: waits with exponential backoff (1s, 2s, 4s, ... up to 1h) // - Multiple accounts: switches to next available account // - All accounts limited: waits minimum reset time then retries // - Server errors (5xx): tries next endpoint, marks account for 60s cooldown // Endpoint fallback order: // 1. daily-cloudcode-pa.sandbox.googleapis.com // 2. autopush-cloudcode-pa.sandbox.googleapis.com // 3. cloudcode-pa.googleapis.com ``` -------------------------------- ### Account Manager for Multi-Account Load Balancing (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt Manages multiple Google accounts with automatic rotation and per-model rate limit tracking. It prioritizes paid accounts and maintains sticky account selection until errors occur. Dependencies include 'opencode-google-antigravity-auth/src/plugin/accounts' and 'opencode-google-antigravity-auth/src/plugin/storage'. ```typescript import { AccountManager } from "opencode-google-antigravity-auth/src/plugin/accounts"; import { loadAccounts, saveAccounts } from "opencode-google-antigravity-auth/src/plugin/storage"; // Load existing accounts from storage const storedAccounts = await loadAccounts(); // storedAccounts = { // version: 3, // accounts: [ // { email: "user1@gmail.com", refreshToken: "...", projectId: "...", tier: "paid" }, // { email: "user2@gmail.com", refreshToken: "...", projectId: "...", tier: "free" } // ], // activeIndex: 0 // } // Initialize account manager with current auth and stored accounts const auth = { type: "oauth", refresh: "...", access: "...", expires: Date.now() + 3600000 }; const accountManager = new AccountManager(auth, storedAccounts); // Get best available account for a model family (prioritizes paid accounts) const account = accountManager.getCurrentOrNextForFamily("gemini-flash"); // account = { // index: 0, // email: "user1@gmail.com", // tier: "paid", // parts: { refreshToken: "...", projectId: "..." }, // rateLimitResetTimes: {}, // lastUsed: 1704067200000 // } // Mark account as rate-limited for specific model family accountManager.markRateLimited(account, 60000, "gemini-flash"); // 60 second cooldown // Get next available account (auto-rotates to user2 since user1 is rate-limited) const nextAccount = accountManager.getCurrentOrNextForFamily("gemini-flash"); // nextAccount.email = "user2@gmail.com" // Check minimum wait time if all accounts are rate-limited const waitTimeMs = accountManager.getMinWaitTimeForFamily("gemini-pro"); if (waitTimeMs > 0) { console.log(`All accounts rate-limited. Wait ${waitTimeMs}ms before retry.`); } // Persist account state await accountManager.save(); ``` -------------------------------- ### OAuth Authorization Flow Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt Initiate the OAuth flow to authenticate with Google accounts via Antigravity. This involves generating an authorization URL and then exchanging the authorization code for tokens. ```APIDOC ## OAuth Authorization Flow Initiate the OAuth flow to authenticate with Google accounts via Antigravity. The `authorizeAntigravity` function generates a PKCE-secured authorization URL that redirects users to Google's OAuth consent screen. The state parameter encodes the PKCE verifier and project ID for secure token exchange. ```typescript import { authorizeAntigravity, exchangeAntigravity } from "opencode-google-antigravity-auth"; // Start OAuth flow - generates authorization URL with PKCE const authorization = await authorizeAntigravity("my-project-id"); // authorization = { // url: "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&response_type=code&...", // verifier: "abc123...", // PKCE verifier for token exchange // projectId: "my-project-id" // } console.log(`Open this URL to authenticate: ${authorization.url}`); // After user completes browser flow, extract code and state from callback URL const callbackUrl = new URL("http://localhost:36742/oauth-callback?code=AUTH_CODE&state=STATE"); const code = callbackUrl.searchParams.get("code"); const state = callbackUrl.searchParams.get("state"); // Exchange authorization code for tokens const result = await exchangeAntigravity(code, state); if (result.type === "success") { console.log("Authentication successful!"); console.log(`Email: ${result.email}`); console.log(`Project ID: ${result.projectId}`); console.log(`Account tier: ${result.tier}`); // "free" or "paid" console.log(`Access token expires: ${new Date(result.expires)}`); // result.refresh contains the refresh token for persistent auth // result.access contains the short-lived access token } else { console.error(`Authentication failed: ${result.error}`); } ``` ``` -------------------------------- ### Plugin Registration Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt Register the Antigravity OAuth Plugin in your Opencode configuration to enable Google authentication. ```APIDOC ## Plugin Registration Register the plugin in your Opencode configuration to enable Antigravity OAuth authentication. The plugin exports `AntigravityOAuthPlugin` as its main entry point, which integrates with Opencode's plugin system to provide authentication handlers, a custom fetch wrapper for API requests, and the google_search tool. ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["opencode-google-antigravity-auth"], "provider": { "google": { "npm": "@ai-sdk/google", "models": { "gemini-3-pro-preview": { "id": "gemini-3-pro-preview", "name": "Gemini 3 Pro", "limit": { "context": 1000000, "output": 64000 }, "modalities": { "input": ["text", "image", "video", "audio", "pdf"], "output": ["text"] }, "variants": { "low": { "options": { "thinkingConfig": { "thinkingLevel": "low", "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingLevel": "medium", "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingLevel": "high", "includeThoughts": true } } } } }, "gemini-claude-sonnet-4-5-thinking": { "id": "gemini-claude-sonnet-4-5-thinking", "name": "Claude Sonnet 4.5", "limit": { "context": 200000, "output": 64000 }, "modalities": { "input": ["text", "image", "pdf"], "output": ["text"] }, "variants": { "low": { "options": { "thinkingConfig": { "thinkingBudget": 4000, "includeThoughts": true } } }, "medium": { "options": { "thinkingConfig": { "thinkingBudget": 16000, "includeThoughts": true } } }, "high": { "options": { "thinkingConfig": { "thinkingBudget": 32000, "includeThoughts": true } } } } } } } } } ``` ``` -------------------------------- ### Implement Session Recovery with TypeScript Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt This snippet shows how to implement session recovery for Claude thinking block order errors. It demonstrates creating a recovery hook, checking if an error is recoverable using `isRecoverableError`, and handling session error events to attempt recovery. Session recovery can be disabled via an environment variable. ```typescript import { createSessionRecoveryHook, isRecoverableError } from "opencode-google-antigravity-auth/src/plugin/recovery"; // Create recovery hook during plugin initialization const sessionRecovery = createSessionRecoveryHook({ client, directory }); // Check if an error is recoverable const error = { data: { error: { message: "messages.3: thinking block must start with preceding text block" } } }; if (isRecoverableError(error)) { console.log("This error can be automatically recovered"); // Error types detected: // - "thinking_block_order": Thinking block not preceded by text } // Handle session error event const sessionErrorEvent = { type: "session.error", properties: { sessionID: "session-123", messageID: "msg-456", error: error } }; // Attempt recovery (called automatically by plugin's event handler) const recovered = await sessionRecovery.handleSessionRecovery({ id: "msg-456", role: "assistant", sessionID: "session-123", error: error }); if (recovered) { // Recovery succeeded - session will be prompted to continue // User sees toast: "Session Recovered - Continuing where you left off..." } else { // Recovery failed - user needs to retry manually } // Disable session recovery via environment variable: // ANTIGRAVITY_SESSION_RECOVERY=0 ``` -------------------------------- ### Antigravity OAuth Authorization and Token Exchange (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt This TypeScript code demonstrates the OAuth 2.0 flow for authenticating with Google's Antigravity API using the `opencode-google-antigravity-auth` library. It covers initiating the authorization URL generation, handling the callback, and exchanging the authorization code for access and refresh tokens. ```typescript import { authorizeAntigravity, exchangeAntigravity } from "opencode-google-antigravity-auth"; // Start OAuth flow - generates authorization URL with PKCE const authorization = await authorizeAntigravity("my-project-id"); // authorization = { // url: "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&response_type=code&...", // verifier: "abc123...", // PKCE verifier for token exchange // projectId: "my-project-id" // } console.log(`Open this URL to authenticate: ${authorization.url}`); // After user completes browser flow, extract code and state from callback URL const callbackUrl = new URL("http://localhost:36742/oauth-callback?code=AUTH_CODE&state=STATE"); const code = callbackUrl.searchParams.get("code"); const state = callbackUrl.searchParams.get("state"); // Exchange authorization code for tokens const result = await exchangeAntigravity(code, state); if (result.type === "success") { console.log("Authentication successful!"); console.log(`Email: ${result.email}`); console.log(`Project ID: ${result.projectId}`); console.log(`Account tier: ${result.tier}`); // "free" or "paid" console.log(`Access token expires: ${new Date(result.expires)}`); // result.refresh contains the refresh token for persistent auth // result.access contains the short-lived access token } else { console.error(`Authentication failed: ${result.error}`); } ``` -------------------------------- ### Disable Problematic MCP Servers for Gemini Tool Compatibility Source: https://github.com/shekohex/opencode-google-antigravity-auth/blob/main/README.md Gemini API has strict naming conventions for tool names. This configuration snippet shows how to disable specific MCP servers that might have incompatible tool names by setting their value to `false` within the `tools` configuration for a given model. ```json { "provider": { "google": { "models": { "gemini-3-pro-preview": { "tools": { "21st-dev-magic_*": false } } } } } } ``` -------------------------------- ### Transform Gemini Requests for Claude Proxy Models (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt This function transforms Gemini-format requests into a Claude-compatible format, suitable for proxy models. It handles schema conversion, thinking configuration, and function call ID matching. Dependencies include the 'opencode-google-antigravity-auth/src/plugin/transform/claude' module. ```typescript import { transformClaudeRequest } from "opencode-google-antigravity-auth/src/plugin/transform/claude"; // Gemini-format request (from AI SDK) const geminiRequest = { contents: [ { role: "user", parts: [{ text: "List files in current directory" }] } ], tools: [{ functionDeclarations: [{ name: "bash", description: "Execute bash command", parametersJsonSchema: { // AI SDK format $schema: "http://json-schema.org/draft-07/schema#", type: "object", properties: { command: { type: "string" } }, required: ["command"] } }] }], generationConfig: { thinkingConfig: { thinkingBudget: 16000, includeThoughts: true } } }; // Transform for Claude const context = { projectId: "my-project", model: "gemini-claude-sonnet-4-5-thinking", streaming: true, requestId: "req-123", family: "claude", sessionId: "session-456" }; const result = transformClaudeRequest(context, geminiRequest); // Result body is wrapped for Antigravity backend: // { // project: "my-project", // model: "gemini-claude-sonnet-4-5-thinking", // userAgent: "antigravity", // requestType: "agent", // requestId: "req-123", // request: { // contents: [...], // tools: [{ // functionDeclarations: [{ // name: "bash", // description: "Execute bash command", // parameters: { // Converted from parametersJsonSchema // type: "object", // Ensured // properties: { command: { type: "string" } }, // required: ["command"] // // $schema removed // } // }] // }], // toolConfig: { functionCallingConfig: { mode: "VALIDATED" } }, // generationConfig: { // thinkingConfig: { // thinking_budget: 16000, // Snake_case for backend // include_thoughts: true // }, // maxOutputTokens: 64000 // Auto-bumped for thinking models // }, // sessionId: "session-456" // } // } ``` -------------------------------- ### Refresh Expired OAuth Access Tokens (TypeScript) Source: https://context7.com/shekohex/opencode-google-antigravity-auth/llms.txt The `refreshAccessToken` function automatically refreshes expired OAuth access tokens using stored refresh tokens. It handles revoked tokens by clearing credentials and integrates with an account manager for multi-account state. This function is crucial for maintaining uninterrupted API access. ```typescript import { refreshAccessToken } from "opencode-google-antigravity-auth/src/plugin/token"; // Check if token is expired before making requests const auth = { type: "oauth", refresh: "refresh_token|project-id", // Format: refreshToken|projectId access: "current_access_token", expires: Date.now() - 1000 // Expired }; // Token is expired, refresh it const refreshedAuth = await refreshAccessToken(auth, client); if (refreshedAuth) { console.log("Token refreshed successfully"); console.log(`New access token: ${refreshedAuth.access}`); console.log(`Expires at: ${new Date(refreshedAuth.expires)}`); // Continue with API request using refreshedAuth.access } else { // Refresh failed - token may be revoked console.log("Token refresh failed. Re-authentication required."); console.log("Run: opencode auth login"); } // The plugin automatically handles this in createAntigravityFetch: // - Checks token expiration before each request // - Refreshes automatically when needed // - Updates stored credentials after successful refresh // - Handles invalid_grant errors by clearing credentials ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.