Skip to main content
Glama
MemoryRecovery.integration.test.ts18.9 kB
/** * Memory Recovery Integration Tests * * Tests the complete memory recovery system including RecoveryEngine, * recovery strategies, and MCP server integration. */ import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { GradualDegradationManager } from "../../cognitive/forgetting/GradualDegradationManager.js"; import { RecoveryEngine } from "../../cognitive/forgetting/RecoveryEngine.js"; import { MetadataPreservationLevel, RecoveryCue, RecoveryMetadata, RecoveryResult, } from "../../interfaces/forgetting.js"; import { CognitiveMCPServer } from "../../server/CognitiveMCPServer.js"; import { Concept, Episode } from "../../types/core.js"; import { RecoverMemoryArgs } from "../../types/mcp.js"; describe("Memory Recovery Integration Tests", () => { let server: CognitiveMCPServer; let recoveryEngine: RecoveryEngine; let degradationManager: GradualDegradationManager; beforeEach(async () => { // Initialize components server = new CognitiveMCPServer(); await server.initialize(true); // Test mode recoveryEngine = new RecoveryEngine(); degradationManager = new GradualDegradationManager(); }); afterEach(async () => { // Cleanup if (degradationManager) { await degradationManager.cleanup(); } }); describe("RecoveryEngine Core Functionality", () => { it("should successfully recover memory using associative cues", async () => { const memoryId = "test_memory_001"; const recoveryCues: RecoveryCue[] = [ { type: "associative", value: "related_concept", strength: 0.8, source: "test", }, { type: "semantic", value: "important_keyword", strength: 0.7, source: "test", }, ]; const recoveryMetadata: RecoveryMetadata = { original_memory_id: memoryId, original_content_hash: "test_hash_123", original_importance: 0.8, original_timestamp: Date.now() - 86400000, // 1 day ago degradation_history: [], recovery_cues: recoveryCues, association_fingerprint: { strong_associations: ["concept_a", "concept_b"], weak_associations: ["concept_c"], semantic_clusters: ["cluster_1"], temporal_neighbors: ["memory_002"], contextual_tags: ["test_context"], }, content_summary: "Test memory content for recovery", recovery_difficulty_estimate: 0.3, preservation_timestamp: Date.now() - 86400000, }; const result = await recoveryEngine.attemptRecovery( memoryId, recoveryCues, recoveryMetadata ); expect(result).toBeDefined(); expect(result.success).toBe(true); expect(result.recovery_confidence).toBeGreaterThan(0.3); expect(result.recovery_attempts.length).toBeGreaterThan(0); expect(result.recovery_method).toBeDefined(); expect(result.recovery_time_ms).toBeGreaterThanOrEqual(0); }); it("should handle recovery with insufficient cues gracefully", async () => { const memoryId = "test_memory_002"; const weakCues: RecoveryCue[] = [ { type: "semantic", value: "vague_term", strength: 0.1, // Very weak cue source: "test", }, ]; const result = await recoveryEngine.attemptRecovery(memoryId, weakCues); expect(result).toBeDefined(); // With very weak cues, recovery might still succeed but with low confidence expect(result.recovery_confidence).toBeLessThan(0.5); expect(result.recovery_attempts.length).toBeGreaterThan(0); // The system should handle weak cues gracefully // Recovery may succeed or fail, but should provide meaningful feedback expect(result.recovery_method).toBeDefined(); expect(result.quality_assessment).toBeDefined(); }); it("should assess recovery confidence accurately", async () => { const recoveredContent = { content: "Recovered memory content", confidence: 0.7, }; const originalMetadata: RecoveryMetadata = { original_memory_id: "test_memory_003", original_content_hash: "original_hash", original_importance: 0.9, original_timestamp: Date.now() - 3600000, // 1 hour ago degradation_history: [ { stage_id: "initial_fade", applied_timestamp: Date.now() - 1800000, degradation_factor: 0.1, content_before_hash: "before_hash", content_after_hash: "after_hash", metadata_preserved: MetadataPreservationLevel.FULL, reversible: true, }, ], recovery_cues: [ { type: "semantic", value: "test_cue", strength: 0.8, source: "test", }, ], association_fingerprint: { strong_associations: ["assoc_1", "assoc_2"], weak_associations: [], semantic_clusters: ["cluster_1"], temporal_neighbors: [], contextual_tags: ["test"], }, content_summary: "Test content summary", recovery_difficulty_estimate: 0.4, preservation_timestamp: Date.now() - 3600000, }; const confidenceAssessment = await recoveryEngine.assessRecoveryConfidence( recoveredContent, originalMetadata ); expect(confidenceAssessment).toBeDefined(); expect(confidenceAssessment.overall_confidence).toBeGreaterThan(0); expect(confidenceAssessment.overall_confidence).toBeLessThanOrEqual(1); expect(confidenceAssessment.content_accuracy_estimate).toBeDefined(); expect(confidenceAssessment.completeness_estimate).toBeDefined(); expect(confidenceAssessment.reliability_factors).toBeInstanceOf(Array); expect(confidenceAssessment.uncertainty_sources).toBeInstanceOf(Array); expect(confidenceAssessment.validation_suggestions).toBeInstanceOf(Array); }); it("should track recovery success and update statistics", async () => { const memoryId = "test_memory_004"; const recoveryResult: RecoveryResult = { success: true, recovered_memory: { id: memoryId, content: "test content", activation: 0.8, last_accessed: Date.now(), relations: [], } as Concept, recovery_confidence: 0.8, recovery_method: "associative_recovery", partial_recovery: false, missing_elements: [], recovery_metadata_used: { original_memory_id: memoryId, original_content_hash: "test_hash", original_importance: 0.7, original_timestamp: Date.now(), degradation_history: [], recovery_cues: [], association_fingerprint: { strong_associations: [], weak_associations: [], semantic_clusters: [], temporal_neighbors: [], contextual_tags: [], }, content_summary: "", recovery_difficulty_estimate: 0.5, preservation_timestamp: Date.now(), }, }; await recoveryEngine.trackRecoverySuccess(memoryId, recoveryResult); const statistics = await recoveryEngine.getRecoveryStatistics(); expect(statistics.total_recovery_attempts).toBeGreaterThan(0); expect(statistics.successful_recoveries).toBeGreaterThan(0); expect(statistics.average_recovery_confidence).toBeGreaterThan(0); }); }); describe("Integration with Gradual Degradation Manager", () => { it("should preserve recovery metadata during degradation", async () => { const testMemory: Episode = { content: "Test episode content for degradation and recovery", timestamp: Date.now(), importance: 0.8, context: { session_id: "test_session", domain: "test_domain", }, emotional_tags: ["positive"], decay_factor: 0.1, }; const degradationProcess = await degradationManager.initiateDegradation( testMemory, 0.5 // 50% degradation ); expect(degradationProcess).toBeDefined(); expect(degradationProcess.status.recovery_metadata).toBeDefined(); const recoveryMetadata = degradationProcess.status.recovery_metadata!; expect(recoveryMetadata.original_memory_id).toBeDefined(); expect(recoveryMetadata.original_memory_id).toBe( degradationProcess.memory_id ); expect(recoveryMetadata.recovery_cues.length).toBeGreaterThan(0); expect(recoveryMetadata.association_fingerprint).toBeDefined(); expect(recoveryMetadata.content_summary).toBeDefined(); }); it("should successfully recover memory after degradation", async () => { const testMemory: Concept = { id: "concept_001", content: "Important concept for testing recovery", activation: 0.9, last_accessed: Date.now(), relations: ["concept_002", "concept_003"], }; // Start degradation process const degradationProcess = await degradationManager.initiateDegradation( testMemory, 0.3 ); // Execute one degradation stage await degradationManager.executeNextStage(degradationProcess.process_id); // Attempt recovery using preserved metadata const recoveryMetadata = degradationProcess.status.recovery_metadata!; const recoveryCues = recoveryMetadata.recovery_cues; const recoveryResult = await recoveryEngine.attemptRecovery( testMemory.id, recoveryCues, recoveryMetadata ); expect(recoveryResult.success).toBe(true); expect(recoveryResult.recovery_confidence).toBeGreaterThan(0.3); expect(recoveryResult.recovered_memory).toBeDefined(); }); }); describe("MCP Server Integration", () => { it("should handle recover_memory tool request successfully", async () => { const args: RecoverMemoryArgs = { memory_id: "test_memory_mcp_001", recovery_cues: [ { type: "semantic", value: "important_keyword", strength: 0.8, }, { type: "contextual", value: "test_context", strength: 0.6, }, { type: "associative", value: "related_memory", strength: 0.7, }, ], max_recovery_attempts: 3, confidence_threshold: 0.4, context: { session_id: "test_session", domain: "test_domain", }, }; const result = await server.handleRecoverMemory(args); expect(result).toBeDefined(); expect(result.success).toBeDefined(); expect(result.memory_id).toBe(args.memory_id); expect(result.recovery_confidence).toBeGreaterThanOrEqual(0); expect(result.recovery_confidence).toBeLessThanOrEqual(1); expect(result.recovery_method).toBeDefined(); expect(result.recovery_attempts).toBeInstanceOf(Array); expect(result.quality_assessment).toBeDefined(); expect(result.recovery_time_ms).toBeGreaterThanOrEqual(0); }); it("should validate recover_memory arguments correctly", async () => { // Test with valid arguments to ensure the method works const validArgs: RecoverMemoryArgs = { memory_id: "test_id", recovery_cues: [{ type: "semantic", value: "test" }], }; const result = await server.handleRecoverMemory(validArgs); expect(result).toBeDefined(); expect(result.memory_id).toBe("test_id"); expect(result.success).toBeDefined(); expect(result.recovery_confidence).toBeGreaterThanOrEqual(0); expect(result.recovery_confidence).toBeLessThanOrEqual(1); // Note: Validation testing would typically be done through the MCP protocol // The validation logic is tested separately in the MCP server integration }); it("should handle recovery with different strategy combinations", async () => { const baseArgs: RecoverMemoryArgs = { memory_id: "test_memory_strategies", recovery_cues: [ { type: "semantic", value: "keyword1", strength: 0.8 }, { type: "associative", value: "related_item", strength: 0.7 }, { type: "contextual", value: "context_info", strength: 0.6 }, ], }; // Test with specific strategies const strategiesArgs = { ...baseArgs, recovery_strategies: ["associative_recovery", "schema_based_recovery"], }; const result = await server.handleRecoverMemory(strategiesArgs); expect(result.recovery_attempts.length).toBeGreaterThan(0); expect( result.recovery_attempts.some( (a) => a.strategy_name === "associative_recovery" ) ).toBe(true); }); it("should provide detailed quality assessment", async () => { const args: RecoverMemoryArgs = { memory_id: "test_memory_quality", recovery_cues: [ { type: "semantic", value: "detailed_content", strength: 0.9 }, { type: "temporal", value: "2024-01-15", strength: 0.7 }, ], confidence_threshold: 0.3, }; const result = await server.handleRecoverMemory(args); expect(result.quality_assessment).toBeDefined(); expect(result.quality_assessment.overall_quality).toBeGreaterThanOrEqual( 0 ); expect(result.quality_assessment.overall_quality).toBeLessThanOrEqual(1); expect(result.quality_assessment.content_coherence).toBeDefined(); expect(result.quality_assessment.contextual_consistency).toBeDefined(); expect(result.quality_assessment.quality_issues).toBeInstanceOf(Array); }); }); describe("Recovery Strategy Performance", () => { it("should demonstrate different strategy effectiveness", async () => { const memoryId = "strategy_test_memory"; // Test associative recovery const associativeCues: RecoveryCue[] = [ { type: "associative", value: "strong_association", strength: 0.9, source: "test", }, ]; const associativeResult = await recoveryEngine.attemptRecovery( memoryId, associativeCues ); // Test semantic recovery const semanticCues: RecoveryCue[] = [ { type: "semantic", value: "key_concept", strength: 0.8, source: "test", }, { type: "contextual", value: "relevant_context", strength: 0.7, source: "test", }, ]; const semanticResult = await recoveryEngine.attemptRecovery( memoryId + "_semantic", semanticCues ); // Both should attempt recovery expect(associativeResult.recovery_attempts.length).toBeGreaterThan(0); expect(semanticResult.recovery_attempts.length).toBeGreaterThan(0); // Should use different strategies const associativeStrategies = associativeResult.recovery_attempts.map( (a) => a.strategy_name ); const semanticStrategies = semanticResult.recovery_attempts.map( (a) => a.strategy_name ); expect(associativeStrategies).toContain("associative_recovery"); expect(semanticStrategies).toContain("schema_based_recovery"); }); it("should improve recovery success over time", async () => { const memoryId = "learning_test_memory"; const recoveryCues: RecoveryCue[] = [ { type: "semantic", value: "learning_keyword", strength: 0.7, source: "test", }, ]; // Perform multiple recovery attempts const results: RecoveryResult[] = []; for (let i = 0; i < 3; i++) { const result = await recoveryEngine.attemptRecovery( `${memoryId}_${i}`, recoveryCues ); results.push(result); // Simulate positive user validation await recoveryEngine.trackRecoverySuccess(`${memoryId}_${i}`, result, { memory_id: `${memoryId}_${i}`, user_confirms_accuracy: true, accuracy_rating: 0.8, completeness_rating: 0.7, validation_timestamp: Date.now(), }); } // Check that statistics are being tracked const statistics = await recoveryEngine.getRecoveryStatistics(); expect(statistics.total_recovery_attempts).toBeGreaterThanOrEqual(3); expect(statistics.strategy_success_rates.size).toBeGreaterThan(0); }); }); describe("Error Handling and Edge Cases", () => { it("should handle recovery engine errors gracefully", async () => { // Test with invalid memory ID format await expect(recoveryEngine.attemptRecovery("", [])).rejects.toThrow( "Recovery cues are required" ); // Test with malformed cues const invalidCues = [ { type: "invalid", value: "", strength: -1, source: "test" } as any, ]; // Should handle gracefully without crashing const result = await recoveryEngine.attemptRecovery( "test_memory_error", invalidCues ); expect(result).toBeDefined(); expect(result.success).toBe(false); }); it("should handle MCP server validation errors", async () => { // Test that the server handles edge cases gracefully // Note: Direct validation testing requires MCP protocol integration // Test with minimal valid arguments const minimalArgs: RecoverMemoryArgs = { memory_id: "test_validation", recovery_cues: [{ type: "semantic", value: "test" }], }; const result = await server.handleRecoverMemory(minimalArgs); expect(result).toBeDefined(); expect(result.success).toBeDefined(); // The server should handle edge cases without crashing expect(result.recovery_attempts).toBeInstanceOf(Array); expect(result.quality_assessment).toBeDefined(); }); it("should handle timeout scenarios", async () => { // Test with complex recovery scenario that might timeout const complexArgs: RecoverMemoryArgs = { memory_id: "complex_memory_timeout_test", recovery_cues: Array.from({ length: 10 }, (_, i) => ({ type: "semantic" as const, value: `complex_cue_${i}`, strength: 0.5, })), max_recovery_attempts: 10, }; // Should complete within reasonable time const startTime = Date.now(); const result = await server.handleRecoverMemory(complexArgs); const endTime = Date.now(); expect(result).toBeDefined(); expect(endTime - startTime).toBeLessThan(30000); // Should complete within 30 seconds }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ThoughtMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server