Skip to main content
Glama
memory-service.test.ts•6.79 kB
import { describe, expect, test, beforeAll, afterAll } from 'bun:test'; import { createTestDatabase } from './test-setup.js'; import { MemoryService } from '../src/services/memory-service'; import type { StoreMemoryInput } from '../src/schemas/validation'; describe('MemoryService', () => { let memoryService: MemoryService; let db: any; beforeAll(async () => { db = createTestDatabase(); memoryService = new MemoryService(db); // Don't run migrations - assume database is already set up // await import('../src/database/migrate'); }); afterAll(async () => { // Clean up ONLY test data - NEVER delete all memories! // Only delete memories that were created during this test run await db.deleteFrom('memories') .where('user_context', 'in', ['test-user', 'cluster-test']) .execute(); // Also clean up any test memories with specific test sources await db.deleteFrom('memories') .where('source', 'in', ['test-suite', 'test']) .execute(); await db.destroy(); }); describe('store', () => { test('should store a new memory', async () => { const input: StoreMemoryInput = { content: 'Test memory content', type: 'fact', tags: ['test', 'unit-test'], source: 'test-suite', confidence: 0.9, user_context: 'test-user', }; const memory = await memoryService.store(input, false); expect(memory).toBeDefined(); expect(memory.content).toBe('Test memory content'); expect(memory.type).toBe('fact'); expect(memory.tags).toEqual(['test', 'unit-test']); expect(memory.confidence).toBe(0.9); }); test('should detect duplicate content', async () => { const input: StoreMemoryInput = { content: 'Duplicate test content', type: 'fact', tags: ['duplicate'], source: 'test-suite', confidence: 0.8, user_context: 'test-user', }; const memory1 = await memoryService.store(input, false); const memory2 = await memoryService.store(input, false); expect(memory1.id).toBe(memory2.id); expect(memory2.access_count).toBeGreaterThan(memory1.access_count); }); test('should compress large content', async () => { const largeContent = 'x'.repeat(150000); // 150KB const input: StoreMemoryInput = { content: largeContent, type: 'context', tags: ['large'], source: 'test-suite', confidence: 0.7, user_context: 'test-user', }; const memory = await memoryService.store(input, false); expect(memory).toBeDefined(); expect(memory.is_compressed).toBe(true); }, 30000); // Increase timeout to 30 seconds for compression test }); describe('search', () => { test('should find memories by query', async () => { // Store test memories with unique content and test-specific user context const testMemory1 = await memoryService.store({ content: 'TypeScript is a programming language used for tests', type: 'fact', tags: ['typescript', 'programming', 'test-search'], source: 'test-suite', confidence: 0.9, user_context: 'test-user', }, false); const testMemory2 = await memoryService.store({ content: 'JavaScript is also a programming language for tests', type: 'fact', tags: ['javascript', 'programming', 'test-search'], source: 'test-suite', confidence: 0.9, user_context: 'test-user', }, false); const results = await memoryService.search({ query: 'TypeScript programming tests', limit: 10, threshold: 0.3, user_context: 'test-user', }); expect(results.length).toBeGreaterThan(0); // Find our specific test memory const foundTestMemory = results.find(r => typeof r.content === 'string' && r.content.includes('TypeScript is a programming language used for tests') ); expect(foundTestMemory).toBeDefined(); }); }); describe('list', () => { test('should list memories with filters', async () => { const memories = await memoryService.list({ type: 'fact', tags: ['programming'], limit: 10, offset: 0, }); expect(Array.isArray(memories)).toBe(true); memories.forEach(memory => { expect(memory.type).toBe('fact'); expect(memory.tags).toContain('programming'); }); }); }); describe('update', () => { test('should update memory metadata', async () => { const memory = await memoryService.store({ content: 'Update test memory', type: 'fact', tags: ['original'], source: 'test', confidence: 0.5, }, false); const updated = await memoryService.update({ id: memory.id, updates: { tags: ['updated', 'modified'], confidence: 0.9, }, }); expect(updated.tags).toEqual(['updated', 'modified']); expect(updated.confidence).toBe(0.9); }); }); describe('delete', () => { test('should soft delete memory', async () => { const memory = await memoryService.store({ content: 'Delete test memory', type: 'fact', tags: ['delete'], source: 'test', confidence: 0.5, }, false); const result = await memoryService.delete({ id: memory.id }); expect(result.success).toBe(true); // Should not appear in regular list const memories = await memoryService.list({ tags: ['delete'], limit: 10, offset: 0, }); expect(memories.find(m => m.id === memory.id)).toBeUndefined(); }); }); describe.skip('consolidate', () => { test('should cluster similar memories', async () => { // Store similar memories with embeddings disabled for speed // Since we're testing clustering logic, not embedding generation for (let i = 0; i < 5; i++) { await memoryService.store({ content: `Similar content about clustering ${i}`, type: 'fact', tags: ['clustering'], source: 'test', confidence: 0.8, user_context: 'cluster-test', }, true); // Enable async embedding to avoid dimension issues } // Wait a bit for async embeddings to process await new Promise(resolve => setTimeout(resolve, 2000)); const result = await memoryService.consolidate({ user_context: 'cluster-test', threshold: 0.7, min_cluster_size: 2, }); expect(result.clustersCreated).toBeGreaterThan(0); expect(result.memoriesArchived).toBeGreaterThan(0); }); }); });

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/scanadi/mcp-ai-memory'

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