cortexweaver
Version:
CortexWeaver is a command-line interface (CLI) tool that orchestrates a swarm of specialized AI agents, powered by Claude Code and Gemini CLI, to assist in software development. It transforms a high-level project plan (plan.md) into a series of coordinate
251 lines • 10.1 kB
JavaScript
;
/**
* Error Recovery Core Module
*
* Contains the main error recovery orchestration logic, circuit breakers, and learning mechanisms
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorRecoveryCore = void 0;
const error_types_1 = require("../types/error-types");
const strategies_1 = require("./strategies");
class ErrorRecoveryCore {
constructor(cognitiveCanvas, codeSavant) {
this.circuitBreakers = new Map();
this.learningDatabase = new Map();
this.activeRecoveries = new Map();
this.defaultRetryConfig = {
maxAttempts: 3,
baseDelayMs: 1000,
maxDelayMs: 30000,
backoffMultiplier: 2,
jitterMs: 500,
shouldRetry: (error, attemptNumber) => {
return error.retryable && attemptNumber <= error.maxRetries;
}
};
this.cognitiveCanvas = cognitiveCanvas;
this.strategies = new strategies_1.ErrorRecoveryStrategies(cognitiveCanvas, codeSavant);
}
/**
* Main error recovery orchestration method
*/
async recoverFromError(error, operation, config) {
const recoveryId = `recovery-${error.id}`;
console.log(`Starting error recovery for ${error.id}: ${error.message}`);
const result = {
success: false,
recoveryStrategy: error.getRecoveryStrategy(),
attempts: [],
escalationRequired: false,
learningData: {}
};
this.activeRecoveries.set(recoveryId, result);
try {
// Check circuit breaker
if (this.isCircuitBreakerOpen(error)) {
console.log(`Circuit breaker open for ${error.category}, skipping recovery`);
result.escalationRequired = true;
return result;
}
// Apply learning from previous similar errors
const learningData = this.findSimilarErrorLearning(error);
if (learningData) {
result.recoveryStrategy = learningData.successfulRecoveryStrategy;
console.log(`Applying learned recovery strategy: ${result.recoveryStrategy}`);
}
// Execute recovery strategy
switch (result.recoveryStrategy) {
case error_types_1.RecoveryStrategy.RETRY:
result.success = await this.strategies.executeRetryStrategy(error, operation, result, { ...this.defaultRetryConfig, ...config });
break;
case error_types_1.RecoveryStrategy.CODESAVANT:
result.success = await this.strategies.executeCodeSavantStrategy(error, operation, result);
break;
case error_types_1.RecoveryStrategy.FALLBACK:
result.success = await this.strategies.executeFallbackStrategy(error, operation, result);
break;
case error_types_1.RecoveryStrategy.ESCALATE:
result.escalationRequired = true;
await this.strategies.escalateToHuman(error, result);
break;
case error_types_1.RecoveryStrategy.ABORT:
console.log(`Aborting operation due to non-recoverable error: ${error.message}`);
result.finalError = error;
break;
default:
result.success = await this.strategies.executeRetryStrategy(error, operation, result, { ...this.defaultRetryConfig, ...config });
}
// Update learning database
if (result.success) {
this.updateLearningDatabase(error, result.recoveryStrategy);
this.updateCircuitBreaker(error, true);
}
else {
this.updateCircuitBreaker(error, false);
// Check if circuit breaker should trigger escalation
if (this.shouldEscalateAfterFailure(error)) {
result.escalationRequired = true;
}
}
// Store recovery pheromone
await this.storeRecoveryPheromone(error, result);
}
catch (recoveryError) {
console.error(`Error during recovery process: ${recoveryError}`);
result.finalError = new error_types_1.CortexError(`Recovery process failed: ${recoveryError.message}`, {
severity: error_types_1.ErrorSeverity.HIGH,
category: error_types_1.ErrorCategory.INFRASTRUCTURE,
context: error.context,
cause: recoveryError
});
}
finally {
this.activeRecoveries.delete(recoveryId);
}
return result;
}
/**
* Check if circuit breaker is open for error category
*/
isCircuitBreakerOpen(error) {
const key = `${error.category}-${error.context.agentType || 'unknown'}`;
const breaker = this.circuitBreakers.get(key);
if (!breaker)
return false;
if (breaker.isOpen) {
const now = Date.now();
if (now >= breaker.nextAttemptTime) {
// Try to close circuit breaker
breaker.isOpen = false;
breaker.failureCount = 0;
return false;
}
return true;
}
return false;
}
/**
* Update circuit breaker state
*/
updateCircuitBreaker(error, success) {
const key = `${error.category}-${error.context.agentType || 'unknown'}`;
let breaker = this.circuitBreakers.get(key);
if (!breaker) {
breaker = {
isOpen: false,
failureCount: 0,
lastFailureTime: 0,
nextAttemptTime: 0,
threshold: 5,
timeout: 60000 // 1 minute
};
this.circuitBreakers.set(key, breaker);
}
if (success) {
breaker.failureCount = 0;
breaker.isOpen = false;
}
else {
breaker.failureCount++;
breaker.lastFailureTime = Date.now();
if (breaker.failureCount >= breaker.threshold) {
breaker.isOpen = true;
breaker.nextAttemptTime = Date.now() + breaker.timeout;
console.log(`Circuit breaker opened for ${key}`);
}
}
}
/**
* Find similar error learning data
*/
findSimilarErrorLearning(error) {
const pattern = this.generateErrorPattern(error);
return this.learningDatabase.get(pattern) || null;
}
/**
* Update learning database with successful recovery
*/
updateLearningDatabase(error, strategy) {
const pattern = this.generateErrorPattern(error);
const existing = this.learningDatabase.get(pattern);
if (existing) {
existing.usage_count++;
existing.success_rate = (existing.success_rate * (existing.usage_count - 1) + 1) / existing.usage_count;
existing.lastUsed = new Date().toISOString();
}
else {
this.learningDatabase.set(pattern, {
errorPattern: pattern,
successfulRecoveryStrategy: strategy,
contextSimilarity: 1.0,
applicabilityScore: 1.0,
usage_count: 1,
success_rate: 1.0,
lastUsed: new Date().toISOString()
});
}
}
/**
* Generate error pattern for learning
*/
generateErrorPattern(error) {
return `${error.category}-${error.severity}-${error.context.phase}`;
}
/**
* Store recovery pheromone for learning
*/
async storeRecoveryPheromone(error, result) {
try {
const pheromone = {
id: `recovery-${error.id}`,
type: 'error_recovery',
strength: result.success ? 0.7 : 0.3,
context: 'error_recovery',
metadata: {
errorId: error.id,
errorCategory: error.category,
errorSeverity: error.severity,
recoveryStrategy: result.recoveryStrategy,
success: result.success,
attemptCount: result.attempts.length,
escalationRequired: result.escalationRequired,
taskId: error.context.taskId,
agentType: error.context.agentId
},
createdAt: new Date().toISOString(),
expiresAt: new Date(Date.now() + 7200000).toISOString() // 2 hours
};
await this.cognitiveCanvas.createPheromone(pheromone);
}
catch (pheromoneError) {
console.warn('Failed to store recovery pheromone:', pheromoneError);
}
}
/**
* Check if failure should trigger escalation
*/
shouldEscalateAfterFailure(error) {
const key = `${error.category}-${error.context.agentType || 'unknown'}`;
const breaker = this.circuitBreakers.get(key);
return breaker ? breaker.isOpen : false;
}
/**
* Get recovery statistics for monitoring
*/
getRecoveryStatistics() {
const totalRecoveries = this.learningDatabase.size;
const successfulRecoveries = Array.from(this.learningDatabase.values())
.filter(data => data.success_rate > 0).length;
const averageAttempts = Array.from(this.learningDatabase.values())
.reduce((sum, data) => sum + data.usage_count, 0) / (totalRecoveries || 1);
return {
totalRecoveries,
successRate: totalRecoveries > 0 ? successfulRecoveries / totalRecoveries : 0,
averageAttempts,
circuitBreakerStates: new Map(this.circuitBreakers),
learningDatabase: new Map(this.learningDatabase)
};
}
}
exports.ErrorRecoveryCore = ErrorRecoveryCore;
//# sourceMappingURL=core.js.map