import { MemoryConfig, DEFAULT_MEMORY_CONFIG, MemoryType, MemorySource } from './types'; import { storeMemoryWithDeduplication } from './deduplication'; import { evictLowHeatMemories, buildAccessUpdateQuery } from './memoryDecay'; import { getPrimaryMemoryType } from './typedMemory'; import { processAssistantForMemory } from './assistantMemory'; import { shouldStoreUserMessage } from './smartFilter'; import { computeRetrievalParams, buildDynamicRetrievalQuery, processRetrievedMemories } from './dynamicRetrieval'; export class ImprovedMemoryService { private db: any; private config: MemoryConfig; private embedFn: (t: string) => Promise; private insertCount = 0; constructor(db: any, embedFn: (t: string) => Promise, config = DEFAULT_MEMORY_CONFIG) { this.db = db; this.embedFn = embedFn; this.config = config; } async retrieve(userMessage: string, embedding: number[]) { const params = computeRetrievalParams(userMessage, this.config); const { sql, queryParams } = buildDynamicRetrievalQuery(embedding, params); const raw = await this.db.getAll(sql, queryParams); const typed = raw.map((r: any) => ({ record: { id: r.id, text: r.text, embedding: [], type: r.type, source: r.source, createdAt: r.created_at, lastAccessedAt: r.last_accessed_at, accessCount: r.access_count, importance: r.importance }, cosineSimilarity: r.similarity })); const { formattedContext, memoriesUsed } = processRetrievedMemories(typed, params, this.config); if (memoriesUsed.length) { const { sql: s, params: p } = buildAccessUpdateQuery(memoriesUsed); await this.db.run(s, p); } return { context: formattedContext, memoryIds: memoriesUsed }; } async storeUserMessage(text: string, embedding: number[]) { const f = shouldStoreUserMessage(text, this.config); if (!f.store) return { stored: false, reason: f.reason }; const result = await storeMemoryWithDeduplication(this.db, f.textToStore, embedding, getPrimaryMemoryType(f.textToStore), 'user', this.config); if (++this.insertCount % 50 === 0) await this.evict(); return { stored: result.operation !== 'NOOP', operation: result.operation }; } async storeAssistantReply(reply: string) { const c = await processAssistantForMemory(reply, this.embedFn); if (!c) return { stored: false }; const r = await storeMemoryWithDeduplication(this.db, c.text, c.embedding, c.type, c.source, this.config); return { stored: r.operation !== 'NOOP', operation: r.operation }; } async evict() { return evictLowHeatMemories(this.db, this.config); } } export * from './types'; export { cosineSimilarity } from './deduplication'; export { computeDecayFactor, computeHeatScore } from './memoryDecay'; export { routeToMemoryType, getPrimaryMemoryType, formatMemoriesByType } from './typedMemory'; export { shouldStoreAssistantMessage, extractAssistantMemory } from './assistantMemory'; export { scoreMessageForMemory, shouldStoreUserMessage, classifyMessageIntent } from './smartFilter'; export { computeRetrievalParams, estimateQueryComplexity, inferRelevantMemoryTypes } from './dynamicRetrieval';