claude-cortex 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +291 -0
  2. package/dist/api/events.d.ts +134 -0
  3. package/dist/api/events.d.ts.map +1 -0
  4. package/dist/api/events.js +73 -0
  5. package/dist/api/events.js.map +1 -0
  6. package/dist/api/visualization-server.d.ts +11 -0
  7. package/dist/api/visualization-server.d.ts.map +1 -0
  8. package/dist/api/visualization-server.js +653 -0
  9. package/dist/api/visualization-server.js.map +1 -0
  10. package/dist/context/project-context.d.ts +57 -0
  11. package/dist/context/project-context.d.ts.map +1 -0
  12. package/dist/context/project-context.js +135 -0
  13. package/dist/context/project-context.js.map +1 -0
  14. package/dist/database/init.d.ts +49 -0
  15. package/dist/database/init.d.ts.map +1 -0
  16. package/dist/database/init.js +336 -0
  17. package/dist/database/init.js.map +1 -0
  18. package/dist/embeddings/generator.d.ts +20 -0
  19. package/dist/embeddings/generator.d.ts.map +1 -0
  20. package/dist/embeddings/generator.js +77 -0
  21. package/dist/embeddings/generator.js.map +1 -0
  22. package/dist/embeddings/index.d.ts +2 -0
  23. package/dist/embeddings/index.d.ts.map +1 -0
  24. package/dist/embeddings/index.js +2 -0
  25. package/dist/embeddings/index.js.map +1 -0
  26. package/dist/errors.d.ts +74 -0
  27. package/dist/errors.d.ts.map +1 -0
  28. package/dist/errors.js +131 -0
  29. package/dist/errors.js.map +1 -0
  30. package/dist/index.d.ts +16 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +83 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/memory/activation.d.ts +69 -0
  35. package/dist/memory/activation.d.ts.map +1 -0
  36. package/dist/memory/activation.js +168 -0
  37. package/dist/memory/activation.js.map +1 -0
  38. package/dist/memory/consolidate.d.ts +96 -0
  39. package/dist/memory/consolidate.d.ts.map +1 -0
  40. package/dist/memory/consolidate.js +400 -0
  41. package/dist/memory/consolidate.js.map +1 -0
  42. package/dist/memory/contradiction.d.ts +69 -0
  43. package/dist/memory/contradiction.d.ts.map +1 -0
  44. package/dist/memory/contradiction.js +286 -0
  45. package/dist/memory/contradiction.js.map +1 -0
  46. package/dist/memory/decay.d.ts +62 -0
  47. package/dist/memory/decay.d.ts.map +1 -0
  48. package/dist/memory/decay.js +184 -0
  49. package/dist/memory/decay.js.map +1 -0
  50. package/dist/memory/salience.d.ts +36 -0
  51. package/dist/memory/salience.d.ts.map +1 -0
  52. package/dist/memory/salience.js +200 -0
  53. package/dist/memory/salience.js.map +1 -0
  54. package/dist/memory/similarity.d.ts +57 -0
  55. package/dist/memory/similarity.d.ts.map +1 -0
  56. package/dist/memory/similarity.js +114 -0
  57. package/dist/memory/similarity.js.map +1 -0
  58. package/dist/memory/store.d.ts +170 -0
  59. package/dist/memory/store.d.ts.map +1 -0
  60. package/dist/memory/store.js +973 -0
  61. package/dist/memory/store.js.map +1 -0
  62. package/dist/memory/types.d.ts +91 -0
  63. package/dist/memory/types.d.ts.map +1 -0
  64. package/dist/memory/types.js +30 -0
  65. package/dist/memory/types.js.map +1 -0
  66. package/dist/server.d.ts +12 -0
  67. package/dist/server.d.ts.map +1 -0
  68. package/dist/server.js +466 -0
  69. package/dist/server.js.map +1 -0
  70. package/dist/tools/context.d.ts +135 -0
  71. package/dist/tools/context.d.ts.map +1 -0
  72. package/dist/tools/context.js +273 -0
  73. package/dist/tools/context.js.map +1 -0
  74. package/dist/tools/forget.d.ts +53 -0
  75. package/dist/tools/forget.d.ts.map +1 -0
  76. package/dist/tools/forget.js +179 -0
  77. package/dist/tools/forget.js.map +1 -0
  78. package/dist/tools/recall.d.ts +74 -0
  79. package/dist/tools/recall.d.ts.map +1 -0
  80. package/dist/tools/recall.js +140 -0
  81. package/dist/tools/recall.js.map +1 -0
  82. package/dist/tools/remember.d.ts +65 -0
  83. package/dist/tools/remember.d.ts.map +1 -0
  84. package/dist/tools/remember.js +147 -0
  85. package/dist/tools/remember.js.map +1 -0
  86. package/dist/worker/brain-worker.d.ts +100 -0
  87. package/dist/worker/brain-worker.d.ts.map +1 -0
  88. package/dist/worker/brain-worker.js +261 -0
  89. package/dist/worker/brain-worker.js.map +1 -0
  90. package/dist/worker/link-discovery.d.ts +47 -0
  91. package/dist/worker/link-discovery.d.ts.map +1 -0
  92. package/dist/worker/link-discovery.js +103 -0
  93. package/dist/worker/link-discovery.js.map +1 -0
  94. package/dist/worker/predictive-consolidation.d.ts +46 -0
  95. package/dist/worker/predictive-consolidation.d.ts.map +1 -0
  96. package/dist/worker/predictive-consolidation.js +110 -0
  97. package/dist/worker/predictive-consolidation.js.map +1 -0
  98. package/dist/worker/types.d.ts +91 -0
  99. package/dist/worker/types.d.ts.map +1 -0
  100. package/dist/worker/types.js +22 -0
  101. package/dist/worker/types.js.map +1 -0
  102. package/package.json +59 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Spreading Activation System
