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,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main Orchestrator - Coordinates all components for conversation memory indexing and retrieval.
|
|
3
|
+
*
|
|
4
|
+
* ConversationMemory is the primary interface for the cccmemory-mcp system.
|
|
5
|
+
* It orchestrates parsing, storage, extraction, and search of Claude Code conversation history.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const memory = new ConversationMemory();
|
|
10
|
+
* await memory.indexConversations({
|
|
11
|
+
* projectPath: '/path/to/project',
|
|
12
|
+
* enableGitIntegration: true
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import { getSQLiteManager } from "./storage/SQLiteManager.js";
|
|
17
|
+
import { ConversationStorage } from "./storage/ConversationStorage.js";
|
|
18
|
+
import { ConversationParser } from "./parsers/ConversationParser.js";
|
|
19
|
+
import { DecisionExtractor } from "./parsers/DecisionExtractor.js";
|
|
20
|
+
import { MistakeExtractor } from "./parsers/MistakeExtractor.js";
|
|
21
|
+
import { GitIntegrator } from "./parsers/GitIntegrator.js";
|
|
22
|
+
import { RequirementsExtractor } from "./parsers/RequirementsExtractor.js";
|
|
23
|
+
import { SemanticSearch } from "./search/SemanticSearch.js";
|
|
24
|
+
import { getWorktreeInfo } from "./utils/worktree.js";
|
|
25
|
+
/**
|
|
26
|
+
* Main orchestrator for conversation memory operations.
|
|
27
|
+
*
|
|
28
|
+
* Coordinates parsing, storage, extraction, and search across:
|
|
29
|
+
* - Conversation parsing from JSONL files
|
|
30
|
+
* - Decision, mistake, and requirement extraction
|
|
31
|
+
* - Git commit integration
|
|
32
|
+
* - Semantic search with embeddings
|
|
33
|
+
*/
|
|
34
|
+
export class ConversationMemory {
|
|
35
|
+
sqliteManager;
|
|
36
|
+
storage;
|
|
37
|
+
parser;
|
|
38
|
+
decisionExtractor;
|
|
39
|
+
mistakeExtractor;
|
|
40
|
+
requirementsExtractor;
|
|
41
|
+
semanticSearch;
|
|
42
|
+
constructor() {
|
|
43
|
+
this.sqliteManager = getSQLiteManager();
|
|
44
|
+
this.storage = new ConversationStorage(this.sqliteManager);
|
|
45
|
+
// Enable caching by default for better performance
|
|
46
|
+
// Cache up to 100 query results for 5 minutes
|
|
47
|
+
this.storage.enableCache({ maxSize: 100, ttlMs: 300000 });
|
|
48
|
+
this.parser = new ConversationParser();
|
|
49
|
+
this.decisionExtractor = new DecisionExtractor();
|
|
50
|
+
this.mistakeExtractor = new MistakeExtractor();
|
|
51
|
+
this.requirementsExtractor = new RequirementsExtractor();
|
|
52
|
+
this.semanticSearch = new SemanticSearch(this.sqliteManager);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Index conversations for a project.
|
|
56
|
+
*
|
|
57
|
+
* This is the main entry point for processing conversation history.
|
|
58
|
+
* It performs the following operations:
|
|
59
|
+
* 1. Parse conversation JSONL files from the project
|
|
60
|
+
* 2. Store conversations, messages, and tool interactions
|
|
61
|
+
* 3. Extract decisions, mistakes, and requirements
|
|
62
|
+
* 4. Link git commits (if enabled)
|
|
63
|
+
* 5. Generate semantic embeddings for search
|
|
64
|
+
*
|
|
65
|
+
* @param options - Configuration options for indexing
|
|
66
|
+
* @returns Result object containing:
|
|
67
|
+
* - `embeddings_generated`: Whether embeddings were successfully generated
|
|
68
|
+
* - `embedding_error`: Error message if embedding generation failed
|
|
69
|
+
* - `indexed_folders`: List of folders that were indexed
|
|
70
|
+
* - `database_path`: Path to the SQLite database
|
|
71
|
+
*
|
|
72
|
+
* @throws {Error} If project path doesn't exist or conversation files can't be parsed
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const result = await memory.indexConversations({
|
|
77
|
+
* projectPath: '/Users/me/my-project',
|
|
78
|
+
* enableGitIntegration: true,
|
|
79
|
+
* excludeMcpConversations: 'self-only'
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* if (result.embeddings_generated) {
|
|
83
|
+
* console.error('Indexed folders:', result.indexed_folders);
|
|
84
|
+
* } else {
|
|
85
|
+
* console.warn('Embeddings failed:', result.embedding_error);
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
async indexConversations(options) {
|
|
90
|
+
const { canonicalPath, worktreePaths } = getWorktreeInfo(options.projectPath);
|
|
91
|
+
console.error("\n=== Indexing Conversations ===");
|
|
92
|
+
console.error(`Project: ${canonicalPath}`);
|
|
93
|
+
if (options.sessionId) {
|
|
94
|
+
console.error(`Session: ${options.sessionId} (single session mode)`);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
console.error(`Mode: All sessions`);
|
|
98
|
+
}
|
|
99
|
+
if (worktreePaths.length > 1) {
|
|
100
|
+
console.error(`Worktrees: ${worktreePaths.join(", ")}`);
|
|
101
|
+
}
|
|
102
|
+
// Parse conversations
|
|
103
|
+
let parseResult = this.parser.parseProjects(worktreePaths, options.sessionId, canonicalPath, options.lastIndexedMs);
|
|
104
|
+
// Filter MCP conversations if requested
|
|
105
|
+
if (options.excludeMcpConversations || options.excludeMcpServers) {
|
|
106
|
+
parseResult = this.filterMcpConversations(parseResult, options);
|
|
107
|
+
}
|
|
108
|
+
// Store basic entities (skip FTS rebuild for performance, will rebuild once at end)
|
|
109
|
+
await this.storage.storeConversations(parseResult.conversations);
|
|
110
|
+
await this.storage.storeMessages(parseResult.messages, true);
|
|
111
|
+
await this.storage.storeToolUses(parseResult.tool_uses);
|
|
112
|
+
await this.storage.storeToolResults(parseResult.tool_results);
|
|
113
|
+
await this.storage.storeFileEdits(parseResult.file_edits);
|
|
114
|
+
// Only store thinking blocks if explicitly enabled (default: false for privacy)
|
|
115
|
+
if (options.includeThinking === true) {
|
|
116
|
+
await this.storage.storeThinkingBlocks(parseResult.thinking_blocks);
|
|
117
|
+
}
|
|
118
|
+
// Extract decisions
|
|
119
|
+
console.error("\n=== Extracting Decisions ===");
|
|
120
|
+
const decisions = this.decisionExtractor.extractDecisions(parseResult.messages, parseResult.thinking_blocks);
|
|
121
|
+
await this.storage.storeDecisions(decisions, true);
|
|
122
|
+
// Rebuild FTS indexes once after all data is stored
|
|
123
|
+
this.storage.rebuildAllFts();
|
|
124
|
+
// Extract mistakes
|
|
125
|
+
console.error("\n=== Extracting Mistakes ===");
|
|
126
|
+
const mistakes = this.mistakeExtractor.extractMistakes(parseResult.messages, parseResult.tool_results);
|
|
127
|
+
await this.storage.storeMistakes(mistakes);
|
|
128
|
+
// Extract requirements and validations
|
|
129
|
+
console.error("\n=== Extracting Requirements ===");
|
|
130
|
+
const requirements = this.requirementsExtractor.extractRequirements(parseResult.messages);
|
|
131
|
+
await this.storage.storeRequirements(requirements);
|
|
132
|
+
const validations = this.requirementsExtractor.extractValidations(parseResult.tool_uses, parseResult.tool_results, parseResult.messages);
|
|
133
|
+
await this.storage.storeValidations(validations);
|
|
134
|
+
// Git integration
|
|
135
|
+
if (options.enableGitIntegration !== false) {
|
|
136
|
+
try {
|
|
137
|
+
console.error("\n=== Integrating Git History ===");
|
|
138
|
+
const gitIntegrator = new GitIntegrator(canonicalPath);
|
|
139
|
+
const commits = await gitIntegrator.linkCommitsToConversations(parseResult.conversations, parseResult.file_edits, decisions);
|
|
140
|
+
await this.storage.storeGitCommits(commits);
|
|
141
|
+
console.error(`✓ Linked ${commits.length} git commits`);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.error("⚠️ Git integration failed:", error);
|
|
145
|
+
console.error(" Conversations will be indexed without git commit links");
|
|
146
|
+
console.error(" This is normal if the project is not a git repository");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Index for semantic search
|
|
150
|
+
console.error("\n=== Indexing for Semantic Search ===");
|
|
151
|
+
let embeddingError;
|
|
152
|
+
try {
|
|
153
|
+
await this.semanticSearch.indexMessages(parseResult.messages);
|
|
154
|
+
await this.semanticSearch.indexDecisions(decisions);
|
|
155
|
+
await this.semanticSearch.indexMistakes(mistakes);
|
|
156
|
+
// Also index any decisions/mistakes in DB that are missing embeddings
|
|
157
|
+
// (catches items created before embeddings were available)
|
|
158
|
+
await this.semanticSearch.indexMissingDecisionEmbeddings();
|
|
159
|
+
await this.semanticSearch.indexMissingMistakeEmbeddings();
|
|
160
|
+
console.error("✓ Semantic indexing complete");
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
embeddingError = error.message;
|
|
164
|
+
console.error("⚠️ Semantic indexing failed:", error);
|
|
165
|
+
console.error(" Embeddings may not be available - falling back to full-text search");
|
|
166
|
+
console.error(" Install @xenova/transformers for semantic search: npm install @xenova/transformers");
|
|
167
|
+
// Don't throw - allow indexing to complete with FTS fallback
|
|
168
|
+
}
|
|
169
|
+
// Print stats
|
|
170
|
+
console.error("\n=== Indexing Complete ===");
|
|
171
|
+
const stats = this.storage.getStats();
|
|
172
|
+
console.error(`Conversations: ${stats.conversations.count}`);
|
|
173
|
+
console.error(`Messages: ${stats.messages.count}`);
|
|
174
|
+
console.error(`Decisions: ${stats.decisions.count}`);
|
|
175
|
+
console.error(`Mistakes: ${stats.mistakes.count}`);
|
|
176
|
+
console.error(`Git Commits: ${stats.git_commits.count}`);
|
|
177
|
+
// Return embedding status and indexing metadata
|
|
178
|
+
return {
|
|
179
|
+
embeddings_generated: !embeddingError,
|
|
180
|
+
embedding_error: embeddingError,
|
|
181
|
+
indexed_folders: parseResult.indexed_folders,
|
|
182
|
+
database_path: this.sqliteManager.getDbPath(),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Search conversations using natural language query.
|
|
187
|
+
*
|
|
188
|
+
* Uses semantic search with embeddings if available, otherwise falls back to full-text search.
|
|
189
|
+
*
|
|
190
|
+
* @param query - Natural language search query
|
|
191
|
+
* @param limit - Maximum number of results to return (default: 10)
|
|
192
|
+
* @returns Array of search results with messages, conversations, and similarity scores
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const results = await memory.search('authentication bug fix', 5);
|
|
197
|
+
* results.forEach(r => {
|
|
198
|
+
* console.error(`${r.similarity}: ${r.snippet}`);
|
|
199
|
+
* });
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
async search(query, limit = 10) {
|
|
203
|
+
return this.semanticSearch.searchConversations(query, limit);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Search for decisions using natural language query.
|
|
207
|
+
*
|
|
208
|
+
* Searches through extracted decisions to find relevant architectural choices and technical decisions.
|
|
209
|
+
*
|
|
210
|
+
* @param query - Natural language search query
|
|
211
|
+
* @param limit - Maximum number of results to return (default: 10)
|
|
212
|
+
* @returns Array of decision search results with similarity scores
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```typescript
|
|
216
|
+
* const decisions = await memory.searchDecisions('database choice', 3);
|
|
217
|
+
* decisions.forEach(d => {
|
|
218
|
+
* console.error(`Decision: ${d.decision.decision_text}`);
|
|
219
|
+
* console.error(`Rationale: ${d.decision.rationale}`);
|
|
220
|
+
* });
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
async searchDecisions(query, limit = 10) {
|
|
224
|
+
return this.semanticSearch.searchDecisions(query, limit);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get the timeline of changes for a specific file.
|
|
228
|
+
*
|
|
229
|
+
* Returns all edits, commits, and related conversations for a file across its history.
|
|
230
|
+
*
|
|
231
|
+
* @param filePath - Path to the file (relative to project root)
|
|
232
|
+
* @returns Timeline of file changes with conversations and commits
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* const timeline = memory.getFileTimeline('src/index.ts');
|
|
237
|
+
* console.error(`${timeline.length} changes to this file`);
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
getFileTimeline(filePath) {
|
|
241
|
+
return this.storage.getFileTimeline(filePath);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get statistics about the indexed conversation data.
|
|
245
|
+
*
|
|
246
|
+
* @returns Object containing counts for conversations, messages, decisions, mistakes, and commits
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* const stats = memory.getStats();
|
|
251
|
+
* console.error(`Indexed ${stats.conversations.count} conversations`);
|
|
252
|
+
* console.error(`Extracted ${stats.decisions.count} decisions`);
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
getStats() {
|
|
256
|
+
return this.storage.getStats();
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Get the underlying storage instance for direct database access.
|
|
260
|
+
*
|
|
261
|
+
* Use with caution - prefer using the high-level methods when possible.
|
|
262
|
+
*
|
|
263
|
+
* @returns ConversationStorage instance
|
|
264
|
+
* @internal
|
|
265
|
+
*/
|
|
266
|
+
getStorage() {
|
|
267
|
+
return this.storage;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get the semantic search instance for advanced search operations.
|
|
271
|
+
*
|
|
272
|
+
* @returns SemanticSearch instance
|
|
273
|
+
* @internal
|
|
274
|
+
*/
|
|
275
|
+
getSemanticSearch() {
|
|
276
|
+
return this.semanticSearch;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Filter MCP conversations from parse results.
|
|
280
|
+
*
|
|
281
|
+
* Implements the exclusion logic for MCP tool conversations to prevent
|
|
282
|
+
* self-referential loops and reduce noise in the index.
|
|
283
|
+
*
|
|
284
|
+
* Strategy: Filter at MESSAGE level, not conversation level.
|
|
285
|
+
* - Keep all conversations
|
|
286
|
+
* - Exclude only messages that invoke specified MCP tools and their responses
|
|
287
|
+
*/
|
|
288
|
+
filterMcpConversations(result, options) {
|
|
289
|
+
// Determine which MCP servers to exclude
|
|
290
|
+
const serversToExclude = new Set();
|
|
291
|
+
if (options.excludeMcpServers && options.excludeMcpServers.length > 0) {
|
|
292
|
+
// Explicit list of servers to exclude
|
|
293
|
+
options.excludeMcpServers.forEach(s => serversToExclude.add(s));
|
|
294
|
+
}
|
|
295
|
+
else if (options.excludeMcpConversations === 'self-only') {
|
|
296
|
+
// Exclude only cccmemory server
|
|
297
|
+
serversToExclude.add('cccmemory');
|
|
298
|
+
}
|
|
299
|
+
else if (options.excludeMcpConversations === 'all-mcp' || options.excludeMcpConversations === true) {
|
|
300
|
+
// Exclude all MCP tool uses - collect all server names from tool uses
|
|
301
|
+
for (const toolUse of result.tool_uses) {
|
|
302
|
+
if (toolUse.tool_name.startsWith('mcp__')) {
|
|
303
|
+
const parts = toolUse.tool_name.split('__');
|
|
304
|
+
if (parts.length >= 2) {
|
|
305
|
+
serversToExclude.add(parts[1]);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (serversToExclude.size === 0) {
|
|
311
|
+
return result; // Nothing to filter
|
|
312
|
+
}
|
|
313
|
+
// Build set of excluded tool_use IDs (tools from excluded servers)
|
|
314
|
+
const excludedToolUseIds = new Set();
|
|
315
|
+
for (const toolUse of result.tool_uses) {
|
|
316
|
+
if (toolUse.tool_name.startsWith('mcp__')) {
|
|
317
|
+
const parts = toolUse.tool_name.split('__');
|
|
318
|
+
if (parts.length >= 2 && serversToExclude.has(parts[1])) {
|
|
319
|
+
excludedToolUseIds.add(toolUse.id);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// Build set of excluded message IDs (messages containing excluded tool uses or their results)
|
|
324
|
+
const excludedMessageIds = new Set();
|
|
325
|
+
// Exclude assistant messages that contain excluded tool uses
|
|
326
|
+
for (const toolUse of result.tool_uses) {
|
|
327
|
+
if (excludedToolUseIds.has(toolUse.id)) {
|
|
328
|
+
excludedMessageIds.add(toolUse.message_id);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
// Exclude user messages that contain tool results for excluded tool uses
|
|
332
|
+
for (const toolResult of result.tool_results) {
|
|
333
|
+
if (excludedToolUseIds.has(toolResult.tool_use_id)) {
|
|
334
|
+
excludedMessageIds.add(toolResult.message_id);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (excludedMessageIds.size > 0) {
|
|
338
|
+
console.error(`\n⚠️ Excluding ${excludedMessageIds.size} message(s) containing MCP tool calls from: ${Array.from(serversToExclude).join(', ')}`);
|
|
339
|
+
}
|
|
340
|
+
// Build set of remaining message IDs after filtering
|
|
341
|
+
const remainingMessageIds = new Set(result.messages
|
|
342
|
+
.filter(m => !excludedMessageIds.has(m.id))
|
|
343
|
+
.map(m => m.id));
|
|
344
|
+
// Filter messages and related entities
|
|
345
|
+
// IMPORTANT: file_edits must also be filtered to avoid FK constraint violations
|
|
346
|
+
return {
|
|
347
|
+
conversations: result.conversations, // Keep ALL conversations
|
|
348
|
+
messages: result.messages.filter(m => !excludedMessageIds.has(m.id)),
|
|
349
|
+
tool_uses: result.tool_uses.filter(t => !excludedToolUseIds.has(t.id)),
|
|
350
|
+
tool_results: result.tool_results.filter(tr => !excludedToolUseIds.has(tr.tool_use_id)),
|
|
351
|
+
file_edits: result.file_edits.filter(fe => remainingMessageIds.has(fe.message_id)),
|
|
352
|
+
thinking_blocks: result.thinking_blocks.filter(tb => remainingMessageIds.has(tb.message_id)),
|
|
353
|
+
indexed_folders: result.indexed_folders, // Preserve folder metadata
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
//# sourceMappingURL=ConversationMemory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationMemory.js","sourceRoot":"","sources":["../src/ConversationMemory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QueryCache - LRU cache for database query results
|
|
3
|
+
*
|
|
4
|
+
* Provides an in-memory caching layer with:
|
|
5
|
+
* - LRU (Least Recently Used) eviction policy
|
|
6
|
+
* - TTL (Time To Live) for automatic expiration
|
|
7
|
+
* - Cache statistics (hits, misses, evictions, hit rate)
|
|
8
|
+
* - Smart invalidation support
|
|
9
|
+
*
|
|
10
|
+
* Use this to cache expensive database queries like conversation searches,
|
|
11
|
+
* file timelines, and decision lookups.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const cache = new QueryCache({ maxSize: 100, ttlMs: 60000 });
|
|
16
|
+
*
|
|
17
|
+
* // Store query result
|
|
18
|
+
* cache.set('conversations:all', conversations);
|
|
19
|
+
*
|
|
20
|
+
* // Retrieve from cache
|
|
21
|
+
* const cached = cache.get('conversations:all');
|
|
22
|
+
* if (cached) {
|
|
23
|
+
* return cached; // Cache hit
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // Cache miss - query database
|
|
27
|
+
* const result = await queryDatabase();
|
|
28
|
+
* cache.set('conversations:all', result);
|
|
29
|
+
* return result;
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Configuration options for QueryCache
|
|
34
|
+
*/
|
|
35
|
+
export interface QueryCacheConfig {
|
|
36
|
+
/** Maximum number of entries to store */
|
|
37
|
+
maxSize: number;
|
|
38
|
+
/** Time to live in milliseconds before entries expire */
|
|
39
|
+
ttlMs: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Cache statistics for monitoring
|
|
43
|
+
*/
|
|
44
|
+
export interface CacheStats {
|
|
45
|
+
/** Number of cache hits */
|
|
46
|
+
hits: number;
|
|
47
|
+
/** Number of cache misses */
|
|
48
|
+
misses: number;
|
|
49
|
+
/** Number of entries evicted */
|
|
50
|
+
evictions: number;
|
|
51
|
+
/** Cache hit rate (0-1) */
|
|
52
|
+
hitRate: number;
|
|
53
|
+
/** Current cache size */
|
|
54
|
+
size: number;
|
|
55
|
+
/** Maximum cache size */
|
|
56
|
+
maxSize: number;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* LRU cache with TTL support for database query results.
|
|
60
|
+
*
|
|
61
|
+
* Uses a Map for O(1) access and maintains LRU order by moving
|
|
62
|
+
* accessed entries to the end of the Map.
|
|
63
|
+
*/
|
|
64
|
+
export declare class QueryCache {
|
|
65
|
+
private cache;
|
|
66
|
+
private readonly config;
|
|
67
|
+
private stats;
|
|
68
|
+
/**
|
|
69
|
+
* Create a new QueryCache.
|
|
70
|
+
*
|
|
71
|
+
* @param config - Cache configuration
|
|
72
|
+
* @throws {Error} If configuration is invalid
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // Create cache with 100 entries, 1 minute TTL
|
|
77
|
+
* const cache = new QueryCache({ maxSize: 100, ttlMs: 60000 });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
constructor(config?: Partial<QueryCacheConfig>);
|
|
81
|
+
/**
|
|
82
|
+
* Store a value in the cache.
|
|
83
|
+
*
|
|
84
|
+
* If the key already exists, updates the value and resets TTL.
|
|
85
|
+
* If cache is full, evicts the least recently used entry.
|
|
86
|
+
*
|
|
87
|
+
* @param key - Cache key
|
|
88
|
+
* @param value - Value to cache
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* cache.set('user:123', { id: 123, name: 'Alice' });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
set<T>(key: string, value: T): void;
|
|
96
|
+
/**
|
|
97
|
+
* Retrieve a value from the cache.
|
|
98
|
+
*
|
|
99
|
+
* Returns undefined if key doesn't exist or entry has expired.
|
|
100
|
+
* Updates access order (moves entry to end as most recently used).
|
|
101
|
+
*
|
|
102
|
+
* @param key - Cache key
|
|
103
|
+
* @returns Cached value or undefined
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const user = cache.get<User>('user:123');
|
|
108
|
+
* if (user) {
|
|
109
|
+
* console.log('Cache hit:', user.name);
|
|
110
|
+
* } else {
|
|
111
|
+
* console.log('Cache miss');
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
get<T>(key: string): T | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a key exists in the cache.
|
|
118
|
+
*
|
|
119
|
+
* Returns false if key doesn't exist or entry has expired.
|
|
120
|
+
* Updates access order (moves entry to end as most recently used).
|
|
121
|
+
*
|
|
122
|
+
* @param key - Cache key
|
|
123
|
+
* @returns True if key exists and not expired
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* if (cache.has('user:123')) {
|
|
128
|
+
* const user = cache.get('user:123');
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
has(key: string): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Delete a key from the cache.
|
|
135
|
+
*
|
|
136
|
+
* Does nothing if key doesn't exist.
|
|
137
|
+
*
|
|
138
|
+
* @param key - Cache key to delete
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* cache.delete('user:123');
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
delete(key: string): void;
|
|
146
|
+
/**
|
|
147
|
+
* Clear all entries from the cache.
|
|
148
|
+
*
|
|
149
|
+
* Resets the cache but preserves statistics.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* cache.clear(); // Remove all cached data
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
clear(): void;
|
|
157
|
+
/**
|
|
158
|
+
* Get current cache size.
|
|
159
|
+
*
|
|
160
|
+
* @returns Number of entries in cache
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* console.log(`Cache contains ${cache.size()} entries`);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
size(): number;
|
|
168
|
+
/**
|
|
169
|
+
* Get cache statistics.
|
|
170
|
+
*
|
|
171
|
+
* Provides insight into cache performance:
|
|
172
|
+
* - Hit/miss counts
|
|
173
|
+
* - Hit rate percentage
|
|
174
|
+
* - Eviction count
|
|
175
|
+
* - Current size
|
|
176
|
+
*
|
|
177
|
+
* @returns Cache statistics object
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* const stats = cache.getStats();
|
|
182
|
+
* console.log(`Hit rate: ${(stats.hitRate * 100).toFixed(1)}%`);
|
|
183
|
+
* console.log(`Evictions: ${stats.evictions}`);
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
getStats(): CacheStats;
|
|
187
|
+
/**
|
|
188
|
+
* Reset statistics counters.
|
|
189
|
+
*
|
|
190
|
+
* Clears hit/miss/eviction counts but preserves cached data.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* cache.resetStats(); // Start fresh statistics
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
resetStats(): void;
|
|
198
|
+
/**
|
|
199
|
+
* Check if an entry has expired based on TTL.
|
|
200
|
+
*
|
|
201
|
+
* @param entry - Cache entry to check
|
|
202
|
+
* @returns True if entry is expired
|
|
203
|
+
* @internal
|
|
204
|
+
*/
|
|
205
|
+
private isExpired;
|
|
206
|
+
/**
|
|
207
|
+
* Remove all expired entries from the cache.
|
|
208
|
+
*
|
|
209
|
+
* Called automatically by size() to keep cache clean.
|
|
210
|
+
*
|
|
211
|
+
* @internal
|
|
212
|
+
*/
|
|
213
|
+
private cleanupExpired;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=QueryCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryCache.d.ts","sourceRoot":"","sources":["../../src/cache/QueryCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;CACf;AAYD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,KAAK,CAIX;IAEF;;;;;;;;;;;OAWG;gBACS,MAAM,GAAE,OAAO,CAAC,gBAAgB,CAAM;IAkBlD;;;;;;;;;;;;;OAaG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAsBnC;;;;;;;;;;;;;;;;;;OAkBG;IACH,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAuBlC;;;;;;;;;;;;;;;OAeG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAoBzB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB;;;;;;;;;OASG;IACH,KAAK,IAAI,IAAI;IAIb;;;;;;;;;OASG;IACH,IAAI,IAAI,MAAM;IAMd;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,IAAI,UAAU;IActB;;;;;;;;;OASG;IACH,UAAU,IAAI,IAAI;IAQlB;;;;;;OAMG;IACH,OAAO,CAAC,SAAS;IAKjB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;CAavB"}
|