Skip to main content
Glama
ConsolidationEngine.test.ts13.4 kB
/** * Unit tests for ConsolidationEngine */ import { beforeEach, describe, expect, it } from "vitest"; import { ConsolidationEngine } from "../../cognitive/ConsolidationEngine.js"; import { Context, Episode } from "../../types/core.js"; describe("ConsolidationEngine", () => { let consolidationEngine: ConsolidationEngine; let mockContext: Context; beforeEach(async () => { consolidationEngine = new ConsolidationEngine({ consolidation_threshold: 0.3, // Lower threshold for testing pattern_similarity_threshold: 0.3, // Lower threshold for testing minimum_episode_count: 2, importance_weight: 0.4, recency_weight: 0.3, frequency_weight: 0.3, max_patterns_per_cycle: 10, pruning_threshold: 0.1, }); mockContext = { session_id: "test-session", domain: "test-domain", urgency: 0.5, complexity: 0.6, }; await consolidationEngine.initialize(); }); describe("initialization", () => { it("should initialize successfully", async () => { const status = consolidationEngine.getStatus(); expect(status.initialized).toBe(true); expect(status.name).toBe("ConsolidationEngine"); }); it("should start with empty consolidation history", () => { const stats = consolidationEngine.getConsolidationStats(); expect(stats.length).toBe(0); }); }); describe("pattern extraction", () => { it("should extract patterns from similar episodes", () => { const episodes: Episode[] = [ { content: { text: "Learning about machine learning algorithms" }, context: { ...mockContext, domain: "ai" }, timestamp: Date.now() - 3600000, emotional_tags: ["curious"], importance: 0.8, decay_factor: 1.0, }, { content: { text: "Studying machine learning techniques" }, context: { ...mockContext, domain: "ai" }, timestamp: Date.now() - 1800000, emotional_tags: ["focused"], importance: 0.7, decay_factor: 1.0, }, { content: { text: "Reading about machine learning applications" }, context: { ...mockContext, domain: "ai" }, timestamp: Date.now() - 900000, emotional_tags: ["interested"], importance: 0.9, decay_factor: 1.0, }, ]; const patterns = consolidationEngine.extractPatterns(episodes); expect(patterns.length).toBeGreaterThan(0); expect(patterns[0].confidence).toBeGreaterThan(0); expect(patterns[0].salience).toBeGreaterThan(0); }); it("should not extract patterns from insufficient episodes", () => { const episodes: Episode[] = [ { content: { text: "Single episode" }, context: mockContext, timestamp: Date.now(), emotional_tags: [], importance: 0.8, decay_factor: 1.0, }, ]; const patterns = consolidationEngine.extractPatterns(episodes); expect(patterns.length).toBe(0); }); it("should limit patterns to max per cycle", () => { const smallEngine = new ConsolidationEngine({ max_patterns_per_cycle: 1, }); // Create many similar episodes that could generate multiple patterns const episodes: Episode[] = []; for (let i = 0; i < 10; i++) { episodes.push({ content: { text: `Learning topic ${i}`, category: "education" }, context: { ...mockContext, domain: "education" }, timestamp: Date.now() - i * 1000, emotional_tags: ["learning"], importance: 0.8, decay_factor: 1.0, }); } const patterns = smallEngine.extractPatterns(episodes); expect(patterns.length).toBeLessThanOrEqual(1); }); }); describe("consolidation process", () => { it("should consolidate episodes into concepts", () => { const episodes: Episode[] = [ { content: { text: "Neural networks learn patterns from data" }, context: { ...mockContext, domain: "ai" }, timestamp: Date.now() - 7200000, emotional_tags: ["fascinated"], importance: 0.9, decay_factor: 0.8, }, { content: { text: "Deep neural networks use multiple layers" }, context: { ...mockContext, domain: "ai" }, timestamp: Date.now() - 3600000, emotional_tags: ["curious"], importance: 0.8, decay_factor: 0.9, }, { content: { text: "Neural network training requires large datasets" }, context: { ...mockContext, domain: "ai" }, timestamp: Date.now() - 1800000, emotional_tags: ["understanding"], importance: 0.85, decay_factor: 0.95, }, ]; const concepts = consolidationEngine.consolidate(episodes); expect(concepts.length).toBeGreaterThan(0); expect(concepts[0].id).toBeDefined(); expect(concepts[0].content).toBeDefined(); expect(concepts[0].activation).toBeGreaterThan(0); }); it("should return empty array for insufficient episodes", () => { const episodes: Episode[] = [ { content: { text: "Single episode" }, context: mockContext, timestamp: Date.now(), emotional_tags: [], importance: 0.8, decay_factor: 1.0, }, ]; const concepts = consolidationEngine.consolidate(episodes); expect(concepts.length).toBe(0); }); it("should track consolidation results", () => { const episodes: Episode[] = [ { content: { text: "First learning experience" }, context: mockContext, timestamp: Date.now() - 3600000, emotional_tags: ["learning"], importance: 0.8, decay_factor: 1.0, }, { content: { text: "Second learning experience" }, context: mockContext, timestamp: Date.now() - 1800000, emotional_tags: ["learning"], importance: 0.7, decay_factor: 1.0, }, ]; consolidationEngine.consolidate(episodes); const lastResult = consolidationEngine.getLastConsolidationResult(); expect(lastResult).toBeDefined(); expect(lastResult?.episodes_processed).toBe(2); const stats = consolidationEngine.getConsolidationStats(); expect(stats.length).toBe(1); }); }); describe("connection strengthening", () => { it("should strengthen connections between related concepts", () => { const concepts = [ { id: "concept-1", content: { text: "Machine learning algorithms" }, embedding: [0.1, 0.2, 0.3, 0.4], relations: [], activation: 0.8, last_accessed: Date.now(), }, { id: "concept-2", content: { text: "Neural network architectures" }, embedding: [0.15, 0.25, 0.35, 0.45], // Similar to concept-1 relations: [], activation: 0.7, last_accessed: Date.now(), }, ]; const strengthenedCount = consolidationEngine.strengthenConnections(concepts); expect(strengthenedCount).toBeGreaterThanOrEqual(0); }); it("should not strengthen weak connections", () => { const concepts = [ { id: "concept-1", content: { text: "Machine learning" }, embedding: [1.0, 0.0, 0.0, 0.0], relations: [], activation: 0.8, last_accessed: Date.now() - 7200000, // 2 hours ago }, { id: "concept-2", content: { text: "Cooking recipes" }, embedding: [0.0, 1.0, 0.0, 0.0], // Very different relations: [], activation: 0.2, // Very different activation last_accessed: Date.now() - 3600000, // 1 hour ago }, ]; const strengthenedCount = consolidationEngine.strengthenConnections(concepts); expect(strengthenedCount).toBe(0); }); }); describe("consolidation statistics", () => { it("should maintain consolidation history", () => { const episodes1: Episode[] = [ { content: { text: "First batch episode 1" }, context: mockContext, timestamp: Date.now() - 3600000, emotional_tags: ["learning"], importance: 0.8, decay_factor: 1.0, }, { content: { text: "First batch episode 2" }, context: mockContext, timestamp: Date.now() - 1800000, emotional_tags: ["learning"], importance: 0.7, decay_factor: 1.0, }, ]; const episodes2: Episode[] = [ { content: { text: "Second batch episode 1" }, context: mockContext, timestamp: Date.now() - 900000, emotional_tags: ["understanding"], importance: 0.9, decay_factor: 1.0, }, { content: { text: "Second batch episode 2" }, context: mockContext, timestamp: Date.now() - 450000, emotional_tags: ["understanding"], importance: 0.8, decay_factor: 1.0, }, ]; consolidationEngine.consolidate(episodes1); consolidationEngine.consolidate(episodes2); const stats = consolidationEngine.getConsolidationStats(); expect(stats.length).toBe(2); const lastResult = consolidationEngine.getLastConsolidationResult(); expect(lastResult?.episodes_processed).toBe(2); }); }); describe("error handling", () => { it("should handle invalid process input", async () => { await expect( consolidationEngine.process("invalid" as any) ).rejects.toThrow(); }); it("should handle valid process input", async () => { const episodes: Episode[] = [ { content: { text: "Process test episode 1" }, context: mockContext, timestamp: Date.now() - 1800000, emotional_tags: [], importance: 0.8, decay_factor: 1.0, }, { content: { text: "Process test episode 2" }, context: mockContext, timestamp: Date.now() - 900000, emotional_tags: [], importance: 0.7, decay_factor: 1.0, }, ]; const result = await consolidationEngine.process(episodes); expect(Array.isArray(result)).toBe(true); }); it("should handle empty episode arrays gracefully", () => { const concepts = consolidationEngine.consolidate([]); expect(concepts).toEqual([]); }); }); describe("pattern classification", () => { it("should classify different types of patterns", () => { const emotionalEpisodes: Episode[] = [ { content: { text: "Happy learning experience" }, context: mockContext, timestamp: Date.now() - 3600000, emotional_tags: ["happy", "excited"], importance: 0.8, decay_factor: 1.0, }, { content: { text: "Joyful discovery moment" }, context: mockContext, timestamp: Date.now() - 1800000, emotional_tags: ["joy", "excited"], importance: 0.9, decay_factor: 1.0, }, ]; const domainEpisodes: Episode[] = [ { content: { text: "AI research discussion" }, context: { ...mockContext, domain: "artificial-intelligence" }, timestamp: Date.now() - 3600000, emotional_tags: [], importance: 0.8, decay_factor: 1.0, }, { content: { text: "Machine learning study session" }, context: { ...mockContext, domain: "artificial-intelligence" }, timestamp: Date.now() - 1800000, emotional_tags: [], importance: 0.7, decay_factor: 1.0, }, ]; const emotionalPatterns = consolidationEngine.extractPatterns(emotionalEpisodes); const domainPatterns = consolidationEngine.extractPatterns(domainEpisodes); // Should extract patterns (exact classification depends on implementation details) expect(emotionalPatterns.length + domainPatterns.length).toBeGreaterThan( 0 ); }); }); describe("reset functionality", () => { it("should reset consolidation state", () => { const episodes: Episode[] = [ { content: { text: "Reset test episode 1" }, context: mockContext, timestamp: Date.now() - 1800000, emotional_tags: [], importance: 0.8, decay_factor: 1.0, }, { content: { text: "Reset test episode 2" }, context: mockContext, timestamp: Date.now() - 900000, emotional_tags: [], importance: 0.7, decay_factor: 1.0, }, ]; consolidationEngine.consolidate(episodes); expect(consolidationEngine.getConsolidationStats().length).toBe(1); consolidationEngine.reset(); expect(consolidationEngine.getConsolidationStats().length).toBe(0); expect(consolidationEngine.getLastConsolidationResult()).toBeNull(); }); }); });

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