// ============================================================ // TYPES — Memory system type definitions // ============================================================ /** * Memory types following ENGRAM's categorization (arxiv 2511.12960): * - episodic: Events that happened ("We discussed X on Tuesday") * - semantic: Stable facts/preferences ("User is allergic to peanuts") * - procedural: Instructions/workflows ("Always format code with black") */ export type MemoryType = 'episodic' | 'semantic' | 'procedural'; /** * Source of the memory — who said it */ export type MemorySource = 'user' | 'assistant'; /** * Memory record stored in SQLite */ export interface MemoryRecord { id: string; text: string; embedding: number[]; // float32 vector from embedding model type: MemoryType; // ENGRAM-style typed classification source: MemorySource; // who said this createdAt: number; // Unix timestamp (ms) lastAccessedAt: number; // For decay calculation accessCount: number; // Heat score (MemoryOS-style) importance: number; // 0-1 importance score conversationId?: string; // Which conversation this came from metadata?: Record; } /** * Retrieved memory with computed relevance score */ export interface ScoredMemory extends MemoryRecord { cosineSimilarity: number; // Raw cosine similarity decayedScore: number; // After time-decay weighting finalScore: number; // Combined relevance score } /** * Memory operation (Mem0-style ADD/UPDATE/DELETE/NOOP) */ export type MemoryOperation = 'ADD' | 'UPDATE' | 'DELETE' | 'NOOP'; /** * Result of the deduplication check */ export interface DeduplicationResult { operation: MemoryOperation; existingMemoryId?: string; // ID of the memory to update/delete mergedText?: string; // New text if merging } /** * Configuration for the improved memory system */ export interface MemoryConfig { // Deduplication deduplicationThreshold: number; // Cosine sim above this = duplicate (default: 0.85) mergeThreshold: number; // Between this and dedup = merge (default: 0.70) // Decay decayHalfLifeHours: number; // Time for memory relevance to halve (default: 168 = 1 week) minDecayFactor: number; // Floor for decay (default: 0.3 — never fully forgotten) // Retrieval defaultTopK: number; // Default number of memories to retrieve (default: 7) minSimilarityThreshold: number; // Minimum cosine similarity (default: 0.40) maxContextTokens: number; // Max tokens budget for injected memories (default: 300) // Storage maxMemories: number; // Max total memories before eviction (default: 500) evictionBatchSize: number; // How many to evict at once (default: 50) // Smart filtering minMessageLength: number; // Skip messages shorter than this (default: 15 chars) skipPatterns: RegExp[]; // Patterns to always skip } /** * Default configuration */ export const DEFAULT_MEMORY_CONFIG: MemoryConfig = { deduplicationThreshold: 0.85, mergeThreshold: 0.70, decayHalfLifeHours: 168, // 1 week minDecayFactor: 0.3, defaultTopK: 7, minSimilarityThreshold: 0.40, maxContextTokens: 300, maxMemories: 500, evictionBatchSize: 50, minMessageLength: 15, skipPatterns: [ /^(hi|hey|hello|yo|sup|ok|okay|yes|no|yeah|nah|sure|thanks|ty|thx|lol|haha|hmm|brb|gtg|bye|gn|gm)[\s!.?]*$/i, /^[^a-zA-Z]*$/, // Only emojis/symbols /^.{1,5}$/, // Very short (1-5 chars) ], };