UNPKG

@cyqlelabs/mcp-dual-cycle-reasoner

Version:

MCP server implementing dual-cycle metacognitive reasoning framework for autonomous agents

202 lines (201 loc) • 8.79 kB
import { Sentinel } from './sentinel.js'; import { Adjudicator } from './adjudicator.js'; import { v4 as uuidv4 } from 'uuid'; import chalk from 'chalk'; /** * The Dual-Cycle Engine implements the metacognitive framework described in the DUAL-CYCLE document. * It consists of two interconnected cycles: * - Cognitive Cycle (The "Doer"): Direct interaction with the environment * - Metacognitive Cycle (The "Thinker"): Monitors and controls the cognitive cycle */ export class DualCycleEngine { sentinel; adjudicator; currentTrace; isMonitoring = false; interventionCount = 0; constructor(config) { this.sentinel = new Sentinel(config); this.adjudicator = new Adjudicator(); this.currentTrace = this.initializeTrace(); } /** * Initialize a new cognitive trace for monitoring */ initializeTrace() { return { recent_actions: [], current_context: undefined, goal: '', step_count: 0 }; } /** * Start metacognitive monitoring of an agent's cognitive trace */ startMonitoring(initialGoal, initialBeliefs = []) { this.isMonitoring = true; this.currentTrace = this.initializeTrace(); this.currentTrace.goal = initialGoal; this.interventionCount = 0; console.log(chalk.blue('🧠 Dual-Cycle Engine: Metacognitive monitoring started')); console.log(chalk.gray(`Goal: ${initialGoal}`)); console.log(chalk.gray(`Initial beliefs: ${initialBeliefs.length}`)); } /** * Stop metacognitive monitoring */ stopMonitoring() { this.isMonitoring = false; console.log(chalk.blue('🧠 Dual-Cycle Engine: Monitoring stopped')); console.log(chalk.gray(`Total interventions: ${this.interventionCount}`)); } /** * Process a new cognitive trace update (called by the cognitive cycle) */ async processTraceUpdate(trace) { if (!this.isMonitoring) { return { intervention_required: false }; } // Update current trace this.currentTrace = { ...this.currentTrace, ...trace }; console.log(chalk.gray(`\nšŸ“Š Processing trace update: ${trace.recent_actions.length} actions, step ${trace.step_count}`)); // METACOGNITIVE CYCLE - Phase 1: MONITOR const loopDetection = this.monitorForLoops(trace); if (!loopDetection.detected) { console.log(chalk.green('āœ… No loops detected - cognitive cycle proceeding normally')); return { intervention_required: false, loop_detected: loopDetection }; } console.log(chalk.yellow(`āš ļø Loop detected: ${loopDetection.type} (confidence: ${(loopDetection.confidence * 100).toFixed(1)}%)`)); console.log(chalk.yellow(` Details: ${loopDetection.details}`)); // METACOGNITIVE CYCLE - Phase 2: INTERPRET/DETECT const diagnosis = await this.interpretFailure(loopDetection, trace); console.log(chalk.red(`šŸ” Diagnosis: ${diagnosis.primary_hypothesis} (confidence: ${(diagnosis.confidence * 100).toFixed(1)}%)`)); console.log(chalk.red(` Evidence: ${diagnosis.evidence.join('; ')}`)); // METACOGNITIVE CYCLE - Phase 3: PLAN (Meta-Level) const recoveryPlan = this.planRecovery(diagnosis, trace); console.log(chalk.blue(`šŸ› ļø Recovery plan: ${recoveryPlan.pattern}`)); console.log(chalk.blue(` Rationale: ${recoveryPlan.rationale}`)); // METACOGNITIVE CYCLE - Phase 4: CONTROL (Meta-Level) const beliefRevision = await this.controlCognition(loopDetection, diagnosis, trace); console.log(chalk.magenta(`🧠 Beliefs revised: ${beliefRevision.revised_beliefs.length} beliefs, ${beliefRevision.removed_beliefs.length} removed`)); // Store this experience for future learning this.storeExperience(loopDetection, diagnosis, recoveryPlan, trace); this.interventionCount++; const explanation = this.generateInterventionExplanation(loopDetection, diagnosis, recoveryPlan, beliefRevision); console.log(chalk.cyan(`\nšŸ’” Intervention #${this.interventionCount}: ${explanation}`)); return { intervention_required: true, loop_detected: loopDetection, diagnosis, recovery_plan: recoveryPlan, revised_beliefs: beliefRevision, explanation }; } /** * METACOGNITIVE CYCLE - Phase 1: MONITOR * Uses the Sentinel to detect problematic patterns */ monitorForLoops(trace) { return this.sentinel.detectLoop(trace, 'hybrid'); } /** * METACOGNITIVE CYCLE - Phase 2: INTERPRET/DETECT * Uses the Adjudicator to diagnose the failure */ async interpretFailure(loopResult, trace) { return await this.adjudicator.diagnoseFailure(loopResult, trace); } /** * METACOGNITIVE CYCLE - Phase 3: PLAN (Meta-Level) * Uses the Adjudicator to generate a recovery plan */ planRecovery(diagnosis, trace) { return this.adjudicator.generateRecoveryPlan(diagnosis, trace); } /** * METACOGNITIVE CYCLE - Phase 4: CONTROL (Meta-Level) * Revises beliefs and prepares cognitive control signals */ async controlCognition(loopResult, diagnosis, trace) { const contradictingEvidence = `Loop detected: ${loopResult.type}. Diagnosis: ${diagnosis.primary_hypothesis}. Current strategy is ineffective.`; // For simplified traces, we'll use empty beliefs array as default const currentBeliefs = []; return await this.adjudicator.reviseBeliefs(currentBeliefs, contradictingEvidence, trace); } /** * Store the experience for case-based reasoning */ storeExperience(loopResult, diagnosis, recoveryPlan, trace) { const experience = { id: uuidv4(), problem_description: `${loopResult.type} loop detected: ${diagnosis.primary_hypothesis} in context: ${this.extractContextSummary(trace)}`, solution: `Apply ${recoveryPlan.pattern} strategy: ${recoveryPlan.rationale}`, outcome: false, // Will be updated when outcome is known timestamp: Date.now() }; this.adjudicator.storeExperience(experience); } /** * Generate a human-readable explanation of the intervention */ generateInterventionExplanation(loopResult, diagnosis, recoveryPlan, beliefRevision) { const loopType = loopResult.type?.replace('_', ' ') || 'unknown'; const hypothesis = diagnosis.primary_hypothesis.replace('_', ' '); const pattern = recoveryPlan.pattern.replace('_', ' '); return `Detected ${loopType} loop (${(loopResult.confidence * 100).toFixed(0)}% confidence). ` + `Diagnosed as ${hypothesis} issue. ` + `Applying ${pattern} recovery strategy. ` + `Revised ${beliefRevision.revised_beliefs.length} beliefs to maintain consistency.`; } /** * Extract a summary of the current context for case storage */ extractContextSummary(trace) { const recentActions = trace.recent_actions.slice(-3).join(' -> '); const currentContext = trace.current_context || 'unknown'; return `Goal: ${trace.goal.substring(0, 50)}..., ` + `Recent actions: ${recentActions}, ` + `Context: ${currentContext}, ` + `Step: ${trace.step_count}`; } /** * Get current monitoring status and statistics */ getMonitoringStatus() { return { is_monitoring: this.isMonitoring, intervention_count: this.interventionCount, current_goal: this.currentTrace.goal, trace_length: this.currentTrace.recent_actions.length }; } /** * Update the outcome of a previously generated recovery plan */ updateRecoveryOutcome(successful, explanation) { // In a full implementation, this would update the most recent case // For now, we'll just log it console.log(chalk.cyan(`šŸ“ Recovery outcome updated: ${successful ? 'SUCCESS' : 'FAILURE'} - ${explanation}`)); } /** * Reset the engine state (useful for testing or new sessions) */ reset() { this.sentinel.reset(); this.currentTrace = this.initializeTrace(); this.isMonitoring = false; this.interventionCount = 0; console.log(chalk.blue('šŸ”„ Dual-Cycle Engine reset')); } /** * Get similar cases for analysis */ getSimilarCases(problemDescription, maxResults = 5) { return this.adjudicator.retrieveSimilarCases(problemDescription, maxResults); } }