UNPKG

jay-code

Version:

Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability

421 lines (357 loc) 13.2 kB
/** * Jay-Code Orchestrator: Single Model Intelligence with Mathematical Agent Coordination * Integrates Model Manager, Planning Agent, and QA Agent with deterministic operations */ import { EventEmitter } from 'events'; import { ModelManager, ModelConfig } from './model-manager.js'; import { PlanningAgent, Task, ExecutionPlan } from './planning-agent.js'; import { QAAgent, QAReport } from './qa-agent.js'; import { JayCodeConfigManager, JayCodeConfig } from '../core/jay-config.js'; export interface ExecutionContext { sessionId: string; userId: string; timestamp: Date; environment: 'development' | 'testing' | 'production'; memoryNamespace?: string; } export interface TaskRequest { id: string; description: string; requirements: string[]; context?: any; priority: number; estimatedComplexity?: number; } export interface ExecutionResult { taskId: string; success: boolean; generatedCode?: string; executionPlan?: ExecutionPlan; qaReport?: QAReport; metrics: ExecutionMetrics; errors: string[]; warnings: string[]; artifacts: ResultArtifact[]; } export interface ExecutionMetrics { startTime: Date; endTime: Date; totalDuration: number; planningDuration: number; generationDuration: number; qaDuration: number; modelSwitches: number; memoryOperations: number; cacheHits: number; } export interface ResultArtifact { type: 'code' | 'documentation' | 'test' | 'schema'; name: string; content: string; hash: string; metadata: any; } export class JayCodeOrchestrator extends EventEmitter { private modelManager: ModelManager; private planningAgent: PlanningAgent; private qaAgent: QAAgent; private configManager: JayCodeConfigManager; private config: JayCodeConfig; private activeTasks: Map<string, ExecutionContext> = new Map(); constructor(configPath?: string) { super(); this.configManager = new JayCodeConfigManager(configPath); this.config = this.configManager.getConfig(); this.initializeComponents(); } private initializeComponents(): void { // Initialize Model Manager with primary and fallback models const modelConfig = this.configManager.getModelConfig(); this.modelManager = new ModelManager(modelConfig.primary, modelConfig.fallback); // Initialize Planning Agent with mathematical configuration const planningConfig = this.configManager.getPlanningAgentConfig(); this.planningAgent = new PlanningAgent({ complexityThreshold: planningConfig.complexityThreshold, maxSubTasks: planningConfig.maxSubTasks }); // Initialize QA Agent with statistical configuration const qaConfig = this.configManager.getQAAgentConfig(); this.qaAgent = new QAAgent({ passThreshold: qaConfig.passThreshold, strictMode: qaConfig.strictMode, autoFix: qaConfig.autoFix }); // Set up event listeners for component coordination this.setupEventListeners(); } private setupEventListeners(): void { this.modelManager.on('fallback-activated', (data) => { this.emit('model-fallback', data); }); this.modelManager.on('health-update', (data) => { this.emit('model-health-update', data); }); this.planningAgent.on('task-decomposed', (data) => { this.emit('task-decomposed', data); }); this.planningAgent.on('execution-coordinated', (data) => { this.emit('execution-coordinated', data); }); this.qaAgent.on('review-completed', (data) => { this.emit('qa-completed', data); }); } /** * Main task execution with mathematical precision and formal verification */ async executeTask(taskRequest: TaskRequest, context: ExecutionContext): Promise<ExecutionResult> { const startTime = new Date(); const errors: string[] = []; const warnings: string[] = []; const artifacts: ResultArtifact[] = []; try { // Register active task this.activeTasks.set(taskRequest.id, context); this.emit('task-started', { taskId: taskRequest.id, context }); // Step 1: Task Analysis and Planning (if enabled) let executionPlan: ExecutionPlan | undefined; const planningStartTime = Date.now(); if (this.config.agents.planning.enabled) { const task: Task = { id: taskRequest.id, description: taskRequest.description, complexity: taskRequest.estimatedComplexity || 0.5, dependencies: [], requirements: taskRequest.requirements, estimatedTokens: this.estimateTokens(taskRequest.description), priority: taskRequest.priority }; const subTasks = await this.planningAgent.breakdownTask(task); executionPlan = { id: `plan_${taskRequest.id}`, originalTask: task, subTasks, dependencyGraph: new Map(), criticalPath: [], estimatedDuration: this.estimateDuration(subTasks), prompt: this.buildPrompt(task, subTasks), context: taskRequest.context }; await this.planningAgent.coordinateExecution(executionPlan); } const planningDuration = Date.now() - planningStartTime; // Step 2: Code Generation using Single Model Intelligence const generationStartTime = Date.now(); const prompt = executionPlan ? executionPlan.prompt : this.buildSimplePrompt(taskRequest); const generatedCode = await this.modelManager.generateCode(prompt, { context: taskRequest.context, temperature: 0.2, // Lower temperature for more deterministic results maxTokens: executionPlan ? executionPlan.subTasks.reduce((sum, st) => sum + st.estimatedTokens, 0) : this.estimateTokens(taskRequest.description) }); const generationDuration = Date.now() - generationStartTime; // Step 3: Quality Assurance Analysis (if enabled) let qaReport: QAReport | undefined; const qaStartTime = Date.now(); if (this.config.agents.qa.enabled) { qaReport = await this.qaAgent.reviewCode(generatedCode, { requirements: taskRequest.requirements, context: taskRequest.context, standards: this.config.validation.enterpriseCompliance.standards }); // Handle QA failures if (!qaReport.passed && this.config.agents.qa.autoFix) { warnings.push('Code quality below threshold, attempting auto-fix'); // Could implement auto-fix logic here } } const qaDuration = Date.now() - qaStartTime; // Step 4: Create Result Artifacts artifacts.push({ type: 'code', name: `${taskRequest.id}.generated.ts`, content: generatedCode, hash: this.calculateHash(generatedCode), metadata: { model: this.modelManager.getHealthMetrics(), timestamp: new Date(), context: taskRequest.context } }); if (executionPlan) { artifacts.push({ type: 'documentation', name: `${taskRequest.id}.execution-plan.json`, content: JSON.stringify(executionPlan, null, 2), hash: this.calculateHash(JSON.stringify(executionPlan)), metadata: { type: 'execution-plan', subTasks: executionPlan.subTasks.length } }); } if (qaReport) { artifacts.push({ type: 'documentation', name: `${taskRequest.id}.qa-report.json`, content: JSON.stringify(qaReport, null, 2), hash: this.calculateHash(JSON.stringify(qaReport)), metadata: { score: qaReport.analysis.overallScore, passed: qaReport.passed } }); } // Step 5: Finalize Results const endTime = new Date(); const result: ExecutionResult = { taskId: taskRequest.id, success: true, generatedCode, executionPlan, qaReport, metrics: { startTime, endTime, totalDuration: endTime.getTime() - startTime.getTime(), planningDuration, generationDuration, qaDuration, modelSwitches: 0, // Track model switches memoryOperations: 0, // Track memory operations cacheHits: 0 // Track cache hits }, errors, warnings, artifacts }; this.emit('task-completed', { taskId: taskRequest.id, success: true, result }); return result; } catch (error) { errors.push(`Execution failed: ${error.message}`); const result: ExecutionResult = { taskId: taskRequest.id, success: false, metrics: { startTime, endTime: new Date(), totalDuration: Date.now() - startTime.getTime(), planningDuration: 0, generationDuration: 0, qaDuration: 0, modelSwitches: 0, memoryOperations: 0, cacheHits: 0 }, errors, warnings, artifacts }; this.emit('task-failed', { taskId: taskRequest.id, error: error.message, result }); return result; } finally { // Clean up active task this.activeTasks.delete(taskRequest.id); } } private estimateTokens(description: string): number { // Simple token estimation - 4 characters per token average return Math.ceil(description.length / 4) * 10; // Multiply by 10 for code generation } private estimateDuration(subTasks: any[]): number { // Estimate duration based on token count and complexity return subTasks.reduce((sum, task) => sum + task.estimatedTokens * 0.1, 0); } private buildPrompt(task: Task, subTasks: any[]): string { const basePrompt = `Generate high-quality TypeScript code for the following task: Task: ${task.description} Requirements: ${task.requirements.join(', ')} Subtasks to implement: ${subTasks.map((st, i) => `${i + 1}. ${st.description}`).join('\n')} Follow these principles: - Write clean, maintainable TypeScript code - Include proper error handling - Add comprehensive documentation - Follow mathematical precision and deterministic patterns - Ensure enterprise-grade reliability - Use strict typing throughout Generate complete, production-ready code:`; return basePrompt; } private buildSimplePrompt(taskRequest: TaskRequest): string { return `Generate high-quality TypeScript code for: ${taskRequest.description} Requirements: ${taskRequest.requirements.join(', ')} Follow Jay-Code principles: - Mathematical precision and deterministic operations - Enterprise-grade reliability and error handling - Clean, maintainable code with comprehensive documentation - Strict TypeScript typing throughout Generate complete, production-ready code:`; } private calculateHash(content: string): string { // Simple hash function - in production, use crypto.createHash let hash = 0; for (let i = 0; i < content.length; i++) { const char = content.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32-bit integer } return Math.abs(hash).toString(16); } /** * Health check with mathematical performance guarantees */ async healthCheck(): Promise<{ status: 'healthy' | 'degraded' | 'failed'; components: Record<string, boolean>; metrics: any; }> { const componentHealth = { modelManager: await this.modelManager.healthCheck(), planningAgent: this.config.agents.planning.enabled, qaAgent: this.config.agents.qa.enabled, configuration: true }; const overallHealthy = Object.values(componentHealth).every(h => h); return { status: overallHealthy ? 'healthy' : 'degraded', components: componentHealth, metrics: { activeTasks: this.activeTasks.size, modelHealth: this.modelManager.getHealthMetrics(), uptime: process.uptime() } }; } /** * Get current system metrics with statistical analysis */ getMetrics(): any { return { activeTasks: this.activeTasks.size, modelHealth: this.modelManager.getHealthMetrics(), configuration: this.config, uptime: process.uptime(), memoryUsage: process.memoryUsage() }; } } private rulesEngine: DevelopmentRulesEngine; constructor(configPath?: string) { super(); this.configManager = new JayCodeConfigManager(configPath); this.config = this.configManager.getConfig(); this.rulesEngine = new DevelopmentRulesEngine(); this.initializeComponents(); } /** * Validate generated code against Jay-Code development philosophy */ private async validateWithRules(code: string, context: any): Promise<any> { const validation = this.rulesEngine.validateCode(code, context); if (!validation.passed) { this.emit('rules-validation-failed', { score: validation.score, violations: validation.violations, recommendations: validation.recommendations }); } return validation; } // Update executeTask to include rules validation // [The existing executeTask method would be modified to call validateWithRules]