@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,178 @@
1
+ /**
2
+ * Embedding Service
3
+ *
4
+ * Phase 4 Sprint 10: Provides embedding abstractions for semantic search.
5
+ * Supports multiple providers: OpenAI (cloud) and local (transformers.js).
6
+ *
7
+ * @module search/EmbeddingService
8
+ */
9
+ import type { EmbeddingService, EmbeddingConfig } from '../types/index.js';
10
+ /**
11
+ * OpenAI Embedding Service
12
+ *
13
+ * Uses OpenAI's text-embedding-3-small model for generating embeddings.
14
+ * Supports single and batch embedding with rate limit handling.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const service = new OpenAIEmbeddingService('sk-...');
19
+ * const embedding = await service.embed("Hello world");
20
+ * console.log(`Generated ${embedding.length} dimensions`);
21
+ * ```
22
+ */
23
+ export declare class OpenAIEmbeddingService implements EmbeddingService {
24
+ readonly dimensions: number;
25
+ readonly provider = "openai";
26
+ readonly model: string;
27
+ private apiKey;
28
+ /**
29
+ * Create an OpenAI embedding service.
30
+ *
31
+ * @param apiKey - OpenAI API key
32
+ * @param model - Optional model override (default: text-embedding-3-small)
33
+ */
34
+ constructor(apiKey: string, model?: string);
35
+ /**
36
+ * Check if the service is ready.
37
+ */
38
+ isReady(): Promise<boolean>;
39
+ /**
40
+ * Generate embedding for a single text.
41
+ *
42
+ * @param text - Text to embed
43
+ * @returns Embedding vector
44
+ */
45
+ embed(text: string): Promise<number[]>;
46
+ /**
47
+ * Generate embeddings for multiple texts in batch.
48
+ *
49
+ * @param texts - Array of texts to embed
50
+ * @returns Array of embedding vectors
51
+ */
52
+ embedBatch(texts: string[]): Promise<number[][]>;
53
+ /**
54
+ * Internal batch embedding with retry logic.
55
+ */
56
+ private embedBatchInternal;
57
+ /**
58
+ * Check if an error is retryable.
59
+ */
60
+ private isRetryableError;
61
+ /**
62
+ * Sleep for a given duration.
63
+ */
64
+ private sleep;
65
+ }
66
+ /**
67
+ * Local Embedding Service
68
+ *
69
+ * Uses @xenova/transformers for local embedding generation.
70
+ * No API calls needed - runs entirely offline after initial model download.
71
+ *
72
+ * Note: Requires @xenova/transformers to be installed as an optional dependency.
73
+ * If not available, initialization will fail gracefully.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const service = new LocalEmbeddingService();
78
+ * await service.initialize();
79
+ * const embedding = await service.embed("Hello world");
80
+ * ```
81
+ */
82
+ export declare class LocalEmbeddingService implements EmbeddingService {
83
+ readonly dimensions: number;
84
+ readonly provider = "local";
85
+ readonly model: string;
86
+ private pipeline;
87
+ private initialized;
88
+ private initPromise;
89
+ /**
90
+ * Create a local embedding service.
91
+ *
92
+ * @param model - Optional model override (default: Xenova/all-MiniLM-L6-v2)
93
+ */
94
+ constructor(model?: string);
95
+ /**
96
+ * Initialize the model pipeline.
97
+ * Must be called before using embed/embedBatch.
98
+ */
99
+ initialize(): Promise<void>;
100
+ /**
101
+ * Internal initialization.
102
+ */
103
+ private initializeInternal;
104
+ /**
105
+ * Check if the service is ready.
106
+ */
107
+ isReady(): Promise<boolean>;
108
+ /**
109
+ * Generate embedding for a single text.
110
+ *
111
+ * @param text - Text to embed
112
+ * @returns Embedding vector
113
+ */
114
+ embed(text: string): Promise<number[]>;
115
+ /**
116
+ * Generate embeddings for multiple texts in batch.
117
+ * Note: Local processing is done sequentially to avoid memory issues.
118
+ *
119
+ * @param texts - Array of texts to embed
120
+ * @returns Array of embedding vectors
121
+ */
122
+ embedBatch(texts: string[]): Promise<number[][]>;
123
+ /**
124
+ * Ensure the service is initialized.
125
+ */
126
+ private ensureInitialized;
127
+ }
128
+ /**
129
+ * Mock Embedding Service for testing
130
+ *
131
+ * Generates deterministic mock embeddings for testing purposes.
132
+ * Useful for unit tests that don't need real embeddings.
133
+ */
134
+ export declare class MockEmbeddingService implements EmbeddingService {
135
+ readonly dimensions: number;
136
+ readonly provider = "mock";
137
+ readonly model = "mock-model";
138
+ /**
139
+ * Create a mock embedding service.
140
+ *
141
+ * @param dimensions - Number of dimensions for mock embeddings
142
+ */
143
+ constructor(dimensions?: number);
144
+ /**
145
+ * Check if the service is ready.
146
+ */
147
+ isReady(): Promise<boolean>;
148
+ /**
149
+ * Generate a deterministic mock embedding for a text.
150
+ *
151
+ * @param text - Text to embed
152
+ * @returns Mock embedding vector
153
+ */
154
+ embed(text: string): Promise<number[]>;
155
+ /**
156
+ * Generate mock embeddings for multiple texts.
157
+ *
158
+ * @param texts - Array of texts to embed
159
+ * @returns Array of mock embedding vectors
160
+ */
161
+ embedBatch(texts: string[]): Promise<number[][]>;
162
+ /**
163
+ * Simple string hash function.
164
+ */
165
+ private hashString;
166
+ /**
167
+ * Normalize a vector to unit length.
168
+ */
169
+ private normalize;
170
+ }
171
+ /**
172
+ * Create an embedding service based on configuration.
173
+ *
174
+ * @param config - Optional configuration override
175
+ * @returns Embedding service instance, or null if provider is 'none'
176
+ */
177
+ export declare function createEmbeddingService(config?: Partial<EmbeddingConfig>): EmbeddingService | null;
178
+ //# sourceMappingURL=EmbeddingService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmbeddingService.d.ts","sourceRoot":"","sources":["../../src/search/EmbeddingService.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAO3E;;;;;;;;;;;;GAYG;AACH,qBAAa,sBAAuB,YAAW,gBAAgB;IAC7D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,YAAY;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;;OAKG;gBACS,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAS1C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjC;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAK5C;;;;;OAKG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAkBtD;;OAEG;YACW,kBAAkB;IA0DhC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AAmBD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,qBAAsB,YAAW,gBAAgB;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAuC;IAClE,QAAQ,CAAC,QAAQ,WAAW;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAA8B;IAEjD;;;;OAIG;gBACS,KAAK,CAAC,EAAE,MAAM;IAI1B;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC;;OAEG;YACW,kBAAkB;IAkBhC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAWjC;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAS5C;;;;;;OAMG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAWtD;;OAEG;YACW,iBAAiB;CAKhC;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,gBAAgB;IAC3D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,UAAU;IAC3B,QAAQ,CAAC,KAAK,gBAAgB;IAE9B;;;;OAIG;gBACS,UAAU,GAAE,MAAY;IAIpC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjC;;;;;OAKG;IACG,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAe5C;;;;;OAKG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAItD;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,OAAO,CAAC,SAAS;CAalB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,gBAAgB,GAAG,IAAI,CAoBjG"}
@@ -0,0 +1,358 @@
1
+ /**
2
+ * Embedding Service
3
+ *
4
+ * Phase 4 Sprint 10: Provides embedding abstractions for semantic search.
5
+ * Supports multiple providers: OpenAI (cloud) and local (transformers.js).
6
+ *
7
+ * @module search/EmbeddingService
8
+ */
9
+ import { EMBEDDING_DEFAULTS, OPENAI_API_CONFIG, getEmbeddingConfig, } from '../utils/constants.js';
10
+ /**
11
+ * OpenAI Embedding Service
12
+ *
13
+ * Uses OpenAI's text-embedding-3-small model for generating embeddings.
14
+ * Supports single and batch embedding with rate limit handling.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const service = new OpenAIEmbeddingService('sk-...');
19
+ * const embedding = await service.embed("Hello world");
20
+ * console.log(`Generated ${embedding.length} dimensions`);
21
+ * ```
22
+ */
23
+ export class OpenAIEmbeddingService {
24
+ dimensions;
25
+ provider = 'openai';
26
+ model;
27
+ apiKey;
28
+ /**
29
+ * Create an OpenAI embedding service.
30
+ *
31
+ * @param apiKey - OpenAI API key
32
+ * @param model - Optional model override (default: text-embedding-3-small)
33
+ */
34
+ constructor(apiKey, model) {
35
+ if (!apiKey) {
36
+ throw new Error('OpenAI API key is required');
37
+ }
38
+ this.apiKey = apiKey;
39
+ this.model = model || EMBEDDING_DEFAULTS.OPENAI_MODEL;
40
+ this.dimensions = EMBEDDING_DEFAULTS.OPENAI_DIMENSIONS;
41
+ }
42
+ /**
43
+ * Check if the service is ready.
44
+ */
45
+ async isReady() {
46
+ return !!this.apiKey;
47
+ }
48
+ /**
49
+ * Generate embedding for a single text.
50
+ *
51
+ * @param text - Text to embed
52
+ * @returns Embedding vector
53
+ */
54
+ async embed(text) {
55
+ const results = await this.embedBatch([text]);
56
+ return results[0];
57
+ }
58
+ /**
59
+ * Generate embeddings for multiple texts in batch.
60
+ *
61
+ * @param texts - Array of texts to embed
62
+ * @returns Array of embedding vectors
63
+ */
64
+ async embedBatch(texts) {
65
+ if (texts.length === 0) {
66
+ return [];
67
+ }
68
+ // Split into batches if needed
69
+ const maxBatchSize = EMBEDDING_DEFAULTS.OPENAI_MAX_BATCH_SIZE;
70
+ const results = [];
71
+ for (let i = 0; i < texts.length; i += maxBatchSize) {
72
+ const batch = texts.slice(i, i + maxBatchSize);
73
+ const batchResults = await this.embedBatchInternal(batch);
74
+ results.push(...batchResults);
75
+ }
76
+ return results;
77
+ }
78
+ /**
79
+ * Internal batch embedding with retry logic.
80
+ */
81
+ async embedBatchInternal(texts) {
82
+ let lastError = null;
83
+ let backoff = OPENAI_API_CONFIG.INITIAL_BACKOFF_MS;
84
+ for (let attempt = 0; attempt <= OPENAI_API_CONFIG.MAX_RETRIES; attempt++) {
85
+ try {
86
+ const response = await fetch(`${OPENAI_API_CONFIG.BASE_URL}${OPENAI_API_CONFIG.EMBEDDINGS_ENDPOINT}`, {
87
+ method: 'POST',
88
+ headers: {
89
+ 'Content-Type': 'application/json',
90
+ 'Authorization': `Bearer ${this.apiKey}`,
91
+ },
92
+ body: JSON.stringify({
93
+ model: this.model,
94
+ input: texts,
95
+ }),
96
+ });
97
+ if (!response.ok) {
98
+ const errorBody = await response.text();
99
+ // Handle rate limiting
100
+ if (response.status === 429) {
101
+ if (attempt < OPENAI_API_CONFIG.MAX_RETRIES) {
102
+ await this.sleep(backoff);
103
+ backoff = Math.min(backoff * 2, OPENAI_API_CONFIG.MAX_BACKOFF_MS);
104
+ continue;
105
+ }
106
+ }
107
+ throw new Error(`OpenAI API error: ${response.status} - ${errorBody}`);
108
+ }
109
+ const data = await response.json();
110
+ // Sort by index to ensure correct order
111
+ const sortedData = [...data.data].sort((a, b) => a.index - b.index);
112
+ return sortedData.map(item => item.embedding);
113
+ }
114
+ catch (error) {
115
+ lastError = error instanceof Error ? error : new Error(String(error));
116
+ // Retry on network errors
117
+ if (attempt < OPENAI_API_CONFIG.MAX_RETRIES && this.isRetryableError(error)) {
118
+ await this.sleep(backoff);
119
+ backoff = Math.min(backoff * 2, OPENAI_API_CONFIG.MAX_BACKOFF_MS);
120
+ continue;
121
+ }
122
+ throw lastError;
123
+ }
124
+ }
125
+ throw lastError || new Error('Failed to generate embeddings after retries');
126
+ }
127
+ /**
128
+ * Check if an error is retryable.
129
+ */
130
+ isRetryableError(error) {
131
+ if (error instanceof Error) {
132
+ // Network errors and rate limits are retryable
133
+ return error.message.includes('fetch') ||
134
+ error.message.includes('network') ||
135
+ error.message.includes('429');
136
+ }
137
+ return false;
138
+ }
139
+ /**
140
+ * Sleep for a given duration.
141
+ */
142
+ sleep(ms) {
143
+ return new Promise(resolve => setTimeout(resolve, ms));
144
+ }
145
+ }
146
+ /**
147
+ * Local Embedding Service
148
+ *
149
+ * Uses @xenova/transformers for local embedding generation.
150
+ * No API calls needed - runs entirely offline after initial model download.
151
+ *
152
+ * Note: Requires @xenova/transformers to be installed as an optional dependency.
153
+ * If not available, initialization will fail gracefully.
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const service = new LocalEmbeddingService();
158
+ * await service.initialize();
159
+ * const embedding = await service.embed("Hello world");
160
+ * ```
161
+ */
162
+ export class LocalEmbeddingService {
163
+ dimensions = EMBEDDING_DEFAULTS.LOCAL_DIMENSIONS;
164
+ provider = 'local';
165
+ model;
166
+ pipeline = null;
167
+ initialized = false;
168
+ initPromise = null;
169
+ /**
170
+ * Create a local embedding service.
171
+ *
172
+ * @param model - Optional model override (default: Xenova/all-MiniLM-L6-v2)
173
+ */
174
+ constructor(model) {
175
+ this.model = model || EMBEDDING_DEFAULTS.LOCAL_MODEL;
176
+ }
177
+ /**
178
+ * Initialize the model pipeline.
179
+ * Must be called before using embed/embedBatch.
180
+ */
181
+ async initialize() {
182
+ if (this.initialized)
183
+ return;
184
+ if (this.initPromise) {
185
+ return this.initPromise;
186
+ }
187
+ this.initPromise = this.initializeInternal();
188
+ return this.initPromise;
189
+ }
190
+ /**
191
+ * Internal initialization.
192
+ */
193
+ async initializeInternal() {
194
+ try {
195
+ // Dynamic import to allow optional dependency
196
+ // @ts-expect-error - @xenova/transformers is an optional peer dependency
197
+ const transformers = await import('@xenova/transformers');
198
+ const { pipeline } = transformers;
199
+ this.pipeline = await pipeline('feature-extraction', this.model);
200
+ this.initialized = true;
201
+ }
202
+ catch (error) {
203
+ this.initPromise = null;
204
+ throw new Error(`Failed to initialize local embedding service: ${error instanceof Error ? error.message : String(error)}. ` +
205
+ 'Make sure @xenova/transformers is installed.');
206
+ }
207
+ }
208
+ /**
209
+ * Check if the service is ready.
210
+ */
211
+ async isReady() {
212
+ if (!this.initialized && !this.initPromise) {
213
+ try {
214
+ await this.initialize();
215
+ }
216
+ catch {
217
+ return false;
218
+ }
219
+ }
220
+ return this.initialized;
221
+ }
222
+ /**
223
+ * Generate embedding for a single text.
224
+ *
225
+ * @param text - Text to embed
226
+ * @returns Embedding vector
227
+ */
228
+ async embed(text) {
229
+ await this.ensureInitialized();
230
+ const pipelineFn = this.pipeline;
231
+ const output = await pipelineFn(text, { pooling: 'mean', normalize: true });
232
+ return Array.from(output.data);
233
+ }
234
+ /**
235
+ * Generate embeddings for multiple texts in batch.
236
+ * Note: Local processing is done sequentially to avoid memory issues.
237
+ *
238
+ * @param texts - Array of texts to embed
239
+ * @returns Array of embedding vectors
240
+ */
241
+ async embedBatch(texts) {
242
+ await this.ensureInitialized();
243
+ const results = [];
244
+ for (const text of texts) {
245
+ const embedding = await this.embed(text);
246
+ results.push(embedding);
247
+ }
248
+ return results;
249
+ }
250
+ /**
251
+ * Ensure the service is initialized.
252
+ */
253
+ async ensureInitialized() {
254
+ if (!this.initialized) {
255
+ await this.initialize();
256
+ }
257
+ }
258
+ }
259
+ /**
260
+ * Mock Embedding Service for testing
261
+ *
262
+ * Generates deterministic mock embeddings for testing purposes.
263
+ * Useful for unit tests that don't need real embeddings.
264
+ */
265
+ export class MockEmbeddingService {
266
+ dimensions;
267
+ provider = 'mock';
268
+ model = 'mock-model';
269
+ /**
270
+ * Create a mock embedding service.
271
+ *
272
+ * @param dimensions - Number of dimensions for mock embeddings
273
+ */
274
+ constructor(dimensions = 384) {
275
+ this.dimensions = dimensions;
276
+ }
277
+ /**
278
+ * Check if the service is ready.
279
+ */
280
+ async isReady() {
281
+ return true;
282
+ }
283
+ /**
284
+ * Generate a deterministic mock embedding for a text.
285
+ *
286
+ * @param text - Text to embed
287
+ * @returns Mock embedding vector
288
+ */
289
+ async embed(text) {
290
+ // Generate deterministic embedding based on text hash
291
+ const hash = this.hashString(text);
292
+ const embedding = [];
293
+ for (let i = 0; i < this.dimensions; i++) {
294
+ // Use hash and index to generate deterministic values
295
+ const value = Math.sin(hash + i * 0.1) * 0.5;
296
+ embedding.push(value);
297
+ }
298
+ // Normalize the vector
299
+ return this.normalize(embedding);
300
+ }
301
+ /**
302
+ * Generate mock embeddings for multiple texts.
303
+ *
304
+ * @param texts - Array of texts to embed
305
+ * @returns Array of mock embedding vectors
306
+ */
307
+ async embedBatch(texts) {
308
+ return Promise.all(texts.map(text => this.embed(text)));
309
+ }
310
+ /**
311
+ * Simple string hash function.
312
+ */
313
+ hashString(str) {
314
+ let hash = 0;
315
+ for (let i = 0; i < str.length; i++) {
316
+ const char = str.charCodeAt(i);
317
+ hash = ((hash << 5) - hash) + char;
318
+ hash = hash & hash; // Convert to 32bit integer
319
+ }
320
+ return hash;
321
+ }
322
+ /**
323
+ * Normalize a vector to unit length.
324
+ */
325
+ normalize(vector) {
326
+ let magnitude = 0;
327
+ for (const v of vector) {
328
+ magnitude += v * v;
329
+ }
330
+ magnitude = Math.sqrt(magnitude);
331
+ if (magnitude === 0) {
332
+ return vector;
333
+ }
334
+ return vector.map(v => v / magnitude);
335
+ }
336
+ }
337
+ /**
338
+ * Create an embedding service based on configuration.
339
+ *
340
+ * @param config - Optional configuration override
341
+ * @returns Embedding service instance, or null if provider is 'none'
342
+ */
343
+ export function createEmbeddingService(config) {
344
+ const envConfig = getEmbeddingConfig();
345
+ const mergedConfig = { ...envConfig, ...config };
346
+ switch (mergedConfig.provider) {
347
+ case 'openai':
348
+ if (!mergedConfig.apiKey) {
349
+ throw new Error('OpenAI API key is required. Set MEMORY_OPENAI_API_KEY environment variable or provide apiKey in config.');
350
+ }
351
+ return new OpenAIEmbeddingService(mergedConfig.apiKey, mergedConfig.model);
352
+ case 'local':
353
+ return new LocalEmbeddingService(mergedConfig.model);
354
+ case 'none':
355
+ default:
356
+ return null;
357
+ }
358
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Fuzzy Search
3
+ *
4
+ * Search with typo tolerance using Levenshtein distance similarity.
5
+ * Uses workerpool for parallel processing on large datasets.
6
+ *
7
+ * @module search/FuzzySearch
8
+ */
9
+ import type { KnowledgeGraph } from '../types/index.js';
10
+ import type { GraphStorage } from '../core/GraphStorage.js';
11
+ /**
12
+ * Default fuzzy search similarity threshold (70% match required).
13
+ * Lower values are more permissive (more typos tolerated).
14
+ * Higher values are stricter (fewer typos tolerated).
15
+ */
16
+ export declare const DEFAULT_FUZZY_THRESHOLD = 0.7;
17
+ /**
18
+ * Options for FuzzySearch constructor.
19
+ */
20
+ export interface FuzzySearchOptions {
21
+ /**
22
+ * Whether to use worker pool for parallel processing.
23
+ * Set to false for testing or when workers are not available.
24
+ * Default: true
25
+ */
26
+ useWorkerPool?: boolean;
27
+ }
28
+ /**
29
+ * Performs fuzzy search with configurable similarity threshold.
30
+ */
31
+ export declare class FuzzySearch {
32
+ private storage;
33
+ /**
34
+ * Phase 4 Sprint 3: Result cache for fuzzy search.
35
+ * Maps cache key -> cached entity names.
36
+ */
37
+ private fuzzyResultCache;
38
+ /**
39
+ * Phase 8: Worker pool using workerpool library.
40
+ * Initialized lazily when needed.
41
+ */
42
+ private workerPool;
43
+ /**
44
+ * Phase 7 Sprint 3: Path to the worker script.
45
+ */
46
+ private workerPath;
47
+ /**
48
+ * Phase 8: Whether to use worker pool for parallel processing.
49
+ * Can be disabled for testing or when workers are not available.
50
+ */
51
+ private useWorkerPool;
52
+ constructor(storage: GraphStorage, options?: FuzzySearchOptions);
53
+ /**
54
+ * Phase 4 Sprint 3: Generate cache key for fuzzy search parameters.
55
+ */
56
+ private generateCacheKey;
57
+ /**
58
+ * Phase 4 Sprint 3: Clear the fuzzy search cache.
59
+ */
60
+ clearCache(): void;
61
+ /**
62
+ * Phase 4 Sprint 3: Invalidate stale cache entries.
63
+ */
64
+ private cleanupCache;
65
+ /**
66
+ * Fuzzy search for entities with typo tolerance and pagination.
67
+ *
68
+ * Uses Levenshtein distance to calculate similarity between strings.
69
+ * Matches if similarity >= threshold (0.0 to 1.0).
70
+ *
71
+ * Phase 4 Sprint 3: Implements result caching for repeated queries.
72
+ *
73
+ * @param query - Search query
74
+ * @param threshold - Similarity threshold (0.0 to 1.0), default DEFAULT_FUZZY_THRESHOLD
75
+ * @param tags - Optional tags filter
76
+ * @param minImportance - Optional minimum importance
77
+ * @param maxImportance - Optional maximum importance
78
+ * @param offset - Number of results to skip (default: 0)
79
+ * @param limit - Maximum number of results (default: 50, max: 200)
80
+ * @returns Filtered knowledge graph with fuzzy matches and pagination applied
81
+ */
82
+ fuzzySearch(query: string, threshold?: number, tags?: string[], minImportance?: number, maxImportance?: number, offset?: number, limit?: number): Promise<KnowledgeGraph>;
83
+ /**
84
+ * Phase 4 Sprint 3: Perform the actual fuzzy matching logic.
85
+ * Extracted from fuzzySearch for cleaner code structure.
86
+ */
87
+ private performFuzzyMatch;
88
+ /**
89
+ * Check if two already-lowercase strings match with fuzzy logic.
90
+ *
91
+ * OPTIMIZED: Skips toLowerCase() calls when strings are already lowercase.
92
+ *
93
+ * @param s1 - First string (already lowercase)
94
+ * @param s2 - Second string (already lowercase)
95
+ * @param threshold - Similarity threshold (0.0 to 1.0)
96
+ * @returns True if strings match fuzzily
97
+ */
98
+ private isFuzzyMatchLower;
99
+ /**
100
+ * Phase 8: Perform fuzzy search using workerpool for parallel processing.
101
+ *
102
+ * Splits entities into chunks and processes them in parallel using worker threads.
103
+ * Falls back to single-threaded search if worker execution fails.
104
+ *
105
+ * @param query - Search query
106
+ * @param threshold - Similarity threshold
107
+ * @param entities - Entities to search
108
+ * @returns Array of matched entities
109
+ */
110
+ private searchWithWorkers;
111
+ /**
112
+ * Phase 8: Shutdown the worker pool and clean up resources.
113
+ *
114
+ * Should be called when FuzzySearch is no longer needed.
115
+ */
116
+ shutdown(): Promise<void>;
117
+ }
118
+ //# sourceMappingURL=FuzzySearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FuzzySearch.d.ts","sourceRoot":"","sources":["../../src/search/FuzzySearch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAU,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAQ5D;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,MAAM,CAAC;AA4C3C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,qBAAa,WAAW;IAwBV,OAAO,CAAC,OAAO;IAvB3B;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAA2C;IAEnE;;;OAGG;IACH,OAAO,CAAC,UAAU,CAAqB;IAEvC;;OAEG;IACH,OAAO,CAAC,UAAU,CAAS;IAE3B;;;OAGG;IACH,OAAO,CAAC,aAAa,CAAU;gBAEX,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,kBAAuB;IAmB3E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAwBpB;;;;;;;;;;;;;;;;OAgBG;IACG,WAAW,CACf,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAAgC,EAC3C,IAAI,CAAC,EAAE,MAAM,EAAE,EACf,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,GAAE,MAAU,EAClB,KAAK,GAAE,MAA8B,GACpC,OAAO,CAAC,cAAc,CAAC;IAsE1B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA0BzB;;;;;;;;;OASG;IACH,OAAO,CAAC,iBAAiB;IAezB;;;;;;;;;;OAUG;YACW,iBAAiB;IAiE/B;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAMhC"}