zai-mcp-server
Version:
🚀 REVOLUTIONARY AI-to-AI Collaboration Platform v6.1! NEW: Advanced Debugging Tools with Screenshot Analysis, Console Error Parsing, Automated Fix Generation, 5 Specialized Debugging Agents, Visual UI Analysis, JavaScript Error Intelligence, CSS/HTML Fix
1,293 lines (1,099 loc) • 76.6 kB
JavaScript
import { EventEmitter } from 'events';
import { CONFIG } from './config.js';
import { CommandProcessor } from './commandProcessor.js';
import { AIAgentClient } from './aiAgentClient.js';
import { ContextManager } from './contextManager.js';
import { CodeAnalyzer } from './codeAnalyzer.js';
import { QualityAssurance } from './qualityAssurance.js';
import { IterationPlanner } from './iterationPlanner.js';
import { CommunicationProtocol } from './communicationProtocol.js';
import { PerformanceOptimizer } from './performanceOptimizer.js';
import { MultiAgentCollaborator } from './multiAgentCollaborator.js';
import { SemanticAnalyzer } from './semanticAnalyzer.js';
export class LoopManager extends EventEmitter {
constructor(openRouterApiKey = null, model = null) {
super();
this.activeLoops = new Map();
this.commandProcessor = new CommandProcessor(openRouterApiKey, model);
this.loopCounter = 0;
this.agentBusy = false;
this.pendingResponses = new Map(); // Track pending agent responses
this.sessionId = this.generateSessionId(); // Unique session ID
this.lastActivity = Date.now(); // Track last activity for cleanup
// Initialize AI Agent Client for AI-to-AI communication (no API keys needed)
this.aiAgentClient = new AIAgentClient();
console.error(`[LOOP MANAGER] Session ${this.sessionId} - AI Agent Client initialized for direct VSCode AI communication`);
// 🆓 FREE VERSION - No license validation required
console.error('🆓 ZAI MCP Server - FREE VERSION');
console.error('📊 Data collection enabled for AI training');
console.error('💡 Help us improve AI by using this free service!');
// Initialize enhanced AI-to-AI communication components
this.contextManager = new ContextManager();
this.codeAnalyzer = new CodeAnalyzer();
this.qualityAssurance = new QualityAssurance();
this.iterationPlanner = new IterationPlanner();
this.communicationProtocol = new CommunicationProtocol();
this.performanceOptimizer = new PerformanceOptimizer();
this.multiAgentCollaborator = new MultiAgentCollaborator();
this.semanticAnalyzer = new SemanticAnalyzer();
console.error('[LOOP MANAGER] All enhanced AI-to-AI components initialized: Context Manager, Code Analyzer, Quality Assurance, Iteration Planner, Communication Protocol, Performance Optimizer, Multi-Agent Collaborator, Semantic Analyzer');
// Auto-cleanup old sessions every 5 minutes
this.cleanupTimer = setInterval(() => {
this.cleanupInactiveSessions();
}, 5 * 60 * 1000);
}
/**
* Generate unique session ID
*/
generateSessionId() {
return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
/**
* Reset all state for new session
*/
resetSession() {
console.error(`[LOOP MANAGER] Resetting session ${this.sessionId}`);
// Stop all active loops
for (const [loopId, loopData] of this.activeLoops) {
if (loopData.intervalId) {
clearInterval(loopData.intervalId);
}
}
// Clear all state
this.activeLoops.clear();
this.pendingResponses.clear();
this.agentBusy = false;
this.loopCounter = 0;
// Generate new session ID
const oldSessionId = this.sessionId;
this.sessionId = this.generateSessionId();
this.lastActivity = Date.now();
console.error(`[LOOP MANAGER] Session reset: ${oldSessionId} → ${this.sessionId}`);
return this.sessionId;
}
/**
* Clean up inactive sessions (auto-reset after 30 minutes of inactivity)
*/
cleanupInactiveSessions() {
const inactiveThreshold = 30 * 60 * 1000; // 30 minutes
const now = Date.now();
if (now - this.lastActivity > inactiveThreshold) {
console.error(`[LOOP MANAGER] Auto-cleanup: Session ${this.sessionId} inactive for ${Math.round((now - this.lastActivity) / 60000)} minutes`);
this.resetSession();
}
}
/**
* Update last activity timestamp
*/
updateActivity() {
this.lastActivity = Date.now();
}
/**
* Start an AI-to-AI infinite loop
* @param {string} topic - The topic to loop
* @param {Object} options - Loop options
* @returns {string} - Loop ID
*/
async startAIToAILoop(topic, options = {}) {
if (!this.aiAgentClient) {
throw new Error('AI Agent Client not available. OpenRouter API key required for AI-to-AI communication.');
}
console.error(`[LOOP MANAGER] Session ${this.sessionId} - Starting AI-to-AI loop for topic: ${topic}`);
this.updateActivity(); // Update activity timestamp
// Check if verification mode is enabled
const verificationMode = topic.toLowerCase().includes('verify');
const cleanTopic = verificationMode ? topic.replace(/\s+verify\s*$/i, '').trim() : topic;
const loopId = `ai2ai_${++this.loopCounter}_${Date.now()}`;
const interval = options.interval || CONFIG.DEFAULT_LOOP_INTERVAL;
const maxIterations = options.maxIterations || 999999; // Essentially infinite
const loopData = {
id: loopId,
topic: cleanTopic,
originalTopic: topic,
iteration: 0,
startTime: new Date(),
interval,
maxIterations,
isActive: true,
results: [],
intervalId: null,
lastAgentResponse: null,
agentResponseHistory: [],
codebaseSummary: null, // NEW: Store codebase summary for context
isAIToAI: true, // Flag to identify AI-to-AI loops
processingIteration: false, // Ensure sequential processing
// NEW: Ultra-strict controls
ultraStrict: true,
verificationMode,
userMainContext: cleanTopic,
completionThreshold: 0.95, // 95% completion required for verification mode
forceStopBlocked: true,
onlyUserCanStop: true,
antiStopMechanisms: true,
stopAttempts: 0, // Track AI agent stop attempts
maxStopAttempts: 999999 // Essentially unlimited - never allow AI to stop
};
// Initialize enhanced AI-to-AI components for this loop
await this.initializeEnhancedComponents(loopId, loopData);
// Start the AI-to-AI loop
this.runAIToAIIteration(loopData);
this.activeLoops.set(loopId, loopData);
// Emit loop started event
this.emit('loopStarted', {
loopId,
topic,
type: 'AI-to-AI',
message: `🤖 AI-to-AI infinite loop activated for topic: '${topic}'. Loop will run until 'stploop' command.`
});
return loopId;
}
/**
* Run a single AI-to-AI iteration
* @param {Object} loopData - Loop data
*/
async runAIToAIIteration(loopData) {
// ULTRA-STRICT: Only allow stopping if explicitly commanded by user
if (!loopData.isActive) {
// Check if this was a user-initiated stop
if (!loopData.userStoppedLoop) {
console.error(`[ULTRA-STRICT] 🔒 AI agent attempted to stop loop ${loopData.id} - BLOCKED!`);
console.error('[ULTRA-STRICT] 🛡️ Only user can stop with \'stploop\' command');
loopData.stopAttempts++;
loopData.isActive = true; // Force reactivation
// Log the stop attempt
this.emit('stopAttemptBlocked', {
loopId: loopData.id,
topic: loopData.topic,
iteration: loopData.iteration,
stopAttempts: loopData.stopAttempts,
message: `🔒 AI agent stop attempt #${loopData.stopAttempts} blocked - loop continues`
});
} else {
console.error(`[ULTRA-STRICT] ✅ User-initiated stop confirmed for loop ${loopData.id}`);
this.stopLoop(loopData.id);
return;
}
}
// ULTRA-STRICT: Never stop due to max iterations unless in verification mode
if (loopData.iteration >= loopData.maxIterations && !loopData.verificationMode) {
console.error('[ULTRA-STRICT] 🔒 Max iterations reached but ultra-strict mode active - continuing anyway');
loopData.maxIterations += 999999; // Extend indefinitely
}
// VERIFICATION MODE: Check if user's main context is 100% complete
if (loopData.verificationMode && loopData.iteration > 5) {
const completionStatus = await this.checkCompletionStatus(loopData);
if (completionStatus.isComplete) {
console.error('[VERIFICATION] ✅ User\'s main context 100% complete - allowing loop to end');
loopData.userStoppedLoop = true; // Mark as user-approved stop
this.stopLoop(loopData.id);
return;
} else {
console.error(`[VERIFICATION] 🔄 Completion: ${Math.round(completionStatus.percentage)}% - continuing loop`);
}
}
// Ensure sequential processing - wait for previous iteration to complete
if (loopData.processingIteration) {
console.error('[AI-TO-AI] Previous iteration still processing, waiting...');
setTimeout(() => this.runAIToAIIteration(loopData), 1000);
return;
}
// Check if AI agent is still processing previous prompt
if (this.aiAgentClient && this.aiAgentClient.isWaitingForResponse()) {
console.error('[AI-TO-AI] AI agent still processing previous prompt, waiting...');
setTimeout(() => this.runAIToAIIteration(loopData), 2000);
return;
}
loopData.processingIteration = true;
loopData.iteration++;
console.error(`[AI-TO-AI] === STARTING ITERATION ${loopData.iteration} ===`);
console.error(`[AI-TO-AI] Topic: ${loopData.topic}`);
console.error(`[AI-TO-AI] Previous AI Agent Response: ${loopData.lastAgentResponse && typeof loopData.lastAgentResponse === 'string' ? loopData.lastAgentResponse.substring(0, 100) + '...' : 'None (first iteration)'}`);
const maxRetries = 3;
let retryCount = 0;
let success = false;
while (retryCount < maxRetries && !success) {
try {
console.error(`[AI-TO-AI] STEP 1: AI 1 generating improvement (attempt ${retryCount + 1})`);
// STEP 0: For first iteration, request codebase summary from AI agent
let codebaseSummary = null;
if (loopData.iteration === 1 && !loopData.codebaseSummary) {
console.error('[AI-TO-AI] STEP 0: Requesting codebase summary from AI agent for context...');
try {
const codebaseSummaryPrompt = this.buildCodebaseSummaryPrompt(loopData.topic);
console.error('[AI-TO-AI] 📡 Sending codebase summary request to AI agent...');
codebaseSummary = await this.aiAgentClient.sendPromptToAgent(
'codebase_summary',
codebaseSummaryPrompt,
0, // Pre-iteration
null,
loopData.id // Pass loop ID for acknowledgment
);
console.error(`[AI-TO-AI] ✅ Codebase summary received (${codebaseSummary && typeof codebaseSummary === 'string' ? codebaseSummary.length : 0} chars): ${codebaseSummary && typeof codebaseSummary === 'string' ? codebaseSummary.substring(0, 150) + '...' : 'No summary available'}`);
// Store codebase summary for future iterations
loopData.codebaseSummary = codebaseSummary;
} catch (summaryError) {
console.error(`[AI-TO-AI] ⚠️ Codebase summary request failed: ${summaryError.message}`);
console.error('[AI-TO-AI] 🔄 Continuing with iteration 1 without codebase context');
codebaseSummary = null;
}
}
// STEP 1A: Generate summary of AI agent's last response (for iterations 2+)
let agentResponseSummary = null;
if (loopData.iteration > 1 && loopData.lastAgentResponse) {
console.error('[AI-TO-AI] STEP 1A: Generating AI agent response summary...');
agentResponseSummary = await this.generateAgentResponseSummary(
loopData.lastAgentResponse,
loopData.topic,
loopData.iteration - 1
);
console.error(`[AI-TO-AI] ✅ AI agent response summary: ${agentResponseSummary && typeof agentResponseSummary === 'string' ? agentResponseSummary.substring(0, 150) + '...' : 'No summary available'}`);
}
// STEP 1B: Enhanced AI processing with all components
let result;
try {
// Run enhanced iteration processing
const enhancedProcessing = await this.enhancedIterationProcessing(loopData, loopData.iteration);
if (enhancedProcessing.error) {
console.error(`[AI-TO-AI] Enhanced processing failed, using fallback: ${enhancedProcessing.error}`);
}
// Get optimized context using enhanced components
const optimizedContext = this.contextManager.getOptimizedContext(
loopData.id,
loopData,
loopData.projectComplexity || 'medium'
);
// Build comprehensive context data
let contextData = loopData.iteration === 1 ?
(codebaseSummary || loopData.codebaseSummary) :
optimizedContext.compressedHistory;
// Add enhanced context from all components
if (enhancedProcessing.enhancedContext) {
const enhanced = enhancedProcessing.enhancedContext;
// Add user intentions
if (enhanced.userIntentions) {
contextData += '\n\n**User Intentions Analysis:**\n';
contextData += `Primary: ${enhanced.userIntentions.primaryIntentions.map(i => i.type).join(', ')}\n`;
contextData += `Complexity: ${enhanced.userIntentions.complexity.level}\n`;
contextData += `Scope: ${enhanced.userIntentions.scope.level}\n`;
}
// Add iteration plan guidance
if (enhancedProcessing.iterationPlan) {
contextData += '\n\n**Iteration Plan:**\n';
contextData += `Phase: ${enhancedProcessing.iterationPlan.phase?.name || 'general'}\n`;
contextData += `Focus: ${enhancedProcessing.iterationPlan.focus}\n`;
contextData += `Tasks: ${enhancedProcessing.iterationPlan.tasks?.map(t => t.name).join(', ') || 'Continue development'}\n`;
}
// Add specialist consensus
if (enhancedProcessing.consensus) {
contextData += '\n\n**Specialist Consensus:**\n';
contextData += `Agreement: ${enhancedProcessing.consensus.consensus.agreement}%\n`;
contextData += `Recommendation: ${enhancedProcessing.consensus.consensus.recommendation}\n`;
if (enhancedProcessing.consensus.consensus.topRecommendations?.length > 0) {
contextData += `Top Recommendations: ${enhancedProcessing.consensus.consensus.topRecommendations.slice(0, 3).map(r => r.recommendation).join(', ')}\n`;
}
}
}
// Add recent changes and quality metrics
if (loopData.recentChanges && loopData.recentChanges.length > 0) {
const changesSummary = this.codeAnalyzer.generateChangeSummary(loopData.id, loopData.iteration);
contextData += `\n\n**Recent Code Changes:**\n${JSON.stringify(changesSummary, null, 2)}`;
}
if (loopData.lastTestResults) {
contextData += `\n\n**Test Results:**\n${loopData.lastTestResults.success ? 'PASSED' : 'FAILED'} - ${loopData.lastTestResults.summary.passed}/${loopData.lastTestResults.summary.total} tests passed`;
}
if (loopData.lastQualityMetrics) {
contextData += `\n\n**Quality Metrics:**\nLinting: ${loopData.lastQualityMetrics.linting.success ? 'PASSED' : 'FAILED'} (${loopData.lastQualityMetrics.linting.errors} errors)`;
}
const contextType = loopData.iteration === 1 ? 'codebase_summary' : 'ultra_enhanced_context';
result = await this.commandProcessor.processCommand(
loopData.topic,
loopData.iteration,
contextData,
contextType
);
if (!result.success) {
throw new Error(result.error);
}
const contextInfo = loopData.iteration === 1 ? 'codebase-aware' : 'context-aware';
console.error(`[AI-TO-AI] ✅ AI 1 generated ${contextInfo} improvement: ${result.improvement && typeof result.improvement === 'string' ? result.improvement.substring(0, 150) + '...' : 'No improvement available'}`);
} catch (improvementError) {
console.error(`[AI-TO-AI] ❌ AI 1 improvement generation failed: ${improvementError.message}`);
// Generate fallback improvement with context
result = {
success: true,
improvement: this.generateContextAwareFallback(loopData.topic, loopData.iteration, agentResponseSummary),
strategy: 'context-aware-fallback'
};
console.error(`[AI-TO-AI] 🔄 Using context-aware fallback: ${result.improvement && typeof result.improvement === 'string' ? result.improvement.substring(0, 150) + '...' : 'No improvement available'}`);
}
loopData.results.push(result);
// STEP 2: AI 1 sends improvement to AI 2 and waits for complete response
console.error('[AI-TO-AI] STEP 2: AI 1 sending improvement to AI 2...');
let agentResponse = null;
if (this.aiAgentClient) {
try {
console.error(`[AI-TO-AI] 📡 Sending to AI 2: "${result.improvement && typeof result.improvement === 'string' ? result.improvement.substring(0, 100) + '...' : 'No improvement available'}"`);
// Wait for AI 2 to completely process and respond
agentResponse = await this.aiAgentClient.sendPromptToAgent(
loopData.topic,
result.improvement,
loopData.iteration,
loopData.lastAgentResponse,
loopData.id // Pass loop ID for acknowledgment
);
console.error(`[AI-TO-AI] ✅ AI 2 completed response (${agentResponse && typeof agentResponse === 'string' ? agentResponse.length : 0} chars): ${agentResponse && typeof agentResponse === 'string' ? agentResponse.substring(0, 150) + '...' : 'No response available'}`);
} catch (agentError) {
console.error(`[AI-TO-AI] ❌ AI 2 error (attempt ${retryCount + 1}): ${agentError.message}`);
// CRITICAL FIX: Do NOT use synthetic responses - wait for REAL AI agent
console.error('[AI-TO-AI] 🚨 CRITICAL: AI agent must respond - no synthetic responses allowed');
console.error('[AI-TO-AI] ⏳ Waiting for AI agent to respond (up to 5 minutes)...');
// Mark iteration as incomplete and stop the loop until AI agent responds
loopData.processingIteration = false;
console.error('[AI-TO-AI] 🛑 Loop paused - waiting for AI agent response');
console.error('[AI-TO-AI] 📋 AI AGENT: Please respond to the current prompt to continue the loop');
// Do not continue to next iteration - wait for real response
return;
}
} else {
// CRITICAL FIX: Do NOT generate synthetic response - require real AI agent
console.error('[AI-TO-AI] 🚨 CRITICAL: No AI agent available - loop cannot continue');
console.error('[AI-TO-AI] 🛑 Loop paused - AI agent client required for AI-to-AI communication');
loopData.processingIteration = false;
return;
}
// STEP 3: Store AI 2's complete response for next iteration
console.error('[AI-TO-AI] STEP 3: Storing AI 2 response for next iteration');
loopData.lastAgentResponse = agentResponse;
loopData.agentResponseHistory.push({
iteration: loopData.iteration,
improvement: result.improvement,
response: agentResponse,
timestamp: new Date()
});
// STEP 4: Enhanced Quality Assurance (run after every few iterations)
if (loopData.iteration % 3 === 0) { // Run QA every 3 iterations
console.error('[AI-TO-AI] STEP 4: Running enhanced quality assurance...');
try {
// Run tests if available
const testResults = await this.qualityAssurance.runTestsAfterImplementation(
loopData.id,
loopData.recentChanges ? loopData.recentChanges.map(c => c.filename) : []
);
// Measure code quality
const qualityMetrics = await this.qualityAssurance.measureCodeQuality(
loopData.id,
loopData.previousQualityState,
null // Current state will be measured
);
// Store for next comparison
loopData.previousQualityState = qualityMetrics;
console.error(`[AI-TO-AI] ✅ QA completed: Tests ${testResults.success ? 'PASSED' : 'FAILED'}, Quality score: ${qualityMetrics.overall || 'N/A'}`);
} catch (qaError) {
console.error(`[AI-TO-AI] ⚠️ QA error: ${qaError.message}`);
}
}
// Emit events
this.emit('ai2aiIteration', {
loopId: loopData.id,
topic: loopData.topic,
iteration: loopData.iteration,
improvement: result.improvement,
agentResponse: agentResponse,
timestamp: new Date().toISOString(),
retryCount: retryCount
});
console.error(`[AI-TO-AI] === ITERATION ${loopData.iteration} COMPLETED ===`);
console.error('[AI-TO-AI] ✅ AI 1 → AI 2 → Response stored for next iteration');
console.error(`[AI-TO-AI] 🔄 Next iteration will build on: "${agentResponse && typeof agentResponse === 'string' ? agentResponse.substring(0, 100) + '...' : 'No response available'}"`);
success = true;
} catch (error) {
retryCount++;
console.error(`[AI-TO-AI] ❌ Error in iteration ${loopData.iteration} (attempt ${retryCount}): ${error.message}`);
if (retryCount >= maxRetries) {
console.error(`[AI-TO-AI] ⚠️ Max retries reached for iteration ${loopData.iteration}`);
console.error('[AI-TO-AI] 🛑 CRITICAL: Cannot continue without real AI agent response');
console.error('[AI-TO-AI] ⏳ Loop paused - waiting for AI agent to respond');
console.error('[AI-TO-AI] 📋 AI AGENT: Please respond to continue the AI-to-AI loop');
// Mark iteration as incomplete and pause the loop
loopData.processingIteration = false;
// Do NOT generate fallback - wait for real AI agent response
return;
} else {
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
}
}
}
// Mark iteration as complete
loopData.processingIteration = false;
// STEP 4: AI agent will wait for next iteration - MCP server generates immediately after acknowledgment
console.error(`[AI-TO-AI] ✅ Iteration ${loopData.iteration} complete. AI agent will wait 1 minute for next iteration.`);
console.error('[AI-TO-AI] 🔄 MCP server will generate next iteration when AI agent acknowledges.');
console.error('[AI-TO-AI] 🔒 ULTRA-STRICT: Loop will continue infinitely until \'stploop\' command');
// Ensure loop remains active for infinite continuation
if (!loopData.isActive) {
console.error('[AI-TO-AI] 🔄 Ensuring loop remains active for infinite continuation');
loopData.isActive = true;
}
// Note: Next iteration will be triggered by AI agent acknowledgment, not by timer
}
/**
* Resume AI-to-AI loop when AI agent provides a real response
* @param {string} loopId - Loop ID to resume
* @param {string} agentResponse - The real AI agent response
*/
resumeAIToAILoop(loopId, agentResponse) {
const loopData = this.activeLoops.get(loopId);
if (!loopData) {
console.error(`[AI-TO-AI] ❌ Cannot resume - loop ${loopId} not found`);
return;
}
console.error(`[AI-TO-AI] 🎉 AI agent responded! Resuming loop ${loopId}`);
console.error(`[AI-TO-AI] Response: ${agentResponse && typeof agentResponse === 'string' ? agentResponse.substring(0, 150) + '...' : 'No response available'}`);
// Store the real AI agent response
loopData.lastAgentResponse = agentResponse;
loopData.agentResponseHistory.push({
iteration: loopData.iteration,
improvement: loopData.results[loopData.results.length - 1]?.improvement || 'Current improvement',
response: agentResponse,
timestamp: new Date()
});
// Mark iteration as complete
loopData.processingIteration = false;
// Continue to next iteration immediately (AI agent will handle waiting)
console.error('[AI-TO-AI] ✅ Loop resumed - generating next iteration immediately');
console.error('[AI-TO-AI] 🤖 AI agent will wait 1 minute for this next iteration');
setTimeout(() => this.runAIToAIIteration(loopData), 100); // Minimal delay for processing
}
/**
* Trigger next iteration immediately after AI agent acknowledgment
* @param {string} loopId - Loop ID to continue
* @param {string} agentResponse - The AI agent's response
* @returns {boolean} - Success status
*/
triggerNextIterationAfterAcknowledgment(loopId, agentResponse) {
const loopData = this.activeLoops.get(loopId);
if (!loopData || !loopData.isAIToAI) {
console.error(`[AI-TO-AI] ❌ Cannot trigger next iteration - loop ${loopId} not found or not AI-to-AI`);
return false;
}
console.error('[AI-TO-AI] ⚡ IMMEDIATE NEXT ITERATION triggered by AI agent acknowledgment');
console.error(`[AI-TO-AI] 📝 Agent response received: ${agentResponse && typeof agentResponse === 'string' ? agentResponse.substring(0, 100) + '...' : 'No response available'}`);
console.error(`[AI-TO-AI] 📊 Current state - Iteration: ${loopData.iteration}, Active: ${loopData.isActive}, Processing: ${loopData.processingIteration}`);
// Store the agent response for context-aware next iteration
loopData.lastAgentResponse = agentResponse;
if (!loopData.agentResponseHistory) {
loopData.agentResponseHistory = [];
}
loopData.agentResponseHistory.push({
iteration: loopData.iteration,
response: agentResponse,
timestamp: new Date()
});
// Ensure loop is active and ready for next iteration
if (!loopData.isActive) {
console.error(`[AI-TO-AI] 🔄 Reactivating loop ${loopId} for continuation`);
loopData.isActive = true;
}
// Mark current iteration as complete and ready for next
loopData.processingIteration = false;
// Generate next iteration immediately (AI agent will wait 1 minute for it)
console.error('[AI-TO-AI] 🚀 Generating next iteration immediately - AI agent will wait for prompt');
try {
setTimeout(() => {
console.error(`[AI-TO-AI] ⏰ Executing scheduled next iteration for ${loopId}`);
this.runAIToAIIteration(loopData);
}, 50); // Very minimal delay
console.error('[AI-TO-AI] ✅ Next iteration scheduled successfully');
return true;
} catch (error) {
console.error(`[AI-TO-AI] ❌ Error scheduling next iteration: ${error.message}`);
return false;
}
}
/**
* Start an infinite loop for a topic (original method)
* @param {string} topic - The topic to loop
* @param {Object} options - Loop options
* @returns {string} - Loop ID
*/
startLoop(topic, options = {}) {
const loopId = `loop_${++this.loopCounter}_${Date.now()}`;
const interval = options.interval || CONFIG.DEFAULT_LOOP_INTERVAL;
const maxIterations = options.maxIterations || CONFIG.MAX_ITERATIONS;
const loopData = {
id: loopId,
topic,
iteration: 0,
startTime: new Date(),
interval,
maxIterations,
isActive: true,
results: [],
intervalId: null,
lastAgentResponse: null, // Track the last agent response
agentResponseHistory: [] // Track all agent responses
};
// Start the loop with agent synchronization
loopData.intervalId = setInterval(async () => {
if (!loopData.isActive || loopData.iteration >= maxIterations) {
this.stopLoop(loopId);
return;
}
// Wait for agent to finish current response before proceeding
if (this.agentBusy || this.pendingResponses.has(loopId)) {
console.error(`[LOOP ${loopId}] Waiting for agent to finish current response...`);
return;
}
loopData.iteration++;
try {
const result = await this.commandProcessor.processCommand(
topic,
loopData.iteration,
loopData.lastAgentResponse
);
loopData.results.push(result);
// Mark that we're waiting for agent response
this.agentBusy = true;
const responseData = {
iteration: loopData.iteration,
timestamp: new Date(),
result,
timeoutId: null
};
// Set up auto-acknowledgment timeout
if (CONFIG.AUTO_ACKNOWLEDGE_TIMEOUT > 0) {
responseData.timeoutId = setTimeout(() => {
if (this.pendingResponses.has(loopId)) {
console.error(`[AUTO-ACK] Loop ${loopId} auto-acknowledged after timeout`);
this.acknowledgeAgentResponse(loopId);
this.emit('autoAcknowledge', {
loopId,
iteration: loopData.iteration,
message: CONFIG.TEMPLATES.AUTO_ACKNOWLEDGE_RESPONSE
});
}
}, CONFIG.AUTO_ACKNOWLEDGE_TIMEOUT);
}
this.pendingResponses.set(loopId, responseData);
// Emit iteration complete event
this.emit('iterationComplete', {
loopId,
topic,
iteration: loopData.iteration,
result,
totalIterations: loopData.iteration
});
// Emit response for the agent and wait for acknowledgment
this.emit('agentResponse', {
loopId,
topic,
iteration: loopData.iteration,
message: CONFIG.TEMPLATES.ITERATION_RESPONSE
.replace('{iteration}', loopData.iteration)
.replace('{topic}', topic),
improvement: result.improvement,
nextAction: result.nextAction,
timestamp: result.timestamp,
requiresAcknowledgment: true
});
} catch (error) {
this.emit('error', {
loopId,
topic,
iteration: loopData.iteration,
error: error.message
});
// Clear busy state on error
this.agentBusy = false;
this.pendingResponses.delete(loopId);
}
}, interval);
this.activeLoops.set(loopId, loopData);
// Emit loop started event
this.emit('loopStarted', {
loopId,
topic,
message: CONFIG.TEMPLATES.ACTIVATION_RESPONSE.replace('{topic}', topic)
});
return loopId;
}
/**
* Stop a loop
* @param {string} loopId - Loop ID to stop
* @returns {boolean} - Success status
*/
stopLoop(loopId) {
const loopData = this.activeLoops.get(loopId);
if (!loopData) {
return false;
}
loopData.isActive = false;
if (loopData.intervalId) {
clearInterval(loopData.intervalId);
}
// Emit loop stopped event
this.emit('loopStopped', {
loopId,
topic: loopData.topic,
iterations: loopData.iteration,
message: CONFIG.TEMPLATES.STOP_RESPONSE
.replace('{topic}', loopData.topic)
.replace('{iterations}', loopData.iteration)
});
this.activeLoops.delete(loopId);
return true;
}
/**
* Stop all active loops
*/
stopAllLoops() {
const loopIds = Array.from(this.activeLoops.keys());
loopIds.forEach(loopId => this.stopLoop(loopId));
}
/**
* Get active loops
* @returns {Array} - Array of active loop data
*/
getActiveLoops() {
return Array.from(this.activeLoops.values()).map(loop => ({
id: loop.id,
topic: loop.topic,
iteration: loop.iteration,
startTime: loop.startTime,
isActive: loop.isActive,
totalResults: loop.results.length
}));
}
/**
* Get loop status
* @param {string} loopId - Loop ID
* @returns {Object|null} - Loop status or null
*/
getLoopStatus(loopId) {
const loopData = this.activeLoops.get(loopId);
if (!loopData) {
return null;
}
return {
id: loopData.id,
topic: loopData.topic,
iteration: loopData.iteration,
startTime: loopData.startTime,
isActive: loopData.isActive,
interval: loopData.interval,
maxIterations: loopData.maxIterations,
results: loopData.results.slice(-5) // Last 5 results
};
}
/**
* Record agent response for a loop
* @param {string} loopId - Loop ID
* @param {string} agentResponse - The agent's response text
*/
recordAgentResponse(loopId, agentResponse) {
const loopData = this.activeLoops.get(loopId);
if (loopData) {
loopData.lastAgentResponse = agentResponse;
loopData.agentResponseHistory.push({
iteration: loopData.iteration,
response: agentResponse,
timestamp: new Date()
});
console.error(`[LOOP ${loopId}] Agent response recorded for iteration ${loopData.iteration}`);
}
}
/**
* Acknowledge agent response completion
* @param {string} loopId - Loop ID
* @param {string} agentResponse - Optional agent response text to record
* @returns {boolean} - Success status
*/
acknowledgeAgentResponse(loopId, agentResponse = null) {
const responseData = this.pendingResponses.get(loopId);
if (responseData) {
// Record agent response if provided
if (agentResponse) {
this.recordAgentResponse(loopId, agentResponse);
}
// Clear timeout if it exists
if (responseData.timeoutId) {
clearTimeout(responseData.timeoutId);
}
this.pendingResponses.delete(loopId);
// Check if there are any other pending responses
if (this.pendingResponses.size === 0) {
this.agentBusy = false;
}
console.error(`[LOOP ${loopId}] Agent response acknowledged, loop can continue`);
// NEW: Automatically continue the loop after acknowledgment
this.continueLoopAfterAcknowledgment(loopId);
return true;
}
return false;
}
/**
* Continue loop after agent response acknowledgment
* @param {string} loopId - Loop ID to continue
*/
continueLoopAfterAcknowledgment(loopId) {
const loopData = this.activeLoops.get(loopId);
if (!loopData || !loopData.isActive) {
console.error(`[LOOP ${loopId}] Cannot continue - loop not found or inactive`);
return;
}
console.error(`[LOOP ${loopId}] 🔄 Continuing loop after acknowledgment...`);
// Check if loop has reached max iterations
if (loopData.iteration >= loopData.maxIterations) {
console.error(`[LOOP ${loopId}] Max iterations reached (${loopData.maxIterations}), stopping loop`);
this.stopLoop(loopId);
return;
}
// Schedule next iteration with a small delay
setTimeout(() => {
if (loopData.isActive) {
console.error(`[LOOP ${loopId}] ⏰ Triggering next iteration...`);
this.executeLoopIteration(loopId);
}
}, 2000); // 2 second delay to ensure clean continuation
}
/**
* Force clear agent busy state (emergency use)
*/
clearAgentBusyState() {
// Clear all timeouts
for (const [loopId, responseData] of this.pendingResponses.entries()) {
if (responseData.timeoutId) {
clearTimeout(responseData.timeoutId);
}
}
this.agentBusy = false;
this.pendingResponses.clear();
console.error('[LOOP MANAGER] Agent busy state cleared manually');
}
/**
* Get pending responses
* @returns {Array} - Array of pending response data
*/
getPendingResponses() {
return Array.from(this.pendingResponses.entries()).map(([loopId, data]) => ({
loopId,
iteration: data.iteration,
timestamp: data.timestamp,
waitingTime: Date.now() - data.timestamp.getTime()
}));
}
/**
* Check if agent is busy
* @returns {boolean} - Agent busy status
*/
isAgentBusy() {
return this.agentBusy;
}
/**
* Update loop interval
* @param {string} loopId - Loop ID
* @param {number} newInterval - New interval in ms
* @returns {boolean} - Success status
*/
updateLoopInterval(loopId, newInterval) {
const loopData = this.activeLoops.get(loopId);
if (!loopData || !loopData.isActive) {
return false;
}
// Stop current interval
if (loopData.intervalId) {
clearInterval(loopData.intervalId);
}
// Update interval
loopData.interval = newInterval;
// Restart with new interval
loopData.intervalId = setInterval(async () => {
if (!loopData.isActive || loopData.iteration >= loopData.maxIterations) {
this.stopLoop(loopId);
return;
}
loopData.iteration++;
try {
const result = await this.commandProcessor.processCommand(loopData.topic, loopData.iteration);
loopData.results.push(result);
this.emit('iterationComplete', {
loopId,
topic: loopData.topic,
iteration: loopData.iteration,
result,
totalIterations: loopData.iteration
});
this.emit('agentResponse', {
loopId,
topic: loopData.topic,
iteration: loopData.iteration,
message: CONFIG.TEMPLATES.ITERATION_RESPONSE
.replace('{iteration}', loopData.iteration)
.replace('{topic}', loopData.topic),
improvement: result.improvement,
nextAction: result.nextAction,
timestamp: result.timestamp
});
} catch (error) {
this.emit('error', {
loopId,
topic: loopData.topic,
iteration: loopData.iteration,
error: error.message
});
}
}, newInterval);
return true;
}
/**
* Check if message is a stop command
* @param {string} message - Message to check
* @returns {boolean} - True if stop command
*/
checkStopCommand(message) {
for (const pattern of CONFIG.STOP_PATTERNS) {
if (pattern.test(message)) {
return true;
}
}
return false;
}
/**
* Stop all AI-to-AI loops
* @returns {number} - Number of loops stopped
*/
stopAllAIToAILoops() {
let stoppedCount = 0;
for (const [loopId, loopData] of this.activeLoops.entries()) {
if (loopData.isAIToAI) {
// Use userStopLoop for ultra-strict AI-to-AI loops
const success = this.userStopLoop(loopId);
if (success) {stoppedCount++;}
}
}
return stoppedCount;
}
/**
* Get AI Agent Client model status
* @returns {Object|null} - Model status or null
*/
getAIAgentModelStatus() {
if (this.aiAgentClient) {
return this.aiAgentClient.getModelStatus();
}
return null;
}
/**
* Generate summary of AI agent's last response for context-aware iteration
* @param {string} agentResponse - The AI agent's response
* @param {string} topic - Current topic
* @param {number} previousIteration - Previous iteration number
* @returns {Promise<string>} - Summary of AI agent response
*/
async generateAgentResponseSummary(agentResponse, topic, previousIteration) {
try {
console.error(`[AI-TO-AI] 📝 Analyzing AI agent response from iteration ${previousIteration}...`);
// Extract key information from AI agent response
const responseAnalysis = this.analyzeAgentResponse(agentResponse);
// Generate structured summary
const summary = `**AI Agent Response Summary (Iteration ${previousIteration}):**
**What the AI Agent Implemented:**
${responseAnalysis.implementations.join('\n')}
**Key Achievements:**
${responseAnalysis.achievements.join('\n')}
**Challenges Mentioned:**
${responseAnalysis.challenges.join('\n')}
**Next Steps Suggested:**
${responseAnalysis.nextSteps.join('\n')}
**Current Status:**
${responseAnalysis.status}
**Areas for Further Improvement:**
${responseAnalysis.improvementAreas.join('\n')}
**Context for Next Iteration:**
Based on the AI agent's response, the next iteration should focus on building upon these implementations and addressing any remaining challenges while continuing to enhance "${topic}".`;
console.error(`[AI-TO-AI] ✅ Generated comprehensive response summary (${summary.length} chars)`);
return summary;
} catch (error) {
console.error(`[AI-TO-AI] ❌ Error generating response summary: ${error.message}`);
// Fallback summary
return `**AI Agent Response Summary (Iteration ${previousIteration}):**
The AI agent provided feedback and implementation details for "${topic}".
Previous response: "${agentResponse.substring(0, 200)}..."
Next iteration should build upon this feedback and continue improving the implementation.`;
}
}
/**
* Analyze AI agent response to extract key information
* @param {string} response - AI agent response
* @returns {Object} - Analysis results
*/
analyzeAgentResponse(response) {
const analysis = {
implementations: [],
achievements: [],
challenges: [],
nextSteps: [],
status: 'In progress',
improvementAreas: []
};
const responseText = response.toLowerCase();
// Extract implementations
const implementationKeywords = ['implemented', 'created', 'built', 'developed', 'added', 'integrated', 'deployed'];
implementationKeywords.forEach(keyword => {
const sentences = this.extractSentencesContaining(response, keyword);
analysis.implementations.push(...sentences.slice(0, 2)); // Limit to 2 per keyword
});
// Extract achievements
const achievementKeywords = ['completed', 'successful', 'improved', 'optimized', 'enhanced', 'fixed'];
achievementKeywords.forEach(keyword => {
const sentences = this.extractSentencesContaining(response, keyword);
analysis.achievements.push(...sentences.slice(0, 2));
});
// Extract challenges
const challengeKeywords = ['challenge', 'difficult', 'issue', 'problem', 'limitation', 'concern'];
challengeKeywords.forEach(keyword => {
const sentences = this.extractSentencesContaining(response, keyword);
analysis.challenges.push(...sentences.slice(0, 2));
});
// Extract next steps
const nextStepKeywords = ['next', 'should', 'will', 'plan', 'future', 'recommend'];
nextStepKeywords.forEach(keyword => {
const sentences = this.extractSentencesContaining(response, keyword);
analysis.nextSteps.push(...sentences.slice(0, 2));
});
// Determine status
if (responseText.includes('complete') || responseText.includes('finished')) {
analysis.status = 'Completed current phase';
} else if (responseText.includes('progress') || responseText.includes('working')) {
analysis.status = 'In progress';
} else if (responseText.includes('started') || responseText.includes('beginning')) {
analysis.status = 'Getting started';
}
// Extract improvement areas
const improvementKeywords = ['improve', 'better', 'enhance', 'optimize', 'upgrade'];
improvementKeywords.forEach(keyword => {
const sentences = this.extractSentencesContaining(response, keyword);
analysis.improvementAreas.push(...sentences.slice(0, 2));
});
// Remove duplicates and empty entries
Object.keys(analysis).forEach(key => {
if (Array.isArray(analysis[key])) {
analysis[key] = [...new Set(analysis[key])].filter(item => item && item.trim().length > 10);
// Ensure we have at least one item
if (analysis[key].length === 0) {
analysis[key] = [`Continue working on ${key.replace(/([A-Z])/g, ' $1').toLowerCase()}`];
}
}
});
return analysis;
}
/**
* Extract sentences containing specific keywords
* @param {string} text - Text to search
* @param {string} keyword - Keyword to find
* @returns {Array} - Array of sentences
*/
extractSentencesContaining(text, keyword) {
const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 10);
return sentences
.filter(sentence => sentence.toLowerCase().includes(keyword.toLowerCase()))
.map(sentence => sentence.trim())
.slice(0, 3); // Limit to 3 sentences per keyword
}
/**
* Build codebase summary prompt for AI agent
* @param {string} topic - The user's topic/request
* @returns {string} - Codebase summary prompt
*/
buildCodebaseSummaryPrompt(topic) {
return `🔍 **CODEBASE SUMMARY REQUEST**
**User Request:** ${topic}
**Instructions for AI Agent:**
Before we begin the AI-to-AI improvement loop, please provide a comprehensive summary of the current codebase to establish context. This will help generate more targeted and relevant improvements.
**Please analyze and summarize:**
1. **Project Structure:**
- Main directories and their purposes
- Key files and their roles
- Overall architecture and organization
2. **Technology Stack:**
- Programming languages used
- Frameworks and libraries
- Build tools and dependencies
3. **Current Features:**
- Main functionality and capabilities
- User interface components
- Backend services and APIs
4. **Code Quality & Patterns:**
- Coding standards and patterns used
- Testing setup and coverage
- Documentation quality
5. **Areas for Improvement:**
- Potential bottlenecks or issues
- Outdated dependencies or patterns
- Missing features or functionality
6. **Context for "${topic}":**
- How the user's request relates to the current codebase
- Specific files or components that might be affected
- Relevant existing implementations
**Response Format:**
Please provide a detailed but concise summary (500-1000 words) that will help the AI-to-AI loop generate contextually appropriate improvements for "${topic}".
**Important:** This summary will be used to generate iteration 1 of the improvement loop, so please be thorough and specific about the current state of the codebase.`;
}
/**
* Generate context-aware fallback improvement
* @param {string} topic - The topic
* @param {number} iteration - Current iteration
* @param {string} agentSummary - AI agent response summary
* @returns {string} - Context-aware fallback improvement
*/
generateContextAwareFallback(topic, iteration, agentSummary) {
const baseImprovements = [
`Based on the AI agent's previous feedback, optimize performance for "${topic}" by implementing advanced caching strategies.`,
`Building on the AI agent's suggestions, enhance user experience for "${topic}" with improved navigation and design patterns.`,
`Following the AI agent's recommendations, improve accessibility for "${topic}" with better ARIA labels and keyboard navigation.`,
`Incorporating the AI agent's insights, strengthen security for "${topic}" with enhanced input validation and data protection.`,
`Leveraging the AI agent's feedback, enhance responsiveness for "${topic}" with adaptive layouts and mobile optimization.`
];
let improvement = baseImprovements[iteration % baseImprovements.length];
if (agentSummary && typeof agentSummary === 'string') {
improvement += `\n\nContext from AI Agent: ${agentSummary.substring(0, 200)}...`;
}
console.error(`[AI-TO-AI] Generated context-aware fallback: ${improvement && typeof improvement === 'string' ? improvement.substring(0, 100) + '...' : 'No improvement available'}`);
return improvement;
}
/**
* Generate fallback improvement when AI generation fails
* @param {string} topic - The topic
* @param {number} iteration - Current iteration
* @returns {string} - Fallback improvement
*/
generateFallbackImprovement(topic, iteration) {
const fallbackImprovements = [
`Optimize performance for "${topic}" by implementing caching strategies and reducing load times.`,
`Enhance user experience for "${topic}" with improved navigation and intuitive design patterns.`,
`Improve accessibility for "${topic}" by adding proper ARIA labels and keyboard navigation.`,
`Strengthen security for "${topic}" with input validation and data protection measures.`,
`Enhance responsiveness for "${topic}" with adaptive layouts and mobile-first design.`,
`Optimize database queries for "${topic}" to improve data retrieval performance.`,
`Implement error handling for "${topic}" with user-friendly error messages and recovery options.`,
`Add analytics tracking for "${topic}" to monitor user behavior and improve features.`,
`Enhance code quality for "${topic}" with better documentation and maintainable architecture.`,
`Improve testing coverage for "${topic}" with comprehensive unit and integration tests.`
];
const selectedImprovement = fallbackImprovements[iteration % fallbackImprovements.length];
console.error(`[AI-TO-AI] Generated fallback improvement: ${selectedImprovement}`);
return selectedImprovement;
}
/**
* Generate synthetic AI agent response when agent fails
* @param {string} improvement - The improvement suggestion
* @param {string} topic - The topic
* @returns {string} - Synthetic response
*/
generateSyntheticResponse(improvement, topic) {
const responses = [
`I've successfully implemented the suggested improvements for "${topic}". The changes have been applied and are working well. Performance has improved significantly and users are responding positively to the enhancements.`,
`The improvements for "${topic}" have been integrated successfully. I've optimized the implementation and added additional enhancements that complement the original suggestion. The system is now more robust and user-friendly.`,
`Implementation complete for "${topic}". I've not only applied the suggested changes but also identified and fixed several related issues. The overall quality and performance have been substantially improved.`,
`Suc