@danielsimonjr/memory-mcp 0.48.0 → 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.
- package/LICENSE +22 -0
- package/README.md +2000 -194
- package/dist/__tests__/file-path.test.js +7 -11
- package/dist/__tests__/knowledge-graph.test.js +3 -8
- package/dist/core/EntityManager.d.ts +266 -0
- package/dist/core/EntityManager.d.ts.map +1 -0
- package/dist/core/EntityManager.js +85 -133
- package/dist/core/GraphEventEmitter.d.ts +202 -0
- package/dist/core/GraphEventEmitter.d.ts.map +1 -0
- package/dist/core/GraphEventEmitter.js +346 -0
- package/dist/core/GraphStorage.d.ts +395 -0
- package/dist/core/GraphStorage.d.ts.map +1 -0
- package/dist/core/GraphStorage.js +643 -31
- package/dist/core/GraphTraversal.d.ts +141 -0
- package/dist/core/GraphTraversal.d.ts.map +1 -0
- package/dist/core/GraphTraversal.js +573 -0
- package/dist/core/HierarchyManager.d.ts +111 -0
- package/dist/core/HierarchyManager.d.ts.map +1 -0
- package/dist/{features → core}/HierarchyManager.js +14 -9
- package/dist/core/ManagerContext.d.ts +72 -0
- package/dist/core/ManagerContext.d.ts.map +1 -0
- package/dist/core/ManagerContext.js +118 -0
- package/dist/core/ObservationManager.d.ts +85 -0
- package/dist/core/ObservationManager.d.ts.map +1 -0
- package/dist/core/ObservationManager.js +51 -57
- package/dist/core/RelationManager.d.ts +131 -0
- package/dist/core/RelationManager.d.ts.map +1 -0
- package/dist/core/RelationManager.js +31 -7
- package/dist/core/SQLiteStorage.d.ts +354 -0
- package/dist/core/SQLiteStorage.d.ts.map +1 -0
- package/dist/core/SQLiteStorage.js +917 -0
- package/dist/core/StorageFactory.d.ts +45 -0
- package/dist/core/StorageFactory.d.ts.map +1 -0
- package/dist/core/StorageFactory.js +64 -0
- package/dist/core/TransactionManager.d.ts +464 -0
- package/dist/core/TransactionManager.d.ts.map +1 -0
- package/dist/core/TransactionManager.js +490 -13
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -2
- package/dist/features/AnalyticsManager.d.ts +44 -0
- package/dist/features/AnalyticsManager.d.ts.map +1 -0
- package/dist/features/AnalyticsManager.js +3 -2
- package/dist/features/ArchiveManager.d.ts +133 -0
- package/dist/features/ArchiveManager.d.ts.map +1 -0
- package/dist/features/ArchiveManager.js +221 -14
- package/dist/features/CompressionManager.d.ts +117 -0
- package/dist/features/CompressionManager.d.ts.map +1 -0
- package/dist/features/CompressionManager.js +189 -20
- package/dist/features/IOManager.d.ts +225 -0
- package/dist/features/IOManager.d.ts.map +1 -0
- package/dist/features/IOManager.js +1041 -0
- package/dist/features/StreamingExporter.d.ts +123 -0
- package/dist/features/StreamingExporter.d.ts.map +1 -0
- package/dist/features/StreamingExporter.js +203 -0
- package/dist/features/TagManager.d.ts +147 -0
- package/dist/features/TagManager.d.ts.map +1 -0
- package/dist/features/index.d.ts +12 -0
- package/dist/features/index.d.ts.map +1 -0
- package/dist/features/index.js +5 -6
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -10
- package/dist/memory.jsonl +1 -26
- package/dist/search/BasicSearch.d.ts +51 -0
- package/dist/search/BasicSearch.d.ts.map +1 -0
- package/dist/search/BasicSearch.js +9 -3
- package/dist/search/BooleanSearch.d.ts +98 -0
- package/dist/search/BooleanSearch.d.ts.map +1 -0
- package/dist/search/BooleanSearch.js +156 -9
- package/dist/search/EmbeddingService.d.ts +178 -0
- package/dist/search/EmbeddingService.d.ts.map +1 -0
- package/dist/search/EmbeddingService.js +358 -0
- package/dist/search/FuzzySearch.d.ts +118 -0
- package/dist/search/FuzzySearch.d.ts.map +1 -0
- package/dist/search/FuzzySearch.js +241 -25
- package/dist/search/QueryCostEstimator.d.ts +111 -0
- package/dist/search/QueryCostEstimator.d.ts.map +1 -0
- package/dist/search/QueryCostEstimator.js +355 -0
- package/dist/search/RankedSearch.d.ts +71 -0
- package/dist/search/RankedSearch.d.ts.map +1 -0
- package/dist/search/RankedSearch.js +54 -6
- package/dist/search/SavedSearchManager.d.ts +79 -0
- package/dist/search/SavedSearchManager.d.ts.map +1 -0
- package/dist/search/SearchFilterChain.d.ts +120 -0
- package/dist/search/SearchFilterChain.d.ts.map +1 -0
- package/dist/search/SearchFilterChain.js +2 -4
- package/dist/search/SearchManager.d.ts +326 -0
- package/dist/search/SearchManager.d.ts.map +1 -0
- package/dist/search/SearchManager.js +148 -0
- package/dist/search/SearchSuggestions.d.ts +27 -0
- package/dist/search/SearchSuggestions.d.ts.map +1 -0
- package/dist/search/SearchSuggestions.js +1 -1
- package/dist/search/SemanticSearch.d.ts +149 -0
- package/dist/search/SemanticSearch.d.ts.map +1 -0
- package/dist/search/SemanticSearch.js +323 -0
- package/dist/search/TFIDFEventSync.d.ts +85 -0
- package/dist/search/TFIDFEventSync.d.ts.map +1 -0
- package/dist/search/TFIDFEventSync.js +133 -0
- package/dist/search/TFIDFIndexManager.d.ts +151 -0
- package/dist/search/TFIDFIndexManager.d.ts.map +1 -0
- package/dist/search/TFIDFIndexManager.js +232 -17
- package/dist/search/VectorStore.d.ts +235 -0
- package/dist/search/VectorStore.d.ts.map +1 -0
- package/dist/search/VectorStore.js +311 -0
- package/dist/search/index.d.ts +21 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +12 -0
- package/dist/server/MCPServer.d.ts +21 -0
- package/dist/server/MCPServer.d.ts.map +1 -0
- package/dist/server/MCPServer.js +4 -4
- package/dist/server/responseCompressor.d.ts +94 -0
- package/dist/server/responseCompressor.d.ts.map +1 -0
- package/dist/server/responseCompressor.js +127 -0
- package/dist/server/toolDefinitions.d.ts +27 -0
- package/dist/server/toolDefinitions.d.ts.map +1 -0
- package/dist/server/toolDefinitions.js +188 -17
- package/dist/server/toolHandlers.d.ts +41 -0
- package/dist/server/toolHandlers.d.ts.map +1 -0
- package/dist/server/toolHandlers.js +467 -75
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -1
- package/dist/types/types.d.ts +1654 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +9 -0
- package/dist/utils/compressedCache.d.ts +192 -0
- package/dist/utils/compressedCache.d.ts.map +1 -0
- package/dist/utils/compressedCache.js +309 -0
- package/dist/utils/compressionUtil.d.ts +214 -0
- package/dist/utils/compressionUtil.d.ts.map +1 -0
- package/dist/utils/compressionUtil.js +247 -0
- package/dist/utils/constants.d.ts +245 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +124 -0
- package/dist/utils/entityUtils.d.ts +321 -0
- package/dist/utils/entityUtils.d.ts.map +1 -0
- package/dist/utils/entityUtils.js +434 -4
- package/dist/utils/errors.d.ts +95 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +24 -0
- package/dist/utils/formatters.d.ts +145 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/{paginationUtils.js → formatters.js} +54 -3
- package/dist/utils/index.d.ts +23 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +69 -31
- package/dist/utils/indexes.d.ts +270 -0
- package/dist/utils/indexes.d.ts.map +1 -0
- package/dist/utils/indexes.js +526 -0
- package/dist/utils/logger.d.ts +24 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/operationUtils.d.ts +124 -0
- package/dist/utils/operationUtils.d.ts.map +1 -0
- package/dist/utils/operationUtils.js +175 -0
- package/dist/utils/parallelUtils.d.ts +72 -0
- package/dist/utils/parallelUtils.d.ts.map +1 -0
- package/dist/utils/parallelUtils.js +169 -0
- package/dist/utils/schemas.d.ts +374 -0
- package/dist/utils/schemas.d.ts.map +1 -0
- package/dist/utils/schemas.js +302 -2
- package/dist/utils/searchAlgorithms.d.ts +99 -0
- package/dist/utils/searchAlgorithms.d.ts.map +1 -0
- package/dist/utils/searchAlgorithms.js +167 -0
- package/dist/utils/searchCache.d.ts +108 -0
- package/dist/utils/searchCache.d.ts.map +1 -0
- package/dist/utils/taskScheduler.d.ts +290 -0
- package/dist/utils/taskScheduler.d.ts.map +1 -0
- package/dist/utils/taskScheduler.js +466 -0
- package/dist/workers/index.d.ts +12 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +9 -0
- package/dist/workers/levenshteinWorker.d.ts +60 -0
- package/dist/workers/levenshteinWorker.d.ts.map +1 -0
- package/dist/workers/levenshteinWorker.js +98 -0
- package/package.json +17 -4
- package/dist/__tests__/edge-cases/edge-cases.test.js +0 -406
- package/dist/__tests__/integration/workflows.test.js +0 -449
- package/dist/__tests__/performance/benchmarks.test.js +0 -413
- package/dist/__tests__/unit/core/EntityManager.test.js +0 -334
- package/dist/__tests__/unit/core/GraphStorage.test.js +0 -205
- package/dist/__tests__/unit/core/RelationManager.test.js +0 -274
- package/dist/__tests__/unit/features/CompressionManager.test.js +0 -350
- package/dist/__tests__/unit/search/BasicSearch.test.js +0 -311
- package/dist/__tests__/unit/search/BooleanSearch.test.js +0 -432
- package/dist/__tests__/unit/search/FuzzySearch.test.js +0 -448
- package/dist/__tests__/unit/search/RankedSearch.test.js +0 -379
- package/dist/__tests__/unit/utils/levenshtein.test.js +0 -77
- package/dist/core/KnowledgeGraphManager.js +0 -423
- package/dist/features/BackupManager.js +0 -311
- package/dist/features/ExportManager.js +0 -305
- package/dist/features/ImportExportManager.js +0 -50
- package/dist/features/ImportManager.js +0 -328
- package/dist/memory-saved-searches.jsonl +0 -0
- package/dist/memory-tag-aliases.jsonl +0 -0
- package/dist/types/analytics.types.js +0 -6
- package/dist/types/entity.types.js +0 -7
- package/dist/types/import-export.types.js +0 -7
- package/dist/types/search.types.js +0 -7
- package/dist/types/tag.types.js +0 -6
- package/dist/utils/dateUtils.js +0 -89
- package/dist/utils/filterUtils.js +0 -155
- package/dist/utils/levenshtein.js +0 -62
- package/dist/utils/pathUtils.js +0 -115
- package/dist/utils/responseFormatter.js +0 -55
- package/dist/utils/tagUtils.js +0 -107
- package/dist/utils/tfidf.js +0 -90
- package/dist/utils/validationHelper.js +0 -99
- package/dist/utils/validationUtils.js +0 -109
package/dist/utils/pathUtils.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Path Utilities
|
|
3
|
-
*
|
|
4
|
-
* Helper functions for file path management and backward compatibility.
|
|
5
|
-
* Handles memory file path resolution with environment variable support.
|
|
6
|
-
*
|
|
7
|
-
* @module utils/pathUtils
|
|
8
|
-
*/
|
|
9
|
-
import { promises as fs } from 'fs';
|
|
10
|
-
import path from 'path';
|
|
11
|
-
import { fileURLToPath } from 'url';
|
|
12
|
-
import { FileOperationError } from './errors.js';
|
|
13
|
-
/**
|
|
14
|
-
* Validate and normalize a file path to prevent path traversal attacks.
|
|
15
|
-
*
|
|
16
|
-
* This function:
|
|
17
|
-
* - Normalizes the path to canonical form
|
|
18
|
-
* - Converts relative paths to absolute paths
|
|
19
|
-
* - Detects and prevents path traversal attempts (..)
|
|
20
|
-
*
|
|
21
|
-
* @param filePath - The file path to validate
|
|
22
|
-
* @param baseDir - Optional base directory for relative paths (defaults to process.cwd())
|
|
23
|
-
* @returns Validated absolute file path
|
|
24
|
-
* @throws {FileOperationError} If path traversal is detected or path is invalid
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```typescript
|
|
28
|
-
* // Valid paths
|
|
29
|
-
* validateFilePath('/var/data/memory.jsonl'); // Returns absolute path
|
|
30
|
-
* validateFilePath('data/memory.jsonl'); // Returns absolute path from cwd
|
|
31
|
-
*
|
|
32
|
-
* // Invalid paths (throws FileOperationError)
|
|
33
|
-
* validateFilePath('../../../etc/passwd'); // Path traversal detected
|
|
34
|
-
* validateFilePath('/var/data/../../../etc/passwd'); // Path traversal detected
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
export function validateFilePath(filePath, baseDir = process.cwd()) {
|
|
38
|
-
// Normalize path to remove redundant separators and resolve . and ..
|
|
39
|
-
const normalized = path.normalize(filePath);
|
|
40
|
-
// Convert to absolute path
|
|
41
|
-
const absolute = path.isAbsolute(normalized)
|
|
42
|
-
? normalized
|
|
43
|
-
: path.join(baseDir, normalized);
|
|
44
|
-
// After normalization, check if path still contains .. which would indicate
|
|
45
|
-
// traversal beyond the base directory
|
|
46
|
-
const finalNormalized = path.normalize(absolute);
|
|
47
|
-
// Split path into segments and check for suspicious patterns
|
|
48
|
-
const segments = finalNormalized.split(path.sep);
|
|
49
|
-
if (segments.includes('..')) {
|
|
50
|
-
throw new FileOperationError(`Path traversal detected in file path: ${filePath}`, filePath);
|
|
51
|
-
}
|
|
52
|
-
return finalNormalized;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Default memory file path (in same directory as compiled code).
|
|
56
|
-
*/
|
|
57
|
-
export const defaultMemoryPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '../memory.jsonl');
|
|
58
|
-
/**
|
|
59
|
-
* Ensure memory file path with backward compatibility migration.
|
|
60
|
-
*
|
|
61
|
-
* Handles:
|
|
62
|
-
* 1. Custom MEMORY_FILE_PATH environment variable (with path traversal protection)
|
|
63
|
-
* 2. Backward compatibility: migrates memory.json to memory.jsonl
|
|
64
|
-
* 3. Absolute vs relative path resolution
|
|
65
|
-
*
|
|
66
|
-
* @returns Resolved and validated memory file path
|
|
67
|
-
* @throws {FileOperationError} If path traversal is detected in MEMORY_FILE_PATH
|
|
68
|
-
*
|
|
69
|
-
* @example
|
|
70
|
-
* ```typescript
|
|
71
|
-
* // Use environment variable
|
|
72
|
-
* process.env.MEMORY_FILE_PATH = '/data/memory.jsonl';
|
|
73
|
-
* const path = await ensureMemoryFilePath(); // '/data/memory.jsonl'
|
|
74
|
-
*
|
|
75
|
-
* // Use default path
|
|
76
|
-
* delete process.env.MEMORY_FILE_PATH;
|
|
77
|
-
* const path = await ensureMemoryFilePath(); // './memory.jsonl'
|
|
78
|
-
*
|
|
79
|
-
* // Invalid path (throws error)
|
|
80
|
-
* process.env.MEMORY_FILE_PATH = '../../../etc/passwd';
|
|
81
|
-
* await ensureMemoryFilePath(); // Throws FileOperationError
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
export async function ensureMemoryFilePath() {
|
|
85
|
-
if (process.env.MEMORY_FILE_PATH) {
|
|
86
|
-
// Custom path provided, validate and resolve to absolute
|
|
87
|
-
const baseDir = path.dirname(fileURLToPath(import.meta.url)) + '/../';
|
|
88
|
-
const validatedPath = validateFilePath(process.env.MEMORY_FILE_PATH, baseDir);
|
|
89
|
-
return validatedPath;
|
|
90
|
-
}
|
|
91
|
-
// No custom path set, check for backward compatibility migration
|
|
92
|
-
const oldMemoryPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '../memory.json');
|
|
93
|
-
const newMemoryPath = defaultMemoryPath;
|
|
94
|
-
try {
|
|
95
|
-
// Check if old file exists
|
|
96
|
-
await fs.access(oldMemoryPath);
|
|
97
|
-
try {
|
|
98
|
-
// Check if new file exists
|
|
99
|
-
await fs.access(newMemoryPath);
|
|
100
|
-
// Both files exist, use new one (no migration needed)
|
|
101
|
-
return newMemoryPath;
|
|
102
|
-
}
|
|
103
|
-
catch {
|
|
104
|
-
// Old file exists, new file doesn't - migrate
|
|
105
|
-
console.log('[INFO] Found legacy memory.json file, migrating to memory.jsonl for JSONL format compatibility');
|
|
106
|
-
await fs.rename(oldMemoryPath, newMemoryPath);
|
|
107
|
-
console.log('[INFO] Successfully migrated memory.json to memory.jsonl');
|
|
108
|
-
return newMemoryPath;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// Old file doesn't exist, use new path
|
|
113
|
-
return newMemoryPath;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Tool Response Formatter Utilities
|
|
3
|
-
*
|
|
4
|
-
* Centralizes response formatting for MCP tool calls to eliminate
|
|
5
|
-
* redundant JSON.stringify patterns across the codebase.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Formats data as an MCP tool response with JSON content.
|
|
9
|
-
* Centralizes the response format to ensure consistency and reduce duplication.
|
|
10
|
-
*
|
|
11
|
-
* @param data - Any data to be JSON stringified
|
|
12
|
-
* @returns Formatted MCP tool response
|
|
13
|
-
*/
|
|
14
|
-
export function formatToolResponse(data) {
|
|
15
|
-
return {
|
|
16
|
-
content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Formats a simple text message as an MCP tool response.
|
|
21
|
-
* Use for success messages that don't need JSON formatting.
|
|
22
|
-
*
|
|
23
|
-
* @param message - Plain text message
|
|
24
|
-
* @returns Formatted MCP tool response
|
|
25
|
-
*/
|
|
26
|
-
export function formatTextResponse(message) {
|
|
27
|
-
return {
|
|
28
|
-
content: [{ type: 'text', text: message }],
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Formats raw string content as an MCP tool response.
|
|
33
|
-
* Use for export formats that return pre-formatted strings (markdown, CSV, etc.)
|
|
34
|
-
*
|
|
35
|
-
* @param content - Raw string content
|
|
36
|
-
* @returns Formatted MCP tool response
|
|
37
|
-
*/
|
|
38
|
-
export function formatRawResponse(content) {
|
|
39
|
-
return {
|
|
40
|
-
content: [{ type: 'text', text: content }],
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Formats an error as an MCP tool response with isError flag.
|
|
45
|
-
*
|
|
46
|
-
* @param error - Error object or message string
|
|
47
|
-
* @returns Formatted MCP tool error response
|
|
48
|
-
*/
|
|
49
|
-
export function formatErrorResponse(error) {
|
|
50
|
-
const message = error instanceof Error ? error.message : error;
|
|
51
|
-
return {
|
|
52
|
-
content: [{ type: 'text', text: message }],
|
|
53
|
-
isError: true,
|
|
54
|
-
};
|
|
55
|
-
}
|
package/dist/utils/tagUtils.js
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tag Normalization and Matching Utilities
|
|
3
|
-
*
|
|
4
|
-
* Centralizes tag operations to eliminate duplicate normalization logic
|
|
5
|
-
* across the codebase. All tags are normalized to lowercase for consistent matching.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Normalizes a single tag to lowercase and trimmed.
|
|
9
|
-
*
|
|
10
|
-
* @param tag - Tag to normalize
|
|
11
|
-
* @returns Normalized tag
|
|
12
|
-
*/
|
|
13
|
-
export function normalizeTag(tag) {
|
|
14
|
-
return tag.toLowerCase().trim();
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Normalizes an array of tags to lowercase.
|
|
18
|
-
* Handles undefined/null input gracefully.
|
|
19
|
-
*
|
|
20
|
-
* @param tags - Array of tags to normalize, or undefined
|
|
21
|
-
* @returns Normalized tags array, or empty array if input is undefined/null
|
|
22
|
-
*/
|
|
23
|
-
export function normalizeTags(tags) {
|
|
24
|
-
if (!tags || tags.length === 0)
|
|
25
|
-
return [];
|
|
26
|
-
return tags.map(tag => tag.toLowerCase());
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Checks if an entity's tags include any of the specified search tags.
|
|
30
|
-
* Both inputs are normalized before comparison.
|
|
31
|
-
*
|
|
32
|
-
* @param entityTags - Tags on the entity (may be undefined)
|
|
33
|
-
* @param searchTags - Tags to search for (may be undefined)
|
|
34
|
-
* @returns true if any search tag matches any entity tag, false if no match or either is empty
|
|
35
|
-
*/
|
|
36
|
-
export function hasMatchingTag(entityTags, searchTags) {
|
|
37
|
-
if (!entityTags || entityTags.length === 0)
|
|
38
|
-
return false;
|
|
39
|
-
if (!searchTags || searchTags.length === 0)
|
|
40
|
-
return false;
|
|
41
|
-
const normalizedEntity = normalizeTags(entityTags);
|
|
42
|
-
const normalizedSearch = normalizeTags(searchTags);
|
|
43
|
-
return normalizedSearch.some(tag => normalizedEntity.includes(tag));
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Checks if entity tags include ALL of the specified required tags.
|
|
47
|
-
*
|
|
48
|
-
* @param entityTags - Tags on the entity (may be undefined)
|
|
49
|
-
* @param requiredTags - All tags that must be present
|
|
50
|
-
* @returns true if all required tags are present
|
|
51
|
-
*/
|
|
52
|
-
export function hasAllTags(entityTags, requiredTags) {
|
|
53
|
-
if (!entityTags || entityTags.length === 0)
|
|
54
|
-
return false;
|
|
55
|
-
if (requiredTags.length === 0)
|
|
56
|
-
return true;
|
|
57
|
-
const normalizedEntity = normalizeTags(entityTags);
|
|
58
|
-
return normalizeTags(requiredTags).every(tag => normalizedEntity.includes(tag));
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Filters entities by tag match.
|
|
62
|
-
* Returns all entities if searchTags is empty or undefined.
|
|
63
|
-
*
|
|
64
|
-
* @param entities - Array of entities with optional tags property
|
|
65
|
-
* @param searchTags - Tags to filter by
|
|
66
|
-
* @returns Filtered entities that have at least one matching tag
|
|
67
|
-
*/
|
|
68
|
-
export function filterByTags(entities, searchTags) {
|
|
69
|
-
if (!searchTags || searchTags.length === 0) {
|
|
70
|
-
return entities;
|
|
71
|
-
}
|
|
72
|
-
const normalizedSearch = normalizeTags(searchTags);
|
|
73
|
-
return entities.filter(entity => {
|
|
74
|
-
if (!entity.tags || entity.tags.length === 0)
|
|
75
|
-
return false;
|
|
76
|
-
const normalizedEntity = normalizeTags(entity.tags);
|
|
77
|
-
return normalizedSearch.some(tag => normalizedEntity.includes(tag));
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Adds new tags to an existing tag array, avoiding duplicates.
|
|
82
|
-
* All tags are normalized to lowercase.
|
|
83
|
-
*
|
|
84
|
-
* @param existingTags - Current tags (may be undefined)
|
|
85
|
-
* @param newTags - Tags to add
|
|
86
|
-
* @returns Combined tags array with no duplicates
|
|
87
|
-
*/
|
|
88
|
-
export function addUniqueTags(existingTags, newTags) {
|
|
89
|
-
const existing = normalizeTags(existingTags);
|
|
90
|
-
const toAdd = normalizeTags(newTags);
|
|
91
|
-
const uniqueNew = toAdd.filter(tag => !existing.includes(tag));
|
|
92
|
-
return [...existing, ...uniqueNew];
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Removes specified tags from an existing tag array.
|
|
96
|
-
* Comparison is case-insensitive.
|
|
97
|
-
*
|
|
98
|
-
* @param existingTags - Current tags (may be undefined)
|
|
99
|
-
* @param tagsToRemove - Tags to remove
|
|
100
|
-
* @returns Tags array with specified tags removed
|
|
101
|
-
*/
|
|
102
|
-
export function removeTags(existingTags, tagsToRemove) {
|
|
103
|
-
if (!existingTags || existingTags.length === 0)
|
|
104
|
-
return [];
|
|
105
|
-
const toRemoveNormalized = normalizeTags(tagsToRemove);
|
|
106
|
-
return existingTags.filter(tag => !toRemoveNormalized.includes(tag.toLowerCase()));
|
|
107
|
-
}
|
package/dist/utils/tfidf.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TF-IDF (Term Frequency-Inverse Document Frequency) Utilities
|
|
3
|
-
*
|
|
4
|
-
* Algorithms for calculating TF-IDF scores used in ranked search.
|
|
5
|
-
* TF-IDF measures how important a term is to a document in a collection.
|
|
6
|
-
*
|
|
7
|
-
* @module utils/tfidf
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Calculate Term Frequency (TF) for a term in a document.
|
|
11
|
-
*
|
|
12
|
-
* TF = (Number of times term appears in document) / (Total terms in document)
|
|
13
|
-
*
|
|
14
|
-
* @param term - The search term
|
|
15
|
-
* @param document - The document text
|
|
16
|
-
* @returns Term frequency (0.0 to 1.0)
|
|
17
|
-
*/
|
|
18
|
-
export function calculateTF(term, document) {
|
|
19
|
-
const termLower = term.toLowerCase();
|
|
20
|
-
const tokens = tokenize(document);
|
|
21
|
-
if (tokens.length === 0)
|
|
22
|
-
return 0;
|
|
23
|
-
const termCount = tokens.filter(t => t === termLower).length;
|
|
24
|
-
return termCount / tokens.length;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Calculate Inverse Document Frequency (IDF) for a term across documents.
|
|
28
|
-
*
|
|
29
|
-
* IDF = log(Total documents / Documents containing term)
|
|
30
|
-
*
|
|
31
|
-
* @param term - The search term
|
|
32
|
-
* @param documents - Array of document texts
|
|
33
|
-
* @returns Inverse document frequency
|
|
34
|
-
*/
|
|
35
|
-
export function calculateIDF(term, documents) {
|
|
36
|
-
if (documents.length === 0)
|
|
37
|
-
return 0;
|
|
38
|
-
const termLower = term.toLowerCase();
|
|
39
|
-
const docsWithTerm = documents.filter(doc => tokenize(doc).includes(termLower)).length;
|
|
40
|
-
if (docsWithTerm === 0)
|
|
41
|
-
return 0;
|
|
42
|
-
return Math.log(documents.length / docsWithTerm);
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Calculate TF-IDF score for a term in a document.
|
|
46
|
-
*
|
|
47
|
-
* TF-IDF = TF * IDF
|
|
48
|
-
*
|
|
49
|
-
* Higher scores indicate more important/relevant terms.
|
|
50
|
-
*
|
|
51
|
-
* @param term - The search term
|
|
52
|
-
* @param document - The document text
|
|
53
|
-
* @param documents - Array of all documents
|
|
54
|
-
* @returns TF-IDF score
|
|
55
|
-
*/
|
|
56
|
-
export function calculateTFIDF(term, document, documents) {
|
|
57
|
-
const tf = calculateTF(term, document);
|
|
58
|
-
const idf = calculateIDF(term, documents);
|
|
59
|
-
return tf * idf;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Tokenize text into lowercase words.
|
|
63
|
-
*
|
|
64
|
-
* Splits on whitespace and removes punctuation.
|
|
65
|
-
*
|
|
66
|
-
* @param text - Text to tokenize
|
|
67
|
-
* @returns Array of lowercase tokens
|
|
68
|
-
*/
|
|
69
|
-
export function tokenize(text) {
|
|
70
|
-
return text
|
|
71
|
-
.toLowerCase()
|
|
72
|
-
.replace(/[^\w\s]/g, ' ')
|
|
73
|
-
.split(/\s+/)
|
|
74
|
-
.filter(token => token.length > 0);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Calculate TF-IDF scores for multiple search terms.
|
|
78
|
-
*
|
|
79
|
-
* @param terms - Array of search terms
|
|
80
|
-
* @param document - The document text
|
|
81
|
-
* @param documents - Array of all documents
|
|
82
|
-
* @returns Map of term to TF-IDF score
|
|
83
|
-
*/
|
|
84
|
-
export function calculateMultiTermTFIDF(terms, document, documents) {
|
|
85
|
-
const scores = new Map();
|
|
86
|
-
for (const term of terms) {
|
|
87
|
-
scores.set(term, calculateTFIDF(term, document, documents));
|
|
88
|
-
}
|
|
89
|
-
return scores;
|
|
90
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Zod Schema Validation Helper
|
|
3
|
-
*
|
|
4
|
-
* Centralizes Zod validation patterns to eliminate redundant error formatting
|
|
5
|
-
* and validation logic across the codebase.
|
|
6
|
-
*/
|
|
7
|
-
import { ValidationError } from './errors.js';
|
|
8
|
-
/**
|
|
9
|
-
* Formats Zod errors into human-readable strings.
|
|
10
|
-
*
|
|
11
|
-
* @param error - Zod error object
|
|
12
|
-
* @returns Array of formatted error messages
|
|
13
|
-
*/
|
|
14
|
-
export function formatZodErrors(error) {
|
|
15
|
-
return error.issues.map(issue => {
|
|
16
|
-
const path = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';
|
|
17
|
-
return `${path}${issue.message}`;
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Validates data against a Zod schema and returns the typed result.
|
|
22
|
-
* Throws ValidationError with formatted error messages on failure.
|
|
23
|
-
*
|
|
24
|
-
* @param data - The data to validate
|
|
25
|
-
* @param schema - The Zod schema to validate against
|
|
26
|
-
* @param errorMessage - Custom error message prefix (default: 'Validation failed')
|
|
27
|
-
* @returns The validated and typed data
|
|
28
|
-
* @throws ValidationError if validation fails
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```typescript
|
|
32
|
-
* const entities = validateWithSchema(
|
|
33
|
-
* input,
|
|
34
|
-
* BatchCreateEntitiesSchema,
|
|
35
|
-
* 'Invalid entity data'
|
|
36
|
-
* );
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
export function validateWithSchema(data, schema, errorMessage = 'Validation failed') {
|
|
40
|
-
const result = schema.safeParse(data);
|
|
41
|
-
if (!result.success) {
|
|
42
|
-
const errors = formatZodErrors(result.error);
|
|
43
|
-
throw new ValidationError(errorMessage, errors);
|
|
44
|
-
}
|
|
45
|
-
return result.data;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Validates data and returns a result object instead of throwing.
|
|
49
|
-
* Useful when you want to handle validation errors gracefully.
|
|
50
|
-
*
|
|
51
|
-
* @param data - The data to validate
|
|
52
|
-
* @param schema - The Zod schema to validate against
|
|
53
|
-
* @returns Result object with success status and either data or errors
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```typescript
|
|
57
|
-
* const result = validateSafe(input, EntitySchema);
|
|
58
|
-
* if (result.success) {
|
|
59
|
-
* console.log(result.data);
|
|
60
|
-
* } else {
|
|
61
|
-
* console.error(result.errors);
|
|
62
|
-
* }
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
65
|
-
export function validateSafe(data, schema) {
|
|
66
|
-
const result = schema.safeParse(data);
|
|
67
|
-
if (result.success) {
|
|
68
|
-
return { success: true, data: result.data };
|
|
69
|
-
}
|
|
70
|
-
return { success: false, errors: formatZodErrors(result.error) };
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Validates an array of items against a schema.
|
|
74
|
-
* Returns detailed information about which items failed validation.
|
|
75
|
-
*
|
|
76
|
-
* @param items - Array of items to validate
|
|
77
|
-
* @param schema - Zod schema for individual items
|
|
78
|
-
* @param errorMessage - Custom error message prefix
|
|
79
|
-
* @returns Array of validated items
|
|
80
|
-
* @throws ValidationError if any item fails validation
|
|
81
|
-
*/
|
|
82
|
-
export function validateArrayWithSchema(items, schema, errorMessage = 'Array validation failed') {
|
|
83
|
-
const errors = [];
|
|
84
|
-
const validated = [];
|
|
85
|
-
for (let i = 0; i < items.length; i++) {
|
|
86
|
-
const result = schema.safeParse(items[i]);
|
|
87
|
-
if (result.success) {
|
|
88
|
-
validated.push(result.data);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
const itemErrors = formatZodErrors(result.error);
|
|
92
|
-
errors.push(...itemErrors.map(e => `[${i}] ${e}`));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (errors.length > 0) {
|
|
96
|
-
throw new ValidationError(errorMessage, errors);
|
|
97
|
-
}
|
|
98
|
-
return validated;
|
|
99
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validation Utilities
|
|
3
|
-
*
|
|
4
|
-
* Helper functions for validating entities, relations, and other data structures.
|
|
5
|
-
*
|
|
6
|
-
* @module utils/validationUtils
|
|
7
|
-
*/
|
|
8
|
-
import { IMPORTANCE_RANGE } from './constants.js';
|
|
9
|
-
/**
|
|
10
|
-
* Type guard to check if value is a non-null object.
|
|
11
|
-
*/
|
|
12
|
-
function isObject(value) {
|
|
13
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Validate an entity object.
|
|
17
|
-
*
|
|
18
|
-
* Checks required fields and data types.
|
|
19
|
-
*
|
|
20
|
-
* @param entity - Entity to validate (unknown type for runtime validation)
|
|
21
|
-
* @returns Validation result
|
|
22
|
-
*/
|
|
23
|
-
export function validateEntity(entity) {
|
|
24
|
-
const errors = [];
|
|
25
|
-
if (!isObject(entity)) {
|
|
26
|
-
return { valid: false, errors: ['Entity must be an object'] };
|
|
27
|
-
}
|
|
28
|
-
if (!entity.name || typeof entity.name !== 'string' || entity.name.trim() === '') {
|
|
29
|
-
errors.push('Entity name is required and must be a non-empty string');
|
|
30
|
-
}
|
|
31
|
-
if (!entity.entityType || typeof entity.entityType !== 'string' || entity.entityType.trim() === '') {
|
|
32
|
-
errors.push('Entity type is required and must be a non-empty string');
|
|
33
|
-
}
|
|
34
|
-
if (!Array.isArray(entity.observations)) {
|
|
35
|
-
errors.push('Observations must be an array');
|
|
36
|
-
}
|
|
37
|
-
else if (!entity.observations.every((o) => typeof o === 'string')) {
|
|
38
|
-
errors.push('All observations must be strings');
|
|
39
|
-
}
|
|
40
|
-
if (entity.tags !== undefined) {
|
|
41
|
-
if (!Array.isArray(entity.tags)) {
|
|
42
|
-
errors.push('Tags must be an array');
|
|
43
|
-
}
|
|
44
|
-
else if (!entity.tags.every((t) => typeof t === 'string')) {
|
|
45
|
-
errors.push('All tags must be strings');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (entity.importance !== undefined) {
|
|
49
|
-
if (typeof entity.importance !== 'number') {
|
|
50
|
-
errors.push('Importance must be a number');
|
|
51
|
-
}
|
|
52
|
-
else if (!validateImportance(entity.importance)) {
|
|
53
|
-
errors.push('Importance must be between 0 and 10');
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return { valid: errors.length === 0, errors };
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Validate a relation object.
|
|
60
|
-
*
|
|
61
|
-
* Checks required fields and data types.
|
|
62
|
-
*
|
|
63
|
-
* @param relation - Relation to validate (unknown type for runtime validation)
|
|
64
|
-
* @returns Validation result
|
|
65
|
-
*/
|
|
66
|
-
export function validateRelation(relation) {
|
|
67
|
-
const errors = [];
|
|
68
|
-
if (!isObject(relation)) {
|
|
69
|
-
return { valid: false, errors: ['Relation must be an object'] };
|
|
70
|
-
}
|
|
71
|
-
if (!relation.from || typeof relation.from !== 'string' || relation.from.trim() === '') {
|
|
72
|
-
errors.push('Relation "from" is required and must be a non-empty string');
|
|
73
|
-
}
|
|
74
|
-
if (!relation.to || typeof relation.to !== 'string' || relation.to.trim() === '') {
|
|
75
|
-
errors.push('Relation "to" is required and must be a non-empty string');
|
|
76
|
-
}
|
|
77
|
-
if (!relation.relationType || typeof relation.relationType !== 'string' || relation.relationType.trim() === '') {
|
|
78
|
-
errors.push('Relation type is required and must be a non-empty string');
|
|
79
|
-
}
|
|
80
|
-
return { valid: errors.length === 0, errors };
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Validate importance level (must be 0-10).
|
|
84
|
-
*
|
|
85
|
-
* @param importance - Importance value to validate
|
|
86
|
-
* @returns True if valid
|
|
87
|
-
*/
|
|
88
|
-
export function validateImportance(importance) {
|
|
89
|
-
return typeof importance === 'number'
|
|
90
|
-
&& !isNaN(importance)
|
|
91
|
-
&& importance >= IMPORTANCE_RANGE.MIN
|
|
92
|
-
&& importance <= IMPORTANCE_RANGE.MAX;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Validate an array of tags.
|
|
96
|
-
*
|
|
97
|
-
* @param tags - Tags array to validate (unknown type for runtime validation)
|
|
98
|
-
* @returns Validation result
|
|
99
|
-
*/
|
|
100
|
-
export function validateTags(tags) {
|
|
101
|
-
const errors = [];
|
|
102
|
-
if (!Array.isArray(tags)) {
|
|
103
|
-
return { valid: false, errors: ['Tags must be an array'] };
|
|
104
|
-
}
|
|
105
|
-
if (!tags.every((t) => typeof t === 'string' && t.trim() !== '')) {
|
|
106
|
-
errors.push('All tags must be non-empty strings');
|
|
107
|
-
}
|
|
108
|
-
return { valid: errors.length === 0, errors };
|
|
109
|
-
}
|