File size: 3,600 Bytes
1a772d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// ============================================================
// 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<string, unknown>;
}

/**
 * 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)
  ],
};