@danielsimonjr/memory-mcp 0.7.2 → 0.41.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/dist/__tests__/edge-cases/edge-cases.test.js +406 -0
- package/dist/__tests__/file-path.test.js +5 -5
- package/dist/__tests__/integration/workflows.test.js +449 -0
- package/dist/__tests__/knowledge-graph.test.js +8 -3
- package/dist/__tests__/performance/benchmarks.test.js +411 -0
- package/dist/__tests__/unit/core/EntityManager.test.js +334 -0
- package/dist/__tests__/unit/core/GraphStorage.test.js +205 -0
- package/dist/__tests__/unit/core/RelationManager.test.js +274 -0
- package/dist/__tests__/unit/features/CompressionManager.test.js +350 -0
- package/dist/__tests__/unit/search/BasicSearch.test.js +311 -0
- package/dist/__tests__/unit/search/BooleanSearch.test.js +432 -0
- package/dist/__tests__/unit/search/FuzzySearch.test.js +448 -0
- package/dist/__tests__/unit/search/RankedSearch.test.js +379 -0
- package/dist/__tests__/unit/utils/levenshtein.test.js +77 -0
- package/dist/core/EntityManager.js +554 -0
- package/dist/core/GraphStorage.js +172 -0
- package/dist/core/KnowledgeGraphManager.js +400 -0
- package/dist/core/ObservationManager.js +129 -0
- package/dist/core/RelationManager.js +186 -0
- package/dist/core/TransactionManager.js +389 -0
- package/dist/core/index.js +9 -0
- package/dist/features/AnalyticsManager.js +222 -0
- package/dist/features/ArchiveManager.js +74 -0
- package/dist/features/BackupManager.js +311 -0
- package/dist/features/CompressionManager.js +310 -0
- package/dist/features/ExportManager.js +305 -0
- package/dist/features/HierarchyManager.js +219 -0
- package/dist/features/ImportExportManager.js +50 -0
- package/dist/features/ImportManager.js +328 -0
- package/dist/features/TagManager.js +210 -0
- package/dist/features/index.js +12 -0
- package/dist/index.js +13 -996
- package/dist/memory.jsonl +225 -0
- package/dist/search/BasicSearch.js +161 -0
- package/dist/search/BooleanSearch.js +304 -0
- package/dist/search/FuzzySearch.js +115 -0
- package/dist/search/RankedSearch.js +206 -0
- package/dist/search/SavedSearchManager.js +145 -0
- package/dist/search/SearchManager.js +305 -0
- package/dist/search/SearchSuggestions.js +57 -0
- package/dist/search/TFIDFIndexManager.js +217 -0
- package/dist/search/index.js +10 -0
- package/dist/server/MCPServer.js +889 -0
- package/dist/types/analytics.types.js +6 -0
- package/dist/types/entity.types.js +7 -0
- package/dist/types/import-export.types.js +7 -0
- package/dist/types/index.js +12 -0
- package/dist/types/search.types.js +7 -0
- package/dist/types/tag.types.js +6 -0
- package/dist/utils/constants.js +127 -0
- package/dist/utils/dateUtils.js +89 -0
- package/dist/utils/errors.js +121 -0
- package/dist/utils/index.js +13 -0
- package/dist/utils/levenshtein.js +62 -0
- package/dist/utils/logger.js +33 -0
- package/dist/utils/pathUtils.js +115 -0
- package/dist/utils/schemas.js +184 -0
- package/dist/utils/searchCache.js +209 -0
- package/dist/utils/tfidf.js +90 -0
- package/dist/utils/validationUtils.js +109 -0
- package/package.json +50 -48
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tag Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages tag aliases and canonical tag resolution.
|
|
5
|
+
*
|
|
6
|
+
* @module features/TagManager
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'fs/promises';
|
|
9
|
+
/**
|
|
10
|
+
* Manages tag alias system for synonym mapping.
|
|
11
|
+
*/
|
|
12
|
+
export class TagManager {
|
|
13
|
+
tagAliasesFilePath;
|
|
14
|
+
constructor(tagAliasesFilePath) {
|
|
15
|
+
this.tagAliasesFilePath = tagAliasesFilePath;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Load all tag aliases from JSONL file.
|
|
19
|
+
*
|
|
20
|
+
* @returns Array of tag aliases
|
|
21
|
+
*/
|
|
22
|
+
async loadTagAliases() {
|
|
23
|
+
try {
|
|
24
|
+
const data = await fs.readFile(this.tagAliasesFilePath, 'utf-8');
|
|
25
|
+
const lines = data.split('\n').filter((line) => line.trim() !== '');
|
|
26
|
+
return lines.map((line) => JSON.parse(line));
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Save tag aliases to JSONL file.
|
|
37
|
+
*
|
|
38
|
+
* @param aliases - Array of tag aliases
|
|
39
|
+
*/
|
|
40
|
+
async saveTagAliases(aliases) {
|
|
41
|
+
const lines = aliases.map(a => JSON.stringify(a));
|
|
42
|
+
await fs.writeFile(this.tagAliasesFilePath, lines.join('\n'));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve a tag through aliases to get its canonical form.
|
|
46
|
+
*
|
|
47
|
+
* This method follows the alias chain to find the canonical (main) tag name.
|
|
48
|
+
* All tags are normalized to lowercase for consistency.
|
|
49
|
+
* If the tag has no alias, it returns the tag itself as canonical.
|
|
50
|
+
*
|
|
51
|
+
* @param tag - Tag to resolve (can be alias or canonical)
|
|
52
|
+
* @returns Canonical tag name (lowercase)
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const manager = new TagManager(tagAliasesPath);
|
|
57
|
+
*
|
|
58
|
+
* // Set up: assume "js" is aliased to "javascript"
|
|
59
|
+
* await manager.addTagAlias('js', 'javascript');
|
|
60
|
+
*
|
|
61
|
+
* // Resolve alias to canonical
|
|
62
|
+
* const canonical = await manager.resolveTag('js');
|
|
63
|
+
* console.log(canonical); // "javascript"
|
|
64
|
+
*
|
|
65
|
+
* // Resolve canonical tag (returns as-is)
|
|
66
|
+
* const unchanged = await manager.resolveTag('javascript');
|
|
67
|
+
* console.log(unchanged); // "javascript"
|
|
68
|
+
*
|
|
69
|
+
* // Resolve unknown tag (returns normalized)
|
|
70
|
+
* const unknown = await manager.resolveTag('PYTHON');
|
|
71
|
+
* console.log(unknown); // "python"
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
async resolveTag(tag) {
|
|
75
|
+
const aliases = await this.loadTagAliases();
|
|
76
|
+
const normalized = tag.toLowerCase();
|
|
77
|
+
// Check if this tag is an alias
|
|
78
|
+
const alias = aliases.find(a => a.alias === normalized);
|
|
79
|
+
if (alias) {
|
|
80
|
+
return alias.canonical;
|
|
81
|
+
}
|
|
82
|
+
// Return as-is (might be canonical or unaliased tag)
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Add a tag alias (synonym mapping).
|
|
87
|
+
*
|
|
88
|
+
* Creates a mapping from an alias (synonym) to a canonical (main) tag.
|
|
89
|
+
* This enables flexible tagging where users can use different terms
|
|
90
|
+
* that all resolve to the same canonical tag.
|
|
91
|
+
*
|
|
92
|
+
* Validation rules:
|
|
93
|
+
* - Prevents duplicate aliases (same alias can't map to different canonicals)
|
|
94
|
+
* - Prevents chained aliases (alias must point to canonical, not another alias)
|
|
95
|
+
* - All tags are normalized to lowercase
|
|
96
|
+
*
|
|
97
|
+
* @param alias - The alias/synonym (will be normalized to lowercase)
|
|
98
|
+
* @param canonical - The canonical (main) tag name (will be normalized to lowercase)
|
|
99
|
+
* @param description - Optional description explaining the alias relationship
|
|
100
|
+
* @returns Newly created TagAlias object with metadata
|
|
101
|
+
* @throws {Error} If alias already exists or would create chained aliases
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const manager = new TagManager(tagAliasesPath);
|
|
106
|
+
*
|
|
107
|
+
* // Create simple alias
|
|
108
|
+
* await manager.addTagAlias('js', 'javascript', 'Common abbreviation');
|
|
109
|
+
*
|
|
110
|
+
* // Create multiple aliases for same canonical
|
|
111
|
+
* await manager.addTagAlias('py', 'python');
|
|
112
|
+
* await manager.addTagAlias('py3', 'python', 'Python 3.x');
|
|
113
|
+
*
|
|
114
|
+
* // Error: duplicate alias
|
|
115
|
+
* try {
|
|
116
|
+
* await manager.addTagAlias('js', 'ecmascript'); // Fails - 'js' already aliased
|
|
117
|
+
* } catch (error) {
|
|
118
|
+
* console.error('Alias already exists');
|
|
119
|
+
* }
|
|
120
|
+
*
|
|
121
|
+
* // Error: chained alias
|
|
122
|
+
* await manager.addTagAlias('js', 'javascript');
|
|
123
|
+
* try {
|
|
124
|
+
* await manager.addTagAlias('javascript', 'ecmascript'); // Fails - can't alias canonical
|
|
125
|
+
* } catch (error) {
|
|
126
|
+
* console.error('Cannot create chained aliases');
|
|
127
|
+
* }
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
async addTagAlias(alias, canonical, description) {
|
|
131
|
+
const aliases = await this.loadTagAliases();
|
|
132
|
+
const normalizedAlias = alias.toLowerCase();
|
|
133
|
+
const normalizedCanonical = canonical.toLowerCase();
|
|
134
|
+
// Check if alias already exists
|
|
135
|
+
if (aliases.some(a => a.alias === normalizedAlias)) {
|
|
136
|
+
throw new Error(`Tag alias "${alias}" already exists`);
|
|
137
|
+
}
|
|
138
|
+
// Prevent aliasing to another alias (aliases should point to canonical tags)
|
|
139
|
+
if (aliases.some(a => a.canonical === normalizedAlias)) {
|
|
140
|
+
throw new Error(`Cannot create alias to "${alias}" because it is a canonical tag with existing aliases`);
|
|
141
|
+
}
|
|
142
|
+
const newAlias = {
|
|
143
|
+
alias: normalizedAlias,
|
|
144
|
+
canonical: normalizedCanonical,
|
|
145
|
+
description,
|
|
146
|
+
createdAt: new Date().toISOString(),
|
|
147
|
+
};
|
|
148
|
+
aliases.push(newAlias);
|
|
149
|
+
await this.saveTagAliases(aliases);
|
|
150
|
+
return newAlias;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* List all tag aliases.
|
|
154
|
+
*
|
|
155
|
+
* @returns Array of all tag aliases
|
|
156
|
+
*/
|
|
157
|
+
async listTagAliases() {
|
|
158
|
+
return await this.loadTagAliases();
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Remove a tag alias.
|
|
162
|
+
*
|
|
163
|
+
* @param alias - Alias to remove
|
|
164
|
+
* @returns True if removed, false if not found
|
|
165
|
+
*/
|
|
166
|
+
async removeTagAlias(alias) {
|
|
167
|
+
const aliases = await this.loadTagAliases();
|
|
168
|
+
const normalizedAlias = alias.toLowerCase();
|
|
169
|
+
const initialLength = aliases.length;
|
|
170
|
+
const filtered = aliases.filter(a => a.alias !== normalizedAlias);
|
|
171
|
+
if (filtered.length === initialLength) {
|
|
172
|
+
return false; // Alias not found
|
|
173
|
+
}
|
|
174
|
+
await this.saveTagAliases(filtered);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get all aliases (synonyms) for a canonical tag.
|
|
179
|
+
*
|
|
180
|
+
* Returns all alias names that resolve to the specified canonical tag.
|
|
181
|
+
* Useful for discovering alternative names users might use for a tag.
|
|
182
|
+
* The canonical tag name is normalized to lowercase.
|
|
183
|
+
*
|
|
184
|
+
* @param canonicalTag - Canonical tag name (will be normalized to lowercase)
|
|
185
|
+
* @returns Array of alias names (all lowercase)
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```typescript
|
|
189
|
+
* const manager = new TagManager(tagAliasesPath);
|
|
190
|
+
*
|
|
191
|
+
* // Set up some aliases
|
|
192
|
+
* await manager.addTagAlias('js', 'javascript');
|
|
193
|
+
* await manager.addTagAlias('ecmascript', 'javascript');
|
|
194
|
+
* await manager.addTagAlias('es6', 'javascript');
|
|
195
|
+
*
|
|
196
|
+
* // Get all aliases for canonical tag
|
|
197
|
+
* const aliases = await manager.getAliasesForTag('javascript');
|
|
198
|
+
* console.log(aliases); // ['js', 'ecmascript', 'es6']
|
|
199
|
+
*
|
|
200
|
+
* // Empty array if no aliases
|
|
201
|
+
* const noAliases = await manager.getAliasesForTag('python');
|
|
202
|
+
* console.log(noAliases); // []
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
async getAliasesForTag(canonicalTag) {
|
|
206
|
+
const aliases = await this.loadTagAliases();
|
|
207
|
+
const normalized = canonicalTag.toLowerCase();
|
|
208
|
+
return aliases.filter(a => a.canonical === normalized).map(a => a.alias);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Features Module Barrel Export
|
|
3
|
+
*/
|
|
4
|
+
export { TagManager } from './TagManager.js';
|
|
5
|
+
export { HierarchyManager } from './HierarchyManager.js';
|
|
6
|
+
export { AnalyticsManager } from './AnalyticsManager.js';
|
|
7
|
+
export { CompressionManager } from './CompressionManager.js';
|
|
8
|
+
export { ArchiveManager } from './ArchiveManager.js';
|
|
9
|
+
export { BackupManager } from './BackupManager.js';
|
|
10
|
+
export { ExportManager } from './ExportManager.js';
|
|
11
|
+
export { ImportManager } from './ImportManager.js';
|
|
12
|
+
export { ImportExportManager } from './ImportExportManager.js';
|