/** * Integration Adapters * * Provides native integration support for 3rd party AI coding tools. * Supports OpenClaw, Claude Code CLI, Cursor, Aider, and custom integrations. */ import { IntegrationAdapter, IntegrationType, IntegrationStatus, IntegrationConfig, RequestClassification, DelegationDecision, DelegationResult, ProgressEvent, DelegationRequest, DelegationResponse, AgentType } from '../core/types'; import { RequestClassifier } from '../core/request-classifier'; import { DelegationEngine } from '../core/delegation-engine'; import { AgentPoolManager } from '../pool/agent-pool-manager'; import { ProgressStreamer } from '../streaming/progress-streamer'; import { QualityGate } from '../quality/quality-gate'; // ============================================================================ // Base Integration Adapter // ============================================================================ export abstract class BaseIntegrationAdapter implements IntegrationAdapter { abstract type: IntegrationType; abstract name: string; abstract version: string; protected classifier: RequestClassifier; protected delegationEngine: DelegationEngine; protected poolManager: AgentPoolManager; protected progressStreamer: ProgressStreamer; protected qualityGate: QualityGate; protected initialized: boolean = false; constructor( classifier: RequestClassifier, delegationEngine: DelegationEngine, poolManager: AgentPoolManager, progressStreamer: ProgressStreamer, qualityGate: QualityGate ) { this.classifier = classifier; this.delegationEngine = delegationEngine; this.poolManager = poolManager; this.progressStreamer = progressStreamer; this.qualityGate = qualityGate; } abstract initialize(config: any): Promise; abstract shutdown(): Promise; abstract classifyRequest(request: any): Promise; abstract delegateRequest(request: any, decision: DelegationDecision): Promise; abstract streamProgress(requestId: string, callback: (event: ProgressEvent) => void): void; abstract getStatus(): IntegrationStatus; abstract getCapabilities(): string[]; /** * Check if adapter is ready */ isReady(): boolean { return this.initialized && this.poolManager.getPoolStats().idleCount > 0; } } // ============================================================================ // OpenClaw Integration Adapter // ============================================================================ export class OpenClawAdapter extends BaseIntegrationAdapter { type: IntegrationType = 'openclaw'; name = 'OpenClaw Integration'; version = '1.0.0'; private config: IntegrationConfig | null = null; private eventHandlers: Map void>> = new Map(); async initialize(config: IntegrationConfig): Promise { this.config = config; // Configure pool for OpenClaw pattern (4 projects × 3 roles) this.poolManager = new AgentPoolManager({ maxSize: 50, minIdle: 12, ...config.pool }); this.initialized = true; } async shutdown(): Promise { await this.poolManager.shutdown(); this.eventHandlers.clear(); this.initialized = false; } async classifyRequest(request: any): Promise { // Convert OpenClaw request format const classifiableRequest = { content: request.prompt || request.content || request.message, type: this.detectRequestType(request), files: request.files || request.context?.files, metadata: { projectId: request.projectId, conversationId: request.conversationId, ...request.metadata }, timestamp: Date.now() }; return this.classifier.classify(classifiableRequest); } async delegateRequest(request: any, decision: DelegationDecision): Promise { const requestId = `openclaw-${Date.now()}`; // Start progress tracking this.progressStreamer.startTracking(requestId); this.progressStreamer.acknowledge(requestId); // Execute delegation const result = await this.delegationEngine.executeDelegation( { content: request.prompt || request.content, type: this.detectRequestType(request), files: request.files, metadata: request.metadata, timestamp: Date.now() }, decision, async (agentType, agentId, req) => { // Notify delegation this.progressStreamer.notifyDelegation(requestId, agentType, agentId); // Simulate agent execution (would call actual agent in production) return this.executeOpenClawAgent(agentType, agentId, req, request); } ); // Validate result const validation = await this.qualityGate.validate(result, { requestId, originalRequest: request, classification: await this.classifyRequest(request), delegationDecision: decision, assignedAgents: result.agentsUsed, status: result.success ? 'completed' : 'failed', startTime: new Date(), result }); // Complete progress if (validation.passed) { this.progressStreamer.complete(requestId); } else { this.progressStreamer.error(requestId, validation.issues.map(i => i.message).join(', ')); } return result; } private async executeOpenClawAgent( agentType: AgentType, agentId: string, request: any, originalRequest: any ): Promise { const startTime = Date.now(); // In production, this would call the actual OpenClaw agent // For now, return a simulated result await this.simulateProcessing(100, 2000); return { success: true, output: `[${agentType}] Processed: ${request.content?.slice(0, 100)}...`, confidence: 0.85, tokensUsed: Math.floor(Math.random() * 500) + 100, duration: Date.now() - startTime, agentsUsed: [agentId], needsReview: false }; } private async simulateProcessing(minMs: number, maxMs: number): Promise { const delay = Math.floor(Math.random() * (maxMs - minMs)) + minMs; await new Promise(resolve => setTimeout(resolve, delay)); } streamProgress(requestId: string, callback: (event: ProgressEvent) => void): void { this.progressStreamer.subscribe(requestId, callback); } getStatus(): IntegrationStatus { const poolStats = this.poolManager.getPoolStats(); const mainAgentState = this.delegationEngine.getMainAgentState(); return { connected: this.initialized, ready: this.isReady(), agentPoolAvailable: poolStats.idleCount > 0, currentLoad: poolStats.busyPercentage, queueLength: 0, averageResponseTime: mainAgentState.averageResponseTime }; } getCapabilities(): string[] { return [ 'parallel-execution', 'deterministic-pipeline', 'workspace-isolation', 'progress-streaming', 'quality-validation', 'auto-escalation', 'lobster-workflows' ]; } private detectRequestType(request: any): 'code' | 'question' | 'task' | 'analysis' | 'review' | 'refactor' | 'debug' { const content = (request.prompt || request.content || '').toLowerCase(); if (/review|check|audit/i.test(content)) return 'review'; if (/debug|fix|error|issue/i.test(content)) return 'debug'; if (/refactor|rewrite|restructure/i.test(content)) return 'refactor'; if (/analyze|investigate|examine/i.test(content)) return 'analysis'; if (/implement|create|build|add/i.test(content)) return 'task'; if (/\?|what|how|why|when/i.test(content)) return 'question'; return 'code'; } // OpenClaw-specific methods on(event: string, handler: (event: any) => void): void { if (!this.eventHandlers.has(event)) { this.eventHandlers.set(event, new Set()); } this.eventHandlers.get(event)!.add(handler); } off(event: string, handler: (event: any) => void): void { this.eventHandlers.get(event)?.delete(handler); } private emit(event: string, data: any): void { this.eventHandlers.get(event)?.forEach(handler => { try { handler(data); } catch (e) { console.error('Event handler error:', e); } }); } } // ============================================================================ // Claude Code CLI Integration Adapter // ============================================================================ export class ClaudeCodeAdapter extends BaseIntegrationAdapter { type: IntegrationType = 'claude-code'; name = 'Claude Code CLI Integration'; version = '1.0.0'; private config: IntegrationConfig | null = null; private tools: any[] = []; async initialize(config: IntegrationConfig): Promise { this.config = config; // Register Claude Code specific tools this.registerDefaultTools(); this.initialized = true; } async shutdown(): Promise { this.tools = []; this.initialized = false; } private registerDefaultTools(): void { this.tools = [ { name: 'delegate_task', description: 'Delegate a task to a specialized subagent', input_schema: { type: 'object', properties: { task_type: { type: 'string', enum: ['explorer', 'researcher', 'coder', 'reviewer', 'planner', 'analyzer'] }, prompt: { type: 'string' }, files: { type: 'array', items: { type: 'string' } } }, required: ['task_type', 'prompt'] } }, { name: 'check_pool_status', description: 'Check the status of the agent pool', input_schema: { type: 'object', properties: {} } } ]; } async classifyRequest(request: any): Promise { const classifiableRequest = { content: request.content || request.prompt || request.message, type: this.detectRequestType(request), files: request.files || [], metadata: { toolUse: request.tool_use, ...request.metadata }, timestamp: Date.now() }; return this.classifier.classify(classifiableRequest); } async delegateRequest(request: any, decision: DelegationDecision): Promise { const requestId = `claude-code-${Date.now()}`; this.progressStreamer.startTracking(requestId); this.progressStreamer.acknowledge(requestId, 'Claude Code: Processing request...'); const result = await this.delegationEngine.executeDelegation( { content: request.content || request.prompt, type: this.detectRequestType(request), files: request.files || [], metadata: request.metadata, timestamp: Date.now() }, decision, async (agentType, agentId, req) => { this.progressStreamer.notifyDelegation(requestId, agentType, agentId); return this.executeClaudeCodeAgent(agentType, agentId, req, request); } ); const validation = await this.qualityGate.validate(result, { requestId, originalRequest: request, classification: await this.classifyRequest(request), delegationDecision: decision, assignedAgents: result.agentsUsed, status: result.success ? 'completed' : 'failed', startTime: new Date(), result }); if (validation.shouldEscalate) { this.progressStreamer.escalate(requestId, validation.issues.map(i => i.message).join(', ')); } else if (validation.passed) { this.progressStreamer.complete(requestId); } return result; } private async executeClaudeCodeAgent( agentType: AgentType, agentId: string, request: any, originalRequest: any ): Promise { const startTime = Date.now(); await new Promise(resolve => setTimeout(resolve, 500 + Math.random() * 1500)); return { success: true, output: `[Claude Code - ${agentType}] ${request.content?.slice(0, 100)}`, confidence: 0.9, tokensUsed: Math.floor(Math.random() * 300) + 50, duration: Date.now() - startTime, agentsUsed: [agentId], needsReview: agentType === 'planner' }; } streamProgress(requestId: string, callback: (event: ProgressEvent) => void): void { this.progressStreamer.subscribe(requestId, callback); } getStatus(): IntegrationStatus { const poolStats = this.poolManager.getPoolStats(); return { connected: this.initialized, ready: this.isReady(), agentPoolAvailable: poolStats.idleCount > 0, currentLoad: poolStats.busyPercentage, queueLength: 0, averageResponseTime: 3000 }; } getCapabilities(): string[] { return [ 'tool-use', 'context-compaction', 'subagent-spawning', 'progress-streaming', 'quality-validation', 'auto-compaction', 'persistent-memory' ]; } getTools(): any[] { return this.tools; } private detectRequestType(request: any): 'code' | 'question' | 'task' | 'analysis' | 'review' | 'refactor' | 'debug' { const content = (request.content || request.prompt || '').toLowerCase(); if (/review|check/i.test(content)) return 'review'; if (/debug|fix|error/i.test(content)) return 'debug'; if (/refactor/i.test(content)) return 'refactor'; if (/analyze/i.test(content)) return 'analysis'; if (/implement|create|build/i.test(content)) return 'task'; if (/\?|what|how/i.test(content)) return 'question'; return 'code'; } } // ============================================================================ // Generic Integration Adapter // ============================================================================ export class GenericAdapter extends BaseIntegrationAdapter { type: IntegrationType = 'generic'; name = 'Generic Integration'; version = '1.0.0'; private config: IntegrationConfig | null = null; async initialize(config: IntegrationConfig): Promise { this.config = config; this.initialized = true; } async shutdown(): Promise { this.initialized = false; } async classifyRequest(request: any): Promise { return this.classifier.classify({ content: request.content || request.prompt || String(request), type: 'code', files: request.files || [], metadata: request.metadata || {}, timestamp: Date.now() }); } async delegateRequest(request: any, decision: DelegationDecision): Promise { const requestId = `generic-${Date.now()}`; this.progressStreamer.startTracking(requestId); const result = await this.delegationEngine.executeDelegation( { content: request.content || String(request), type: 'code', files: [], metadata: {}, timestamp: Date.now() }, decision, async (agentType, agentId, req) => { return { success: true, output: `Processed by ${agentType}`, confidence: 0.8, tokensUsed: 100, duration: 1000, agentsUsed: [agentId], needsReview: false }; } ); return result; } streamProgress(requestId: string, callback: (event: ProgressEvent) => void): void { this.progressStreamer.subscribe(requestId, callback); } getStatus(): IntegrationStatus { const poolStats = this.poolManager.getPoolStats(); return { connected: this.initialized, ready: this.isReady(), agentPoolAvailable: poolStats.idleCount > 0, currentLoad: poolStats.busyPercentage, queueLength: 0, averageResponseTime: 5000 }; } getCapabilities(): string[] { return ['delegation', 'classification', 'progress-streaming']; } } // ============================================================================ // Factory Functions // ============================================================================ export function createOpenClawAdapter( classifier: RequestClassifier, delegationEngine: DelegationEngine, poolManager: AgentPoolManager, progressStreamer: ProgressStreamer, qualityGate: QualityGate ): OpenClawAdapter { return new OpenClawAdapter(classifier, delegationEngine, poolManager, progressStreamer, qualityGate); } export function createClaudeCodeAdapter( classifier: RequestClassifier, delegationEngine: DelegationEngine, poolManager: AgentPoolManager, progressStreamer: ProgressStreamer, qualityGate: QualityGate ): ClaudeCodeAdapter { return new ClaudeCodeAdapter(classifier, delegationEngine, poolManager, progressStreamer, qualityGate); } export function createGenericAdapter( classifier: RequestClassifier, delegationEngine: DelegationEngine, poolManager: AgentPoolManager, progressStreamer: ProgressStreamer, qualityGate: QualityGate ): GenericAdapter { return new GenericAdapter(classifier, delegationEngine, poolManager, progressStreamer, qualityGate); } // ============================================================================ // Export // ============================================================================ export default { BaseIntegrationAdapter, OpenClawAdapter, ClaudeCodeAdapter, GenericAdapter, createOpenClawAdapter, createClaudeCodeAdapter, createGenericAdapter };