3
+ *
4
+ * Implements brain-like spreading activation where accessing a memory
5
+ * "primes" related memories, making them easier to recall.
6
+ *
7
+ * EPHEMERAL: This cache is session-only and does not persist to disk.
8
+ * Each MCP server restart starts with a fresh activation state.
9
+ *
10
+ * Based on spreading activation theory in cognitive psychology:
11
+ * - Collins & Loftus (1975) semantic network model
12
+ * - Activation spreads through associative links
13
+ * - Activation decays over time (exponential decay)
14
+ */
15
+ import { getRelatedMemories } from './store.js';
16
+ /**
17
+ * In-memory activation cache
18
+ * Ephemeral - cleared on process restart
19
+ */
20
+ const activationCache = new Map();
21
+ // Configuration
22
+ const DECAY_HALF_LIFE_MINUTES = 30; // Activation halves every 30 minutes
23
+ const SPREAD_FACTOR = 0.5; // How much activation spreads (50% of link strength)
24
+ const MAX_SPREAD_DEPTH = 1; // Only spread to direct neighbors (not neighbors of neighbors)
25
+ const MAX_ACTIVATION_BOOST = 0.2; // Cap search boost at 20%
26
+ /**
27
+ * Activate a memory and spread activation to linked memories
28
+ *
29
+ * When a memory is accessed, it becomes fully activated (1.0).
30
+ * Linked memories receive partial activation based on link strength.
31
+ *
32
+ * @param memoryId - The ID of the memory being accessed
33
+ */
34
+ export function activateMemory(memoryId) {
35
+ const now = Date.now();
36
+ // Fully activate the accessed memory
37
+ activationCache.set(memoryId, {
38
+ memoryId,
39
+ activationLevel: 1.0,
40
+ timestamp: now,
41
+ });
42
+ // Spread activation to linked memories
43
+ try {
44
+ const related = getRelatedMemories(memoryId);
45
+ for (const link of related) {
46
+ // Calculate spread amount: link strength * spread factor
47
+ const spreadAmount = link.strength * SPREAD_FACTOR;
48
+ // Get existing activation (if any)
49
+ const existing = activationCache.get(link.memory.id);
50
+ const existingLevel = existing
51
+ ? getDecayedActivation(existing, now)
52
+ : 0;
53
+ // Add activation (cap at 1.0)
54
+ const newLevel = Math.min(1.0, existingLevel + spreadAmount);
55
+ activationCache.set(link.memory.id, {
56
+ memoryId: link.memory.id,
57
+ activationLevel: newLevel,
58
+ timestamp: now,
59
+ });
60
+ }
61
+ }
62
+ catch (e) {
63
+ // Don't fail memory access if spreading fails
64
+ console.error('[claude-cortex] Activation spreading failed:', e);
65
+ }
66
+ }
67
+ /**
68
+ * Calculate decayed activation level
69
+ *
70
+ * Uses exponential decay: level * 0.5^(minutes / half_life)
71
+ */
72
+ function getDecayedActivation(entry, now) {
73
+ const ageMinutes = (now - entry.timestamp) / (1000 * 60);
74
+ const decayFactor = Math.pow(0.5, ageMinutes / DECAY_HALF_LIFE_MINUTES);
75
+ return entry.activationLevel * decayFactor;
76
+ }
77
+ /**
78
+ * Get the activation boost for a memory in search scoring
79
+ *
80
+ * Returns 0 if memory is not activated or activation has fully decayed.
81
+ * Returns up to MAX_ACTIVATION_BOOST for fully activated memories.
82
+ *
83
+ * @param memoryId - The ID of the memory to check
84
+ * @returns Activation boost (0 to MAX_ACTIVATION_BOOST)
85
+ */
86
+ export function getActivationBoost(memoryId) {
87
+ const entry = activationCache.get(memoryId);
88
+ if (!entry)
89
+ return 0;
90
+ const now = Date.now();
91
+ const decayedLevel = getDecayedActivation(entry, now);
92
+ // If activation is negligible, clean up the entry
93
+ if (decayedLevel < 0.01) {
94
+ activationCache.delete(memoryId);
95
+ return 0;
96
+ }
97
+ // Scale to max boost (e.g., 1.0 activation -> 0.2 boost)
98
+ return decayedLevel * MAX_ACTIVATION_BOOST;
99
+ }
100
+ /**
101
+ * Get current activation level for a memory (for debugging/dashboard)
102
+ *
103
+ * @param memoryId - The ID of the memory to check
104
+ * @returns Current activation level (0-1) or null if not activated
105
+ */
106
+ export function getActivationLevel(memoryId) {
107
+ const entry = activationCache.get(memoryId);
108
+ if (!entry)
109
+ return null;
110
+ const decayedLevel = getDecayedActivation(entry, Date.now());
111
+ if (decayedLevel < 0.01)
112
+ return null;
113
+ return decayedLevel;
114
+ }
115
+ /**
116
+ * Get all currently activated memories with their levels
117
+ * Useful for dashboard visualization
118
+ *
119
+ * @returns Array of {memoryId, activationLevel} for all activated memories
120
+ */
121
+ export function getActiveMemories() {
122
+ const now = Date.now();
123
+ const active = [];
124
+ for (const entry of activationCache.values()) {
125
+ const level = getDecayedActivation(entry, now);
126
+ if (level >= 0.01) {
127
+ active.push({ memoryId: entry.memoryId, activationLevel: level });
128
+ }
129
+ }
130
+ return active.sort((a, b) => b.activationLevel - a.activationLevel);
131
+ }
132
+ /**
133
+ * Clear the activation cache
134
+ * Useful for testing or manual reset
135
+ */
136
+ export function clearActivationCache() {
137
+ activationCache.clear();
138
+ }
139
+ /**
140
+ * Prune stale entries from the activation cache
141
+ * Call periodically to prevent memory bloat
142
+ */
143
+ export function pruneActivationCache() {
144
+ const now = Date.now();
145
+ let pruned = 0;
146
+ for (const [memoryId, entry] of activationCache) {
147
+ if (getDecayedActivation(entry, now) < 0.01) {
148
+ activationCache.delete(memoryId);
149
+ pruned++;
150
+ }
151
+ }
152
+ return pruned;
153
+ }
154
+ /**
155
+ * Get activation cache statistics
156
+ */
157
+ export function getActivationStats() {
158
+ const active = getActiveMemories();
159
+ const avgActivation = active.length > 0
160
+ ? active.reduce((sum, a) => sum + a.activationLevel, 0) / active.length
161
+ : 0;
162
+ return {
163
+ totalEntries: activationCache.size,
164
+ activeEntries: active.length,
165
+ averageActivation: avgActivation,
166
+ };
167
+ }
168
+ //# sourceMappingURL=activation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activation.js","sourceRoot":"","sources":["../../src/memory/activation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Memory Consolidation System
3
+ *
4
+ * Like sleep consolidation in human brains, this system:
5
+ * - Moves worthy short-term memories to long-term storage
6
+ * - Strengthens frequently accessed memories
7
+ * - Cleans up decayed/irrelevant memories
8
+ * - Merges similar memories to reduce redundancy
9
+ */
10
+ import { Memory, MemoryConfig, ConsolidationResult, ContextSummary } from './types.js';
11
+ /**
12
+ * Run full consolidation process
13
+ * This is like the brain's sleep consolidation - should be run periodically
14
+ */
15
+ export declare function consolidate(config?: MemoryConfig): ConsolidationResult;
16
+ /**
17
+ * Enforce maximum memory limits
18
+ * Removes lowest-priority memories when limits are exceeded
19
+ */
20
+ export declare function enforceMemoryLimits(config?: MemoryConfig): number;
21
+ /**
22
+ * Find and merge similar memories
23
+ * Reduces redundancy while preserving important information
24
+ */
25
+ export declare function mergeSimilarMemories(project?: string, similarityThreshold?: number): number;
26
+ /**
27
+ * Generate a context summary for session start
28
+ * Provides a high-level view of relevant memories
29
+ */
30
+ export declare function generateContextSummary(project?: string, config?: MemoryConfig): Promise<ContextSummary>;
31
+ /**
32
+ * Format context summary as a readable string
33
+ */
34
+ export declare function formatContextSummary(summary: ContextSummary): string;
35
+ /**
36
+ * Start a new session
37
+ * Creates a session record and returns relevant context
38
+ */
39
+ export declare function startSession(project?: string): Promise<{
40
+ sessionId: number;
41
+ context: ContextSummary;
42
+ }>;
43
+ /**
44
+ * End a session
45
+ * Updates session record with summary
46
+ */
47
+ export declare function endSession(sessionId: number, summary?: string): void;
48
+ /**
49
+ * Get suggested context for the current query
50
+ * Returns memories that might be relevant to what the user is working on
51
+ */
52
+ export declare function getSuggestedContext(currentContext: string, project?: string, limit?: number): Promise<Memory[]>;
53
+ /**
54
+ * Export memories as JSON (for backup/transfer)
55
+ */
56
+ export declare function exportMemories(project?: string): string;
57
+ /**
58
+ * Import memories from JSON
59
+ */
60
+ export declare function importMemories(json: string): number;
61
+ /**
62
+ * Vacuum database to reclaim space after deletions
63
+ * Run periodically or after major cleanup operations
64
+ */
65
+ export declare function vacuumDatabase(): {
66
+ success: boolean;
67
+ message: string;
68
+ };
69
+ /**
70
+ * Preview what consolidation would do without actually doing it
71
+ * Useful for dry-run mode
72
+ */
73
+ export declare function previewConsolidation(config?: MemoryConfig): {
74
+ toPromote: Memory[];
75
+ toDelete: Memory[];
76
+ totalShortTerm: number;
77
+ totalLongTerm: number;
78
+ };
79
+ /**
80
+ * Check if consolidation should be triggered based on memory state
81
+ * Returns true if consolidation is recommended
82
+ */
83
+ export declare function shouldTriggerConsolidation(config?: MemoryConfig): {
84
+ shouldRun: boolean;
85
+ reason: string;
86
+ };
87
+ /**
88
+ * Full cleanup: consolidate + vacuum
89
+ * Best run periodically to keep database healthy
90
+ */
91
+ export declare function fullCleanup(config?: MemoryConfig): {
92
+ consolidation: ConsolidationResult;
93
+ vacuumed: boolean;
94
+ merged: number;
95
+ };
96
+ //# sourceMappingURL=consolidate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../../src/memory/consolidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,MAAM,EACN,YAAY,EAEZ,mBAAmB,EACnB,cAAc,EACf,MAAM,YAAY,CAAC;AAuBpB;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,GAAE,YAA6B,GACpC,mBAAmB,CA0DrB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,YAA6B,GAAG,MAAM,CA+CjF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,CAAC,EAAE,MAAM,EAChB,mBAAmB,GAAE,MAAY,GAChC,MAAM,CA6CR;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,GAAE,YAA6B,GACpC,OAAO,CAAC,cAAc,CAAC,CAqCzB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAuCpE;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,cAAc,CAAC;CACzB,CAAC,CAcD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAwBN;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,MAAM,EAChB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAWnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAavD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgCnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAQtE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,GAAE,YAA6B,GACpC;IACD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB,CA8BA;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,GAAE,YAA6B,GACpC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA2BxC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,MAAM,GAAE,YAA6B,GACpC;IAAE,aAAa,EAAE,mBAAmB,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAe3E"}
@@ -0,0 +1,400 @@
1
+ /**
2
+ * Memory Consolidation System
3
+ *
4
+ * Like sleep consolidation in human brains, this system:
5
+ * - Moves worthy short-term memories to long-term storage
6
+ * - Strengthens frequently accessed memories
7
+ * - Cleans up decayed/irrelevant memories
8
+ * - Merges similar memories to reduce redundancy
9
+ */
10
+ import { getDatabase, withTransaction } from '../database/init.js';
11
+ import { DEFAULT_CONFIG, } from './types.js';
12
+ import { getMemoriesByType, getRecentMemories, promoteMemory, deleteMemory, searchMemories, getMemoryStats, updateDecayScores, } from './store.js';
13
+ import { processDecay, } from './decay.js';
14
+ import { detectContradictions, linkContradictions, } from './contradiction.js';
15
+ /**
16
+ * Run full consolidation process
17
+ * This is like the brain's sleep consolidation - should be run periodically
18
+ */
19
+ export function consolidate(config = DEFAULT_CONFIG) {
20
+ // Wrap entire consolidation in a transaction for atomicity
21
+ return withTransaction(() => {
22
+ const db = getDatabase();
23
+ let consolidated = 0;
24
+ let decayed = 0;
25
+ let deleted = 0;
26
+ // Get all short-term memories
27
+ const shortTermMemories = getMemoriesByType('short_term', config.maxShortTermMemories * 2);
28
+ // Process decay for all memories
29
+ const { toDelete, toPromote, updated } = processDecay(shortTermMemories, config);
30
+ // Promote worthy memories
31
+ for (const id of toPromote) {
32
+ promoteMemory(id);
33
+ consolidated++;
34
+ }
35
+ // Delete decayed memories (excluding those just promoted)
36
+ for (const id of toDelete) {
37
+ if (!toPromote.includes(id)) {
38
+ deleteMemory(id);
39
+ deleted++;
40
+ }
41
+ }
42
+ // Update decayed scores in database
43
+ const updateStmt = db.prepare('UPDATE memories SET salience = ? WHERE id = ?');
44
+ for (const [id, score] of updated) {
45
+ if (!toDelete.includes(id)) {
46
+ updateStmt.run(score, id);
47
+ decayed++;
48
+ }
49
+ }
50
+ // Enforce memory limits
51
+ deleted += enforceMemoryLimits(config);
52
+ // Persist updated decay scores for efficient sorting
53
+ updateDecayScores();
54
+ // ORGANIC FEATURE: Contradiction Detection (Phase 3)
55
+ // Detect and link contradicting memories during consolidation
56
+ let contradictionsFound = 0;
57
+ let contradictionsLinked = 0;
58
+ try {
59
+ const contradictions = detectContradictions({ minScore: 0.5, limit: 50 });
60
+ contradictionsFound = contradictions.length;
61
+ contradictionsLinked = linkContradictions(contradictions);
62
+ }
63
+ catch (e) {
64
+ console.error('[claude-cortex] Contradiction detection failed:', e);
65
+ }
66
+ return { consolidated, decayed, deleted, contradictionsFound, contradictionsLinked };
67
+ });
68
+ }
69
+ /**
70
+ * Enforce maximum memory limits
71
+ * Removes lowest-priority memories when limits are exceeded
72
+ */
73
+ export function enforceMemoryLimits(config = DEFAULT_CONFIG) {
74
+ // Note: If called within consolidate(), this is already in a transaction
75
+ // If called standalone, we wrap it for safety
76
+ const db = getDatabase();
77
+ let deleted = 0;
78
+ // Check short-term memory limit
79
+ const shortTermCount = db.prepare("SELECT COUNT(*) as count FROM memories WHERE type = 'short_term'").get().count;
80
+ if (shortTermCount > config.maxShortTermMemories) {
81
+ const toRemove = shortTermCount - config.maxShortTermMemories;
82
+ const lowPriority = db.prepare(`
83
+ SELECT id FROM memories
84
+ WHERE type = 'short_term'
85
+ ORDER BY salience ASC, last_accessed ASC
86
+ LIMIT ?
87
+ `).all(toRemove);
88
+ for (const { id } of lowPriority) {
89
+ deleteMemory(id);
90
+ deleted++;
91
+ }
92
+ }
93
+ // Check long-term memory limit (more lenient)
94
+ const longTermCount = db.prepare("SELECT COUNT(*) as count FROM memories WHERE type = 'long_term'").get().count;
95
+ if (longTermCount > config.maxLongTermMemories) {
96
+ const toRemove = longTermCount - config.maxLongTermMemories;
97
+ const lowPriority = db.prepare(`
98
+ SELECT id FROM memories
99
+ WHERE type = 'long_term'
100
+ ORDER BY salience ASC, access_count ASC, last_accessed ASC
101
+ LIMIT ?
102
+ `).all(toRemove);
103
+ for (const { id } of lowPriority) {
104
+ deleteMemory(id);
105
+ deleted++;
106
+ }
107
+ }
108
+ return deleted;
109
+ }
110
+ /**
111
+ * Find and merge similar memories
112
+ * Reduces redundancy while preserving important information
113
+ */
114
+ export function mergeSimilarMemories(project, similarityThreshold = 0.8) {
115
+ // Wrap in transaction for atomic merge operations
116
+ return withTransaction(() => {
117
+ const db = getDatabase();
118
+ let merged = 0;
119
+ // Get all memories (optionally filtered by project)
120
+ let sql = 'SELECT * FROM memories';
121
+ const params = [];
122
+ if (project) {
123
+ sql += ' WHERE project = ?';
124
+ params.push(project);
125
+ }
126
+ sql += ' ORDER BY created_at ASC';
127
+ const memories = db.prepare(sql).all(...params);
128
+ // Simple similarity check based on title and first 100 chars of content
129
+ const seen = new Map(); // key -> id of primary memory
130
+ for (const row of memories) {
131
+ const key = `${row.title.toLowerCase().trim()}|${row.content.slice(0, 100).toLowerCase()}`;
132
+ if (seen.has(key)) {
133
+ // This is a duplicate, merge into the primary
134
+ const primaryId = seen.get(key);
135
+ // Boost the primary memory's salience
136
+ db.prepare(`
137
+ UPDATE memories
138
+ SET salience = MIN(1.0, salience + 0.1),
139
+ access_count = access_count + 1
140
+ WHERE id = ?
141
+ `).run(primaryId);
142
+ // Delete the duplicate
143
+ deleteMemory(row.id);
144
+ merged++;
145
+ }
146
+ else {
147
+ seen.set(key, row.id);
148
+ }
149
+ }
150
+ return merged;
151
+ });
152
+ }
153
+ /**
154
+ * Generate a context summary for session start
155
+ * Provides a high-level view of relevant memories
156
+ */
157
+ export async function generateContextSummary(project, config = DEFAULT_CONFIG) {
158
+ // Get recent memories
159
+ const recentMemories = getRecentMemories(10, project);
160
+ // Get key architecture decisions
161
+ const keyDecisions = (await searchMemories({
162
+ query: '',
163
+ project,
164
+ category: 'architecture',
165
+ minSalience: 0.6,
166
+ limit: 5,
167
+ }, config)).map(r => r.memory);
168
+ // Get active patterns
169
+ const activePatterns = (await searchMemories({
170
+ query: '',
171
+ project,
172
+ category: 'pattern',
173
+ minSalience: 0.5,
174
+ limit: 5,
175
+ }, config)).map(r => r.memory);
176
+ // Get pending items
177
+ const pendingItems = (await searchMemories({
178
+ query: '',
179
+ project,
180
+ category: 'todo',
181
+ limit: 10,
182
+ }, config)).map(r => r.memory);
183
+ return {
184
+ project,
185
+ recentMemories,
186
+ keyDecisions,
187
+ activePatterns,
188
+ pendingItems,
189
+ };
190
+ }
191
+ /**
192
+ * Format context summary as a readable string
193
+ */
194
+ export function formatContextSummary(summary) {
195
+ const lines = [];
196
+ if (summary.project) {
197
+ lines.push(`## Project: ${summary.project}\n`);
198
+ }
199
+ if (summary.keyDecisions.length > 0) {
200
+ lines.push('### Key Decisions');
201
+ for (const memory of summary.keyDecisions) {
202
+ lines.push(`- **${memory.title}**: ${memory.content.slice(0, 100)}${memory.content.length > 100 ? '...' : ''}`);
203
+ }
204
+ lines.push('');
205
+ }
206
+ if (summary.activePatterns.length > 0) {
207
+ lines.push('### Active Patterns');
208
+ for (const memory of summary.activePatterns) {
209
+ lines.push(`- **${memory.title}**: ${memory.content.slice(0, 100)}${memory.content.length > 100 ? '...' : ''}`);
210
+ }
211
+ lines.push('');
212
+ }
213
+ if (summary.pendingItems.length > 0) {
214
+ lines.push('### Pending Items');
215
+ for (const memory of summary.pendingItems) {
216
+ lines.push(`- [ ] ${memory.title}`);
217
+ }
218
+ lines.push('');
219
+ }
220
+ if (summary.recentMemories.length > 0) {
221
+ lines.push('### Recent Context');
222
+ for (const memory of summary.recentMemories.slice(0, 5)) {
223
+ lines.push(`- ${memory.title} (${memory.category})`);
224
+ }
225
+ }
226
+ return lines.join('\n');
227
+ }
228
+ /**
229
+ * Start a new session
230
+ * Creates a session record and returns relevant context
231
+ */
232
+ export async function startSession(project) {
233
+ const db = getDatabase();
234
+ // Create session record
235
+ const result = db.prepare(`
236
+ INSERT INTO sessions (project) VALUES (?)
237
+ `).run(project || null);
238
+ const sessionId = result.lastInsertRowid;
239
+ // Generate context summary
240
+ const context = await generateContextSummary(project);
241
+ return { sessionId, context };
242
+ }
243
+ /**
244
+ * End a session
245
+ * Updates session record with summary
246
+ */
247
+ export function endSession(sessionId, summary) {
248
+ const db = getDatabase();
249
+ // Get counts from this session
250
+ const stats = db.prepare(`
251
+ SELECT
252
+ (SELECT COUNT(*) FROM memories WHERE created_at >= s.started_at) as created,
253
+ (SELECT COUNT(*) FROM memories WHERE last_accessed >= s.started_at) as accessed
254
+ FROM sessions s WHERE s.id = ?
255
+ `).get(sessionId);
256
+ db.prepare(`
257
+ UPDATE sessions
258
+ SET ended_at = CURRENT_TIMESTAMP,
259
+ summary = ?,
260
+ memories_created = ?,
261
+ memories_accessed = ?
262
+ WHERE id = ?
263
+ `).run(summary || null, stats?.created || 0, stats?.accessed || 0, sessionId);
264
+ }
265
+ /**
266
+ * Get suggested context for the current query
267
+ * Returns memories that might be relevant to what the user is working on
268
+ */
269
+ export async function getSuggestedContext(currentContext, project, limit = 5) {
270
+ // Search for relevant memories based on current context
271
+ const results = await searchMemories({
272
+ query: currentContext,
273
+ project,
274
+ minSalience: 0.4,
275
+ limit,
276
+ includeDecayed: false,
277
+ });
278
+ return results.map(r => r.memory);
279
+ }
280
+ /**
281
+ * Export memories as JSON (for backup/transfer)
282
+ */
283
+ export function exportMemories(project) {
284
+ const db = getDatabase();
285
+ let sql = 'SELECT * FROM memories';
286
+ const params = [];
287
+ if (project) {
288
+ sql += ' WHERE project = ?';
289
+ params.push(project);
290
+ }
291
+ sql += ' ORDER BY created_at ASC';
292
+ const rows = db.prepare(sql).all(...params);
293
+ return JSON.stringify(rows, null, 2);
294
+ }
295
+ /**
296
+ * Import memories from JSON
297
+ */
298
+ export function importMemories(json) {
299
+ // Wrap in transaction for atomic import
300
+ return withTransaction(() => {
301
+ const db = getDatabase();
302
+ const memories = JSON.parse(json);
303
+ const stmt = db.prepare(`
304
+ INSERT INTO memories (type, category, title, content, project, tags, salience, metadata)
305
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
306
+ `);
307
+ let imported = 0;
308
+ for (const memory of memories) {
309
+ try {
310
+ stmt.run(memory.type, memory.category, memory.title, memory.content, memory.project || null, memory.tags || '[]', memory.salience || 0.5, memory.metadata || '{}');
311
+ imported++;
312
+ }
313
+ catch {
314
+ // Skip duplicates or invalid entries
315
+ }
316
+ }
317
+ return imported;
318
+ });
319
+ }
320
+ /**
321
+ * Vacuum database to reclaim space after deletions
322
+ * Run periodically or after major cleanup operations
323
+ */
324
+ export function vacuumDatabase() {
325
+ try {
326
+ const db = getDatabase();
327
+ db.exec('VACUUM');
328
+ return { success: true, message: 'Database vacuumed successfully' };
329
+ }
330
+ catch (error) {
331
+ return { success: false, message: `Vacuum failed: ${error}` };
332
+ }
333
+ }
334
+ /**
335
+ * Preview what consolidation would do without actually doing it
336
+ * Useful for dry-run mode
337
+ */
338
+ export function previewConsolidation(config = DEFAULT_CONFIG) {
339
+ const db = getDatabase();
340
+ // Get all short-term memories
341
+ const shortTermMemories = getMemoriesByType('short_term', config.maxShortTermMemories * 2);
342
+ // Get episodic memories too
343
+ const episodicMemories = getMemoriesByType('episodic', 100);
344
+ // Process decay to see what would happen
345
+ const { toDelete: deleteIds, toPromote: promoteIds } = processDecay([...shortTermMemories, ...episodicMemories], config);
346
+ // Map IDs back to memories
347
+ const allMemories = [...shortTermMemories, ...episodicMemories];
348
+ const toPromote = allMemories.filter(m => promoteIds.includes(m.id));
349
+ const toDelete = allMemories.filter(m => deleteIds.includes(m.id) && !promoteIds.includes(m.id));
350
+ // Get counts
351
+ const totalShortTerm = db.prepare("SELECT COUNT(*) as count FROM memories WHERE type = 'short_term'").get().count;
352
+ const totalLongTerm = db.prepare("SELECT COUNT(*) as count FROM memories WHERE type = 'long_term'").get().count;
353
+ return { toPromote, toDelete, totalShortTerm, totalLongTerm };
354
+ }
355
+ /**
356
+ * Check if consolidation should be triggered based on memory state
357
+ * Returns true if consolidation is recommended
358
+ */
359
+ export function shouldTriggerConsolidation(config = DEFAULT_CONFIG) {
360
+ const stats = getMemoryStats();
361
+ const stmFullness = stats.shortTerm / config.maxShortTermMemories;
362
+ // Trigger early when approaching capacity
363
+ if (stmFullness > 0.8) {
364
+ return {
365
+ shouldRun: true,
366
+ reason: `Short-term memory at ${Math.round(stmFullness * 100)}% capacity`,
367
+ };
368
+ }
369
+ // Check if many memories are below threshold
370
+ const db = getDatabase();
371
+ const lowScoreCount = db.prepare(`
372
+ SELECT COUNT(*) as count FROM memories
373
+ WHERE type = 'short_term' AND decayed_score < ?
374
+ `).get(config.salienceThreshold).count;
375
+ if (lowScoreCount > 10) {
376
+ return {
377
+ shouldRun: true,
378
+ reason: `${lowScoreCount} memories below salience threshold`,
379
+ };
380
+ }
381
+ return { shouldRun: false, reason: 'No consolidation needed' };
382
+ }
383
+ /**
384
+ * Full cleanup: consolidate + vacuum
385
+ * Best run periodically to keep database healthy
386
+ */
387
+ export function fullCleanup(config = DEFAULT_CONFIG) {
388
+ // Run consolidation
389
+ const consolidation = consolidate(config);
390
+ // Merge similar memories
391
+ const merged = mergeSimilarMemories();
392
+ // Vacuum if we deleted anything
393
+ let vacuumed = false;
394
+ if (consolidation.deleted > 0 || merged > 0) {
395
+ const vacResult = vacuumDatabase();
396
+ vacuumed = vacResult.success;
397
+ }
398
+ return { consolidation, vacuumed, merged };
399
+ }
400
+ //# sourceMappingURL=consolidate.js.map