cccmemory 1.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 +21 -0
- package/README.md +349 -0
- package/dist/ConversationMemory.d.ts +231 -0
- package/dist/ConversationMemory.d.ts.map +1 -0
- package/dist/ConversationMemory.js +357 -0
- package/dist/ConversationMemory.js.map +1 -0
- package/dist/cache/QueryCache.d.ts +215 -0
- package/dist/cache/QueryCache.d.ts.map +1 -0
- package/dist/cache/QueryCache.js +294 -0
- package/dist/cache/QueryCache.js.map +1 -0
- package/dist/cli/commands.d.ts +9 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +954 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/help.d.ts +16 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +361 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/index.d.ts +30 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +111 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context/ContextInjector.d.ts +38 -0
- package/dist/context/ContextInjector.d.ts.map +1 -0
- package/dist/context/ContextInjector.js +235 -0
- package/dist/context/ContextInjector.js.map +1 -0
- package/dist/documentation/CodeAnalyzer.d.ts +29 -0
- package/dist/documentation/CodeAnalyzer.d.ts.map +1 -0
- package/dist/documentation/CodeAnalyzer.js +122 -0
- package/dist/documentation/CodeAnalyzer.js.map +1 -0
- package/dist/documentation/ConversationAnalyzer.d.ts +19 -0
- package/dist/documentation/ConversationAnalyzer.d.ts.map +1 -0
- package/dist/documentation/ConversationAnalyzer.js +157 -0
- package/dist/documentation/ConversationAnalyzer.js.map +1 -0
- package/dist/documentation/CrossReferencer.d.ts +67 -0
- package/dist/documentation/CrossReferencer.d.ts.map +1 -0
- package/dist/documentation/CrossReferencer.js +247 -0
- package/dist/documentation/CrossReferencer.js.map +1 -0
- package/dist/documentation/DocumentationGenerator.d.ts +22 -0
- package/dist/documentation/DocumentationGenerator.d.ts.map +1 -0
- package/dist/documentation/DocumentationGenerator.js +57 -0
- package/dist/documentation/DocumentationGenerator.js.map +1 -0
- package/dist/documentation/MarkdownFormatter.d.ts +26 -0
- package/dist/documentation/MarkdownFormatter.d.ts.map +1 -0
- package/dist/documentation/MarkdownFormatter.js +301 -0
- package/dist/documentation/MarkdownFormatter.js.map +1 -0
- package/dist/documentation/types.d.ts +176 -0
- package/dist/documentation/types.d.ts.map +1 -0
- package/dist/documentation/types.js +5 -0
- package/dist/documentation/types.js.map +1 -0
- package/dist/embeddings/ConfigManager.d.ts +46 -0
- package/dist/embeddings/ConfigManager.d.ts.map +1 -0
- package/dist/embeddings/ConfigManager.js +177 -0
- package/dist/embeddings/ConfigManager.js.map +1 -0
- package/dist/embeddings/EmbeddingConfig.d.ts +39 -0
- package/dist/embeddings/EmbeddingConfig.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingConfig.js +132 -0
- package/dist/embeddings/EmbeddingConfig.js.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts +51 -0
- package/dist/embeddings/EmbeddingGenerator.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingGenerator.js +157 -0
- package/dist/embeddings/EmbeddingGenerator.js.map +1 -0
- package/dist/embeddings/EmbeddingProvider.d.ts +34 -0
- package/dist/embeddings/EmbeddingProvider.d.ts.map +1 -0
- package/dist/embeddings/EmbeddingProvider.js +6 -0
- package/dist/embeddings/EmbeddingProvider.js.map +1 -0
- package/dist/embeddings/ModelRegistry.d.ts +48 -0
- package/dist/embeddings/ModelRegistry.d.ts.map +1 -0
- package/dist/embeddings/ModelRegistry.js +170 -0
- package/dist/embeddings/ModelRegistry.js.map +1 -0
- package/dist/embeddings/VectorStore.d.ts +114 -0
- package/dist/embeddings/VectorStore.d.ts.map +1 -0
- package/dist/embeddings/VectorStore.js +393 -0
- package/dist/embeddings/VectorStore.js.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/OllamaEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js +125 -0
- package/dist/embeddings/providers/OllamaEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts +40 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js +129 -0
- package/dist/embeddings/providers/OpenAIEmbeddings.js.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts +38 -0
- package/dist/embeddings/providers/TransformersEmbeddings.d.ts.map +1 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js +115 -0
- package/dist/embeddings/providers/TransformersEmbeddings.js.map +1 -0
- package/dist/handoff/SessionHandoffStore.d.ts +80 -0
- package/dist/handoff/SessionHandoffStore.d.ts.map +1 -0
- package/dist/handoff/SessionHandoffStore.js +314 -0
- package/dist/handoff/SessionHandoffStore.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +27 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +157 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/memory/WorkingMemoryStore.d.ts +83 -0
- package/dist/memory/WorkingMemoryStore.d.ts.map +1 -0
- package/dist/memory/WorkingMemoryStore.js +318 -0
- package/dist/memory/WorkingMemoryStore.js.map +1 -0
- package/dist/memory/types.d.ts +192 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +8 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/parsers/CodexConversationParser.d.ts +51 -0
- package/dist/parsers/CodexConversationParser.d.ts.map +1 -0
- package/dist/parsers/CodexConversationParser.js +301 -0
- package/dist/parsers/CodexConversationParser.js.map +1 -0
- package/dist/parsers/ConversationParser.d.ts +286 -0
- package/dist/parsers/ConversationParser.d.ts.map +1 -0
- package/dist/parsers/ConversationParser.js +795 -0
- package/dist/parsers/ConversationParser.js.map +1 -0
- package/dist/parsers/DecisionExtractor.d.ts +144 -0
- package/dist/parsers/DecisionExtractor.d.ts.map +1 -0
- package/dist/parsers/DecisionExtractor.js +434 -0
- package/dist/parsers/DecisionExtractor.js.map +1 -0
- package/dist/parsers/GitIntegrator.d.ts +156 -0
- package/dist/parsers/GitIntegrator.d.ts.map +1 -0
- package/dist/parsers/GitIntegrator.js +348 -0
- package/dist/parsers/GitIntegrator.js.map +1 -0
- package/dist/parsers/MistakeExtractor.d.ts +151 -0
- package/dist/parsers/MistakeExtractor.d.ts.map +1 -0
- package/dist/parsers/MistakeExtractor.js +460 -0
- package/dist/parsers/MistakeExtractor.js.map +1 -0
- package/dist/parsers/RequirementsExtractor.d.ts +166 -0
- package/dist/parsers/RequirementsExtractor.d.ts.map +1 -0
- package/dist/parsers/RequirementsExtractor.js +338 -0
- package/dist/parsers/RequirementsExtractor.js.map +1 -0
- package/dist/realtime/ConversationWatcher.d.ts +87 -0
- package/dist/realtime/ConversationWatcher.d.ts.map +1 -0
- package/dist/realtime/ConversationWatcher.js +204 -0
- package/dist/realtime/ConversationWatcher.js.map +1 -0
- package/dist/realtime/IncrementalParser.d.ts +83 -0
- package/dist/realtime/IncrementalParser.d.ts.map +1 -0
- package/dist/realtime/IncrementalParser.js +232 -0
- package/dist/realtime/IncrementalParser.js.map +1 -0
- package/dist/realtime/LiveExtractor.d.ts +72 -0
- package/dist/realtime/LiveExtractor.d.ts.map +1 -0
- package/dist/realtime/LiveExtractor.js +288 -0
- package/dist/realtime/LiveExtractor.js.map +1 -0
- package/dist/search/SemanticSearch.d.ts +121 -0
- package/dist/search/SemanticSearch.d.ts.map +1 -0
- package/dist/search/SemanticSearch.js +823 -0
- package/dist/search/SemanticSearch.js.map +1 -0
- package/dist/storage/BackupManager.d.ts +58 -0
- package/dist/storage/BackupManager.d.ts.map +1 -0
- package/dist/storage/BackupManager.js +223 -0
- package/dist/storage/BackupManager.js.map +1 -0
- package/dist/storage/ConversationStorage.d.ts +341 -0
- package/dist/storage/ConversationStorage.d.ts.map +1 -0
- package/dist/storage/ConversationStorage.js +792 -0
- package/dist/storage/ConversationStorage.js.map +1 -0
- package/dist/storage/DeletionService.d.ts +70 -0
- package/dist/storage/DeletionService.d.ts.map +1 -0
- package/dist/storage/DeletionService.js +253 -0
- package/dist/storage/DeletionService.js.map +1 -0
- package/dist/storage/GlobalIndex.d.ts +133 -0
- package/dist/storage/GlobalIndex.d.ts.map +1 -0
- package/dist/storage/GlobalIndex.js +310 -0
- package/dist/storage/GlobalIndex.js.map +1 -0
- package/dist/storage/SQLiteManager.d.ts +114 -0
- package/dist/storage/SQLiteManager.d.ts.map +1 -0
- package/dist/storage/SQLiteManager.js +636 -0
- package/dist/storage/SQLiteManager.js.map +1 -0
- package/dist/storage/migrations.d.ts +54 -0
- package/dist/storage/migrations.d.ts.map +1 -0
- package/dist/storage/migrations.js +285 -0
- package/dist/storage/migrations.js.map +1 -0
- package/dist/storage/schema.sql +436 -0
- package/dist/tools/ToolDefinitions.d.ts +946 -0
- package/dist/tools/ToolDefinitions.d.ts.map +1 -0
- package/dist/tools/ToolDefinitions.js +937 -0
- package/dist/tools/ToolDefinitions.js.map +1 -0
- package/dist/tools/ToolHandlers.d.ts +791 -0
- package/dist/tools/ToolHandlers.d.ts.map +1 -0
- package/dist/tools/ToolHandlers.js +3262 -0
- package/dist/tools/ToolHandlers.js.map +1 -0
- package/dist/types/ToolTypes.d.ts +824 -0
- package/dist/types/ToolTypes.d.ts.map +1 -0
- package/dist/types/ToolTypes.js +6 -0
- package/dist/types/ToolTypes.js.map +1 -0
- package/dist/utils/Logger.d.ts +70 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/dist/utils/Logger.js +131 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/McpConfig.d.ts +54 -0
- package/dist/utils/McpConfig.d.ts.map +1 -0
- package/dist/utils/McpConfig.js +136 -0
- package/dist/utils/McpConfig.js.map +1 -0
- package/dist/utils/ProjectMigration.d.ts +82 -0
- package/dist/utils/ProjectMigration.d.ts.map +1 -0
- package/dist/utils/ProjectMigration.js +416 -0
- package/dist/utils/ProjectMigration.js.map +1 -0
- package/dist/utils/constants.d.ts +75 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +105 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/safeJson.d.ts +37 -0
- package/dist/utils/safeJson.d.ts.map +1 -0
- package/dist/utils/safeJson.js +48 -0
- package/dist/utils/safeJson.js.map +1 -0
- package/dist/utils/sanitization.d.ts +45 -0
- package/dist/utils/sanitization.d.ts.map +1 -0
- package/dist/utils/sanitization.js +153 -0
- package/dist/utils/sanitization.js.map +1 -0
- package/dist/utils/worktree.d.ts +15 -0
- package/dist/utils/worktree.d.ts.map +1 -0
- package/dist/utils/worktree.js +86 -0
- package/dist/utils/worktree.js.map +1 -0
- package/package.json +98 -0
- package/scripts/changelog-check.sh +62 -0
- package/scripts/check-node.js +17 -0
- package/scripts/dev-config.js +56 -0
- package/scripts/postinstall.js +117 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe JSON parsing utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides crash-safe JSON parsing with fallback values.
|
|
5
|
+
* Use this instead of raw JSON.parse() when parsing data from:
|
|
6
|
+
* - Database rows (may be corrupted)
|
|
7
|
+
* - User input
|
|
8
|
+
* - External sources
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Safely parse JSON with a fallback value on error.
|
|
12
|
+
*
|
|
13
|
+
* Unlike JSON.parse(), this function:
|
|
14
|
+
* - Never throws
|
|
15
|
+
* - Handles null/undefined input
|
|
16
|
+
* - Handles non-string input
|
|
17
|
+
* - Returns the fallback on any parse error
|
|
18
|
+
*
|
|
19
|
+
* @param value - The JSON string to parse
|
|
20
|
+
* @param fallback - Value to return if parsing fails
|
|
21
|
+
* @returns Parsed value or fallback
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* // Safe object parsing
|
|
26
|
+
* const data = safeJsonParse(row.metadata, {});
|
|
27
|
+
*
|
|
28
|
+
* // Safe array parsing
|
|
29
|
+
* const files = safeJsonParse(row.files_changed, []);
|
|
30
|
+
*
|
|
31
|
+
* // With specific type
|
|
32
|
+
* interface Config { debug: boolean }
|
|
33
|
+
* const config = safeJsonParse<Config>(jsonStr, { debug: false });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function safeJsonParse(value, fallback) {
|
|
37
|
+
// Handle non-string input
|
|
38
|
+
if (typeof value !== "string" || value === "") {
|
|
39
|
+
return fallback;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(value);
|
|
43
|
+
}
|
|
44
|
+
catch (_error) {
|
|
45
|
+
return fallback;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=safeJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safeJson.js","sourceRoot":"","sources":["../../src/utils/safeJson.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,aAAa,CAAI,KAAgC,EAAE,QAAW;IAC5E,0BAA0B;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC9C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAM,CAAC;IAChC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input sanitization utilities for SQL LIKE queries and path validation
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Sanitize string for use in SQL LIKE patterns
|
|
6
|
+
* Escapes special LIKE characters: %, _, "
|
|
7
|
+
*/
|
|
8
|
+
export declare function sanitizeForLike(input: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Validate and sanitize file path
|
|
11
|
+
* Cross-platform: prevents path traversal attacks and blocks system directories
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateFilePath(filePath: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Validate and normalize project path
|
|
16
|
+
* Cross-platform: handles both Unix (/) and Windows (\) paths
|
|
17
|
+
* Used for converting file paths to Claude project directory names
|
|
18
|
+
*/
|
|
19
|
+
export declare function sanitizeProjectPath(path: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Sanitize SQL identifier (table/column name)
|
|
22
|
+
* Only allows alphanumeric and underscore
|
|
23
|
+
*/
|
|
24
|
+
export declare function sanitizeSQLIdentifier(identifier: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Escape a table name for use in double-quoted SQL identifiers
|
|
27
|
+
* Doubles any embedded double-quotes per SQL standard
|
|
28
|
+
*/
|
|
29
|
+
export declare function escapeTableName(tableName: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Validate database path for use in ATTACH DATABASE statement
|
|
32
|
+
* Prevents SQL injection via path manipulation
|
|
33
|
+
*/
|
|
34
|
+
export declare function validateDatabasePath(dbPath: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Convert a project path to Claude Code's project folder name
|
|
37
|
+
* Cross-platform compatible - handles both Unix and Windows paths
|
|
38
|
+
*
|
|
39
|
+
* Examples:
|
|
40
|
+
* - macOS/Linux: /Users/joker/github/project → -Users-joker-github-project
|
|
41
|
+
* - Windows: C:\Users\user\project → C-Users-user-project
|
|
42
|
+
* - Windows UNC: \\server\share\project → -server-share-project
|
|
43
|
+
*/
|
|
44
|
+
export declare function pathToProjectFolderName(projectPath: string): string;
|
|
45
|
+
//# sourceMappingURL=sanitization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitization.d.ts","sourceRoot":"","sources":["../../src/utils/sanitization.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAYD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA+CzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBxD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAKhE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAqB3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAWnE"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input sanitization utilities for SQL LIKE queries and path validation
|
|
3
|
+
*/
|
|
4
|
+
import { normalize, sep } from 'path';
|
|
5
|
+
/**
|
|
6
|
+
* Sanitize string for use in SQL LIKE patterns
|
|
7
|
+
* Escapes special LIKE characters: %, _, "
|
|
8
|
+
*/
|
|
9
|
+
export function sanitizeForLike(input) {
|
|
10
|
+
return input.replace(/[%_"\\]/g, '\\$&');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Check if a path contains path traversal attempts
|
|
14
|
+
* Only rejects actual '..' path segments, not filenames containing '..'
|
|
15
|
+
*/
|
|
16
|
+
function hasPathTraversal(pathStr) {
|
|
17
|
+
// Split on both Unix and Windows separators
|
|
18
|
+
const segments = pathStr.split(/[\\/]/);
|
|
19
|
+
return segments.some(segment => segment === '..');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate and sanitize file path
|
|
23
|
+
* Cross-platform: prevents path traversal attacks and blocks system directories
|
|
24
|
+
*/
|
|
25
|
+
export function validateFilePath(filePath) {
|
|
26
|
+
// Remove any null bytes
|
|
27
|
+
const cleaned = filePath.replace(/\0/g, '');
|
|
28
|
+
// Check for path traversal attempts (only actual '..' segments)
|
|
29
|
+
if (hasPathTraversal(cleaned)) {
|
|
30
|
+
throw new Error('Path traversal detected: .. is not allowed in file paths');
|
|
31
|
+
}
|
|
32
|
+
// Check for absolute paths outside allowed directories (platform-specific)
|
|
33
|
+
const isWindows = process.platform === 'win32';
|
|
34
|
+
if (isWindows) {
|
|
35
|
+
// Windows system directories (case-insensitive)
|
|
36
|
+
const forbidden = [
|
|
37
|
+
/^[A-Z]:\\Windows\\/i,
|
|
38
|
+
/^[A-Z]:\\Program Files/i,
|
|
39
|
+
/^[A-Z]:\\ProgramData/i,
|
|
40
|
+
/^[A-Z]:\\System/i,
|
|
41
|
+
/^[A-Z]:\\System32/i,
|
|
42
|
+
/^[A-Z]:\\Boot/i,
|
|
43
|
+
];
|
|
44
|
+
if (forbidden.some(pattern => pattern.test(cleaned))) {
|
|
45
|
+
throw new Error('Access to system directories is not allowed');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Unix system directories - comprehensive list
|
|
50
|
+
const forbiddenPaths = [
|
|
51
|
+
'/etc',
|
|
52
|
+
'/sys',
|
|
53
|
+
'/proc',
|
|
54
|
+
'/dev',
|
|
55
|
+
'/boot',
|
|
56
|
+
'/sbin',
|
|
57
|
+
'/bin',
|
|
58
|
+
'/lib',
|
|
59
|
+
'/lib64',
|
|
60
|
+
'/usr/sbin',
|
|
61
|
+
'/var/run',
|
|
62
|
+
'/var/lock',
|
|
63
|
+
];
|
|
64
|
+
if (forbiddenPaths.some(dir => cleaned === dir || cleaned.startsWith(dir + '/'))) {
|
|
65
|
+
throw new Error('Access to system directories is not allowed');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return cleaned;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate and normalize project path
|
|
72
|
+
* Cross-platform: handles both Unix (/) and Windows (\) paths
|
|
73
|
+
* Used for converting file paths to Claude project directory names
|
|
74
|
+
*/
|
|
75
|
+
export function sanitizeProjectPath(path) {
|
|
76
|
+
// Remove null bytes
|
|
77
|
+
const cleaned = path.replace(/\0/g, '');
|
|
78
|
+
// Check for path traversal
|
|
79
|
+
if (cleaned.includes('..')) {
|
|
80
|
+
throw new Error('Path traversal detected in project path');
|
|
81
|
+
}
|
|
82
|
+
// First normalize with Node's native path module for current platform
|
|
83
|
+
let normalized = normalize(cleaned);
|
|
84
|
+
// Then handle any remaining separators from other platforms
|
|
85
|
+
// Replace multiple consecutive slashes/backslashes with single separator
|
|
86
|
+
normalized = normalized.replace(/[\\/]+/g, sep);
|
|
87
|
+
// Remove trailing path separator
|
|
88
|
+
const trailingSepRegex = new RegExp(`${sep.replace(/\\/g, '\\\\')}+$`);
|
|
89
|
+
return normalized.replace(trailingSepRegex, '');
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Sanitize SQL identifier (table/column name)
|
|
93
|
+
* Only allows alphanumeric and underscore
|
|
94
|
+
*/
|
|
95
|
+
export function sanitizeSQLIdentifier(identifier) {
|
|
96
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(identifier)) {
|
|
97
|
+
throw new Error(`Invalid SQL identifier: ${identifier}`);
|
|
98
|
+
}
|
|
99
|
+
return identifier;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Escape a table name for use in double-quoted SQL identifiers
|
|
103
|
+
* Doubles any embedded double-quotes per SQL standard
|
|
104
|
+
*/
|
|
105
|
+
export function escapeTableName(tableName) {
|
|
106
|
+
if (!tableName || tableName.length === 0) {
|
|
107
|
+
throw new Error("Table name cannot be empty");
|
|
108
|
+
}
|
|
109
|
+
// Double any embedded double-quotes (SQL standard escaping)
|
|
110
|
+
return tableName.replace(/"/g, '""');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Validate database path for use in ATTACH DATABASE statement
|
|
114
|
+
* Prevents SQL injection via path manipulation
|
|
115
|
+
*/
|
|
116
|
+
export function validateDatabasePath(dbPath) {
|
|
117
|
+
if (!dbPath || dbPath.length === 0) {
|
|
118
|
+
throw new Error("Database path cannot be empty");
|
|
119
|
+
}
|
|
120
|
+
// Check for single quotes which could break SQL string
|
|
121
|
+
if (dbPath.includes("'")) {
|
|
122
|
+
throw new Error("Database path cannot contain single quotes");
|
|
123
|
+
}
|
|
124
|
+
// Check for null bytes
|
|
125
|
+
if (dbPath.includes("\0")) {
|
|
126
|
+
throw new Error("Database path cannot contain null bytes");
|
|
127
|
+
}
|
|
128
|
+
// Check for path traversal
|
|
129
|
+
if (dbPath.includes("..")) {
|
|
130
|
+
throw new Error("Path traversal detected in database path");
|
|
131
|
+
}
|
|
132
|
+
return dbPath;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Convert a project path to Claude Code's project folder name
|
|
136
|
+
* Cross-platform compatible - handles both Unix and Windows paths
|
|
137
|
+
*
|
|
138
|
+
* Examples:
|
|
139
|
+
* - macOS/Linux: /Users/joker/github/project → -Users-joker-github-project
|
|
140
|
+
* - Windows: C:\Users\user\project → C-Users-user-project
|
|
141
|
+
* - Windows UNC: \\server\share\project → -server-share-project
|
|
142
|
+
*/
|
|
143
|
+
export function pathToProjectFolderName(projectPath) {
|
|
144
|
+
// Normalize the path first
|
|
145
|
+
const normalized = sanitizeProjectPath(projectPath);
|
|
146
|
+
// Replace Windows drive letters (C: → C, D: → D)
|
|
147
|
+
// Replace both forward and backward slashes with dashes
|
|
148
|
+
const folderName = normalized
|
|
149
|
+
.replace(/^([A-Z]):/i, '$1') // Remove colon from drive letter
|
|
150
|
+
.replace(/[\\/]+/g, '-'); // Replace / or \ with -
|
|
151
|
+
return folderName;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=sanitization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitization.js","sourceRoot":"","sources":["../../src/utils/sanitization.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAEtC;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,wBAAwB;IACxB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAE5C,gEAAgE;IAChE,IAAI,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IAED,2EAA2E;IAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;IAE/C,IAAI,SAAS,EAAE,CAAC;QACd,gDAAgD;QAChD,MAAM,SAAS,GAAG;YAChB,qBAAqB;YACrB,yBAAyB;YACzB,uBAAuB;YACvB,kBAAkB;YAClB,oBAAoB;YACpB,gBAAgB;SACjB,CAAC;QACF,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,+CAA+C;QAC/C,MAAM,cAAc,GAAG;YACrB,MAAM;YACN,MAAM;YACN,OAAO;YACP,MAAM;YACN,OAAO;YACP,OAAO;YACP,MAAM;YACN,MAAM;YACN,QAAQ;YACR,WAAW;YACX,UAAU;YACV,WAAW;SACZ,CAAC;QACF,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,KAAK,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YACjF,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAExC,2BAA2B;IAC3B,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,sEAAsE;IACtE,IAAI,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAEpC,4DAA4D;IAC5D,yEAAyE;IACzE,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAEhD,iCAAiC;IACjC,MAAM,gBAAgB,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACvE,OAAO,UAAU,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACtD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,2BAA2B,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IACD,4DAA4D;IAC5D,OAAO,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,uDAAuD;IACvD,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,uBAAuB;IACvB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAAmB;IACzD,2BAA2B;IAC3B,MAAM,UAAU,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAEpD,iDAAiD;IACjD,wDAAwD;IACxD,MAAM,UAAU,GAAG,UAAU;SAC1B,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAE,iCAAiC;SAC9D,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAK,wBAAwB;IAExD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface WorktreeInfo {
|
|
2
|
+
canonicalPath: string;
|
|
3
|
+
worktreePaths: string[];
|
|
4
|
+
isGitRepo: boolean;
|
|
5
|
+
commonDir?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function getGitCommonDir(projectPath: string): string | null;
|
|
8
|
+
export declare function getCanonicalProjectPath(projectPath: string): {
|
|
9
|
+
canonicalPath: string;
|
|
10
|
+
commonDir?: string;
|
|
11
|
+
isGitRepo: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function listWorktreePaths(projectPath: string): string[];
|
|
14
|
+
export declare function getWorktreeInfo(projectPath: string): WorktreeInfo;
|
|
15
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/utils/worktree.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG;IAC5D,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB,CAYA;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB/D;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAiBjE"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { basename, dirname, isAbsolute, resolve } from "path";
|
|
3
|
+
import { realpathSync } from "fs";
|
|
4
|
+
function normalizePath(inputPath) {
|
|
5
|
+
const resolved = resolve(inputPath);
|
|
6
|
+
try {
|
|
7
|
+
return realpathSync(resolved);
|
|
8
|
+
}
|
|
9
|
+
catch (_error) {
|
|
10
|
+
return resolved;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function runGit(args, cwd) {
|
|
14
|
+
try {
|
|
15
|
+
return execFileSync("git", args, {
|
|
16
|
+
cwd,
|
|
17
|
+
encoding: "utf-8",
|
|
18
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
19
|
+
}).trim();
|
|
20
|
+
}
|
|
21
|
+
catch (_error) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function resolveGitPath(rawPath, cwd) {
|
|
26
|
+
const resolved = isAbsolute(rawPath) ? rawPath : resolve(cwd, rawPath);
|
|
27
|
+
return normalizePath(resolved);
|
|
28
|
+
}
|
|
29
|
+
export function getGitCommonDir(projectPath) {
|
|
30
|
+
const normalizedProjectPath = normalizePath(projectPath);
|
|
31
|
+
const output = runGit(["rev-parse", "--git-common-dir"], normalizedProjectPath);
|
|
32
|
+
if (!output) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return resolveGitPath(output, normalizedProjectPath);
|
|
36
|
+
}
|
|
37
|
+
export function getCanonicalProjectPath(projectPath) {
|
|
38
|
+
const normalizedProjectPath = normalizePath(projectPath);
|
|
39
|
+
const commonDir = getGitCommonDir(normalizedProjectPath);
|
|
40
|
+
if (!commonDir) {
|
|
41
|
+
return { canonicalPath: normalizedProjectPath, isGitRepo: false };
|
|
42
|
+
}
|
|
43
|
+
const commonBase = basename(commonDir);
|
|
44
|
+
const canonicalPath = commonBase === ".git" ? normalizePath(dirname(commonDir)) : commonDir;
|
|
45
|
+
return { canonicalPath, commonDir, isGitRepo: true };
|
|
46
|
+
}
|
|
47
|
+
export function listWorktreePaths(projectPath) {
|
|
48
|
+
const normalizedProjectPath = normalizePath(projectPath);
|
|
49
|
+
const output = runGit(["worktree", "list", "--porcelain"], normalizedProjectPath);
|
|
50
|
+
if (!output) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
const worktrees = [];
|
|
54
|
+
for (const line of output.split(/\r?\n/)) {
|
|
55
|
+
if (!line.startsWith("worktree ")) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const rawPath = line.slice("worktree ".length).trim();
|
|
59
|
+
if (!rawPath) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const resolved = resolveGitPath(rawPath, normalizedProjectPath);
|
|
63
|
+
if (!worktrees.includes(resolved)) {
|
|
64
|
+
worktrees.push(resolved);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return worktrees;
|
|
68
|
+
}
|
|
69
|
+
export function getWorktreeInfo(projectPath) {
|
|
70
|
+
const normalizedProjectPath = normalizePath(projectPath);
|
|
71
|
+
const { canonicalPath, commonDir, isGitRepo } = getCanonicalProjectPath(normalizedProjectPath);
|
|
72
|
+
let worktreePaths = listWorktreePaths(normalizedProjectPath);
|
|
73
|
+
if (worktreePaths.length === 0) {
|
|
74
|
+
worktreePaths = [normalizedProjectPath];
|
|
75
|
+
}
|
|
76
|
+
else if (!worktreePaths.includes(normalizedProjectPath)) {
|
|
77
|
+
worktreePaths.push(normalizedProjectPath);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
canonicalPath,
|
|
81
|
+
worktreePaths,
|
|
82
|
+
isGitRepo,
|
|
83
|
+
commonDir,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/utils/worktree.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cccmemory",
|
|
3
|
+
"version": "1.8.0",
|
|
4
|
+
"description": "MCP server for indexing and searching Claude Code conversation history with decision tracking, git integration, and project migration/merge",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"cccmemory": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"scripts",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc && npm run postbuild",
|
|
18
|
+
"postbuild": "cp src/storage/schema.sql dist/storage/",
|
|
19
|
+
"preinstall": "node scripts/check-node.js",
|
|
20
|
+
"postinstall": "node scripts/postinstall.js",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"dev:config": "node scripts/dev-config.js",
|
|
23
|
+
"start": "node dist/index.js",
|
|
24
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
25
|
+
"lint": "eslint .",
|
|
26
|
+
"lint:fix": "eslint . --fix",
|
|
27
|
+
"type-check": "tsc --noEmit",
|
|
28
|
+
"clean": "rm -rf dist",
|
|
29
|
+
"docs": "typedoc --out docs src",
|
|
30
|
+
"test:watch": "npm test -- --watch",
|
|
31
|
+
"test:coverage": "npm test -- --coverage",
|
|
32
|
+
"changelog:check": "bash scripts/changelog-check.sh",
|
|
33
|
+
"pre-push": "npm run type-check && npm run lint && npm run build",
|
|
34
|
+
"prepublishOnly": "npm run build",
|
|
35
|
+
"prepare": "husky"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"mcp",
|
|
39
|
+
"claude",
|
|
40
|
+
"conversation",
|
|
41
|
+
"memory",
|
|
42
|
+
"semantic-search",
|
|
43
|
+
"decision-tracking"
|
|
44
|
+
],
|
|
45
|
+
"author": "xiaolai",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/xiaolai/cccmemory.git"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/xiaolai/cccmemory/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/xiaolai/cccmemory#readme",
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
57
|
+
"@xenova/transformers": "^2.17.2",
|
|
58
|
+
"better-sqlite3": "^11.10.0",
|
|
59
|
+
"chalk": "^5.3.0",
|
|
60
|
+
"chokidar": "^5.0.0",
|
|
61
|
+
"cli-table3": "^0.6.5",
|
|
62
|
+
"commander": "^12.1.0",
|
|
63
|
+
"lru-cache": "^10.0.0",
|
|
64
|
+
"nanoid": "^5.0.0",
|
|
65
|
+
"prompts": "^2.4.2",
|
|
66
|
+
"simple-git": "^3.25.0",
|
|
67
|
+
"sqlite-vec": "^0.1.6"
|
|
68
|
+
},
|
|
69
|
+
"optionalDependencies": {
|
|
70
|
+
"openai": "^6.9.1"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@types/better-sqlite3": "^7.6.11",
|
|
74
|
+
"@types/jest": "^29.5.14",
|
|
75
|
+
"@types/node": "^22.10.5",
|
|
76
|
+
"@types/prompts": "^2.4.9",
|
|
77
|
+
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
78
|
+
"@typescript-eslint/parser": "^8.19.1",
|
|
79
|
+
"eslint": "^9.18.0",
|
|
80
|
+
"globals": "^16.5.0",
|
|
81
|
+
"husky": "^9.1.7",
|
|
82
|
+
"jest": "^29.7.0",
|
|
83
|
+
"lint-staged": "^16.2.6",
|
|
84
|
+
"prettier": "^3.6.2",
|
|
85
|
+
"ts-jest": "^29.2.5",
|
|
86
|
+
"ts-node": "^10.9.2",
|
|
87
|
+
"typescript": "^5.7.3"
|
|
88
|
+
},
|
|
89
|
+
"engines": {
|
|
90
|
+
"node": ">=20 <23"
|
|
91
|
+
},
|
|
92
|
+
"lint-staged": {
|
|
93
|
+
"*.ts": [
|
|
94
|
+
"eslint --fix",
|
|
95
|
+
"prettier --write"
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Changelog checker - Verifies CHANGELOG.md is up to date for releases
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
# Colors for output
|
|
7
|
+
RED='\033[0;31m'
|
|
8
|
+
GREEN='\033[0;32m'
|
|
9
|
+
YELLOW='\033[1;33m'
|
|
10
|
+
NC='\033[0m' # No Color
|
|
11
|
+
|
|
12
|
+
# Get the current version from package.json
|
|
13
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
14
|
+
|
|
15
|
+
# Check if CHANGELOG.md exists
|
|
16
|
+
if [ ! -f "CHANGELOG.md" ]; then
|
|
17
|
+
echo -e "${RED}❌ CHANGELOG.md not found${NC}"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Check if current version is documented in CHANGELOG
|
|
22
|
+
if ! grep -q "\[$CURRENT_VERSION\]" CHANGELOG.md; then
|
|
23
|
+
echo -e "${YELLOW}⚠️ Warning: Version $CURRENT_VERSION not found in CHANGELOG.md${NC}"
|
|
24
|
+
echo ""
|
|
25
|
+
echo "Please add an entry for version $CURRENT_VERSION to CHANGELOG.md"
|
|
26
|
+
echo ""
|
|
27
|
+
echo "Template:"
|
|
28
|
+
echo "----------------------------------------"
|
|
29
|
+
echo "## [$CURRENT_VERSION] - $(date +%Y-%m-%d)"
|
|
30
|
+
echo ""
|
|
31
|
+
echo "### Added"
|
|
32
|
+
echo "- New feature description"
|
|
33
|
+
echo ""
|
|
34
|
+
echo "### Changed"
|
|
35
|
+
echo "- Changed functionality description"
|
|
36
|
+
echo ""
|
|
37
|
+
echo "### Fixed"
|
|
38
|
+
echo "- Bug fix description"
|
|
39
|
+
echo "----------------------------------------"
|
|
40
|
+
echo ""
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Check if [Unreleased] section has content
|
|
45
|
+
UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[[0-9]/p' CHANGELOG.md | grep -v "^## " | grep -v "^$" | wc -l)
|
|
46
|
+
|
|
47
|
+
if [ "$UNRELEASED_CONTENT" -gt 0 ]; then
|
|
48
|
+
echo -e "${YELLOW}⚠️ [Unreleased] section has content${NC}"
|
|
49
|
+
echo ""
|
|
50
|
+
echo "Remember to move unreleased changes to the versioned section before releasing"
|
|
51
|
+
echo ""
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Success
|
|
55
|
+
echo -e "${GREEN}✅ CHANGELOG.md looks good for version $CURRENT_VERSION${NC}"
|
|
56
|
+
|
|
57
|
+
# Show recent entries
|
|
58
|
+
echo ""
|
|
59
|
+
echo "Recent entries:"
|
|
60
|
+
echo "----------------------------------------"
|
|
61
|
+
sed -n '/## \['$CURRENT_VERSION'\]/,/^## /p' CHANGELOG.md | head -20
|
|
62
|
+
echo "----------------------------------------"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-env node */
|
|
3
|
+
/* eslint-disable no-console */
|
|
4
|
+
|
|
5
|
+
const rawVersion = process.versions.node || "0.0.0";
|
|
6
|
+
const major = Number(rawVersion.split(".")[0] || 0);
|
|
7
|
+
const minMajor = 20;
|
|
8
|
+
const maxMajorExclusive = 23;
|
|
9
|
+
|
|
10
|
+
if (Number.isNaN(major) || major < minMajor || major >= maxMajorExclusive) {
|
|
11
|
+
console.error("❌ cccmemory supports Node.js 20 or 22 LTS only.");
|
|
12
|
+
console.error(` Detected Node.js ${rawVersion}.`);
|
|
13
|
+
console.error(" Please switch to Node 20/22 and reinstall:");
|
|
14
|
+
console.error(" - nvm install 22 && nvm use 22");
|
|
15
|
+
console.error(" - npm install -g cccmemory");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Generate MCP configuration for local development testing.
|
|
4
|
+
*
|
|
5
|
+
* Usage: npm run dev:config
|
|
6
|
+
*
|
|
7
|
+
* This outputs the JSON configuration to add to your Claude Code settings
|
|
8
|
+
* for testing the local build instead of the published npm package.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { resolve, dirname } from "path";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const projectRoot = resolve(__dirname, "..");
|
|
17
|
+
const entryPoint = resolve(projectRoot, "dist", "index.js");
|
|
18
|
+
|
|
19
|
+
const config = {
|
|
20
|
+
"cccmemory": {
|
|
21
|
+
command: "node",
|
|
22
|
+
args: [entryPoint],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
console.log(`
|
|
27
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
28
|
+
║ Local Development MCP Configuration ║
|
|
29
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
30
|
+
|
|
31
|
+
Add this to your Claude Code MCP settings (~/.claude.json or VS Code settings):
|
|
32
|
+
|
|
33
|
+
${JSON.stringify({ mcpServers: config }, null, 2)}
|
|
34
|
+
|
|
35
|
+
Or just the server entry:
|
|
36
|
+
|
|
37
|
+
${JSON.stringify(config, null, 2)}
|
|
38
|
+
|
|
39
|
+
────────────────────────────────────────────────────────────────────
|
|
40
|
+
Entry point: ${entryPoint}
|
|
41
|
+
|
|
42
|
+
Steps to test local changes:
|
|
43
|
+
1. Make your code changes
|
|
44
|
+
2. Run: npm run build
|
|
45
|
+
3. Restart Claude Code (Cmd+Shift+P > "Developer: Reload Window" in VS Code)
|
|
46
|
+
4. Test your changes
|
|
47
|
+
|
|
48
|
+
To switch back to published version, use:
|
|
49
|
+
{
|
|
50
|
+
"cccmemory": {
|
|
51
|
+
"command": "npx",
|
|
52
|
+
"args": ["-y", "cccmemory"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
────────────────────────────────────────────────────────────────────
|
|
56
|
+
`);
|