-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
What specific problem does this solve?
Users want free access to Google's Gemini models without needing to manage API keys or set up billing. The recently open-sourced Gemini CLI tool provides OAuth-based authentication that offers free tier access to Gemini models through Google's Code Assist API.
Who is affected: All users, especially new users, developers, and those who want to avoid API costs
When this happens: When users want to use Google Gemini models but don't have API keys set up or want to avoid API usage charges
Current behavior: Users must obtain Google API keys, configure authentication, and pay for API usage from the first request
Expected behavior: Users should be able to access Gemini models through OAuth authentication (like the Gemini CLI tool), which provides free tier access without API keys
Impact: Eliminates API key management, provides free access tier, reduces setup friction, and offers an alternative authentication method that's more secure than API keys
Additional context
This feature was recently implemented in Cline (PR #4472) and provides a sophisticated OAuth-based approach that's superior to the CLI-shelling approach that was previously considered in issue #5118.
Key Benefits:
- Zero configuration: Works automatically after OAuth authentication
- Cost savings: Uses the free tier through Google's Code Assist API
- OAuth security: No need to manage API keys
- Full model support: Supports all Gemini models available in the standard provider
- Complete Independence: Entirely separate from existing Gemini provider - no conflicts or shared code
π οΈ Contributing & Technical Analysis
β
I'm interested in implementing this feature
β
I understand this needs approval before implementation begins
How should this be solved?
This should be implemented as a completely new and independent provider called "Gemini CLI Provider" that uses OAuth authentication with Google's authentication libraries. This is NOT a modification of the existing Gemini provider - it's an entirely separate provider with its own authentication, models, and API endpoints.
What will change:
- Add new
GeminiCliHandlerprovider class with OAuth2 authentication - Create dedicated
GeminiCliProviderUI component - Add separate model definitions and provider registration
- Implement Google Code Assist API integration (different from standard Gemini API)
- Add OAuth credential management with automatic token refresh
- Include provider-specific error handling and rate limiting
User interaction:
- Users will see "Gemini CLI Provider" as a distinct provider option in settings dropdown
- Completely separate from "Google Gemini" provider option
- Setup requires authenticating with Google OAuth (opens browser)
- OAuth credentials are stored locally and refreshed automatically
- No API keys needed - authentication handled via OAuth flow
Acceptance Criteria
Given I want to use Gemini models without API keys
When I select "Gemini CLI Provider" in Roo Code settings
Then I can authenticate via OAuth (browser opens for Google login)
And I can send prompts to Gemini models without API key configuration
And I receive streaming responses from the free tier
And OAuth tokens are automatically refreshed when needed
And this provider is completely independent from the existing "Google Gemini" provider
But I need to complete initial OAuth authentication setup
Given I have both Gemini and Gemini CLI providers configured
When I switch between the two providers
Then each provider uses its own authentication method and endpoints
And there are no conflicts or shared state between providers
And I can use both providers independently in different sessions
Given OAuth credentials expire or become invalid
When I try to use the Gemini CLI provider
Then the system automatically attempts to refresh the token
And on refresh failure, I receive clear instructions to re-authenticate
And failure doesn't affect the regular Gemini provider
But the extension doesn't crash or become unusable
Technical Considerations
Complete Implementation Roadmap
Phase 1: Core Infrastructure
// 1. Add new provider type to shared API types
// File: src/shared/api.ts
export type ApiProvider =
| "anthropic"
| "gemini" // Existing provider
| "gemini-cli" // NEW provider - completely separate
| // ... other providers
// Add new OAuth-specific options
export interface ApiHandlerOptions {
// ... existing options
geminiCliOAuthPath?: string
geminiCliProjectId?: string
}
// Define new model set (may overlap with regular Gemini but separate definitions)
export type GeminiCliModelId = keyof typeof geminiCliModels
export const geminiCliDefaultModelId: GeminiCliModelId = "gemini-2.5-flash"
export const geminiCliModels = {
"gemini-2.5-pro": { /* OAuth-specific model config */ },
"gemini-2.5-flash": { /* OAuth-specific model config */ },
// ... complete model set with OAuth-specific pricing (free tier)
}Phase 2: Provider Implementation
// File: src/api/providers/gemini-cli.ts (ENTIRELY NEW FILE)
import { OAuth2Client } from 'google-auth-library'
import { BaseProvider } from './base-provider'
export class GeminiCliHandler extends BaseProvider {
private authClient: OAuth2Client
private projectId: string | null = null
constructor(options: GeminiCliHandlerOptions) {
super()
// OAuth2 setup using Code Assist endpoints
this.authClient = new OAuth2Client(
OAUTH_CLIENT_ID,
OAUTH_CLIENT_SECRET,
OAUTH_REDIRECT_URI
)
}
// Completely different authentication flow from GeminiHandler
private async initializeAuth(): Promise<void> { /* OAuth implementation */ }
// Different API endpoints than regular Gemini
private async callCodeAssistEndpoint(method: string, body: any): Promise<any> {
/* Code Assist API calls */
}
// Separate streaming implementation
async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
/* OAuth-based streaming via Code Assist API */
}
// Independent model selection
getModel(): { id: GeminiCliModelId; info: ModelInfo } { /* OAuth model logic */ }
}Phase 3: Provider Registration
// File: src/api/index.ts
function createHandlerForProvider(apiProvider: string | undefined, options: any) {
switch (apiProvider) {
case "gemini":
return new GeminiHandler(options) // Existing provider
case "gemini-cli":
return new GeminiCliHandler(options) // NEW provider
// ... other providers
}
}Phase 4: UI Components
// File: webview-ui/src/components/settings/providers/GeminiCliProvider.tsx (NEW FILE)
export const GeminiCliProvider = ({ apiConfiguration, handleInputChange, showModelOptions }: Props) => {
return (
<div>
{/* OAuth-specific configuration UI */}
<VSCodeTextField
value={apiConfiguration?.geminiCliOAuthPath || ""}
placeholder="Default: ~/.gemini/oauth_creds.json"
onInput={handleInputChange("geminiCliOAuthPath")}
>
OAuth Credentials Path (optional)
</VSCodeTextField>
{/* OAuth setup instructions */}
<p>This provider uses OAuth authentication and does not require API keys...</p>
{/* Model selector for OAuth models */}
{showModelOptions && (
<ModelSelector
models={geminiCliModels} // Separate model set
selectedModelId={selectedModelId}
onChange={handleInputChange("apiModelId")}
/>
)}
</div>
)
}Phase 5: Provider UI Integration
// File: webview-ui/src/components/settings/ApiOptions.tsx
export const ApiOptions = () => {
return (
<div>
<VSCodeDropdown>
<VSCodeOption value="gemini">Google Gemini</VSCodeOption> {/* Existing */}
<VSCodeOption value="gemini-cli">Gemini CLI Provider</VSCodeOption> {/* NEW */}
</VSCodeDropdown>
{selectedProvider === "gemini" && <GeminiProvider {...props} />}
{selectedProvider === "gemini-cli" && <GeminiCliProvider {...props} />} {/* NEW */}
</div>
)
}Key Architectural Differences from Existing Gemini Provider
| Aspect | Existing Gemini Provider | New Gemini CLI Provider |
|---|---|---|
| Authentication | API Key based | OAuth2 based |
| API Endpoints | generativelanguage.googleapis.com |
cloudcode-pa.googleapis.com |
| API Version | Standard Gemini API | Code Assist API (v1internal) |
| Cost Model | Pay-per-token | Free tier with rate limits |
| Credential Storage | API key in settings | OAuth tokens in ~/.gemini/oauth_creds.json |
| Token Management | Static API key | Dynamic OAuth with refresh |
| Project Setup | None required | Auto-discovery via Code Assist |
| Account Support | Any Google account | Personal Google accounts only |
| Rate Limiting | Based on API quotas | Free tier limits |
| Streaming Method | Standard HTTP streaming | Server-Sent Events |
Detailed Dependency Analysis
New Dependencies Required:
{
"dependencies": {
"google-auth-library": "^10.1.0" // Already present in Roo Code via Vertex provider
}
}No Additional Dependencies Needed: The google-auth-library package is already included in Roo Code for the Vertex provider, so no new npm dependencies are required.
Complete File Modification List
New Files to Create:
src/api/providers/gemini-cli.ts- Complete OAuth handler implementationwebview-ui/src/components/settings/providers/GeminiCliProvider.tsx- OAuth UI component
Existing Files to Modify:
src/shared/api.ts- Addgemini-cliprovider type and OAuth modelssrc/api/index.ts- Add provider registration casewebview-ui/src/components/settings/ApiOptions.tsx- Add provider dropdown option and componentwebview-ui/src/components/settings/utils/providerUtils.ts- Add model normalizationwebview-ui/src/utils/validate.ts- Add OAuth validation (if needed)- Configuration conversion files for proto serialization
Testing Files to Create:
src/api/providers/__tests__/gemini-cli.test.ts- Complete test suitewebview-ui/src/components/settings/providers/__tests__/GeminiCliProvider.test.tsx- UI tests
OAuth Implementation Details
Authentication Flow:
// OAuth2 Configuration (from Cline implementation)
const OAUTH_CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"
const OAUTH_CLIENT_SECRET = "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"
const OAUTH_REDIRECT_URI = "http://localhost:45289"
// Code Assist API Endpoints
const CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com"
const CODE_ASSIST_API_VERSION = "v1internal"
// Key Methods:
1. loadOAuthCredentials() - Load from ~/.gemini/oauth_creds.json
2. initializeAuth() - Setup OAuth2Client with token refresh
3. discoverProjectId() - Auto-discover GCP project via Code Assist API
4. callCodeAssistEndpoint() - Make authenticated API calls
5. parseSSEStream() - Handle Server-Sent Events streamingProject ID Discovery Process:
- Call
loadCodeAssistendpoint with default project - If no existing project, call
onboardUserendpoint - Poll for onboarding completion
- Extract discovered project ID for future requests
Error Handling & Rate Limiting
OAuth-Specific Error Handling:
- 401 Unauthorized β Automatic token refresh attempt
- 403 Forbidden β Re-authentication required
- 429 Rate Limited β Free tier limit exceeded (special UI messaging)
Rate Limit Error UI Enhancement:
// Special handling for Gemini CLI rate limits in ChatRow.tsx
if (isRateLimitError && apiConfiguration?.apiProvider === "gemini-cli") {
return (
<div className="rate-limit-warning">
<p>You've hit the API rate limit. This is likely due to free tier limits.</p>
<a href="https://codeassist.google/">Learn about tier limits</a>
</div>
)
}Comprehensive Testing Strategy
Unit Tests Required:
-
OAuth Authentication Tests
- Token loading and validation
- Automatic token refresh
- Authentication failure handling
- Project ID discovery
-
API Integration Tests
- Code Assist endpoint calls
- Server-Sent Events parsing
- Rate limit handling
- Error response processing
-
Provider Interface Tests
- Model selection and validation
- Message creation and streaming
- Cost calculation (free tier)
- Independence from Gemini provider
-
UI Component Tests
- OAuth configuration interface
- Model selector functionality
- Error state display
- Authentication flow UX
Performance & Security Considerations
Performance Optimizations:
- OAuth token caching and reuse
- Automatic background token refresh
- Efficient SSE stream parsing
- Connection pooling for API calls
Security Measures:
- Secure OAuth credential storage
- Token expiration handling
- HTTPS-only API communication
- Input validation and sanitization
Compatibility Safeguards:
- No shared state with existing Gemini provider
- Independent configuration storage
- Separate error handling paths
- Isolated model definitions
Trade-offs and Risks
Alternatives considered:
- Modify existing Gemini provider: Rejected to avoid complexity and maintain clean separation
- CLI shelling approach (issue Add Gemini CLI provider supportΒ #5118): Rejected in favor of direct OAuth integration
- Unified OAuth/API key provider: Decided against to keep authentication methods clear and separate
Potential risks:
- OAuth complexity: Mitigated by using proven
google-auth-libraryand Cline's implementation as reference - Code duplication: Some overlap with Gemini provider, but necessary for independence
- Free tier limits: Clear error messaging and rate limit handling implemented
- Google API changes: Risk exists but Code Assist API is actively maintained by Google
Breaking changes:
- None: Completely additive feature with no impact on existing functionality
- Provider independence: Existing Gemini provider continues to work unchanged
- Configuration isolation: No conflicts between OAuth and API key authentication
Metadata
Metadata
Assignees
Labels
Type
Projects
Status