import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { mkdtempSync, rmSync } from 'fs'; import { tmpdir } from 'os'; import { join } from 'path'; import { addMemory, searchMemory, listMemory } from '../src/core/services/memoryService.js'; import { Index } from '../src/core/index.js'; describe('memoryService', () => { let cwd: string; beforeEach(() => { cwd = mkdtempSync(join(tmpdir(), 'ah-mem-')); }); afterEach(() => { rmSync(cwd, { recursive: true, force: true }); }); it('creates and searches memory', () => { const m = addMemory(cwd, { title: 'DNS cache', category: 'technical', content: 'Use TTL' }); expect(m.id.startsWith('MEM-')).toBe(true); expect(searchMemory(cwd, 'TTL')).toHaveLength(1); expect(listMemory(cwd)).toHaveLength(1); }); it('stores relatedTasks in the memory object', () => { const m = addMemory(cwd, { title: 'TTL lesson', category: 'lesson', content: 'Use short TTL', relatedTasks: ['TSK-0001', 'TSK-0002'], }); expect(m.relatedTasks).toEqual(['TSK-0001', 'TSK-0002']); }); it('stores optional tokens, duration, by fields', () => { const m = addMemory(cwd, { title: 'Perf stats', category: 'implementation', content: 'p99=50ms', tokens: 1500, duration: 30_000, by: 'kimi', }); expect(m.tokens).toBe(1500); expect(m.duration).toBe(30_000); expect(m.by).toBe('kimi'); }); it('listMemoryByTask returns entries linked to a given task', () => { addMemory(cwd, { title: 'Related', category: 'technical', content: 'x', relatedTasks: ['TSK-0042'] }); addMemory(cwd, { title: 'Unrelated', category: 'technical', content: 'y', relatedTasks: ['TSK-0099'] }); const index = new Index(cwd); const results = index.listMemoryByTask('TSK-0042'); index.close(); expect(results).toHaveLength(1); expect(results[0].title).toBe('Related'); }); it('listMemoryByTask returns empty when no memory is linked', () => { addMemory(cwd, { title: 'Other', category: 'technical', content: 'y', relatedTasks: ['TSK-0099'] }); const index = new Index(cwd); const results = index.listMemoryByTask('TSK-0001'); index.close(); expect(results).toHaveLength(0); }); });