UNPKG

codecrucible-synth

Version:

Production-Ready AI Development Platform with Multi-Voice Synthesis, Smithery MCP Integration, Enterprise Security, and Zero-Timeout Reliability

427 lines (389 loc) 12 kB
/** * SynthesisCoordinator - Application Layer Implementation * Replaces integrated-system.ts with proper DI-based architecture * * Living Spiral Applied: * - COLLAPSE: Centralized request coordination without tight coupling * - COUNCIL: Multiple service orchestration through interfaces * - SYNTHESIS: Unified response formation from multiple sources * - REBIRTH: Clean execution with proper error handling * - REFLECTION: Performance monitoring and quality assessment * * Council Perspectives: * - Architect: Clean separation between application and infrastructure layers * - Maintainer: Testable, mockable dependencies through DI * - Security Guardian: All requests pass through security validation * - Performance Engineer: Efficient resource utilization and caching * - Explorer: Extensible architecture for new features */ import { EventEmitter } from 'events'; import { DependencyContainer } from '../di/dependency-container.js'; import { CLIENT_TOKEN, HYBRID_ROUTER_TOKEN, CACHE_COORDINATOR_TOKEN, SECURITY_VALIDATOR_TOKEN, STREAMING_MANAGER_TOKEN, PERFORMANCE_MONITOR_TOKEN, } from '../di/service-tokens.js'; import { logger } from '../logger.js'; import { ModelRequest, ModelResponse } from '../types.js'; export interface ApplicationRequest { id?: string; prompt: string; voice?: string; model?: string; temperature?: number; maxTokens?: number; stream?: boolean; useTools?: boolean; context?: Record<string, any>; metadata?: Record<string, any>; } export interface ApplicationResponse { id: string; requestId?: string; content: string; synthesis: { mode: 'single' | 'multi-voice' | 'collaborative'; voices: string[]; conflicts: any[]; consensus: { agreement: number; convergence: number; stability: number; diversity: number; }; finalDecision: { method: string; reasoning: string; confidence: number; alternatives: number; time: number; }; }; metadata: { processingTime: number; voicesConsulted: number; modelsUsed: string[]; totalTokens: number; cachingUsed: boolean; ragUsed: boolean; workflowUsed: boolean; costEstimate: number; }; quality: { overall: number; accuracy: number; completeness: number; relevance: number; creativity: number; }; performance: { responseTime: number; tokenRate: number; cacheHitRate: number; resourceUsage: { memory: number; cpu: number; }; }; } export class SynthesisCoordinator extends EventEmitter { private container: DependencyContainer; private initialized = false; private startTime: number; constructor(container: DependencyContainer) { super(); this.container = container; this.startTime = Date.now(); // Increase max listeners for complex synthesis operations this.setMaxListeners(100); logger.info('SynthesisCoordinator initialized with DI container'); } /** * Initialize the synthesis coordinator */ async initialize(): Promise<void> { if (this.initialized) { return; } try { logger.info('Initializing SynthesisCoordinator...'); // Verify all required services are available await this.verifyDependencies(); this.initialized = true; this.emit('initialized'); logger.info('SynthesisCoordinator initialization complete'); } catch (error) { logger.error('SynthesisCoordinator initialization failed', error); throw error; } } /** * Process application request through synthesis pipeline */ async processRequest(request: ApplicationRequest): Promise<ApplicationResponse> { if (!this.initialized) { await this.initialize(); } const requestId = request.id || this.generateRequestId(); const startTime = Date.now(); logger.info('Processing synthesis request', { requestId, prompt: request.prompt.substring(0, 100), }); try { // Phase 1: Security validation const securityValidator = this.container.resolve(SECURITY_VALIDATOR_TOKEN); const modelRequest: ModelRequest = { prompt: request.prompt, model: request.model, temperature: request.temperature, maxTokens: request.maxTokens, stream: request.stream, context: request.context, }; const validation = await securityValidator.validateRequest(modelRequest); if (!validation.isValid) { throw new Error(`Security validation failed: ${validation.reason}`); } // Phase 2: Request processing through client const client = this.container.resolve(CLIENT_TOKEN); const response = await (client as any).synthesize(modelRequest); // Phase 3: Response synthesis and enhancement const synthesisResponse = await this.synthesizeResponse(request, response, startTime); // Phase 4: Performance recording await this.recordPerformance(requestId, synthesisResponse); logger.info('Synthesis request completed', { requestId, processingTime: Date.now() - startTime, }); return synthesisResponse; } catch (error) { logger.error('Synthesis request failed', error, { requestId }); // Return error response in expected format return this.createErrorResponse(requestId, error, startTime); } } /** * Synthesize enhanced response from basic model response */ private async synthesizeResponse( request: ApplicationRequest, modelResponse: ModelResponse, startTime: number ): Promise<ApplicationResponse> { const processingTime = Date.now() - startTime; // Enhanced synthesis response return { id: `response_${Date.now()}`, requestId: request.id, content: modelResponse.content, synthesis: { mode: 'single', // TODO: Implement multi-voice when voice system is integrated voices: [], conflicts: [], consensus: { agreement: 1, convergence: 1, stability: 1, diversity: 0, }, finalDecision: { method: 'direct', reasoning: 'Single voice response through DI container', confidence: 0.8, alternatives: 0, time: processingTime, }, }, metadata: { processingTime, voicesConsulted: 1, modelsUsed: [modelResponse.model || 'unknown'], totalTokens: modelResponse.tokens_used || modelResponse.metadata?.tokens || 0, cachingUsed: modelResponse.cached || false, ragUsed: false, // TODO: Implement when RAG is integrated workflowUsed: false, // TODO: Implement when workflows are integrated costEstimate: 0, // TODO: Implement cost calculation }, quality: { overall: 0.8, accuracy: 0.8, completeness: 0.8, relevance: 0.8, creativity: 0.7, }, performance: { responseTime: processingTime, tokenRate: this.calculateTokenRate(modelResponse, processingTime), cacheHitRate: 0.0, // TODO: Get from cache coordinator resourceUsage: { memory: this.getMemoryUsage(), cpu: 0.0, // TODO: Implement CPU monitoring }, }, }; } /** * Create error response in standard format */ private createErrorResponse( requestId: string, error: any, startTime: number ): ApplicationResponse { const processingTime = Date.now() - startTime; const errorMessage = error instanceof Error ? error.message : String(error); return { id: `error_${Date.now()}`, requestId, content: `Error processing request: ${errorMessage}`, synthesis: { mode: 'single', voices: [], conflicts: [{ type: 'error', description: errorMessage }], consensus: { agreement: 0, convergence: 0, stability: 0, diversity: 0 }, finalDecision: { method: 'error', reasoning: 'Request failed during processing', confidence: 0.0, alternatives: 0, time: processingTime, }, }, metadata: { processingTime, voicesConsulted: 0, modelsUsed: [], totalTokens: 0, cachingUsed: false, ragUsed: false, workflowUsed: false, costEstimate: 0, }, quality: { overall: 0.0, accuracy: 0.0, completeness: 0.0, relevance: 0.0, creativity: 0.0, }, performance: { responseTime: processingTime, tokenRate: 0.0, cacheHitRate: 0.0, resourceUsage: { memory: this.getMemoryUsage(), cpu: 0.0, }, }, }; } /** * Verify all required dependencies are available */ private async verifyDependencies(): Promise<void> { const requiredServices = [ CLIENT_TOKEN, SECURITY_VALIDATOR_TOKEN, // Optional services that gracefully degrade HYBRID_ROUTER_TOKEN, CACHE_COORDINATOR_TOKEN, STREAMING_MANAGER_TOKEN, PERFORMANCE_MONITOR_TOKEN, ]; for (const token of requiredServices) { try { const service = this.container.resolve(token); if (!service) { logger.warn( `Service ${token.name} not available, continuing with degraded functionality` ); } } catch (error) { if (token === CLIENT_TOKEN || token === SECURITY_VALIDATOR_TOKEN) { throw new Error(`Critical service ${token.name} not available: ${error}`); } logger.warn(`Optional service ${token.name} not available: ${error}`); } } } /** * Record performance metrics */ private async recordPerformance(requestId: string, response: ApplicationResponse): Promise<void> { try { const performanceMonitor = this.container.resolve(PERFORMANCE_MONITOR_TOKEN); if (performanceMonitor && typeof performanceMonitor.recordRequest === 'function') { await performanceMonitor.recordRequest(requestId, { responseTime: response.performance.responseTime, tokenRate: response.performance.tokenRate, success: !response.synthesis.conflicts.length, modelUsed: response.metadata.modelsUsed[0] || 'unknown', }); } } catch (error) { logger.warn('Performance recording failed', error); } } /** * Calculate token processing rate */ private calculateTokenRate(response: ModelResponse, processingTime: number): number { const tokens = response.tokens_used || response.metadata?.tokens || 0; if (tokens === 0 || processingTime === 0) { return 0; } return Math.round((tokens / processingTime) * 1000 * 100) / 100; // tokens per second } /** * Get current memory usage */ private getMemoryUsage(): number { try { const memUsage = process.memoryUsage(); return Math.round(memUsage.heapUsed / (1024 * 1024)); // MB } catch (error) { return 0; } } /** * Generate unique request ID */ private generateRequestId(): string { return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * Get system status */ async getStatus(): Promise<{ initialized: boolean; uptime: number; dependencies: Record<string, boolean>; }> { const dependencies: Record<string, boolean> = {}; const services = [ CLIENT_TOKEN, SECURITY_VALIDATOR_TOKEN, HYBRID_ROUTER_TOKEN, CACHE_COORDINATOR_TOKEN, STREAMING_MANAGER_TOKEN, PERFORMANCE_MONITOR_TOKEN, ]; for (const token of services) { try { const service = this.container.resolve(token); dependencies[token.name] = !!service; } catch (error) { dependencies[token.name] = false; } } return { initialized: this.initialized, uptime: Date.now() - this.startTime, dependencies, }; } }