UNPKG

@clduab11/gemini-flow

Version:

Revolutionary AI agent swarm coordination platform with Google Services integration, multimedia processing, and production-ready monitoring. Features 8 Google AI services, quantum computing capabilities, and enterprise-grade security.

430 lines (362 loc) 11.5 kB
/** * BatchTool - Parallel Execution Engine * * Implements the GOLDEN RULE: "1 MESSAGE = ALL RELATED OPERATIONS" * Enables <100ms agent spawn time through intelligent batching */ import { EventEmitter } from "events"; import { Worker } from "worker_threads"; import { Logger } from "../utils/logger.js"; import { ResourcePool } from "./resource-pool.js"; import { DependencyGraph } from "./dependency-graph.js"; import { PerformanceMonitor } from "../monitoring/performance-monitor.js"; export interface BatchOperation { id: string; type: "agent_spawn" | "task_execute" | "memory_op" | "file_op" | "command"; operation: any; dependencies?: string[]; priority?: number; timeout?: number; } export interface BatchResult { id: string; success: boolean; result?: any; error?: Error; duration: number; metadata?: any; } export class BatchTool extends EventEmitter { private workers: Worker[] = []; private resourcePool: ResourcePool; private dependencyGraph: DependencyGraph; private performanceMonitor: PerformanceMonitor; private logger: Logger; // Configuration private config = { maxWorkers: 8, maxConcurrency: 64, spawnTimeout: 100, // Target: <100ms operationTimeout: 30000, retryAttempts: 3, batchSize: 50, }; // Metrics private metrics = { totalBatches: 0, totalOperations: 0, successfulOps: 0, failedOps: 0, avgSpawnTime: 0, avgBatchTime: 0, }; constructor(config?: Partial<typeof BatchTool.prototype.config>) { super(); this.config = { ...this.config, ...config }; this.resourcePool = new ResourcePool(this.config.maxConcurrency); this.dependencyGraph = new DependencyGraph(); this.performanceMonitor = new PerformanceMonitor(); this.logger = new Logger("BatchTool"); this.initializeWorkers(); } /** * Execute batch of operations in parallel */ async executeBatch(operations: BatchOperation[]): Promise<BatchResult[]> { const batchId = `batch_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const startTime = Date.now(); this.logger.info(`Starting batch execution`, { batchId, operationCount: operations.length, }); this.metrics.totalBatches++; this.metrics.totalOperations += operations.length; try { // Build dependency graph const graph = this.buildDependencyGraph(operations); // Get execution order const executionPlan = graph.getExecutionOrder(); // Execute operations in parallel stages const results: BatchResult[] = []; for (const stage of executionPlan) { const stageResults = await this.executeStage(stage, operations); results.push(...stageResults); } // Update metrics const batchDuration = Date.now() - startTime; this.updateMetrics(results, batchDuration); this.logger.info(`Batch execution completed`, { batchId, duration: batchDuration, successRate: this.calculateSuccessRate(results), }); return results; } catch (error) { this.logger.error("Batch execution failed", error); throw error; } } /** * Execute a single stage of operations in parallel */ private async executeStage( operationIds: string[], operations: BatchOperation[], ): Promise<BatchResult[]> { const stageOps = operations.filter((op) => operationIds.includes(op.id)); // Special optimization for agent spawning const agentOps = stageOps.filter((op) => op.type === "agent_spawn"); if (agentOps.length > 0) { return this.executeAgentSpawnBatch(agentOps); } // Execute other operations in parallel const promises = stageOps.map((op) => this.executeOperation(op)); return Promise.all(promises); } /** * Optimized agent spawning for <100ms target */ private async executeAgentSpawnBatch( operations: BatchOperation[], ): Promise<BatchResult[]> { const startTime = Date.now(); // Pre-allocate resources const resources = await this.resourcePool.allocateBatch(operations.length); // Spawn agents in parallel using worker threads const spawnPromises = operations.map((op, index) => this.spawnAgentOptimized(op, resources[index]), ); const results = await Promise.all(spawnPromises); const spawnTime = Date.now() - startTime; this.logger.debug(`Agent spawn batch completed`, { count: operations.length, duration: spawnTime, avgPerAgent: spawnTime / operations.length, }); return results; } /** * Execute single operation with retry logic */ private async executeOperation( operation: BatchOperation, ): Promise<BatchResult> { const startTime = Date.now(); let lastError: Error | undefined; for (let attempt = 0; attempt < this.config.retryAttempts; attempt++) { try { const result = await this.performOperation(operation); return { id: operation.id, success: true, result, duration: Date.now() - startTime, }; } catch (error: any) { lastError = error; this.logger.warn(`Operation failed, attempt ${attempt + 1}`, { operationId: operation.id, error: error.message, }); if (attempt < this.config.retryAttempts - 1) { await this.delay(Math.pow(2, attempt) * 100); // Exponential backoff } } } return { id: operation.id, success: false, error: lastError, duration: Date.now() - startTime, }; } /** * Perform the actual operation based on type */ private async performOperation(operation: BatchOperation): Promise<any> { switch (operation.type) { case "agent_spawn": return this.spawnAgent(operation.operation); case "task_execute": return this.executeTask(operation.operation); case "memory_op": return this.executeMemoryOp(operation.operation); case "file_op": return this.executeFileOp(operation.operation); case "command": return this.executeCommand(operation.operation); default: throw new Error(`Unknown operation type: ${operation.type}`); } } /** * Optimized agent spawning using pre-allocated resources */ private async spawnAgentOptimized( operation: BatchOperation, resource: any, ): Promise<BatchResult> { const startTime = Date.now(); try { // Use worker thread for agent initialization const worker = this.getAvailableWorker(); const result = await new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error("Agent spawn timeout")); }, this.config.spawnTimeout); worker.postMessage({ type: "spawn_agent", data: operation.operation, resource, }); worker.once("message", (msg) => { clearTimeout(timeout); if (msg.error) { reject(new Error(msg.error)); } else { resolve(msg.result); } }); }); const duration = Date.now() - startTime; // Track spawn time for optimization this.performanceMonitor.recordMetric("agent_spawn_time", duration); return { id: operation.id, success: true, result, duration, metadata: { optimized: true }, }; } catch (error: any) { return { id: operation.id, success: false, error, duration: Date.now() - startTime, }; } } /** * Build dependency graph for execution planning */ private buildDependencyGraph(operations: BatchOperation[]): DependencyGraph { const graph = new DependencyGraph(); // Add all operations as nodes operations.forEach((op) => { graph.addNode(op.id, op); }); // Add dependencies operations.forEach((op) => { if (op.dependencies) { op.dependencies.forEach((dep) => { graph.addDependency(op.id, dep); }); } }); return graph; } /** * Initialize worker threads for parallel execution */ private initializeWorkers() { for (let i = 0; i < this.config.maxWorkers; i++) { const worker = new Worker("./worker.js"); worker.on("error", (error) => { this.logger.error("Worker error", error); }); this.workers.push(worker); } } /** * Get available worker thread */ private getAvailableWorker(): Worker { // Simple round-robin for now return this.workers[Math.floor(Math.random() * this.workers.length)]; } /** * Update metrics after batch execution */ private updateMetrics(results: BatchResult[], batchDuration: number) { const successful = results.filter((r) => r.success).length; const agentSpawns = results.filter( (r) => r.metadata?.optimized && r.success, ); this.metrics.successfulOps += successful; this.metrics.failedOps += results.length - successful; if (agentSpawns.length > 0) { const avgSpawn = agentSpawns.reduce((sum, r) => sum + r.duration, 0) / agentSpawns.length; this.metrics.avgSpawnTime = (this.metrics.avgSpawnTime * (this.metrics.totalBatches - 1) + avgSpawn) / this.metrics.totalBatches; } this.metrics.avgBatchTime = (this.metrics.avgBatchTime * (this.metrics.totalBatches - 1) + batchDuration) / this.metrics.totalBatches; } /** * Calculate success rate for batch */ private calculateSuccessRate(results: BatchResult[]): number { const successful = results.filter((r) => r.success).length; return (successful / results.length) * 100; } /** * Delay utility */ private delay(ms: number): Promise<void> { return new Promise((resolve) => setTimeout(resolve, ms)); } /** * Get batch tool metrics */ getMetrics() { return { ...this.metrics, successRate: (this.metrics.successfulOps / this.metrics.totalOperations) * 100, avgSpawnTimeMs: this.metrics.avgSpawnTime, avgBatchTimeMs: this.metrics.avgBatchTime, throughput: this.metrics.totalOperations / ((this.metrics.avgBatchTime * this.metrics.totalBatches) / 1000), }; } /** * Cleanup resources */ async cleanup() { // Terminate workers await Promise.all(this.workers.map((w) => w.terminate())); this.workers = []; // Cleanup resource pool await this.resourcePool.cleanup(); this.logger.info("BatchTool cleanup completed"); } // Placeholder methods for different operation types private async spawnAgent(_data: any): Promise<any> { // Implementation delegated to agent manager throw new Error("Not implemented - use spawnAgentOptimized"); } private async executeTask(data: any): Promise<any> { // Implementation for task execution return { taskId: data.id, status: "completed" }; } private async executeMemoryOp(data: any): Promise<any> { // Implementation for memory operations return { key: data.key, stored: true }; } private async executeFileOp(data: any): Promise<any> { // Implementation for file operations return { file: data.path, operation: data.type }; } private async executeCommand(data: any): Promise<any> { // Implementation for command execution return { command: data.cmd, exitCode: 0 }; } }