fix(google): Route OAuth requests through Cloud Code API for subscription support#101
Conversation
Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: #100
… key This commit fixes issue #100 where Google OAuth authentication failed with "Request had insufficient authentication scopes" error. Changes: 1. Added all required generative-language OAuth scopes to GOOGLE_OAUTH_SCOPES: - generative-language (main API access) - generative-language.tuning (and readonly) - generative-language.retriever (and readonly) 2. Implemented fallback mechanism in the Google OAuth loader: - Detects OAuth scope errors (403 with insufficient_scope) - Falls back to API key auth (GOOGLE_GENERATIVE_AI_API_KEY or GEMINI_API_KEY) - Logs helpful hints for users to re-authenticate 3. Added case study documentation in docs/case-studies/issue-100/ Users who previously authenticated will need to re-run "agent auth login" to get the new scopes. Users with API keys can continue using the service immediately through the fallback mechanism. Fixes #100 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Follow-up to fix the implementation after discovering that: 1. The generative-language.* scopes are not registered for the Gemini CLI OAuth client 2. Adding unregistered scopes causes a "restricted_client" error (issue #93) The correct solution is to rely on the fallback mechanism: - When OAuth fails with scope error, fall back to API key if available - Keep the OAuth scopes minimal (cloud-platform, userinfo.email, userinfo.profile) Also added the required changeset file for the release process. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
Now working session is ended, feel free to review and add any feedback on the solution draft. |
|
How exactly it is possible that https://github.com/google-gemini/gemini-cli and http://github.com/sst/opencode can work with Google Subscriptions with no API Key? Can we do the same, it is open-source after all. So the root cause of the issue, is not that we don't do fallback, we still can try to do it though. But it should be absolutely enough to just have subscription without API key to just get the access to API. What is the same with our code and what is the different? If you notice an easy fix, please implement it right away, if not - just make sure we have detailed analysis in the markdown file, and also give me summary here as a comment. |
|
🤖 AI Work Session Started Starting automated work session at 2025-12-23T17:43:10.038Z The PR has been converted to draft mode while work is in progress. This comment marks the beginning of an AI work session. Please wait working session to finish, and provide your feedback. |
After analyzing gemini-cli and opencode source code, discovered the real reason why OAuth with cloud-platform scope works in gemini-cli: Key finding: Gemini CLI uses a DIFFERENT API endpoint - Our code: generativelanguage.googleapis.com (requires generative-language.* scopes) - Gemini CLI: cloudcode-pa.googleapis.com/v1internal (accepts cloud-platform scope) The Cloud Code API is a wrapper that: 1. Accepts cloud-platform OAuth tokens 2. Handles subscription tier validation (FREE, STANDARD, etc.) 3. Proxies requests to Generative Language API internally Updated case study with: - Root cause analysis showing API endpoint difference - Code evidence from gemini-cli source - Revised solution recommendations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
🔍 Root Cause Analysis CompleteI analyzed the source code of both gemini-cli and opencode to understand how they work with Google subscriptions without an API key. Here's what I found: 🎯 Key Discovery: Different API EndpointsThe root cause is NOT about OAuth scopes - it's about which API endpoint we call.
📊 Architecture Comparison📁 Evidence from Gemini CLI SourceFrom ```typescript // Requests go to: cloudcode-pa.googleapis.com/v1internal:streamGenerateContent From ```typescript // Same OAuth client ID as ours! ✅ Proper SolutionTo match Gemini CLI's behavior:
📝 Files Updated
|
Implement proper Google OAuth support by routing requests through Google's Cloud Code API (cloudcode-pa.googleapis.com/v1internal) instead of directly calling generativelanguage.googleapis.com. This is the same approach used by the official Gemini CLI and properly supports the cloud-platform OAuth scope that our OAuth client has registered. Changes: - Add URL transformation from Generative Language API to Cloud Code API - Add request body transformation to wrap in Cloud Code format (model, project, request) - Add response body transformation to unwrap Cloud Code responses - Add streaming SSE response transformation support - Add google-cloudcode.ts client for future direct Cloud Code API usage - Keep API key fallback if Cloud Code API fails - Update changeset to minor version for new feature The key insight from analyzing gemini-cli source code: - Gemini CLI uses cloudcode-pa.googleapis.com, not generativelanguage.googleapis.com - Cloud Code API accepts cloud-platform OAuth scope - It handles subscription tiers (FREE, STANDARD) internally Fixes #100 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
✅ Implementation CompleteI've implemented the proper fix using the Cloud Code API approach discovered during research. Changes in this commit
How it worksRequest transformation exampleAI SDK sends: POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
{"contents": [...], "generationConfig": {...}}Transformed to: POST https://cloudcode-pa.googleapis.com/v1internal:generateContent
{"model": "gemini-2.0-flash", "project": "...", "request": {"contents": [...], "generationConfig": {...}}}TestingThis should be tested by:
CI should run shortly to catch any regressions. |
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
Now working session is ended, feel free to review and add any feedback on the solution draft. |
|
Please double check we did our absolute best, on making Gemini work with our agent as in Gemini CLI and OpenCode CLI. And we keeping all possible fallbacks. Also make sure everything is logged at |
|
🤖 AI Work Session Started Starting automated work session at 2025-12-23T18:43:17.129Z The PR has been converted to draft mode while work is in progress. This comment marks the beginning of an AI work session. Please wait working session to finish, and provide your feedback. |
Add debug-level logging throughout the Google OAuth Cloud Code API flow: - Loader initialization with endpoint/version info - Fallback API key availability checks - OAuth scope error detection - URL transformation to Cloud Code API - Model extraction from URLs - Request body transformation - Response transformation (streaming and non-streaming) - Token refresh operations - Cloud Code API request/response lifecycle - Fallback triggering with detailed context All logs use lazy evaluation and only appear with --verbose flag enabled. This helps users debug authentication issues when things go wrong. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
✅ Implementation Verified and EnhancedI've completed a thorough review and enhancement of the Cloud Code API implementation: 🔍 Verification Against Gemini CLICompared our implementation with the official Gemini CLI source code:
🛡️ Fallback Mechanisms PreservedAll fallbacks are in place:
📝 Comprehensive Verbose Logging AddedAll decision points now have debug logging (visible with 🧪 CI Status
📊 Implementation Improvements Over Gemini CLIOur implementation adds:
|
🤖 Solution Draft LogThis log file contains the complete execution trace of the AI solution draft process. 💰 Cost estimation:
Now working session is ended, feel free to review and add any feedback on the solution draft. |
Summary
Implements proper Google OAuth support by routing requests through Google's Cloud Code API (
cloudcode-pa.googleapis.com/v1internal) instead of directly callinggenerativelanguage.googleapis.com.Root Cause Discovery: The official Gemini CLI uses a different API endpoint that accepts the
cloud-platformOAuth scope:generativelanguage.googleapis.comgenerative-language.*scopescloudcode-pa.googleapis.comcloud-platformscopeChanges
src/auth/plugins.ts{ model, project, request }){ response })src/provider/google-cloudcode.ts(new)docs/case-studies/issue-100/README.mdHow it Works
Test Plan
agent auth login→ Google AI Pro/Ultraecho "hi" | agent --model google/gemini-3-proReferences
Fixes #100
🤖 Generated with Claude Code