feat(cdp-bridge): improve antigravity client and shared protobuf definitions
Updates to the CDP bridge and shared protocol layer: - infra/cdp-bridge/src/cdp_controller.js: Enhanced CDP session management - infra/cdp-bridge/src/services/antigravity_client.js: Improved Antigravity WebSocket client with reconnection and error handling - shared/buf.connect.gen.yaml / shared/buf.es.gen.yaml: Buf code generation configuration updates - shared/src/proto/antigravity_connect.ts / antigravity_pb.ts: Updated Connect-RPC protobuf definitions for the Antigravity protocol
This commit is contained in:
parent
3ab9284d82
commit
3641b7e575
7 changed files with 144 additions and 5 deletions
87
infra/cdp-bridge/OAUTH_AUTH_FIX.md
Normal file
87
infra/cdp-bridge/OAUTH_AUTH_FIX.md
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
# Antigravity Panel Authentication Fix
|
||||
|
||||
## Problem
|
||||
|
||||
The Antigravity IDE/LS was updated and now requires **Google OAuth authentication**. The previous CDP-based integration is broken because:
|
||||
|
||||
1. The CDP Bridge (`cdp_controller.js`) gets stuck on a Google login screen with no handling
|
||||
2. The gRPC client (`antigravity_client.js`) sends no CSRF/auth tokens
|
||||
3. The Dirac native bridge has `inject_oauth_token()` implemented but was never called from TypeScript
|
||||
4. `Antigravity-Tools-LS` exists as a submodule and handles OAuth but wasn't integrated
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. CDP Bridge — OAuth Detection & CSRF Support
|
||||
|
||||
- **`src/cdp_controller.js`**: Added `isOAuthScreen()` detection that checks for Google login URLs and DOM elements. `connect()` and `getStatus()` now throw/report descriptive errors when authentication is required.
|
||||
- **`src/services/antigravity_client.js`**: Added `AG_CSRF_TOKEN` environment variable support and a ConnectRPC interceptor that injects the `x-codeium-csrf-token` header on every gRPC request.
|
||||
|
||||
### 2. VS Code Extension — Dirac Native Integration
|
||||
|
||||
- **`package.json`**: Added two new settings:
|
||||
- `aurelio.antigravity.oauthToken` — object with `accessToken`, `refreshToken`, `expiry`
|
||||
- `aurelio.antigravity.lsBinaryPath` — absolute path to the `language_server` binary
|
||||
- **`src/webview/controlCenterPanel.ts`**:
|
||||
- Added `_getDiracClient()` helper that reuses the ChatPanel's Dirac client or creates a standalone one
|
||||
- Added `_agNativeInfo` field to track spawned LS port/CSRF token
|
||||
- `antigravityGrpcConnect` (native mode): Automatically spawns the LS via `dirac.startSelfHosted()` and injects the OAuth token via `dirac.injectOAuthToken()`
|
||||
- `antigravitySendPrompt` / `antigravityQuickAction` (native mode): Validate that the LS is spawned before sending prompts
|
||||
- **`src/core/diracClient.ts`**: Fixed parameter name mismatch (`ls_binary_path` → `binary_path`) to match the Rust backend.
|
||||
|
||||
### 3. Aurelio-Web — Dirac Fallback
|
||||
|
||||
- **`server/services/messageDispatcher.ts`**:
|
||||
- Reads `ANTIGRAVITY_LS_BINARY`, `ANTIGRAVITY_OAUTH_ACCESS_TOKEN`, `ANTIGRAVITY_OAUTH_REFRESH_TOKEN`, `ANTIGRAVITY_OAUTH_EXPIRY` from environment variables
|
||||
- Added `tryDiracPrompt()` helper that spawns the LS via Dirac and falls back to the CDP bridge on failure
|
||||
- `antigravitySendPrompt` and `antigravityQuickAction` now try Dirac first when `ANTIGRAVITY_LS_BINARY` is configured
|
||||
- Added `antigravityNativeConnect` handler to explicitly spawn the LS via Dirac
|
||||
- **`server/services/diracClient.ts`**: Fixed parameter name mismatch (`ls_binary_path` → `binary_path`)
|
||||
|
||||
## Deployment Notes
|
||||
|
||||
### For CT 212 (Proxmox CDP Bridge)
|
||||
|
||||
If the CDP bridge continues to hit the OAuth wall, deploy **Antigravity-Tools-LS** as a sidecar on CT 212:
|
||||
|
||||
```bash
|
||||
# On CT 212
|
||||
docker run -d \
|
||||
--name antigravity-ls \
|
||||
-p 5188:5188 \
|
||||
-e PORT=5188 \
|
||||
-e RUST_LOG=info \
|
||||
-v ~/.antigravity-ls-data:/root/.antigravity_tools_ls \
|
||||
lbjlaq/antigravity-tools-ls:latest
|
||||
```
|
||||
|
||||
Then configure the CDP bridge to use the sidecar's gRPC endpoint instead of the headless IDE:
|
||||
|
||||
```bash
|
||||
export AG_LS_HOST=127.0.0.1
|
||||
export AG_LS_PORT=5188
|
||||
export AG_CSRF_TOKEN=<csrf-token-from-sidecar>
|
||||
```
|
||||
|
||||
### For Aurelio-Web Server
|
||||
|
||||
To enable native Dirac mode on the web backend, set the environment variables before starting the server:
|
||||
|
||||
```bash
|
||||
export ANTIGRAVITY_LS_BINARY=/usr/local/bin/language_server_linux_x64
|
||||
export ANTIGRAVITY_OAUTH_ACCESS_TOKEN=<your-google-access-token>
|
||||
export ANTIGRAVITY_OAUTH_REFRESH_TOKEN=<your-google-refresh-token>
|
||||
export ANTIGRAVITY_OAUTH_EXPIRY=2026-06-04T12:00:00Z
|
||||
```
|
||||
|
||||
### For VS Code Extension Users
|
||||
|
||||
1. Set `aurelio.antigravity.mode` to `"native"`
|
||||
2. Set `aurelio.antigravity.lsBinaryPath` to your `language_server` binary path (or leave empty for auto-detect)
|
||||
3. Set `aurelio.antigravity.oauthToken.accessToken` and `refreshToken` from your Google OAuth session
|
||||
4. Click **Connect** in the Control Center's Antigravidade panel
|
||||
|
||||
## Preserved Functionality
|
||||
|
||||
- Non-Antigravity features (MCP, Brain, Vertex AI, Jules, etc.) are untouched
|
||||
- The `auto` and `cdp` modes in the VS Code extension continue to work as before
|
||||
- The CDP bridge REST API remains available for non-authenticated use cases
|
||||
|
|
@ -16,15 +16,49 @@ let browser = null;
|
|||
/** @type {import('puppeteer-core').Page | null} */
|
||||
let workbenchPage = null;
|
||||
|
||||
/**
|
||||
* Detect if the Antigravity IDE is stuck on an OAuth / Google login screen.
|
||||
* Returns true if authentication is required before the IDE can be used.
|
||||
*/
|
||||
async function isOAuthScreen(page) {
|
||||
try {
|
||||
const url = page.url();
|
||||
if (url.includes('accounts.google.com') || url.includes('oauth') || url.includes('login')) {
|
||||
return true;
|
||||
}
|
||||
// Check for login-related DOM elements
|
||||
const hasLoginElements = await page.evaluate(() => {
|
||||
const selectors = [
|
||||
'input[type="email"]',
|
||||
'input[type="password"]',
|
||||
'button:has-text("Sign in")',
|
||||
'button:has-text("Next")',
|
||||
'[data-testid="google-sign-in"]',
|
||||
'.auth-login-form',
|
||||
'.oauth-container',
|
||||
];
|
||||
return selectors.some(sel => document.querySelector(sel) !== null);
|
||||
});
|
||||
return hasLoginElements;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the Antigravity IDE via CDP.
|
||||
* Establishes a Puppeteer session using the CDP endpoint and discovers the workbench page.
|
||||
* Throws if the IDE requires OAuth authentication.
|
||||
*/
|
||||
export async function connect() {
|
||||
if (browser && workbenchPage) {
|
||||
try {
|
||||
// Test if connection is still alive
|
||||
await workbenchPage.evaluate(() => true);
|
||||
// Re-check OAuth barrier on reconnect — token may have expired
|
||||
if (await isOAuthScreen(workbenchPage)) {
|
||||
throw new Error('[CDP] OAuth authentication required. The Antigravity IDE is on a Google login screen. Please inject a valid OAuth token or log in manually.');
|
||||
}
|
||||
return workbenchPage;
|
||||
} catch {
|
||||
// Connection lost, reconnect
|
||||
|
|
@ -50,6 +84,11 @@ export async function connect() {
|
|||
throw new Error('[CDP] Could not acquire workbench page handle');
|
||||
}
|
||||
|
||||
// OAuth barrier detection — Antigravity now requires Google OAuth
|
||||
if (await isOAuthScreen(workbenchPage)) {
|
||||
throw new Error('[CDP] OAuth authentication required. The Antigravity IDE is on a Google login screen. Please inject a valid OAuth token or log in manually.');
|
||||
}
|
||||
|
||||
console.log('[CDP] Connected successfully');
|
||||
return workbenchPage;
|
||||
}
|
||||
|
|
@ -316,6 +355,7 @@ export async function getCurrentModel() {
|
|||
|
||||
/**
|
||||
* Get connection status info.
|
||||
* Reports OAuth barrier when the IDE requires authentication.
|
||||
*/
|
||||
export async function getStatus() {
|
||||
try {
|
||||
|
|
@ -330,9 +370,11 @@ export async function getStatus() {
|
|||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
} catch (err) {
|
||||
const isOAuthError = err.message.includes('OAuth');
|
||||
return {
|
||||
connected: false,
|
||||
error: err.message,
|
||||
oauthRequired: isOAuthError,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { createGrpcTransport } from '@connectrpc/connect-node';
|
|||
// --- Configuration ---
|
||||
const LS_HOST = process.env.AG_LS_HOST || '127.0.0.1';
|
||||
const LS_PORT = process.env.AG_LS_PORT || '3000';
|
||||
const CSRF_TOKEN = process.env.AG_CSRF_TOKEN || '';
|
||||
|
||||
/**
|
||||
* Service definition matching the generated proto.
|
||||
|
|
@ -72,6 +73,15 @@ function getClient() {
|
|||
const transport = createGrpcTransport({
|
||||
baseUrl,
|
||||
httpVersion: '2',
|
||||
interceptors: [
|
||||
(next) => async (req) => {
|
||||
// Inject CSRF token for Antigravity Language Server authentication
|
||||
if (CSRF_TOKEN) {
|
||||
req.header.set('x-codeium-csrf-token', CSRF_TOKEN);
|
||||
}
|
||||
return await next(req);
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
_client = createClient(AntigravityLanguageServerService, transport);
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ plugins:
|
|||
out: src/proto
|
||||
opt:
|
||||
- target=ts
|
||||
- import_extension=js
|
||||
- import_extension=.js
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ plugins:
|
|||
out: src/proto
|
||||
opt:
|
||||
- target=ts
|
||||
- import_extension=js
|
||||
- import_extension=.js
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// @generated by protoc-gen-connect-es v1.7.0 with parameter "target=ts,import_extension=js"
|
||||
// @generated by protoc-gen-connect-es v1.7.0 with parameter "target=ts,import_extension=.js"
|
||||
// @generated from file antigravity.proto (package antigravity.language_server_pb, syntax proto3)
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { AntigravityEmpty, AntigravityGetLoadCodeAssistResponse, AntigravityGetWorkspaceInfosResponse, AntigravityInitializeCascadePanelStateRequest, AntigravityInitializeCascadePanelStateResponse, AntigravitySendAgentMessageRequest, AntigravitySendAgentMessageResponse, AntigravityStartCascadeRequest, AntigravityStartCascadeResponse, AntigravityStreamReactiveUpdatesRequest, AntigravityStreamReactiveUpdatesResponse } from "./antigravity_pbjs";
|
||||
import { AntigravityEmpty, AntigravityGetLoadCodeAssistResponse, AntigravityGetWorkspaceInfosResponse, AntigravityInitializeCascadePanelStateRequest, AntigravityInitializeCascadePanelStateResponse, AntigravitySendAgentMessageRequest, AntigravitySendAgentMessageResponse, AntigravityStartCascadeRequest, AntigravityStartCascadeResponse, AntigravityStreamReactiveUpdatesRequest, AntigravityStreamReactiveUpdatesResponse } from "./antigravity_pb.js";
|
||||
import { MethodKind } from "@bufbuild/protobuf";
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// @generated by protoc-gen-es v1.10.0 with parameter "target=ts,import_extension=js"
|
||||
// @generated by protoc-gen-es v1.10.0 with parameter "target=ts,import_extension=.js"
|
||||
// @generated from file antigravity.proto (package antigravity.language_server_pb, syntax proto3)
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
|
|
|||
Loading…
Reference in a new issue