Skip to content

feat: integrate native ChatGPT and Anthropic OAuth#395

Open
JollyRogerz wants to merge 11 commits intorowboatlabs:mainfrom
JollyRogerz:feature/native-oauth-integration
Open

feat: integrate native ChatGPT and Anthropic OAuth#395
JollyRogerz wants to merge 11 commits intorowboatlabs:mainfrom
JollyRogerz:feature/native-oauth-integration

Conversation

@JollyRogerz
Copy link

Description

This PR introduces Native OAuth support for ChatGPT Plus and Claude Pro, allowing users to leverage their existing subscriptions directly in Rowboat without needing proxies.

Motivation

Providing an alternative to pay-as-you-go API keys significantly lowers the barrier to entry for users who already pay for AI subscriptions.

Testing Performed

  • Built and type-checked frontend and backend.
  • Manually verified the OAuth PKCE device and browser flows.
  • Verified AI SDK requests successfully inherit the Bearer tokens.

Risk & Limitations

  • These flows utilize reverse-engineered endpoints (auth.openai.com and claude.ai). If OpenAI or Anthropic change their private SSO implementations, these flows may break and require maintenance.

@vercel
Copy link

vercel bot commented Feb 21, 2026

@JollyRogerz is attempting to deploy a commit to the RowBoat Labs Team on Vercel.

A member of the Team first needs to authorize it.

@JollyRogerz JollyRogerz marked this pull request as draft February 22, 2026 01:42
@JollyRogerz JollyRogerz marked this pull request as ready for review February 22, 2026 02:08
JollyRogerz and others added 6 commits February 22, 2026 02:12
- Fix Anthropic OAuth: use correct redirect URI (port 8765, /callback path)
  and Bearer token auth. Removed OAuth button since Anthropic blocked
  third-party OAuth in Feb 2026; now shows API key link instead.
- Fix Antigravity OAuth: dedicated port 51121, correct callback path
- Fix OAuth event mapping: anthropic-native -> anthropic in settings +
  onboarding modal event listeners
- Fast model switching: skip test for connected OAuth providers
- Connection status indicators: green/red dots in model selector per provider
- Status bar: persistent bar showing model, auth type, quota tier, session usage
- Usage tracking: captures token counts from LLM finish-step events
- New hooks: useOAuthState, useUsageTracking
- Anthropic Bearer auth: custom fetch to send OAuth tokens as Authorization
  header instead of x-api-key (for future re-enablement)
- Add antigravity-gateway.ts: session init (loadCodeAssist/onboardUser),
  custom fetch that rewrites @ai-sdk/google requests into the Antigravity
  envelope format, SSE unwrapping with proper line buffering for large
  thoughtSignature fields, and Gemini request sanitization (removes empty
  parts/generationConfig that cause 400 errors)
- Add Antigravity provider case to models.ts with automatic OAuth token
  refresh using the gateway's client credentials
- Add Antigravity UI in settings-dialog: OAuth-only sign-in with built-in
  model catalog (Gemini 3 Flash/Pro, Claude Sonnet 4.6, Claude Opus 4.6)
- Fix status bar cut-off by sidebar: move StatusBar inside SidebarInset
  so it shifts with the peer-aware sidebar layout
- Fix dev startup: unset ELECTRON_RUN_AS_NODE in start script

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JollyRogerz
Copy link
Author

Update: Antigravity (Google Cloud Code) Gateway Integration Added

This PR now includes a third OAuth provider beyond ChatGPT and Anthropic — Google's internal "Antigravity" Cloud Code gateway — which gives users free access to Gemini and Claude models using just a Google account (no API key required).

What's working

Core gateway client (apps/x/packages/core/src/models/antigravity-gateway.ts):

  • Session initialization via loadCodeAssist / onboardUser (handles new user onboarding with long-running operation polling)
  • Custom fetch wrapper that intercepts @ai-sdk/google requests and rewrites them into the Antigravity envelope format ({ model, project, user_prompt_id, request: <gemini body> })
  • Buffered SSE unwrapper — properly handles SSE data that spans multiple TCP chunks (critical for large thoughtSignature base64 fields in thinking models)
  • Request sanitization — removes empty parts: [] model messages and empty generationConfig: {} that cause 400 errors from the gateway
  • Automatic OAuth token refresh using the gateway's embedded client credentials

Settings UI (settings-dialog.tsx):

  • Antigravity shown as an OAuth-only provider (no API key option)
  • Built-in model catalog: Gemini 3 Flash, Gemini 3 Pro (Low/High Thinking), Gemini 3.1 Pro (Low/High Thinking), Claude Sonnet 4.6, Claude Opus 4.6 (Thinking)
  • "Sign in with Google" button using the existing browser OAuth flow

Bug fixes in this update:

  • Status bar was being clipped by the fixed-position sidebar — moved StatusBar inside SidebarInset so it shifts correctly with the sidebar peer layout
  • Dev startup: added unset ELECTRON_RUN_AS_NODE to the Electron start script (VS Code/Cursor terminals inherit this env var which forces Electron into plain Node.js mode)

Bugs fixed during development

Error Root cause Fix
loadCodeAssist failed (401) OAuth tokens expire after ~1h, not auto-refreshed Added refresh logic in createProvider before use
Invalid value at 'enabled_credit_types[0]' Sent "G1" string instead of protobuf enum Removed the field entirely (not required)
Request contains an invalid argument (400) { role: "model", parts: [] } is invalid for Gemini API Sanitize request to remove empty messages
AI_JSONParseError on streaming SSE data with long base64 thoughtSignature split across TCP chunks Implemented proper line buffer across reader.read() calls

Tested

  • Gemini 3 Flash ✅
  • Gemini 3.1 Pro High (thinking) ✅ — responses render correctly including thinking tokens
  • Claude Sonnet 4.6 via Antigravity — pending (model available in catalog)

Not included

  • The test scripts (test-gateway.mjs, test-models.js/mjs) used during debugging are not committed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant