@danielsimonjr/memory-mcp 0.47.1 → 9.8.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 (207) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +2000 -194
  3. package/dist/__tests__/file-path.test.js +5 -5
  4. package/dist/__tests__/knowledge-graph.test.js +3 -8
  5. package/dist/core/EntityManager.d.ts +266 -0
  6. package/dist/core/EntityManager.d.ts.map +1 -0
  7. package/dist/core/EntityManager.js +85 -133
  8. package/dist/core/GraphEventEmitter.d.ts +202 -0
  9. package/dist/core/GraphEventEmitter.d.ts.map +1 -0
  10. package/dist/core/GraphEventEmitter.js +346 -0
  11. package/dist/core/GraphStorage.d.ts +395 -0
  12. package/dist/core/GraphStorage.d.ts.map +1 -0
  13. package/dist/core/GraphStorage.js +643 -31
  14. package/dist/core/GraphTraversal.d.ts +141 -0
  15. package/dist/core/GraphTraversal.d.ts.map +1 -0
  16. package/dist/core/GraphTraversal.js +573 -0
  17. package/dist/core/HierarchyManager.d.ts +111 -0
  18. package/dist/core/HierarchyManager.d.ts.map +1 -0
  19. package/dist/{features → core}/HierarchyManager.js +14 -9
  20. package/dist/core/ManagerContext.d.ts +72 -0
  21. package/dist/core/ManagerContext.d.ts.map +1 -0
  22. package/dist/core/ManagerContext.js +118 -0
  23. package/dist/core/ObservationManager.d.ts +85 -0
  24. package/dist/core/ObservationManager.d.ts.map +1 -0
  25. package/dist/core/ObservationManager.js +51 -57
  26. package/dist/core/RelationManager.d.ts +131 -0
  27. package/dist/core/RelationManager.d.ts.map +1 -0
  28. package/dist/core/RelationManager.js +31 -7
  29. package/dist/core/SQLiteStorage.d.ts +354 -0
  30. package/dist/core/SQLiteStorage.d.ts.map +1 -0
  31. package/dist/core/SQLiteStorage.js +917 -0
  32. package/dist/core/StorageFactory.d.ts +45 -0
  33. package/dist/core/StorageFactory.d.ts.map +1 -0
  34. package/dist/core/StorageFactory.js +64 -0
  35. package/dist/core/TransactionManager.d.ts +464 -0
  36. package/dist/core/TransactionManager.d.ts.map +1 -0
  37. package/dist/core/TransactionManager.js +490 -13
  38. package/dist/core/index.d.ts +17 -0
  39. package/dist/core/index.d.ts.map +1 -0
  40. package/dist/core/index.js +12 -2
  41. package/dist/features/AnalyticsManager.d.ts +44 -0
  42. package/dist/features/AnalyticsManager.d.ts.map +1 -0
  43. package/dist/features/AnalyticsManager.js +14 -13
  44. package/dist/features/ArchiveManager.d.ts +133 -0
  45. package/dist/features/ArchiveManager.d.ts.map +1 -0
  46. package/dist/features/ArchiveManager.js +221 -14
  47. package/dist/features/CompressionManager.d.ts +117 -0
  48. package/dist/features/CompressionManager.d.ts.map +1 -0
  49. package/dist/features/CompressionManager.js +189 -20
  50. package/dist/features/IOManager.d.ts +225 -0
  51. package/dist/features/IOManager.d.ts.map +1 -0
  52. package/dist/features/IOManager.js +1041 -0
  53. package/dist/features/StreamingExporter.d.ts +123 -0
  54. package/dist/features/StreamingExporter.d.ts.map +1 -0
  55. package/dist/features/StreamingExporter.js +203 -0
  56. package/dist/features/TagManager.d.ts +147 -0
  57. package/dist/features/TagManager.d.ts.map +1 -0
  58. package/dist/features/index.d.ts +12 -0
  59. package/dist/features/index.d.ts.map +1 -0
  60. package/dist/features/index.js +5 -6
  61. package/dist/index.d.ts +9 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +12 -45
  64. package/dist/memory.jsonl +1 -18
  65. package/dist/search/BasicSearch.d.ts +51 -0
  66. package/dist/search/BasicSearch.d.ts.map +1 -0
  67. package/dist/search/BasicSearch.js +9 -3
  68. package/dist/search/BooleanSearch.d.ts +98 -0
  69. package/dist/search/BooleanSearch.d.ts.map +1 -0
  70. package/dist/search/BooleanSearch.js +156 -9
  71. package/dist/search/EmbeddingService.d.ts +178 -0
  72. package/dist/search/EmbeddingService.d.ts.map +1 -0
  73. package/dist/search/EmbeddingService.js +358 -0
  74. package/dist/search/FuzzySearch.d.ts +118 -0
  75. package/dist/search/FuzzySearch.d.ts.map +1 -0
  76. package/dist/search/FuzzySearch.js +241 -25
  77. package/dist/search/QueryCostEstimator.d.ts +111 -0
  78. package/dist/search/QueryCostEstimator.d.ts.map +1 -0
  79. package/dist/search/QueryCostEstimator.js +355 -0
  80. package/dist/search/RankedSearch.d.ts +71 -0
  81. package/dist/search/RankedSearch.d.ts.map +1 -0
  82. package/dist/search/RankedSearch.js +54 -6
  83. package/dist/search/SavedSearchManager.d.ts +79 -0
  84. package/dist/search/SavedSearchManager.d.ts.map +1 -0
  85. package/dist/search/SearchFilterChain.d.ts +120 -0
  86. package/dist/search/SearchFilterChain.d.ts.map +1 -0
  87. package/dist/search/SearchFilterChain.js +2 -4
  88. package/dist/search/SearchManager.d.ts +326 -0
  89. package/dist/search/SearchManager.d.ts.map +1 -0
  90. package/dist/search/SearchManager.js +148 -0
  91. package/dist/search/SearchSuggestions.d.ts +27 -0
  92. package/dist/search/SearchSuggestions.d.ts.map +1 -0
  93. package/dist/search/SearchSuggestions.js +1 -1
  94. package/dist/search/SemanticSearch.d.ts +149 -0
  95. package/dist/search/SemanticSearch.d.ts.map +1 -0
  96. package/dist/search/SemanticSearch.js +323 -0
  97. package/dist/search/TFIDFEventSync.d.ts +85 -0
  98. package/dist/search/TFIDFEventSync.d.ts.map +1 -0
  99. package/dist/search/TFIDFEventSync.js +133 -0
  100. package/dist/search/TFIDFIndexManager.d.ts +151 -0
  101. package/dist/search/TFIDFIndexManager.d.ts.map +1 -0
  102. package/dist/search/TFIDFIndexManager.js +232 -17
  103. package/dist/search/VectorStore.d.ts +235 -0
  104. package/dist/search/VectorStore.d.ts.map +1 -0
  105. package/dist/search/VectorStore.js +311 -0
  106. package/dist/search/index.d.ts +21 -0
  107. package/dist/search/index.d.ts.map +1 -0
  108. package/dist/search/index.js +12 -0
  109. package/dist/server/MCPServer.d.ts +21 -0
  110. package/dist/server/MCPServer.d.ts.map +1 -0
  111. package/dist/server/MCPServer.js +4 -4
  112. package/dist/server/responseCompressor.d.ts +94 -0
  113. package/dist/server/responseCompressor.d.ts.map +1 -0
  114. package/dist/server/responseCompressor.js +127 -0
  115. package/dist/server/toolDefinitions.d.ts +27 -0
  116. package/dist/server/toolDefinitions.d.ts.map +1 -0
  117. package/dist/server/toolDefinitions.js +189 -18
  118. package/dist/server/toolHandlers.d.ts +41 -0
  119. package/dist/server/toolHandlers.d.ts.map +1 -0
  120. package/dist/server/toolHandlers.js +467 -75
  121. package/dist/types/index.d.ts +13 -0
  122. package/dist/types/index.d.ts.map +1 -0
  123. package/dist/types/index.js +1 -1
  124. package/dist/types/types.d.ts +1654 -0
  125. package/dist/types/types.d.ts.map +1 -0
  126. package/dist/types/types.js +9 -0
  127. package/dist/utils/compressedCache.d.ts +192 -0
  128. package/dist/utils/compressedCache.d.ts.map +1 -0
  129. package/dist/utils/compressedCache.js +309 -0
  130. package/dist/utils/compressionUtil.d.ts +214 -0
  131. package/dist/utils/compressionUtil.d.ts.map +1 -0
  132. package/dist/utils/compressionUtil.js +247 -0
  133. package/dist/utils/constants.d.ts +245 -0
  134. package/dist/utils/constants.d.ts.map +1 -0
  135. package/dist/utils/constants.js +124 -0
  136. package/dist/utils/entityUtils.d.ts +321 -0
  137. package/dist/utils/entityUtils.d.ts.map +1 -0
  138. package/dist/utils/entityUtils.js +434 -4
  139. package/dist/utils/errors.d.ts +95 -0
  140. package/dist/utils/errors.d.ts.map +1 -0
  141. package/dist/utils/errors.js +24 -0
  142. package/dist/utils/formatters.d.ts +145 -0
  143. package/dist/utils/formatters.d.ts.map +1 -0
  144. package/dist/utils/{paginationUtils.js → formatters.js} +54 -3
  145. package/dist/utils/index.d.ts +23 -0
  146. package/dist/utils/index.d.ts.map +1 -0
  147. package/dist/utils/index.js +69 -31
  148. package/dist/utils/indexes.d.ts +270 -0
  149. package/dist/utils/indexes.d.ts.map +1 -0
  150. package/dist/utils/indexes.js +526 -0
  151. package/dist/utils/logger.d.ts +24 -0
  152. package/dist/utils/logger.d.ts.map +1 -0
  153. package/dist/utils/operationUtils.d.ts +124 -0
  154. package/dist/utils/operationUtils.d.ts.map +1 -0
  155. package/dist/utils/operationUtils.js +175 -0
  156. package/dist/utils/parallelUtils.d.ts +72 -0
  157. package/dist/utils/parallelUtils.d.ts.map +1 -0
  158. package/dist/utils/parallelUtils.js +169 -0
  159. package/dist/utils/schemas.d.ts +374 -0
  160. package/dist/utils/schemas.d.ts.map +1 -0
  161. package/dist/utils/schemas.js +302 -2
  162. package/dist/utils/searchAlgorithms.d.ts +99 -0
  163. package/dist/utils/searchAlgorithms.d.ts.map +1 -0
  164. package/dist/utils/searchAlgorithms.js +167 -0
  165. package/dist/utils/searchCache.d.ts +108 -0
  166. package/dist/utils/searchCache.d.ts.map +1 -0
  167. package/dist/utils/taskScheduler.d.ts +290 -0
  168. package/dist/utils/taskScheduler.d.ts.map +1 -0
  169. package/dist/utils/taskScheduler.js +466 -0
  170. package/dist/workers/index.d.ts +12 -0
  171. package/dist/workers/index.d.ts.map +1 -0
  172. package/dist/workers/index.js +9 -0
  173. package/dist/workers/levenshteinWorker.d.ts +60 -0
  174. package/dist/workers/levenshteinWorker.d.ts.map +1 -0
  175. package/dist/workers/levenshteinWorker.js +98 -0
  176. package/package.json +17 -4
  177. package/dist/__tests__/edge-cases/edge-cases.test.js +0 -406
  178. package/dist/__tests__/integration/workflows.test.js +0 -449
  179. package/dist/__tests__/performance/benchmarks.test.js +0 -413
  180. package/dist/__tests__/unit/core/EntityManager.test.js +0 -334
  181. package/dist/__tests__/unit/core/GraphStorage.test.js +0 -205
  182. package/dist/__tests__/unit/core/RelationManager.test.js +0 -274
  183. package/dist/__tests__/unit/features/CompressionManager.test.js +0 -350
  184. package/dist/__tests__/unit/search/BasicSearch.test.js +0 -311
  185. package/dist/__tests__/unit/search/BooleanSearch.test.js +0 -432
  186. package/dist/__tests__/unit/search/FuzzySearch.test.js +0 -448
  187. package/dist/__tests__/unit/search/RankedSearch.test.js +0 -379
  188. package/dist/__tests__/unit/utils/levenshtein.test.js +0 -77
  189. package/dist/core/KnowledgeGraphManager.js +0 -423
  190. package/dist/features/BackupManager.js +0 -311
  191. package/dist/features/ExportManager.js +0 -305
  192. package/dist/features/ImportExportManager.js +0 -50
  193. package/dist/features/ImportManager.js +0 -328
  194. package/dist/types/analytics.types.js +0 -6
  195. package/dist/types/entity.types.js +0 -7
  196. package/dist/types/import-export.types.js +0 -7
  197. package/dist/types/search.types.js +0 -7
  198. package/dist/types/tag.types.js +0 -6
  199. package/dist/utils/dateUtils.js +0 -89
  200. package/dist/utils/filterUtils.js +0 -155
  201. package/dist/utils/levenshtein.js +0 -62
  202. package/dist/utils/pathUtils.js +0 -115
  203. package/dist/utils/responseFormatter.js +0 -55
  204. package/dist/utils/tagUtils.js +0 -107
  205. package/dist/utils/tfidf.js +0 -90
  206. package/dist/utils/validationHelper.js +0 -99
  207. package/dist/utils/validationUtils.js +0 -109
@@ -0,0 +1,466 @@
1
+ /**
2
+ * Task Scheduler
3
+ *
4
+ * Advanced task scheduling utilities using workerpool.
5
+ * Phase 8 Sprint 4: Priority queues, concurrency control, progress tracking.
6
+ *
7
+ * @module utils/taskScheduler
8
+ */
9
+ import workerpool from '@danielsimonjr/workerpool';
10
+ // ==================== Types ====================
11
+ /**
12
+ * Task priority levels.
13
+ * Higher priority tasks are executed first.
14
+ */
15
+ export var TaskPriority;
16
+ (function (TaskPriority) {
17
+ TaskPriority[TaskPriority["LOW"] = 0] = "LOW";
18
+ TaskPriority[TaskPriority["NORMAL"] = 1] = "NORMAL";
19
+ TaskPriority[TaskPriority["HIGH"] = 2] = "HIGH";
20
+ TaskPriority[TaskPriority["CRITICAL"] = 3] = "CRITICAL";
21
+ })(TaskPriority || (TaskPriority = {}));
22
+ /**
23
+ * Task status in the queue.
24
+ */
25
+ export var TaskStatus;
26
+ (function (TaskStatus) {
27
+ TaskStatus["PENDING"] = "pending";
28
+ TaskStatus["RUNNING"] = "running";
29
+ TaskStatus["COMPLETED"] = "completed";
30
+ TaskStatus["FAILED"] = "failed";
31
+ TaskStatus["CANCELLED"] = "cancelled";
32
+ })(TaskStatus || (TaskStatus = {}));
33
+ /**
34
+ * Priority Task Queue with advanced scheduling.
35
+ *
36
+ * Features:
37
+ * - Priority-based execution (CRITICAL > HIGH > NORMAL > LOW)
38
+ * - Configurable concurrency limits
39
+ * - Progress tracking
40
+ * - Graceful error handling
41
+ * - Task cancellation
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const queue = new TaskQueue({ concurrency: 4 });
46
+ *
47
+ * // Add tasks with different priorities
48
+ * queue.enqueue({
49
+ * id: 'task1',
50
+ * priority: TaskPriority.HIGH,
51
+ * fn: (x: number) => x * 2,
52
+ * input: 5,
53
+ * });
54
+ *
55
+ * // Process all tasks
56
+ * const results = await queue.processAll();
57
+ * ```
58
+ */
59
+ export class TaskQueue {
60
+ queue = [];
61
+ running = new Map();
62
+ completed = [];
63
+ pool = null;
64
+ concurrency;
65
+ defaultTimeout;
66
+ isProcessing = false;
67
+ totalExecutionTime = 0;
68
+ totalProcessed = 0;
69
+ useWorkerPool;
70
+ constructor(options = {}) {
71
+ this.concurrency = options.concurrency ?? Math.max(1, workerpool.cpus - 1);
72
+ this.defaultTimeout = options.timeout ?? 30000;
73
+ this.useWorkerPool = options.useWorkerPool ?? true;
74
+ }
75
+ /**
76
+ * Get or create the worker pool.
77
+ */
78
+ getPool() {
79
+ if (!this.pool) {
80
+ this.pool = workerpool.pool({
81
+ maxWorkers: this.concurrency,
82
+ workerType: 'thread',
83
+ });
84
+ }
85
+ return this.pool;
86
+ }
87
+ /**
88
+ * Add a task to the queue.
89
+ *
90
+ * @param task - Task to add
91
+ * @returns Promise that resolves when the task completes
92
+ */
93
+ enqueue(task) {
94
+ return new Promise((resolve, reject) => {
95
+ const queuedTask = {
96
+ ...task,
97
+ status: TaskStatus.PENDING,
98
+ addedAt: Date.now(),
99
+ resolve: resolve,
100
+ reject,
101
+ };
102
+ // Insert based on priority (higher priority first)
103
+ const insertIndex = this.queue.findIndex(t => t.priority < task.priority);
104
+ if (insertIndex === -1) {
105
+ this.queue.push(queuedTask);
106
+ }
107
+ else {
108
+ this.queue.splice(insertIndex, 0, queuedTask);
109
+ }
110
+ // Start processing if not already running
111
+ if (!this.isProcessing) {
112
+ this.processNext();
113
+ }
114
+ });
115
+ }
116
+ /**
117
+ * Process the next task in the queue.
118
+ */
119
+ async processNext() {
120
+ if (this.running.size >= this.concurrency || this.queue.length === 0) {
121
+ if (this.running.size === 0 && this.queue.length === 0) {
122
+ this.isProcessing = false;
123
+ }
124
+ return;
125
+ }
126
+ this.isProcessing = true;
127
+ const task = this.queue.shift();
128
+ if (!task)
129
+ return;
130
+ task.status = TaskStatus.RUNNING;
131
+ this.running.set(task.id, task);
132
+ const startTime = Date.now();
133
+ try {
134
+ // Execute task - try worker pool first, fall back to direct execution
135
+ let result;
136
+ if (this.useWorkerPool) {
137
+ try {
138
+ const pool = this.getPool();
139
+ const fnString = task.fn.toString();
140
+ const timeout = task.timeout ?? this.defaultTimeout;
141
+ result = await pool
142
+ .exec((input, fnStr) => {
143
+ // eslint-disable-next-line no-new-func
144
+ const fn = new Function('return ' + fnStr)();
145
+ return fn(input);
146
+ }, [task.input, fnString])
147
+ .timeout(timeout);
148
+ }
149
+ catch {
150
+ // Fall back to direct execution
151
+ result = await Promise.resolve(task.fn(task.input));
152
+ }
153
+ }
154
+ else {
155
+ // Direct execution without worker pool
156
+ result = await Promise.resolve(task.fn(task.input));
157
+ }
158
+ const endTime = Date.now();
159
+ const duration = endTime - startTime;
160
+ const taskResult = {
161
+ id: task.id,
162
+ status: TaskStatus.COMPLETED,
163
+ result,
164
+ duration,
165
+ startedAt: startTime,
166
+ completedAt: endTime,
167
+ };
168
+ this.totalExecutionTime += duration;
169
+ this.totalProcessed++;
170
+ this.completed.push(taskResult);
171
+ this.running.delete(task.id);
172
+ task.resolve(taskResult);
173
+ }
174
+ catch (error) {
175
+ const endTime = Date.now();
176
+ const duration = endTime - startTime;
177
+ const taskResult = {
178
+ id: task.id,
179
+ status: TaskStatus.FAILED,
180
+ error: error instanceof Error ? error : new Error(String(error)),
181
+ duration,
182
+ startedAt: startTime,
183
+ completedAt: endTime,
184
+ };
185
+ this.totalProcessed++;
186
+ this.completed.push(taskResult);
187
+ this.running.delete(task.id);
188
+ task.resolve(taskResult);
189
+ }
190
+ // Process next task
191
+ this.processNext();
192
+ }
193
+ /**
194
+ * Cancel a pending task.
195
+ *
196
+ * @param taskId - ID of the task to cancel
197
+ * @returns True if task was cancelled, false if not found or already running
198
+ */
199
+ cancel(taskId) {
200
+ const index = this.queue.findIndex(t => t.id === taskId);
201
+ if (index === -1)
202
+ return false;
203
+ const task = this.queue.splice(index, 1)[0];
204
+ task.status = TaskStatus.CANCELLED;
205
+ const result = {
206
+ id: task.id,
207
+ status: TaskStatus.CANCELLED,
208
+ duration: 0,
209
+ startedAt: Date.now(),
210
+ completedAt: Date.now(),
211
+ };
212
+ task.resolve(result);
213
+ return true;
214
+ }
215
+ /**
216
+ * Wait for all tasks to complete.
217
+ *
218
+ * @returns Array of all task results
219
+ */
220
+ async drain() {
221
+ // Wait for queue to empty and all running tasks to complete
222
+ while (this.queue.length > 0 || this.running.size > 0) {
223
+ await new Promise(resolve => setTimeout(resolve, 10));
224
+ }
225
+ return [...this.completed];
226
+ }
227
+ /**
228
+ * Get queue statistics.
229
+ */
230
+ getStats() {
231
+ return {
232
+ pending: this.queue.length,
233
+ running: this.running.size,
234
+ completed: this.completed.filter(r => r.status === TaskStatus.COMPLETED).length,
235
+ failed: this.completed.filter(r => r.status === TaskStatus.FAILED).length,
236
+ averageExecutionTime: this.totalProcessed > 0 ? this.totalExecutionTime / this.totalProcessed : 0,
237
+ totalProcessed: this.totalProcessed,
238
+ };
239
+ }
240
+ /**
241
+ * Clear all completed results.
242
+ */
243
+ clearCompleted() {
244
+ this.completed = [];
245
+ }
246
+ /**
247
+ * Shutdown the task queue and release resources.
248
+ */
249
+ async shutdown() {
250
+ // Cancel all pending tasks
251
+ for (const task of this.queue) {
252
+ task.status = TaskStatus.CANCELLED;
253
+ task.resolve({
254
+ id: task.id,
255
+ status: TaskStatus.CANCELLED,
256
+ duration: 0,
257
+ startedAt: Date.now(),
258
+ completedAt: Date.now(),
259
+ });
260
+ }
261
+ this.queue = [];
262
+ // Terminate worker pool
263
+ if (this.pool) {
264
+ await this.pool.terminate();
265
+ this.pool = null;
266
+ }
267
+ this.isProcessing = false;
268
+ }
269
+ }
270
+ // ==================== Batch Processing Utilities ====================
271
+ /**
272
+ * Process items in parallel batches with progress tracking.
273
+ *
274
+ * Unlike parallelMap, this provides:
275
+ * - Progress callbacks
276
+ * - Configurable concurrency
277
+ * - Error handling options
278
+ * - Task-level timeouts
279
+ *
280
+ * @template T - Input item type
281
+ * @template R - Output item type
282
+ * @param items - Array of items to process
283
+ * @param fn - Processing function (must be serializable)
284
+ * @param options - Batch processing options
285
+ * @returns Array of results (or errors if stopOnError is false)
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const results = await batchProcess(
290
+ * urls,
291
+ * (url: string) => fetch(url).then(r => r.json()),
292
+ * {
293
+ * concurrency: 5,
294
+ * timeout: 10000,
295
+ * onProgress: ({ completed, total, percentage }) => {
296
+ * console.log(`Progress: ${percentage.toFixed(1)}%`);
297
+ * },
298
+ * }
299
+ * );
300
+ * ```
301
+ */
302
+ export async function batchProcess(items, fn, options = {}) {
303
+ const { concurrency = Math.max(1, workerpool.cpus - 1), timeout = 30000, onProgress, stopOnError = false, } = options;
304
+ const results = [];
305
+ let completed = 0;
306
+ const total = items.length;
307
+ // Process in batches respecting concurrency
308
+ for (let i = 0; i < items.length; i += concurrency) {
309
+ const batch = items.slice(i, i + concurrency);
310
+ const batchPromises = batch.map(async (item, batchIndex) => {
311
+ const itemIndex = i + batchIndex;
312
+ try {
313
+ // Execute with timeout
314
+ const result = await Promise.race([
315
+ Promise.resolve(fn(item)),
316
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Task timeout')), timeout)),
317
+ ]);
318
+ results[itemIndex] = { success: true, result };
319
+ }
320
+ catch (error) {
321
+ const err = error instanceof Error ? error : new Error(String(error));
322
+ results[itemIndex] = { success: false, error: err };
323
+ if (stopOnError) {
324
+ throw err;
325
+ }
326
+ }
327
+ finally {
328
+ completed++;
329
+ if (onProgress) {
330
+ onProgress({
331
+ completed,
332
+ total,
333
+ percentage: (completed / total) * 100,
334
+ currentTaskId: `item-${itemIndex}`,
335
+ });
336
+ }
337
+ }
338
+ });
339
+ await Promise.all(batchPromises);
340
+ }
341
+ return results;
342
+ }
343
+ /**
344
+ * Execute tasks with rate limiting.
345
+ *
346
+ * Ensures tasks don't exceed a specified rate (tasks per second).
347
+ *
348
+ * @template T - Input item type
349
+ * @template R - Output item type
350
+ * @param items - Items to process
351
+ * @param fn - Processing function
352
+ * @param rateLimit - Maximum tasks per second
353
+ * @returns Array of results
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * // Process max 10 items per second
358
+ * const results = await rateLimitedProcess(
359
+ * items,
360
+ * (item) => processItem(item),
361
+ * 10
362
+ * );
363
+ * ```
364
+ */
365
+ export async function rateLimitedProcess(items, fn, rateLimit) {
366
+ const results = [];
367
+ const minInterval = 1000 / rateLimit;
368
+ let lastExecutionTime = 0;
369
+ for (const item of items) {
370
+ // Calculate wait time
371
+ const now = Date.now();
372
+ const timeSinceLast = now - lastExecutionTime;
373
+ if (timeSinceLast < minInterval) {
374
+ await new Promise(resolve => setTimeout(resolve, minInterval - timeSinceLast));
375
+ }
376
+ lastExecutionTime = Date.now();
377
+ const result = await fn(item);
378
+ results.push(result);
379
+ }
380
+ return results;
381
+ }
382
+ /**
383
+ * Retry a function with exponential backoff.
384
+ *
385
+ * @template T - Return type
386
+ * @param fn - Function to retry
387
+ * @param options - Retry options
388
+ * @returns Result of the function
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * const result = await withRetry(
393
+ * () => fetchData(),
394
+ * { maxRetries: 3, baseDelay: 1000 }
395
+ * );
396
+ * ```
397
+ */
398
+ export async function withRetry(fn, options = {}) {
399
+ const { maxRetries = 3, baseDelay = 1000, maxDelay = 30000, onRetry } = options;
400
+ let lastError;
401
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
402
+ try {
403
+ return await fn();
404
+ }
405
+ catch (error) {
406
+ lastError = error instanceof Error ? error : new Error(String(error));
407
+ if (attempt < maxRetries) {
408
+ const delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
409
+ if (onRetry) {
410
+ onRetry(lastError, attempt + 1);
411
+ }
412
+ await new Promise(resolve => setTimeout(resolve, delay));
413
+ }
414
+ }
415
+ }
416
+ throw lastError;
417
+ }
418
+ /**
419
+ * Create a debounced version of a function.
420
+ *
421
+ * @template T - Function arguments type
422
+ * @template R - Return type
423
+ * @param fn - Function to debounce
424
+ * @param delay - Delay in milliseconds
425
+ * @returns Debounced function
426
+ */
427
+ export function debounce(fn, delay) {
428
+ let timeoutId = null;
429
+ let pendingResolve = null;
430
+ return (...args) => {
431
+ return new Promise(resolve => {
432
+ if (timeoutId) {
433
+ clearTimeout(timeoutId);
434
+ }
435
+ pendingResolve = resolve;
436
+ timeoutId = setTimeout(() => {
437
+ const result = fn(...args);
438
+ if (pendingResolve) {
439
+ pendingResolve(result);
440
+ }
441
+ timeoutId = null;
442
+ pendingResolve = null;
443
+ }, delay);
444
+ });
445
+ };
446
+ }
447
+ /**
448
+ * Create a throttled version of a function.
449
+ *
450
+ * @template T - Function arguments type
451
+ * @template R - Return type
452
+ * @param fn - Function to throttle
453
+ * @param limit - Minimum time between calls in milliseconds
454
+ * @returns Throttled function
455
+ */
456
+ export function throttle(fn, limit) {
457
+ let lastCall = 0;
458
+ return (...args) => {
459
+ const now = Date.now();
460
+ if (now - lastCall >= limit) {
461
+ lastCall = now;
462
+ return fn(...args);
463
+ }
464
+ return undefined;
465
+ };
466
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Workers Module
3
+ *
4
+ * Worker thread utilities for parallel processing.
5
+ * Phase 8: Uses workerpool library for worker management.
6
+ *
7
+ * @module workers
8
+ */
9
+ export type { Pool, PoolStats } from '@danielsimonjr/workerpool';
10
+ export type { WorkerInput, MatchResult } from './levenshteinWorker.js';
11
+ export { levenshteinDistance, similarity, searchEntities } from './levenshteinWorker.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGjE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Workers Module
3
+ *
4
+ * Worker thread utilities for parallel processing.
5
+ * Phase 8: Uses workerpool library for worker management.
6
+ *
7
+ * @module workers
8
+ */
9
+ export { levenshteinDistance, similarity, searchEntities } from './levenshteinWorker.js';
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Levenshtein Worker
3
+ *
4
+ * Worker thread for calculating Levenshtein distances in parallel.
5
+ * Uses workerpool for worker management.
6
+ *
7
+ * @module workers/levenshteinWorker
8
+ */
9
+ /**
10
+ * Input data structure for the worker.
11
+ */
12
+ export interface WorkerInput {
13
+ /** Search query string */
14
+ query: string;
15
+ /** Array of entities to search */
16
+ entities: Array<{
17
+ name: string;
18
+ nameLower: string;
19
+ observations: string[];
20
+ }>;
21
+ /** Similarity threshold (0.0 to 1.0) */
22
+ threshold: number;
23
+ }
24
+ /**
25
+ * Match result returned by the worker.
26
+ */
27
+ export interface MatchResult {
28
+ /** Entity name that matched */
29
+ name: string;
30
+ /** Similarity score (0.0 to 1.0) */
31
+ score: number;
32
+ /** Where the match occurred */
33
+ matchedIn: 'name' | 'observation';
34
+ }
35
+ /**
36
+ * Calculate Levenshtein distance between two strings.
37
+ *
38
+ * Uses dynamic programming matrix for efficient computation.
39
+ *
40
+ * @param s1 - First string
41
+ * @param s2 - Second string
42
+ * @returns Levenshtein distance (number of edits)
43
+ */
44
+ export declare function levenshteinDistance(s1: string, s2: string): number;
45
+ /**
46
+ * Calculate similarity score between two strings.
47
+ *
48
+ * @param s1 - First string
49
+ * @param s2 - Second string
50
+ * @returns Similarity score (0.0 to 1.0, where 1.0 is identical)
51
+ */
52
+ export declare function similarity(s1: string, s2: string): number;
53
+ /**
54
+ * Search entities for fuzzy matches.
55
+ *
56
+ * @param data - Worker input containing query, entities, and threshold
57
+ * @returns Array of match results
58
+ */
59
+ export declare function searchEntities(data: WorkerInput): MatchResult[];
60
+ //# sourceMappingURL=levenshteinWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"levenshteinWorker.d.ts","sourceRoot":"","sources":["../../src/workers/levenshteinWorker.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,EAAE,CAAC;KACxB,CAAC,CAAC;IACH,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAgClE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAWzD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE,CAwB/D"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Levenshtein Worker
3
+ *
4
+ * Worker thread for calculating Levenshtein distances in parallel.
5
+ * Uses workerpool for worker management.
6
+ *
7
+ * @module workers/levenshteinWorker
8
+ */
9
+ import workerpool from '@danielsimonjr/workerpool';
10
+ /**
11
+ * Calculate Levenshtein distance between two strings.
12
+ *
13
+ * Uses dynamic programming matrix for efficient computation.
14
+ *
15
+ * @param s1 - First string
16
+ * @param s2 - Second string
17
+ * @returns Levenshtein distance (number of edits)
18
+ */
19
+ export function levenshteinDistance(s1, s2) {
20
+ const len1 = s1.length;
21
+ const len2 = s2.length;
22
+ if (len1 === 0)
23
+ return len2;
24
+ if (len2 === 0)
25
+ return len1;
26
+ const matrix = [];
27
+ // Initialize first column
28
+ for (let i = 0; i <= len1; i++) {
29
+ matrix[i] = [i];
30
+ }
31
+ // Initialize first row
32
+ for (let j = 0; j <= len2; j++) {
33
+ matrix[0][j] = j;
34
+ }
35
+ // Fill matrix
36
+ for (let i = 1; i <= len1; i++) {
37
+ for (let j = 1; j <= len2; j++) {
38
+ const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
39
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
40
+ matrix[i][j - 1] + 1, // insertion
41
+ matrix[i - 1][j - 1] + cost // substitution
42
+ );
43
+ }
44
+ }
45
+ return matrix[len1][len2];
46
+ }
47
+ /**
48
+ * Calculate similarity score between two strings.
49
+ *
50
+ * @param s1 - First string
51
+ * @param s2 - Second string
52
+ * @returns Similarity score (0.0 to 1.0, where 1.0 is identical)
53
+ */
54
+ export function similarity(s1, s2) {
55
+ // Exact match
56
+ if (s1 === s2)
57
+ return 1.0;
58
+ // One contains the other
59
+ if (s1.includes(s2) || s2.includes(s1))
60
+ return 1.0;
61
+ // Calculate Levenshtein-based similarity
62
+ const distance = levenshteinDistance(s1, s2);
63
+ const maxLength = Math.max(s1.length, s2.length);
64
+ return 1 - distance / maxLength;
65
+ }
66
+ /**
67
+ * Search entities for fuzzy matches.
68
+ *
69
+ * @param data - Worker input containing query, entities, and threshold
70
+ * @returns Array of match results
71
+ */
72
+ export function searchEntities(data) {
73
+ const { query, entities, threshold } = data;
74
+ const queryLower = query.toLowerCase();
75
+ const results = [];
76
+ for (const entity of entities) {
77
+ // Check name similarity
78
+ const nameScore = similarity(queryLower, entity.nameLower);
79
+ if (nameScore >= threshold) {
80
+ results.push({ name: entity.name, score: nameScore, matchedIn: 'name' });
81
+ continue;
82
+ }
83
+ // Check observations
84
+ for (const obs of entity.observations) {
85
+ const obsScore = similarity(queryLower, obs);
86
+ if (obsScore >= threshold) {
87
+ results.push({ name: entity.name, score: obsScore, matchedIn: 'observation' });
88
+ break;
89
+ }
90
+ }
91
+ }
92
+ return results;
93
+ }
94
+ // Register worker methods with workerpool
95
+ // Cast to satisfy workerpool's generic type signature
96
+ workerpool.worker({
97
+ searchEntities: searchEntities,
98
+ });
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@danielsimonjr/memory-mcp",
3
- "version": "0.47.1",
4
- "description": "Enhanced MCP memory server with hierarchies, compression, archiving, and 45 advanced tools",
3
+ "version": "9.8.0",
4
+ "description": "Enhanced MCP memory server with hierarchies, compression, archiving, graph algorithms, semantic search, and 55 advanced tools",
5
5
  "license": "MIT",
6
+ "engines": {
7
+ "node": ">=18.0.0"
8
+ },
6
9
  "author": "Daniel Simon Jr. (https://github.com/danielsimonjr)",
7
10
  "homepage": "https://github.com/danielsimonjr/memory-mcp",
8
11
  "bugs": "https://github.com/danielsimonjr/memory-mcp/issues",
@@ -20,7 +23,9 @@
20
23
  "tags",
21
24
  "export",
22
25
  "graphml",
23
- "analytics"
26
+ "analytics",
27
+ "semantic-search",
28
+ "embeddings"
24
29
  ],
25
30
  "type": "module",
26
31
  "main": "./dist/index.js",
@@ -66,15 +71,23 @@
66
71
  "prepare": "npm run build",
67
72
  "watch": "tsc --watch",
68
73
  "test": "vitest run --coverage",
69
- "typecheck": "tsc --noEmit --noUnusedLocals --noUnusedParameters --strict"
74
+ "typecheck": "tsc --noEmit --noUnusedLocals --noUnusedParameters --strict",
75
+ "clean": "shx rm -rf dist",
76
+ "docs:deps": "npx tsx tools/create-dependency-graph/create-dependency-graph.ts"
70
77
  },
71
78
  "dependencies": {
79
+ "@danielsimonjr/workerpool": "^10.0.1",
72
80
  "@modelcontextprotocol/sdk": "^1.21.1",
81
+ "async-mutex": "^0.5.0",
82
+ "better-sqlite3": "^11.7.0",
73
83
  "zod": "^4.1.13"
74
84
  },
75
85
  "devDependencies": {
86
+ "@types/better-sqlite3": "^7.6.12",
87
+ "@types/js-yaml": "^4.0.9",
76
88
  "@types/node": "^22",
77
89
  "@vitest/coverage-v8": "^4.0.13",
90
+ "js-yaml": "^4.1.1",
78
91
  "shx": "^0.4.0",
79
92
  "typescript": "^5.6.2",
80
93
  "vitest": "^4.0.13"