Files
gravity_control/antigravity-sdk-main/src/sdk.ts
CD c3964f8e7a fix(bridge): rawRPC direct polling + SDK analysis docs + trial-and-error log
- Root cause: getDiagnostics.lastStepIndex is stale, SDK EventMonitor cannot detect real-time step changes
- Fix: Direct rawRPC('GetCascadeTrajectorySteps') polling every 5s
- Relay: PLANNER_RESPONSE, NOTIFY_USER, TASK_BOUNDARY, WAITING steps
- Added: docs/discord-bridge-analysis.md (full SDK architecture analysis)
- Added: docs/devlog/entries/20260308-003.md (trial-and-error history)
- Added: antigravity-sdk-main/ source reference
- Vikunja: #252 done, #253 created, #251 commented
2026-03-08 07:08:25 +09:00

230 lines
7.2 KiB
TypeScript

/**
* Main SDK entry point.
*
* Provides a unified interface to Antigravity's agent system
* via verified transport layer (CommandBridge + StateBridge + EventMonitor).
*
* @module AntigravitySDK
*
* @example
* ```typescript
* import { AntigravitySDK } from 'antigravity-sdk';
*
* export function activate(context: vscode.ExtensionContext) {
* const sdk = new AntigravitySDK(context);
* await sdk.initialize();
*
* // List conversations
* const sessions = await sdk.cascade.getSessions();
* console.log(`${sessions.length} conversations`);
*
* // Read preferences (all 16 sentinel values)
* const prefs = await sdk.cascade.getPreferences();
* console.log('Terminal policy:', prefs.terminalExecutionPolicy);
*
* // Monitor for new conversations
* sdk.monitor.onNewConversation(() => {
* console.log('New conversation detected!');
* });
* sdk.monitor.start(3000);
*
* // Clean up
* context.subscriptions.push(sdk);
* }
* ```
*/
import * as vscode from 'vscode';
import { DisposableStore, IDisposable } from './core/disposable';
import { Logger, LogLevel } from './core/logger';
import { AntigravityNotFoundError } from './core/errors';
import { CommandBridge } from './transport/command-bridge';
import { StateBridge } from './transport/state-bridge';
import { EventMonitor } from './transport/event-monitor';
import { LSBridge } from './transport/ls-bridge';
import { CascadeManager } from './cascade/cascade-manager';
import { IntegrationManager } from './integration/integration-manager';
const log = new Logger('SDK');
/**
* SDK initialization options.
*/
export interface ISDKOptions {
/** Enable debug logging */
debug?: boolean;
}
/**
* The main Antigravity SDK class.
*
* Provides access to:
* - `commands` — Execute Antigravity internal commands
* - `state` — Read agent preferences and state from USS
* - `cascade` — Manage Cascade conversations, send messages, read preferences
* - `monitor` — Watch for state changes (new conversations, preference updates)
*
* @example
* ```typescript
* const sdk = new AntigravitySDK(context);
* await sdk.initialize();
* const sessions = await sdk.cascade.getSessions();
* ```
*/
export class AntigravitySDK implements IDisposable {
private readonly _disposables = new DisposableStore();
private _initialized = false;
/** Command bridge for executing Antigravity commands */
public readonly commands: CommandBridge;
/** State bridge for reading USS data */
public readonly state: StateBridge;
/** Cascade manager for conversations, preferences, diagnostics */
public readonly cascade: CascadeManager;
/** Event monitor for watching state changes */
public readonly monitor: EventMonitor;
/** Integration manager for Agent View UI customization */
public readonly integration: IntegrationManager;
/**
* Language Server bridge for headless cascade operations.
* Use this for background cascade creation without UI switching.
*
* @example
* ```typescript
* const id = await sdk.ls.createCascade({ text: 'Analyze coverage' });
* await sdk.ls.sendMessage({ cascadeId: id, text: 'Focus on tests' });
* await sdk.ls.focusCascade(id); // Only when ready to show
* ```
*/
public readonly ls: LSBridge;
/**
* Create a new Antigravity SDK instance.
*
* @param context - VS Code extension context
* @param options - SDK options
*/
constructor(
private readonly _context: vscode.ExtensionContext,
options?: ISDKOptions,
) {
if (options?.debug) {
Logger.setLevel(LogLevel.Debug);
}
// Derive namespace from extension ID for file isolation
// e.g. 'kanezal.better-antigravity' -> 'kanezal-better-antigravity'
const namespace = this._context.extension.id.replace(/\./g, '-');
this.commands = this._disposables.add(new CommandBridge());
this.state = this._disposables.add(new StateBridge());
this.cascade = this._disposables.add(new CascadeManager(this.commands, this.state));
this.monitor = this._disposables.add(new EventMonitor(this.state));
this.integration = this._disposables.add(new IntegrationManager(namespace));
this.ls = new LSBridge(
<T = any>(cmd: string, ...args: any[]) => Promise.resolve(vscode.commands.executeCommand<T>(cmd, ...args))
);
log.info(`SDK created (namespace: ${namespace})`);
}
/**
* Initialize the SDK and verify Antigravity is running.
*
* Call this before using any SDK features.
*
* @throws {AntigravityNotFoundError} If Antigravity is not detected
*/
async initialize(): Promise<void> {
if (this._initialized) {
return;
}
log.info('Initializing SDK...');
// Verify we're running inside Antigravity
const isAntigravity = await this._detectAntigravity();
if (!isAntigravity) {
throw new AntigravityNotFoundError();
}
// Initialize state bridge (opens state.vscdb via sql.js)
await this.state.initialize();
// Initialize cascade manager (loads session list)
await this.cascade.initialize();
// Initialize LS bridge (discovers Language Server port + CSRF token)
const lsOk = await this.ls.initialize();
if (lsOk) {
log.info(`LS bridge ready on port ${this.ls.port} (csrf: ${this.ls.hasCsrfToken ? 'ok' : 'missing'})`);
} else {
log.warn('LS bridge not available — use sdk.ls.setConnection(port, csrfToken) or command fallback');
}
// Refresh integration heartbeat (so renderer script knows extension is active)
this.integration.signalActive();
this._initialized = true;
log.info('SDK initialized successfully');
}
/**
* Check if the SDK has been initialized.
*/
get isInitialized(): boolean {
return this._initialized;
}
/**
* Get the SDK version.
*/
get version(): string {
try {
return require('../package.json').version;
} catch {
return 'unknown';
}
}
/**
* Detect if we're running inside Antigravity IDE.
*/
private async _detectAntigravity(): Promise<boolean> {
try {
// Check for Antigravity-specific commands (VERIFIED naming)
const commands = await this.commands.getAntigravityCommands();
const hasAgentPanel = commands.includes('antigravity.agentPanel.open');
if (hasAgentPanel) {
log.debug(`Detected Antigravity (${commands.length} commands)`);
return true;
}
// Fallback: check env
const appName = vscode.env.appName;
if (appName?.toLowerCase().includes('antigravity')) {
log.debug(`Detected Antigravity via appName: ${appName}`);
return true;
}
return false;
} catch {
return false;
}
}
/**
* Dispose of the SDK and all its resources.
*/
dispose(): void {
log.info('Disposing SDK');
this._disposables.dispose();
}
}