@danielsimonjr/memoryjs 1.0.0 → 1.2.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.
- package/README.md +385 -113
- package/README.md.backup-1768084780988 +266 -0
- package/dist/index.cjs +24156 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +16967 -0
- package/dist/index.d.ts +16963 -11
- package/dist/index.js +23887 -19
- package/dist/index.js.map +1 -1
- package/dist/workers/levenshteinWorker.cjs +102 -0
- package/dist/workers/levenshteinWorker.cjs.map +1 -0
- package/dist/workers/levenshteinWorker.js +57 -91
- package/dist/workers/levenshteinWorker.js.map +1 -1
- package/package.json +75 -69
- package/dist/core/EntityManager.d.ts +0 -268
- package/dist/core/EntityManager.d.ts.map +0 -1
- package/dist/core/EntityManager.js +0 -512
- package/dist/core/EntityManager.js.map +0 -1
- package/dist/core/GraphEventEmitter.d.ts +0 -202
- package/dist/core/GraphEventEmitter.d.ts.map +0 -1
- package/dist/core/GraphEventEmitter.js +0 -347
- package/dist/core/GraphEventEmitter.js.map +0 -1
- package/dist/core/GraphStorage.d.ts +0 -395
- package/dist/core/GraphStorage.d.ts.map +0 -1
- package/dist/core/GraphStorage.js +0 -786
- package/dist/core/GraphStorage.js.map +0 -1
- package/dist/core/GraphTraversal.d.ts +0 -141
- package/dist/core/GraphTraversal.d.ts.map +0 -1
- package/dist/core/GraphTraversal.js +0 -574
- package/dist/core/GraphTraversal.js.map +0 -1
- package/dist/core/HierarchyManager.d.ts +0 -111
- package/dist/core/HierarchyManager.d.ts.map +0 -1
- package/dist/core/HierarchyManager.js +0 -225
- package/dist/core/HierarchyManager.js.map +0 -1
- package/dist/core/ManagerContext.d.ts +0 -76
- package/dist/core/ManagerContext.d.ts.map +0 -1
- package/dist/core/ManagerContext.js +0 -129
- package/dist/core/ManagerContext.js.map +0 -1
- package/dist/core/ObservationManager.d.ts +0 -85
- package/dist/core/ObservationManager.d.ts.map +0 -1
- package/dist/core/ObservationManager.js +0 -124
- package/dist/core/ObservationManager.js.map +0 -1
- package/dist/core/RelationManager.d.ts +0 -131
- package/dist/core/RelationManager.d.ts.map +0 -1
- package/dist/core/RelationManager.js +0 -212
- package/dist/core/RelationManager.js.map +0 -1
- package/dist/core/SQLiteStorage.d.ts +0 -354
- package/dist/core/SQLiteStorage.d.ts.map +0 -1
- package/dist/core/SQLiteStorage.js +0 -919
- package/dist/core/SQLiteStorage.js.map +0 -1
- package/dist/core/StorageFactory.d.ts +0 -45
- package/dist/core/StorageFactory.d.ts.map +0 -1
- package/dist/core/StorageFactory.js +0 -65
- package/dist/core/StorageFactory.js.map +0 -1
- package/dist/core/TransactionManager.d.ts +0 -464
- package/dist/core/TransactionManager.d.ts.map +0 -1
- package/dist/core/TransactionManager.js +0 -869
- package/dist/core/TransactionManager.js.map +0 -1
- package/dist/core/index.d.ts +0 -17
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -20
- package/dist/core/index.js.map +0 -1
- package/dist/features/AnalyticsManager.d.ts +0 -44
- package/dist/features/AnalyticsManager.d.ts.map +0 -1
- package/dist/features/AnalyticsManager.js +0 -224
- package/dist/features/AnalyticsManager.js.map +0 -1
- package/dist/features/ArchiveManager.d.ts +0 -133
- package/dist/features/ArchiveManager.d.ts.map +0 -1
- package/dist/features/ArchiveManager.js +0 -282
- package/dist/features/ArchiveManager.js.map +0 -1
- package/dist/features/CompressionManager.d.ts +0 -119
- package/dist/features/CompressionManager.d.ts.map +0 -1
- package/dist/features/CompressionManager.js +0 -470
- package/dist/features/CompressionManager.js.map +0 -1
- package/dist/features/IOManager.d.ts +0 -225
- package/dist/features/IOManager.d.ts.map +0 -1
- package/dist/features/IOManager.js +0 -1093
- package/dist/features/IOManager.js.map +0 -1
- package/dist/features/KeywordExtractor.d.ts +0 -61
- package/dist/features/KeywordExtractor.d.ts.map +0 -1
- package/dist/features/KeywordExtractor.js +0 -127
- package/dist/features/KeywordExtractor.js.map +0 -1
- package/dist/features/ObservationNormalizer.d.ts +0 -90
- package/dist/features/ObservationNormalizer.d.ts.map +0 -1
- package/dist/features/ObservationNormalizer.js +0 -194
- package/dist/features/ObservationNormalizer.js.map +0 -1
- package/dist/features/StreamingExporter.d.ts +0 -128
- package/dist/features/StreamingExporter.d.ts.map +0 -1
- package/dist/features/StreamingExporter.js +0 -212
- package/dist/features/StreamingExporter.js.map +0 -1
- package/dist/features/TagManager.d.ts +0 -147
- package/dist/features/TagManager.d.ts.map +0 -1
- package/dist/features/TagManager.js +0 -211
- package/dist/features/TagManager.js.map +0 -1
- package/dist/features/index.d.ts +0 -14
- package/dist/features/index.d.ts.map +0 -1
- package/dist/features/index.js +0 -15
- package/dist/features/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/search/BM25Search.d.ts +0 -148
- package/dist/search/BM25Search.d.ts.map +0 -1
- package/dist/search/BM25Search.js +0 -340
- package/dist/search/BM25Search.js.map +0 -1
- package/dist/search/BasicSearch.d.ts +0 -51
- package/dist/search/BasicSearch.d.ts.map +0 -1
- package/dist/search/BasicSearch.js +0 -138
- package/dist/search/BasicSearch.js.map +0 -1
- package/dist/search/BooleanSearch.d.ts +0 -98
- package/dist/search/BooleanSearch.d.ts.map +0 -1
- package/dist/search/BooleanSearch.js +0 -431
- package/dist/search/BooleanSearch.js.map +0 -1
- package/dist/search/EarlyTerminationManager.d.ts +0 -140
- package/dist/search/EarlyTerminationManager.d.ts.map +0 -1
- package/dist/search/EarlyTerminationManager.js +0 -280
- package/dist/search/EarlyTerminationManager.js.map +0 -1
- package/dist/search/EmbeddingCache.d.ts +0 -175
- package/dist/search/EmbeddingCache.d.ts.map +0 -1
- package/dist/search/EmbeddingCache.js +0 -247
- package/dist/search/EmbeddingCache.js.map +0 -1
- package/dist/search/EmbeddingService.d.ts +0 -277
- package/dist/search/EmbeddingService.d.ts.map +0 -1
- package/dist/search/EmbeddingService.js +0 -531
- package/dist/search/EmbeddingService.js.map +0 -1
- package/dist/search/FuzzySearch.d.ts +0 -118
- package/dist/search/FuzzySearch.d.ts.map +0 -1
- package/dist/search/FuzzySearch.js +0 -313
- package/dist/search/FuzzySearch.js.map +0 -1
- package/dist/search/HybridScorer.d.ts +0 -181
- package/dist/search/HybridScorer.d.ts.map +0 -1
- package/dist/search/HybridScorer.js +0 -258
- package/dist/search/HybridScorer.js.map +0 -1
- package/dist/search/HybridSearchManager.d.ts +0 -80
- package/dist/search/HybridSearchManager.d.ts.map +0 -1
- package/dist/search/HybridSearchManager.js +0 -188
- package/dist/search/HybridSearchManager.js.map +0 -1
- package/dist/search/IncrementalIndexer.d.ts +0 -201
- package/dist/search/IncrementalIndexer.d.ts.map +0 -1
- package/dist/search/IncrementalIndexer.js +0 -343
- package/dist/search/IncrementalIndexer.js.map +0 -1
- package/dist/search/OptimizedInvertedIndex.d.ts +0 -163
- package/dist/search/OptimizedInvertedIndex.d.ts.map +0 -1
- package/dist/search/OptimizedInvertedIndex.js +0 -359
- package/dist/search/OptimizedInvertedIndex.js.map +0 -1
- package/dist/search/ParallelSearchExecutor.d.ts +0 -172
- package/dist/search/ParallelSearchExecutor.d.ts.map +0 -1
- package/dist/search/ParallelSearchExecutor.js +0 -310
- package/dist/search/ParallelSearchExecutor.js.map +0 -1
- package/dist/search/QuantizedVectorStore.d.ts +0 -171
- package/dist/search/QuantizedVectorStore.d.ts.map +0 -1
- package/dist/search/QuantizedVectorStore.js +0 -308
- package/dist/search/QuantizedVectorStore.js.map +0 -1
- package/dist/search/QueryAnalyzer.d.ts +0 -76
- package/dist/search/QueryAnalyzer.d.ts.map +0 -1
- package/dist/search/QueryAnalyzer.js +0 -228
- package/dist/search/QueryAnalyzer.js.map +0 -1
- package/dist/search/QueryCostEstimator.d.ts +0 -244
- package/dist/search/QueryCostEstimator.d.ts.map +0 -1
- package/dist/search/QueryCostEstimator.js +0 -653
- package/dist/search/QueryCostEstimator.js.map +0 -1
- package/dist/search/QueryPlanCache.d.ts +0 -220
- package/dist/search/QueryPlanCache.d.ts.map +0 -1
- package/dist/search/QueryPlanCache.js +0 -380
- package/dist/search/QueryPlanCache.js.map +0 -1
- package/dist/search/QueryPlanner.d.ts +0 -58
- package/dist/search/QueryPlanner.d.ts.map +0 -1
- package/dist/search/QueryPlanner.js +0 -138
- package/dist/search/QueryPlanner.js.map +0 -1
- package/dist/search/RankedSearch.d.ts +0 -71
- package/dist/search/RankedSearch.d.ts.map +0 -1
- package/dist/search/RankedSearch.js +0 -239
- package/dist/search/RankedSearch.js.map +0 -1
- package/dist/search/ReflectionManager.d.ts +0 -120
- package/dist/search/ReflectionManager.d.ts.map +0 -1
- package/dist/search/ReflectionManager.js +0 -232
- package/dist/search/ReflectionManager.js.map +0 -1
- package/dist/search/SavedSearchManager.d.ts +0 -79
- package/dist/search/SavedSearchManager.d.ts.map +0 -1
- package/dist/search/SavedSearchManager.js +0 -147
- package/dist/search/SavedSearchManager.js.map +0 -1
- package/dist/search/SearchFilterChain.d.ts +0 -120
- package/dist/search/SearchFilterChain.d.ts.map +0 -1
- package/dist/search/SearchFilterChain.js +0 -186
- package/dist/search/SearchFilterChain.js.map +0 -1
- package/dist/search/SearchManager.d.ts +0 -326
- package/dist/search/SearchManager.d.ts.map +0 -1
- package/dist/search/SearchManager.js +0 -454
- package/dist/search/SearchManager.js.map +0 -1
- package/dist/search/SearchSuggestions.d.ts +0 -27
- package/dist/search/SearchSuggestions.d.ts.map +0 -1
- package/dist/search/SearchSuggestions.js +0 -58
- package/dist/search/SearchSuggestions.js.map +0 -1
- package/dist/search/SemanticSearch.d.ts +0 -149
- package/dist/search/SemanticSearch.d.ts.map +0 -1
- package/dist/search/SemanticSearch.js +0 -324
- package/dist/search/SemanticSearch.js.map +0 -1
- package/dist/search/SymbolicSearch.d.ts +0 -61
- package/dist/search/SymbolicSearch.d.ts.map +0 -1
- package/dist/search/SymbolicSearch.js +0 -164
- package/dist/search/SymbolicSearch.js.map +0 -1
- package/dist/search/TFIDFEventSync.d.ts +0 -85
- package/dist/search/TFIDFEventSync.d.ts.map +0 -1
- package/dist/search/TFIDFEventSync.js +0 -134
- package/dist/search/TFIDFEventSync.js.map +0 -1
- package/dist/search/TFIDFIndexManager.d.ts +0 -151
- package/dist/search/TFIDFIndexManager.d.ts.map +0 -1
- package/dist/search/TFIDFIndexManager.js +0 -433
- package/dist/search/TFIDFIndexManager.js.map +0 -1
- package/dist/search/VectorStore.d.ts +0 -235
- package/dist/search/VectorStore.d.ts.map +0 -1
- package/dist/search/VectorStore.js +0 -312
- package/dist/search/VectorStore.js.map +0 -1
- package/dist/search/index.d.ts +0 -35
- package/dist/search/index.d.ts.map +0 -1
- package/dist/search/index.js +0 -53
- package/dist/search/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -13
- package/dist/types/index.js.map +0 -1
- package/dist/types/types.d.ts +0 -1811
- package/dist/types/types.d.ts.map +0 -1
- package/dist/types/types.js +0 -10
- package/dist/types/types.js.map +0 -1
- package/dist/utils/BatchProcessor.d.ts +0 -271
- package/dist/utils/BatchProcessor.d.ts.map +0 -1
- package/dist/utils/BatchProcessor.js +0 -377
- package/dist/utils/BatchProcessor.js.map +0 -1
- package/dist/utils/MemoryMonitor.d.ts +0 -176
- package/dist/utils/MemoryMonitor.d.ts.map +0 -1
- package/dist/utils/MemoryMonitor.js +0 -306
- package/dist/utils/MemoryMonitor.js.map +0 -1
- package/dist/utils/WorkerPoolManager.d.ts +0 -233
- package/dist/utils/WorkerPoolManager.d.ts.map +0 -1
- package/dist/utils/WorkerPoolManager.js +0 -421
- package/dist/utils/WorkerPoolManager.js.map +0 -1
- package/dist/utils/compressedCache.d.ts +0 -221
- package/dist/utils/compressedCache.d.ts.map +0 -1
- package/dist/utils/compressedCache.js +0 -349
- package/dist/utils/compressedCache.js.map +0 -1
- package/dist/utils/compressionUtil.d.ts +0 -214
- package/dist/utils/compressionUtil.d.ts.map +0 -1
- package/dist/utils/compressionUtil.js +0 -248
- package/dist/utils/compressionUtil.js.map +0 -1
- package/dist/utils/constants.d.ts +0 -245
- package/dist/utils/constants.d.ts.map +0 -1
- package/dist/utils/constants.js +0 -253
- package/dist/utils/constants.js.map +0 -1
- package/dist/utils/entityUtils.d.ts +0 -379
- package/dist/utils/entityUtils.d.ts.map +0 -1
- package/dist/utils/entityUtils.js +0 -649
- package/dist/utils/entityUtils.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -95
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -146
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/formatters.d.ts +0 -145
- package/dist/utils/formatters.d.ts.map +0 -1
- package/dist/utils/formatters.js +0 -133
- package/dist/utils/formatters.js.map +0 -1
- package/dist/utils/index.d.ts +0 -26
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -88
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/indexes.d.ts +0 -270
- package/dist/utils/indexes.d.ts.map +0 -1
- package/dist/utils/indexes.js +0 -527
- package/dist/utils/indexes.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -31
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -41
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/operationUtils.d.ts +0 -124
- package/dist/utils/operationUtils.d.ts.map +0 -1
- package/dist/utils/operationUtils.js +0 -176
- package/dist/utils/operationUtils.js.map +0 -1
- package/dist/utils/parallelUtils.d.ts +0 -76
- package/dist/utils/parallelUtils.d.ts.map +0 -1
- package/dist/utils/parallelUtils.js +0 -192
- package/dist/utils/parallelUtils.js.map +0 -1
- package/dist/utils/schemas.d.ts +0 -556
- package/dist/utils/schemas.d.ts.map +0 -1
- package/dist/utils/schemas.js +0 -485
- package/dist/utils/schemas.js.map +0 -1
- package/dist/utils/searchAlgorithms.d.ts +0 -99
- package/dist/utils/searchAlgorithms.d.ts.map +0 -1
- package/dist/utils/searchAlgorithms.js +0 -168
- package/dist/utils/searchAlgorithms.js.map +0 -1
- package/dist/utils/searchCache.d.ts +0 -108
- package/dist/utils/searchCache.d.ts.map +0 -1
- package/dist/utils/searchCache.js +0 -210
- package/dist/utils/searchCache.js.map +0 -1
- package/dist/utils/taskScheduler.d.ts +0 -294
- package/dist/utils/taskScheduler.d.ts.map +0 -1
- package/dist/utils/taskScheduler.js +0 -487
- package/dist/utils/taskScheduler.js.map +0 -1
- package/dist/workers/index.d.ts +0 -12
- package/dist/workers/index.d.ts.map +0 -1
- package/dist/workers/index.js +0 -10
- package/dist/workers/index.js.map +0 -1
- package/dist/workers/levenshteinWorker.d.ts +0 -60
- package/dist/workers/levenshteinWorker.d.ts.map +0 -1
|
@@ -1,313 +0,0 @@
|
|
|
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 { levenshteinDistance } from '../utils/index.js';
|
|
10
|
-
import { SEARCH_LIMITS } from '../utils/constants.js';
|
|
11
|
-
import { SearchFilterChain } from './SearchFilterChain.js';
|
|
12
|
-
import workerpool from '@danielsimonjr/workerpool';
|
|
13
|
-
import { fileURLToPath } from 'url';
|
|
14
|
-
import { dirname, join, sep } from 'path';
|
|
15
|
-
/**
|
|
16
|
-
* Default fuzzy search similarity threshold (70% match required).
|
|
17
|
-
* Lower values are more permissive (more typos tolerated).
|
|
18
|
-
* Higher values are stricter (fewer typos tolerated).
|
|
19
|
-
*/
|
|
20
|
-
export const DEFAULT_FUZZY_THRESHOLD = 0.7;
|
|
21
|
-
/**
|
|
22
|
-
* Phase 4 Sprint 3: Maximum cache size to prevent memory bloat.
|
|
23
|
-
*/
|
|
24
|
-
const FUZZY_CACHE_MAX_SIZE = 100;
|
|
25
|
-
/**
|
|
26
|
-
* Phase 4 Sprint 3: Cache TTL in milliseconds (5 minutes).
|
|
27
|
-
*/
|
|
28
|
-
const FUZZY_CACHE_TTL_MS = 5 * 60 * 1000;
|
|
29
|
-
/**
|
|
30
|
-
* Phase 7 Sprint 3: Minimum number of entities to activate worker pool.
|
|
31
|
-
*/
|
|
32
|
-
const WORKER_MIN_ENTITIES = 500;
|
|
33
|
-
/**
|
|
34
|
-
* Phase 7 Sprint 3: Maximum threshold for worker pool activation.
|
|
35
|
-
* Higher thresholds have fewer matches, so single-threaded is faster.
|
|
36
|
-
*/
|
|
37
|
-
const WORKER_MAX_THRESHOLD = 0.8;
|
|
38
|
-
/**
|
|
39
|
-
* Performs fuzzy search with configurable similarity threshold.
|
|
40
|
-
*/
|
|
41
|
-
export class FuzzySearch {
|
|
42
|
-
storage;
|
|
43
|
-
/**
|
|
44
|
-
* Phase 4 Sprint 3: Result cache for fuzzy search.
|
|
45
|
-
* Maps cache key -> cached entity names.
|
|
46
|
-
*/
|
|
47
|
-
fuzzyResultCache = new Map();
|
|
48
|
-
/**
|
|
49
|
-
* Phase 8: Worker pool using workerpool library.
|
|
50
|
-
* Initialized lazily when needed.
|
|
51
|
-
*/
|
|
52
|
-
workerPool = null;
|
|
53
|
-
/**
|
|
54
|
-
* Phase 7 Sprint 3: Path to the worker script.
|
|
55
|
-
*/
|
|
56
|
-
workerPath;
|
|
57
|
-
/**
|
|
58
|
-
* Phase 8: Whether to use worker pool for parallel processing.
|
|
59
|
-
* Can be disabled for testing or when workers are not available.
|
|
60
|
-
*/
|
|
61
|
-
useWorkerPool;
|
|
62
|
-
constructor(storage, options = {}) {
|
|
63
|
-
this.storage = storage;
|
|
64
|
-
this.useWorkerPool = options.useWorkerPool ?? true;
|
|
65
|
-
// Calculate worker path using ESM module resolution
|
|
66
|
-
const currentFileUrl = import.meta.url;
|
|
67
|
-
const currentDir = dirname(fileURLToPath(currentFileUrl));
|
|
68
|
-
// Check if we're running from src/ (during tests) or dist/ (production)
|
|
69
|
-
const isRunningFromSrc = currentDir.includes(`${sep}src${sep}`);
|
|
70
|
-
if (isRunningFromSrc) {
|
|
71
|
-
// During tests, worker is in dist/workers/ relative to project root
|
|
72
|
-
const projectRoot = join(currentDir, '..', '..');
|
|
73
|
-
this.workerPath = join(projectRoot, 'dist', 'workers', 'levenshteinWorker.js');
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
// In production, worker is in dist/workers/ relative to current dist/search/
|
|
77
|
-
this.workerPath = join(currentDir, '..', 'workers', 'levenshteinWorker.js');
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Phase 4 Sprint 3: Generate cache key for fuzzy search parameters.
|
|
82
|
-
*/
|
|
83
|
-
generateCacheKey(query, threshold, tags, minImportance, maxImportance, offset, limit) {
|
|
84
|
-
return JSON.stringify({
|
|
85
|
-
q: query.toLowerCase(),
|
|
86
|
-
t: threshold,
|
|
87
|
-
tags: tags?.sort().join(',') ?? '',
|
|
88
|
-
min: minImportance,
|
|
89
|
-
max: maxImportance,
|
|
90
|
-
off: offset,
|
|
91
|
-
lim: limit,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Phase 4 Sprint 3: Clear the fuzzy search cache.
|
|
96
|
-
*/
|
|
97
|
-
clearCache() {
|
|
98
|
-
this.fuzzyResultCache.clear();
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Phase 4 Sprint 3: Invalidate stale cache entries.
|
|
102
|
-
*/
|
|
103
|
-
cleanupCache() {
|
|
104
|
-
const now = Date.now();
|
|
105
|
-
const entries = Array.from(this.fuzzyResultCache.entries());
|
|
106
|
-
// Remove expired entries
|
|
107
|
-
for (const [key, entry] of entries) {
|
|
108
|
-
if (now - entry.timestamp > FUZZY_CACHE_TTL_MS) {
|
|
109
|
-
this.fuzzyResultCache.delete(key);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// If still over limit, remove oldest entries
|
|
113
|
-
if (this.fuzzyResultCache.size > FUZZY_CACHE_MAX_SIZE) {
|
|
114
|
-
const sortedEntries = entries
|
|
115
|
-
.filter(([k]) => this.fuzzyResultCache.has(k))
|
|
116
|
-
.sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
117
|
-
const toRemove = sortedEntries.slice(0, this.fuzzyResultCache.size - FUZZY_CACHE_MAX_SIZE);
|
|
118
|
-
for (const [key] of toRemove) {
|
|
119
|
-
this.fuzzyResultCache.delete(key);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Fuzzy search for entities with typo tolerance and pagination.
|
|
125
|
-
*
|
|
126
|
-
* Uses Levenshtein distance to calculate similarity between strings.
|
|
127
|
-
* Matches if similarity >= threshold (0.0 to 1.0).
|
|
128
|
-
*
|
|
129
|
-
* Phase 4 Sprint 3: Implements result caching for repeated queries.
|
|
130
|
-
*
|
|
131
|
-
* @param query - Search query
|
|
132
|
-
* @param threshold - Similarity threshold (0.0 to 1.0), default DEFAULT_FUZZY_THRESHOLD
|
|
133
|
-
* @param tags - Optional tags filter
|
|
134
|
-
* @param minImportance - Optional minimum importance
|
|
135
|
-
* @param maxImportance - Optional maximum importance
|
|
136
|
-
* @param offset - Number of results to skip (default: 0)
|
|
137
|
-
* @param limit - Maximum number of results (default: 50, max: 200)
|
|
138
|
-
* @returns Filtered knowledge graph with fuzzy matches and pagination applied
|
|
139
|
-
*/
|
|
140
|
-
async fuzzySearch(query, threshold = DEFAULT_FUZZY_THRESHOLD, tags, minImportance, maxImportance, offset = 0, limit = SEARCH_LIMITS.DEFAULT) {
|
|
141
|
-
const graph = await this.storage.loadGraph();
|
|
142
|
-
const queryLower = query.toLowerCase();
|
|
143
|
-
// Phase 4 Sprint 3: Generate cache key and check cache
|
|
144
|
-
const cacheKey = this.generateCacheKey(query, threshold, tags, minImportance, maxImportance, offset, limit);
|
|
145
|
-
const cached = this.fuzzyResultCache.get(cacheKey);
|
|
146
|
-
// Check if cache is valid (entity count hasn't changed)
|
|
147
|
-
if (cached && cached.entityCount === graph.entities.length) {
|
|
148
|
-
const now = Date.now();
|
|
149
|
-
if (now - cached.timestamp < FUZZY_CACHE_TTL_MS) {
|
|
150
|
-
// Return cached results
|
|
151
|
-
const cachedNameSet = new Set(cached.entityNames);
|
|
152
|
-
const cachedEntities = graph.entities.filter(e => cachedNameSet.has(e.name));
|
|
153
|
-
const cachedEntityNames = new Set(cached.entityNames);
|
|
154
|
-
const cachedRelations = graph.relations.filter(r => cachedEntityNames.has(r.from) && cachedEntityNames.has(r.to));
|
|
155
|
-
return { entities: cachedEntities, relations: cachedRelations };
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// Phase 7 Sprint 3: Use worker pool for large graphs with low thresholds
|
|
159
|
-
// Phase 8: Respect useWorkerPool flag for testing
|
|
160
|
-
const shouldUseWorkers = this.useWorkerPool &&
|
|
161
|
-
graph.entities.length >= WORKER_MIN_ENTITIES &&
|
|
162
|
-
threshold < WORKER_MAX_THRESHOLD;
|
|
163
|
-
let fuzzyMatched;
|
|
164
|
-
if (shouldUseWorkers) {
|
|
165
|
-
fuzzyMatched = await this.searchWithWorkers(query, threshold, graph.entities);
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
// Perform single-threaded fuzzy search
|
|
169
|
-
fuzzyMatched = this.performFuzzyMatch(graph.entities, queryLower, threshold);
|
|
170
|
-
}
|
|
171
|
-
// Apply tag and importance filters using SearchFilterChain
|
|
172
|
-
const filters = { tags, minImportance, maxImportance };
|
|
173
|
-
const filteredEntities = SearchFilterChain.applyFilters(fuzzyMatched, filters);
|
|
174
|
-
// Apply pagination using SearchFilterChain
|
|
175
|
-
const pagination = SearchFilterChain.validatePagination(offset, limit);
|
|
176
|
-
const paginatedEntities = SearchFilterChain.paginate(filteredEntities, pagination);
|
|
177
|
-
// Phase 4 Sprint 3: Cache the results
|
|
178
|
-
this.fuzzyResultCache.set(cacheKey, {
|
|
179
|
-
entityNames: paginatedEntities.map(e => e.name),
|
|
180
|
-
entityCount: graph.entities.length,
|
|
181
|
-
timestamp: Date.now(),
|
|
182
|
-
});
|
|
183
|
-
// Cleanup old cache entries periodically
|
|
184
|
-
if (this.fuzzyResultCache.size > FUZZY_CACHE_MAX_SIZE / 2) {
|
|
185
|
-
this.cleanupCache();
|
|
186
|
-
}
|
|
187
|
-
const filteredEntityNames = new Set(paginatedEntities.map(e => e.name));
|
|
188
|
-
const filteredRelations = graph.relations.filter(r => filteredEntityNames.has(r.from) && filteredEntityNames.has(r.to));
|
|
189
|
-
return {
|
|
190
|
-
entities: paginatedEntities,
|
|
191
|
-
relations: filteredRelations,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Phase 4 Sprint 3: Perform the actual fuzzy matching logic.
|
|
196
|
-
* Extracted from fuzzySearch for cleaner code structure.
|
|
197
|
-
*/
|
|
198
|
-
performFuzzyMatch(entities, queryLower, threshold) {
|
|
199
|
-
return entities.filter(e => {
|
|
200
|
-
const lowercased = this.storage.getLowercased(e.name);
|
|
201
|
-
// Check name match (use pre-computed lowercase)
|
|
202
|
-
const nameLower = lowercased?.name ?? e.name.toLowerCase();
|
|
203
|
-
if (this.isFuzzyMatchLower(nameLower, queryLower, threshold))
|
|
204
|
-
return true;
|
|
205
|
-
// Check type match (use pre-computed lowercase)
|
|
206
|
-
const typeLower = lowercased?.entityType ?? e.entityType.toLowerCase();
|
|
207
|
-
if (this.isFuzzyMatchLower(typeLower, queryLower, threshold))
|
|
208
|
-
return true;
|
|
209
|
-
// Check observations (use pre-computed lowercase array)
|
|
210
|
-
const obsLower = lowercased?.observations ?? e.observations.map(o => o.toLowerCase());
|
|
211
|
-
return obsLower.some(o =>
|
|
212
|
-
// For observations, split into words and check each word
|
|
213
|
-
o
|
|
214
|
-
.split(/\s+/)
|
|
215
|
-
.some(word => this.isFuzzyMatchLower(word, queryLower, threshold)) ||
|
|
216
|
-
// Also check if the observation contains the query
|
|
217
|
-
this.isFuzzyMatchLower(o, queryLower, threshold));
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Check if two already-lowercase strings match with fuzzy logic.
|
|
222
|
-
*
|
|
223
|
-
* OPTIMIZED: Skips toLowerCase() calls when strings are already lowercase.
|
|
224
|
-
*
|
|
225
|
-
* @param s1 - First string (already lowercase)
|
|
226
|
-
* @param s2 - Second string (already lowercase)
|
|
227
|
-
* @param threshold - Similarity threshold (0.0 to 1.0)
|
|
228
|
-
* @returns True if strings match fuzzily
|
|
229
|
-
*/
|
|
230
|
-
isFuzzyMatchLower(s1, s2, threshold = 0.7) {
|
|
231
|
-
// Exact match
|
|
232
|
-
if (s1 === s2)
|
|
233
|
-
return true;
|
|
234
|
-
// One contains the other
|
|
235
|
-
if (s1.includes(s2) || s2.includes(s1))
|
|
236
|
-
return true;
|
|
237
|
-
// Calculate similarity using Levenshtein distance
|
|
238
|
-
const distance = levenshteinDistance(s1, s2);
|
|
239
|
-
const maxLength = Math.max(s1.length, s2.length);
|
|
240
|
-
const similarity = 1 - distance / maxLength;
|
|
241
|
-
return similarity >= threshold;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Phase 8: Perform fuzzy search using workerpool for parallel processing.
|
|
245
|
-
*
|
|
246
|
-
* Splits entities into chunks and processes them in parallel using worker threads.
|
|
247
|
-
* Falls back to single-threaded search if worker execution fails.
|
|
248
|
-
*
|
|
249
|
-
* @param query - Search query
|
|
250
|
-
* @param threshold - Similarity threshold
|
|
251
|
-
* @param entities - Entities to search
|
|
252
|
-
* @returns Array of matched entities
|
|
253
|
-
*/
|
|
254
|
-
async searchWithWorkers(query, threshold, entities) {
|
|
255
|
-
try {
|
|
256
|
-
// Initialize worker pool lazily using workerpool
|
|
257
|
-
if (!this.workerPool) {
|
|
258
|
-
// Enable ESM module support for Node.js 20+
|
|
259
|
-
// The 'type: module' option is needed for ESM workers but may not be in @types/node
|
|
260
|
-
const workerThreadOpts = { type: 'module' };
|
|
261
|
-
this.workerPool = workerpool.pool(this.workerPath, {
|
|
262
|
-
maxWorkers: Math.max(1, workerpool.cpus - 1),
|
|
263
|
-
workerType: 'thread',
|
|
264
|
-
workerThreadOpts,
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
// Split entities into chunks based on CPU count
|
|
268
|
-
const numWorkers = Math.max(1, workerpool.cpus - 1);
|
|
269
|
-
const chunkSize = Math.ceil(entities.length / numWorkers);
|
|
270
|
-
const chunks = [];
|
|
271
|
-
for (let i = 0; i < entities.length; i += chunkSize) {
|
|
272
|
-
chunks.push(entities.slice(i, i + chunkSize));
|
|
273
|
-
}
|
|
274
|
-
// Prepare worker inputs with lowercased data
|
|
275
|
-
const workerInputs = chunks.map(chunk => ({
|
|
276
|
-
query,
|
|
277
|
-
threshold,
|
|
278
|
-
entities: chunk.map(e => ({
|
|
279
|
-
name: e.name,
|
|
280
|
-
nameLower: e.name.toLowerCase(),
|
|
281
|
-
observations: e.observations.map(o => o.toLowerCase()),
|
|
282
|
-
})),
|
|
283
|
-
}));
|
|
284
|
-
// Execute all chunks in parallel using workerpool with timeout
|
|
285
|
-
const WORKER_TIMEOUT_MS = 30000; // 30 seconds
|
|
286
|
-
const results = await Promise.all(workerInputs.map(input => this.workerPool.exec('searchEntities', [input])
|
|
287
|
-
.timeout(WORKER_TIMEOUT_MS)));
|
|
288
|
-
// Flatten results and extract matched entity names
|
|
289
|
-
const matchedNames = new Set(results.flat().map(r => r.name));
|
|
290
|
-
// Return entities that matched
|
|
291
|
-
return entities.filter(e => matchedNames.has(e.name));
|
|
292
|
-
}
|
|
293
|
-
catch (error) {
|
|
294
|
-
// Worker execution failed - fall back to single-threaded mode
|
|
295
|
-
console.warn(`Worker pool execution failed, falling back to single-threaded fuzzy search: ${error instanceof Error ? error.message : String(error)}`);
|
|
296
|
-
// Use the existing single-threaded implementation
|
|
297
|
-
const queryLower = query.toLowerCase();
|
|
298
|
-
return this.performFuzzyMatch(entities, queryLower, threshold);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Phase 8: Shutdown the worker pool and clean up resources.
|
|
303
|
-
*
|
|
304
|
-
* Should be called when FuzzySearch is no longer needed.
|
|
305
|
-
*/
|
|
306
|
-
async shutdown() {
|
|
307
|
-
if (this.workerPool) {
|
|
308
|
-
await this.workerPool.terminate();
|
|
309
|
-
this.workerPool = null;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
//# sourceMappingURL=FuzzySearch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FuzzySearch.js","sourceRoot":"","sources":["../../src/search/FuzzySearch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hybrid Scorer
|
|
3
|
-
*
|
|
4
|
-
* Combines semantic, lexical, and symbolic search scores with
|
|
5
|
-
* min-max normalization and configurable weights.
|
|
6
|
-
*
|
|
7
|
-
* Phase 12 Sprint 3: Search Algorithm Optimization
|
|
8
|
-
*
|
|
9
|
-
* @module search/HybridScorer
|
|
10
|
-
*/
|
|
11
|
-
import type { Entity } from '../types/index.js';
|
|
12
|
-
/**
|
|
13
|
-
* Result from semantic search layer.
|
|
14
|
-
*/
|
|
15
|
-
export interface SemanticLayerResult {
|
|
16
|
-
/** Entity name */
|
|
17
|
-
entityName: string;
|
|
18
|
-
/** Similarity score (typically 0-1 for cosine similarity) */
|
|
19
|
-
similarity: number;
|
|
20
|
-
/** The matched entity (if resolved) */
|
|
21
|
-
entity?: Entity;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Result from lexical search layer (TF-IDF or BM25).
|
|
25
|
-
*/
|
|
26
|
-
export interface LexicalSearchResult {
|
|
27
|
-
/** Entity name */
|
|
28
|
-
entityName: string;
|
|
29
|
-
/** Relevance score (unbounded, higher is better) */
|
|
30
|
-
score: number;
|
|
31
|
-
/** The matched entity (if resolved) */
|
|
32
|
-
entity?: Entity;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Result from symbolic search layer.
|
|
36
|
-
*/
|
|
37
|
-
export interface SymbolicSearchResult {
|
|
38
|
-
/** Entity name */
|
|
39
|
-
entityName: string;
|
|
40
|
-
/** Match score (typically 0-1) */
|
|
41
|
-
score: number;
|
|
42
|
-
/** The matched entity (if resolved) */
|
|
43
|
-
entity?: Entity;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Combined result with scores from all layers.
|
|
47
|
-
*/
|
|
48
|
-
export interface ScoredResult {
|
|
49
|
-
/** Entity name */
|
|
50
|
-
entityName: string;
|
|
51
|
-
/** The matched entity */
|
|
52
|
-
entity: Entity;
|
|
53
|
-
/** Individual layer scores (normalized 0-1) */
|
|
54
|
-
scores: {
|
|
55
|
-
semantic: number;
|
|
56
|
-
lexical: number;
|
|
57
|
-
symbolic: number;
|
|
58
|
-
combined: number;
|
|
59
|
-
};
|
|
60
|
-
/** Which layers contributed to this result */
|
|
61
|
-
matchedLayers: ('semantic' | 'lexical' | 'symbolic')[];
|
|
62
|
-
/** Original raw scores before normalization */
|
|
63
|
-
rawScores: {
|
|
64
|
-
semantic?: number;
|
|
65
|
-
lexical?: number;
|
|
66
|
-
symbolic?: number;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Configurable weights for hybrid scoring.
|
|
71
|
-
*/
|
|
72
|
-
export interface HybridWeights {
|
|
73
|
-
/** Weight for semantic layer (default: 0.4) */
|
|
74
|
-
semantic: number;
|
|
75
|
-
/** Weight for lexical layer (default: 0.4) */
|
|
76
|
-
lexical: number;
|
|
77
|
-
/** Weight for symbolic layer (default: 0.2) */
|
|
78
|
-
symbolic: number;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Default weights for hybrid search.
|
|
82
|
-
*/
|
|
83
|
-
export declare const DEFAULT_SCORER_WEIGHTS: HybridWeights;
|
|
84
|
-
/**
|
|
85
|
-
* Options for the HybridScorer.
|
|
86
|
-
*/
|
|
87
|
-
export interface HybridScorerOptions {
|
|
88
|
-
/** Weights for each layer */
|
|
89
|
-
weights?: Partial<HybridWeights>;
|
|
90
|
-
/** Minimum score to include in results (default: 0) */
|
|
91
|
-
minScore?: number;
|
|
92
|
-
/** Whether to normalize weights to sum to 1 (default: true) */
|
|
93
|
-
normalizeWeights?: boolean;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* HybridScorer combines multiple search signals using min-max normalization.
|
|
97
|
-
*
|
|
98
|
-
* Features:
|
|
99
|
-
* 1. Min-max normalization brings all scores to 0-1 range
|
|
100
|
-
* 2. Configurable weights for each layer
|
|
101
|
-
* 3. Handles missing layers gracefully (redistributes weights)
|
|
102
|
-
* 4. Tracks which layers contributed to each result
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```typescript
|
|
106
|
-
* const scorer = new HybridScorer({
|
|
107
|
-
* weights: { semantic: 0.5, lexical: 0.3, symbolic: 0.2 }
|
|
108
|
-
* });
|
|
109
|
-
*
|
|
110
|
-
* const results = scorer.combine(
|
|
111
|
-
* semanticResults,
|
|
112
|
-
* lexicalResults,
|
|
113
|
-
* symbolicResults,
|
|
114
|
-
* entityMap
|
|
115
|
-
* );
|
|
116
|
-
* ```
|
|
117
|
-
*/
|
|
118
|
-
export declare class HybridScorer {
|
|
119
|
-
private weights;
|
|
120
|
-
private minScore;
|
|
121
|
-
private normalizeWeights;
|
|
122
|
-
constructor(options?: HybridScorerOptions);
|
|
123
|
-
/**
|
|
124
|
-
* Get current weights configuration.
|
|
125
|
-
*/
|
|
126
|
-
getWeights(): HybridWeights;
|
|
127
|
-
/**
|
|
128
|
-
* Update weights configuration.
|
|
129
|
-
*/
|
|
130
|
-
setWeights(weights: Partial<HybridWeights>): void;
|
|
131
|
-
/**
|
|
132
|
-
* Perform min-max normalization on scores.
|
|
133
|
-
*
|
|
134
|
-
* Formula: normalized = (x - min) / (max - min)
|
|
135
|
-
*
|
|
136
|
-
* @param scores - Map of entity name to raw score
|
|
137
|
-
* @returns Map of entity name to normalized score (0-1)
|
|
138
|
-
*/
|
|
139
|
-
minMaxNormalize(scores: Map<string, number>): Map<string, number>;
|
|
140
|
-
/**
|
|
141
|
-
* Combine results from all three search layers.
|
|
142
|
-
*
|
|
143
|
-
* @param semanticResults - Results from semantic search
|
|
144
|
-
* @param lexicalResults - Results from lexical search
|
|
145
|
-
* @param symbolicResults - Results from symbolic search
|
|
146
|
-
* @param entityMap - Map of entity names to Entity objects
|
|
147
|
-
* @returns Array of combined results sorted by score
|
|
148
|
-
*/
|
|
149
|
-
combine(semanticResults: SemanticLayerResult[], lexicalResults: LexicalSearchResult[], symbolicResults: SymbolicSearchResult[], entityMap: Map<string, Entity>): ScoredResult[];
|
|
150
|
-
/**
|
|
151
|
-
* Get weights normalized to sum to 1, redistributing for missing layers.
|
|
152
|
-
*
|
|
153
|
-
* @param hasSemantic - Whether semantic results are available
|
|
154
|
-
* @param hasLexical - Whether lexical results are available
|
|
155
|
-
* @param hasSymbolic - Whether symbolic results are available
|
|
156
|
-
* @returns Normalized weights
|
|
157
|
-
*/
|
|
158
|
-
getNormalizedWeights(hasSemantic: boolean, hasLexical: boolean, hasSymbolic: boolean): HybridWeights;
|
|
159
|
-
/**
|
|
160
|
-
* Combine scores from maps directly (alternative interface).
|
|
161
|
-
*
|
|
162
|
-
* @param semanticScores - Map of entity name to semantic score
|
|
163
|
-
* @param lexicalScores - Map of entity name to lexical score
|
|
164
|
-
* @param symbolicScores - Map of entity name to symbolic score
|
|
165
|
-
* @param entityMap - Map of entity names to Entity objects
|
|
166
|
-
* @returns Array of combined results sorted by score
|
|
167
|
-
*/
|
|
168
|
-
combineFromMaps(semanticScores: Map<string, number>, lexicalScores: Map<string, number>, symbolicScores: Map<string, number>, entityMap: Map<string, Entity>): ScoredResult[];
|
|
169
|
-
/**
|
|
170
|
-
* Calculate combined score for a single entity.
|
|
171
|
-
*
|
|
172
|
-
* Useful for scoring individual results without full normalization.
|
|
173
|
-
*
|
|
174
|
-
* @param semanticScore - Normalized semantic score (0-1)
|
|
175
|
-
* @param lexicalScore - Normalized lexical score (0-1)
|
|
176
|
-
* @param symbolicScore - Normalized symbolic score (0-1)
|
|
177
|
-
* @returns Combined weighted score
|
|
178
|
-
*/
|
|
179
|
-
calculateScore(semanticScore: number, lexicalScore: number, symbolicScore: number): number;
|
|
180
|
-
}
|
|
181
|
-
//# sourceMappingURL=HybridScorer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"HybridScorer.d.ts","sourceRoot":"","sources":["../../src/search/HybridScorer.ts"],"names":[],"mappings":"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"}
|