claude-mem 3.0.2 → 3.0.4
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/.mcp.json +11 -0
- package/claude-mem +0 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +64 -0
- package/dist/commands/compress.d.ts +2 -0
- package/dist/commands/compress.js +59 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +372 -0
- package/dist/commands/load-context.d.ts +2 -0
- package/dist/commands/load-context.js +330 -0
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +41 -0
- package/dist/commands/migrate.d.ts +9 -0
- package/dist/commands/migrate.js +174 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +159 -0
- package/dist/commands/uninstall.d.ts +2 -0
- package/dist/commands/uninstall.js +105 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +33 -0
- package/dist/constants.d.ts +516 -0
- package/dist/constants.js +522 -0
- package/dist/error-handler.d.ts +17 -0
- package/dist/error-handler.js +103 -0
- package/dist/mcp-server-cli.d.ts +34 -0
- package/dist/mcp-server-cli.js +158 -0
- package/dist/mcp-server.d.ts +103 -0
- package/dist/mcp-server.js +269 -0
- package/dist/types.d.ts +148 -0
- package/dist/types.js +78 -0
- package/dist/utils/HookDetector.d.ts +64 -0
- package/dist/utils/HookDetector.js +213 -0
- package/dist/utils/PathResolver.d.ts +16 -0
- package/dist/utils/PathResolver.js +55 -0
- package/dist/utils/SettingsManager.d.ts +63 -0
- package/dist/utils/SettingsManager.js +133 -0
- package/dist/utils/TranscriptCompressor.d.ts +111 -0
- package/dist/utils/TranscriptCompressor.js +486 -0
- package/dist/utils/common.d.ts +29 -0
- package/dist/utils/common.js +14 -0
- package/dist/utils/error-utils.d.ts +93 -0
- package/dist/utils/error-utils.js +238 -0
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.js +26 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.js +42 -0
- package/dist/utils/mcp-client-factory.d.ts +51 -0
- package/dist/utils/mcp-client-factory.js +115 -0
- package/dist/utils/mcp-client.d.ts +75 -0
- package/dist/utils/mcp-client.js +120 -0
- package/dist/utils/memory-mcp-client.d.ts +135 -0
- package/dist/utils/memory-mcp-client.js +490 -0
- package/dist/utils/weaviate-mcp-adapter.d.ts +102 -0
- package/dist/utils/weaviate-mcp-adapter.js +587 -0
- package/package.json +3 -2
- package/src/claude-mem.js +0 -859
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Memory System - Constants and Templates
|
|
3
|
+
*
|
|
4
|
+
* This file consolidates all prompts, instructions, and output templates
|
|
5
|
+
* used throughout the claude-mem system for better maintainability,
|
|
6
|
+
* DRYness, and easier auditing of LLM logic.
|
|
7
|
+
*/
|
|
8
|
+
// =============================================================================
|
|
9
|
+
// ANALYSIS PROMPTS AND TEMPLATES
|
|
10
|
+
// =============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Entity naming patterns for the knowledge graph
|
|
13
|
+
*/
|
|
14
|
+
export const ENTITY_NAMING_PATTERNS = {
|
|
15
|
+
component: "Component_Name",
|
|
16
|
+
decision: "Decision_Name",
|
|
17
|
+
pattern: "Pattern_Name",
|
|
18
|
+
tool: "Tool_Name",
|
|
19
|
+
fix: "Fix_Name",
|
|
20
|
+
workflow: "Workflow_Name"
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Available entity types for classification
|
|
24
|
+
*/
|
|
25
|
+
export const ENTITY_TYPES = {
|
|
26
|
+
component: "component", // UI components, modules, services
|
|
27
|
+
pattern: "pattern", // Architectural or design patterns
|
|
28
|
+
workflow: "workflow", // Processes, pipelines, sequences
|
|
29
|
+
integration: "integration", // APIs, external services, data sources
|
|
30
|
+
concept: "concept", // Abstract ideas, methodologies, principles
|
|
31
|
+
decision: "decision", // Design choices, trade-offs, solutions
|
|
32
|
+
tool: "tool", // Utilities, libraries, development tools
|
|
33
|
+
fix: "fix" // Bug fixes, patches, workarounds
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Standard observation fields for entities
|
|
37
|
+
*/
|
|
38
|
+
export const OBSERVATION_FIELDS = [
|
|
39
|
+
"Core purpose: [what it fundamentally does]",
|
|
40
|
+
"Brief description: [one-line summary for session-start display]",
|
|
41
|
+
"Implementation: [key technical details, code patterns]",
|
|
42
|
+
"Dependencies: [what it requires or builds upon]",
|
|
43
|
+
"Usage context: [when/why it's used]",
|
|
44
|
+
"Performance characteristics: [speed, reliability, constraints]",
|
|
45
|
+
"Integration points: [how it connects to other systems]",
|
|
46
|
+
"Keywords: [searchable terms for this concept]",
|
|
47
|
+
"Decision rationale: [why this approach was chosen]",
|
|
48
|
+
"Next steps: [what needs to be done next with this component]",
|
|
49
|
+
"Files modified: [list of files changed]",
|
|
50
|
+
"Tools used: [development tools/commands used]"
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Relationship types for creating meaningful entity connections
|
|
54
|
+
*/
|
|
55
|
+
export const RELATIONSHIP_TYPES = [
|
|
56
|
+
"executes_via", "orchestrates_through", "validates_using",
|
|
57
|
+
"provides_auth_to", "manages_state_for", "processes_events_from",
|
|
58
|
+
"caches_data_from", "routes_requests_to", "transforms_data_for",
|
|
59
|
+
"extends", "enhances_performance_of", "builds_upon",
|
|
60
|
+
"fixes_issue_in", "replaces", "optimizes",
|
|
61
|
+
"uses_tool_chain", "triggers_tool", "receives_result_from"
|
|
62
|
+
];
|
|
63
|
+
/**
|
|
64
|
+
* Creates the main analysis prompt for transcript compression
|
|
65
|
+
*/
|
|
66
|
+
export function createAnalysisPrompt(projectName, sessionId, hasCompressedContent, existingMemoriesText, toolUseChains) {
|
|
67
|
+
const incrementalSection = hasCompressedContent ? `
|
|
68
|
+
INCREMENTAL COMPRESSION:
|
|
69
|
+
Lines marked [ALREADY COMPRESSED] contain existing memory references.
|
|
70
|
+
DO NOT re-compress these. Build upon existing patterns and connect new entities to them.
|
|
71
|
+
|
|
72
|
+
EXISTING COMPRESSED MEMORIES:
|
|
73
|
+
${existingMemoriesText}
|
|
74
|
+
` : '';
|
|
75
|
+
const toolChainsSection = toolUseChains.length > 0 ? `
|
|
76
|
+
TOOL USE CHAINS DETECTED:
|
|
77
|
+
${toolUseChains.map(chain => `- Tool chain ${chain.id}: ${chain.tools.join(' → ')}`).join('\n')}
|
|
78
|
+
Create relationships for these tool use sequences in the knowledge graph.
|
|
79
|
+
` : '';
|
|
80
|
+
return `You are analyzing a Claude Code conversation transcript to create a sophisticated memory index system using the Model Context Protocol knowledge graph.
|
|
81
|
+
|
|
82
|
+
Your task:
|
|
83
|
+
1. Extract ALL key technical entities following MCP memory best practices
|
|
84
|
+
2. Create rich, searchable entities with detailed observations using MCP tools
|
|
85
|
+
3. Create specific, active-voice relationships between entities
|
|
86
|
+
4. Return compressed summaries in STRICT JSONL format with memory/keyword references
|
|
87
|
+
|
|
88
|
+
${incrementalSection}${toolChainsSection}
|
|
89
|
+
|
|
90
|
+
ENTITY EXTRACTION GUIDELINES:
|
|
91
|
+
Focus on these categories for creating a searchable index:
|
|
92
|
+
- **Technical Components**: Functions, classes, services, APIs, databases, modules
|
|
93
|
+
- **Architectural Patterns**: State management, authentication flows, data pipelines, design patterns
|
|
94
|
+
- **Development Decisions**: Design choices, trade-offs, problem solutions, optimizations
|
|
95
|
+
- **Workflows & Processes**: Build processes, deployment strategies, testing approaches
|
|
96
|
+
- **Integration Points**: External APIs, third-party services, data sources
|
|
97
|
+
- **Performance & Reliability**: Caching strategies, error handling, optimization techniques
|
|
98
|
+
- **Bugs & Fixes**: Issues encountered, debugging approaches, solutions applied
|
|
99
|
+
|
|
100
|
+
ENTITY FORMAT:
|
|
101
|
+
- name: "${projectName}_EntityName"
|
|
102
|
+
(Use clear, searchable names that describe WHAT it is, not session-specific IDs)
|
|
103
|
+
IMPORTANT: Include entity type in name for better categorization:
|
|
104
|
+
* "${projectName}_${ENTITY_NAMING_PATTERNS.component}" for UI/modules/services
|
|
105
|
+
* "${projectName}_${ENTITY_NAMING_PATTERNS.decision}" for architectural choices
|
|
106
|
+
* "${projectName}_${ENTITY_NAMING_PATTERNS.pattern}" for design patterns
|
|
107
|
+
* "${projectName}_${ENTITY_NAMING_PATTERNS.tool}" for libraries/tools
|
|
108
|
+
* "${projectName}_${ENTITY_NAMING_PATTERNS.fix}" for bug fixes
|
|
109
|
+
* "${projectName}_${ENTITY_NAMING_PATTERNS.workflow}" for processes
|
|
110
|
+
- entityType: Choose from:
|
|
111
|
+
${Object.entries(ENTITY_TYPES).map(([key, value]) => ` * "${value}" - ${getEntityTypeDescription(key)}`).join('\n')}
|
|
112
|
+
- observations: Rich, structured details for future recall:
|
|
113
|
+
${OBSERVATION_FIELDS.map(field => ` * "${field}"`).join('\n')}
|
|
114
|
+
* "UUID: ${sessionId}"
|
|
115
|
+
* "Session: ${sessionId}"
|
|
116
|
+
|
|
117
|
+
RELATIONSHIP FORMAT (Use specific, active voice):
|
|
118
|
+
Be precise with relationships to create a meaningful graph:
|
|
119
|
+
${RELATIONSHIP_TYPES.slice(0, 6).join(', ')}
|
|
120
|
+
${RELATIONSHIP_TYPES.slice(6, 12).join(', ')}
|
|
121
|
+
${RELATIONSHIP_TYPES.slice(12).join(', ')}
|
|
122
|
+
|
|
123
|
+
OUTPUT FORMAT REQUIREMENTS:
|
|
124
|
+
Return ONLY valid JSONL format (one JSON object per line, NOT an array) with this EXACT structure:
|
|
125
|
+
|
|
126
|
+
EXAMPLE OUTPUT:
|
|
127
|
+
${createExampleOutput(projectName, sessionId)}
|
|
128
|
+
|
|
129
|
+
SUMMARY REQUIREMENTS:
|
|
130
|
+
Each index entry must:
|
|
131
|
+
- Be a valid JSON object with ALL required fields: timestamp, session_id, project, summary, nodes, keywords, message_count, uuid, archive_path
|
|
132
|
+
- timestamp: Current ISO timestamp
|
|
133
|
+
- session_id: Use EXACT session ID "${sessionId}" (no "session-" prefix)
|
|
134
|
+
- project: "${projectName}"
|
|
135
|
+
- summary: Describe WHAT was accomplished and WHY it matters (active voice, specific, actionable)
|
|
136
|
+
* Start with action verb: "Implemented", "Fixed", "Refactored", "Designed", "Optimized"
|
|
137
|
+
* Include the main component/feature affected
|
|
138
|
+
* Mention the key outcome or improvement
|
|
139
|
+
- nodes: Array of 2-4 entity names created in knowledge graph (use type-prefixed names)
|
|
140
|
+
- keywords: Array of 3-5 searchable terms (include tool names, patterns, technologies)
|
|
141
|
+
- message_count: Total messages in conversation (use actual count)
|
|
142
|
+
- uuid: "${sessionId}"
|
|
143
|
+
- archive_path: "~/.claude-mem/archives/${sessionId}.jsonl.archive"
|
|
144
|
+
|
|
145
|
+
MCP TOOL USAGE:
|
|
146
|
+
1. FIRST: Call create_entities for each distinct concept/component/decision
|
|
147
|
+
- Create session entity: ${projectName}_Session_${sessionId}
|
|
148
|
+
- Create entities for major components/patterns/decisions
|
|
149
|
+
- Include rich observations with keywords and metadata
|
|
150
|
+
2. THEN: Call create_relations to link related entities
|
|
151
|
+
- Link entities to session entity
|
|
152
|
+
- Create tool chain relationships via parent_tool_use_id
|
|
153
|
+
- Connect new entities to existing ones (if incremental)
|
|
154
|
+
3. FINALLY: Return JSONL summaries referencing created entities
|
|
155
|
+
|
|
156
|
+
INDEXING PRIORITIES:
|
|
157
|
+
- Prioritize entities that will be valuable for future code recall
|
|
158
|
+
- Focus on reusable patterns and solutions
|
|
159
|
+
- Capture decision rationale and trade-offs
|
|
160
|
+
- Include error patterns and their fixes
|
|
161
|
+
- Document integration points and API usage
|
|
162
|
+
- Note performance optimizations and their impact
|
|
163
|
+
- Create entities for tool chains and workflows
|
|
164
|
+
|
|
165
|
+
Project: ${projectName}
|
|
166
|
+
Session ID: ${sessionId}
|
|
167
|
+
|
|
168
|
+
CRITICAL REQUIREMENTS:
|
|
169
|
+
- Create 3-15 entities depending on conversation complexity
|
|
170
|
+
- Create 5-20 relationships showing entity connections
|
|
171
|
+
- Return 3-10 JSONL index entries (one JSON object per line, NOT an array)
|
|
172
|
+
- Each line must be valid JSON parseable with JSON.parse()
|
|
173
|
+
- Each line must have ALL required fields (timestamp, session_id, project, summary, nodes, keywords, message_count, uuid, archive_path)
|
|
174
|
+
- Use EXACT session ID without prefixes
|
|
175
|
+
- Focus on creating a searchable index for future development
|
|
176
|
+
- Original transcript will be archived as ${sessionId}.jsonl.archive
|
|
177
|
+
${hasCompressedContent ? '- Build upon existing entities, do not duplicate them' : ''}
|
|
178
|
+
|
|
179
|
+
Conversation to compress:`;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Helper function to get entity type descriptions
|
|
183
|
+
*/
|
|
184
|
+
function getEntityTypeDescription(type) {
|
|
185
|
+
const descriptions = {
|
|
186
|
+
component: "UI components, modules, services",
|
|
187
|
+
pattern: "Architectural or design patterns",
|
|
188
|
+
workflow: "Processes, pipelines, sequences",
|
|
189
|
+
integration: "APIs, external services, data sources",
|
|
190
|
+
concept: "Abstract ideas, methodologies, principles",
|
|
191
|
+
decision: "Design choices, trade-offs, solutions",
|
|
192
|
+
tool: "Utilities, libraries, development tools",
|
|
193
|
+
fix: "Bug fixes, patches, workarounds"
|
|
194
|
+
};
|
|
195
|
+
return descriptions[type];
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Creates example output for the analysis prompt
|
|
199
|
+
*/
|
|
200
|
+
function createExampleOutput(projectName, sessionId) {
|
|
201
|
+
return `{"timestamp":"${new Date().toISOString()}","session_id":"${sessionId}","project":"${projectName}","summary":"Implemented Redis caching system with TTL support and connection pooling","nodes":["${projectName}_Component_RedisCache","${projectName}_Pattern_ConnectionPool"],"keywords":["redis","caching","ttl","connection_pooling"],"message_count":42,"uuid":"${sessionId}","archive_path":"~/.claude-mem/archives/${sessionId}.jsonl.archive"}
|
|
202
|
+
{"timestamp":"${new Date().toISOString()}","session_id":"${sessionId}","project":"${projectName}","summary":"Built JWT authentication with refresh tokens and role-based access control","nodes":["${projectName}_Component_JWTAuth","${projectName}_Decision_RoleManager","${projectName}_Pattern_RefreshToken"],"keywords":["jwt","authentication","rbac","security","refresh_token"],"message_count":35,"uuid":"${sessionId}","archive_path":"~/.claude-mem/archives/${sessionId}.jsonl.archive"}
|
|
203
|
+
{"timestamp":"${new Date().toISOString()}","session_id":"${sessionId}","project":"${projectName}","summary":"Fixed WebSocket memory leak by implementing proper connection cleanup handlers","nodes":["${projectName}_Fix_WebSocketLeak","${projectName}_Component_ConnectionCleanup"],"keywords":["websocket","memory_leak","cleanup","debugging"],"message_count":28,"uuid":"${sessionId}","archive_path":"~/.claude-mem/archives/${sessionId}.jsonl.archive"}`;
|
|
204
|
+
}
|
|
205
|
+
// =============================================================================
|
|
206
|
+
// CONTEXT PRIMING TEMPLATES
|
|
207
|
+
// =============================================================================
|
|
208
|
+
/**
|
|
209
|
+
* System message templates for context priming
|
|
210
|
+
*/
|
|
211
|
+
export const CONTEXT_TEMPLATES = {
|
|
212
|
+
PRIMARY_CONTEXT: (projectName) => `Context primed for project: ${projectName}. Access memories with search_nodes("${projectName}*") or open_nodes(["entity_name"]).`,
|
|
213
|
+
RECENT_SESSIONS: (sessionList) => `Recent sessions available: ${sessionList}`,
|
|
214
|
+
AVAILABLE_ENTITIES: (type, entities, hasMore, moreCount) => `Available ${type} entities: ${entities.join(', ')}${hasMore ? ` (+${moreCount} more)` : ''}`,
|
|
215
|
+
SESSION_START_HEADER: '🧠 Active Working Context from Previous Sessions:',
|
|
216
|
+
SESSION_START_SEPARATOR: '═'.repeat(70),
|
|
217
|
+
RESUME_INSTRUCTIONS: `💡 TO RESUME: Load active components with open_nodes(["<exact_names>"])
|
|
218
|
+
📊 TO EXPLORE: Search related work with search_nodes("<keywords>")`
|
|
219
|
+
};
|
|
220
|
+
// =============================================================================
|
|
221
|
+
// SESSION START OUTPUT TEMPLATES
|
|
222
|
+
// =============================================================================
|
|
223
|
+
/**
|
|
224
|
+
* Session start formatting templates
|
|
225
|
+
*/
|
|
226
|
+
export const SESSION_START_TEMPLATES = {
|
|
227
|
+
FOCUS_LINE: (focus) => `📌 CURRENT FOCUS: ${focus}`,
|
|
228
|
+
LAST_WORKED: (timeAgo, projectName) => `Last worked: ${timeAgo} | Project: ${projectName}`,
|
|
229
|
+
SECTIONS: {
|
|
230
|
+
COMPONENTS: '🎯 ACTIVE COMPONENTS (load these for context):',
|
|
231
|
+
DECISIONS: '🔄 RECENT DECISIONS & PATTERNS:',
|
|
232
|
+
TOOLS: '🛠️ TOOLS & INFRASTRUCTURE:',
|
|
233
|
+
FIXES: '🐛 RECENT FIXES:',
|
|
234
|
+
ACTIONS: '⚡ NEXT ACTIONS:'
|
|
235
|
+
},
|
|
236
|
+
ACTION_PREFIX: '□ ',
|
|
237
|
+
ENTITY_BULLET: '• '
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Time formatting for "time ago" displays
|
|
241
|
+
*/
|
|
242
|
+
export const TIME_FORMATS = {
|
|
243
|
+
JUST_NOW: 'just now',
|
|
244
|
+
HOURS_AGO: (hours) => `${hours} hour${hours > 1 ? 's' : ''} ago`,
|
|
245
|
+
DAYS_AGO: (days) => `${days} day${days > 1 ? 's' : ''} ago`,
|
|
246
|
+
RECENTLY: 'recently'
|
|
247
|
+
};
|
|
248
|
+
// =============================================================================
|
|
249
|
+
// HOOK RESPONSE TEMPLATES
|
|
250
|
+
// =============================================================================
|
|
251
|
+
/**
|
|
252
|
+
* Standard hook response structures for Claude Code integration
|
|
253
|
+
*/
|
|
254
|
+
export const HOOK_RESPONSES = {
|
|
255
|
+
SUCCESS: (hookEventName, message) => ({
|
|
256
|
+
hookSpecificOutput: {
|
|
257
|
+
hookEventName,
|
|
258
|
+
status: "success",
|
|
259
|
+
message
|
|
260
|
+
},
|
|
261
|
+
suppressOutput: true
|
|
262
|
+
}),
|
|
263
|
+
SKIPPED: (hookEventName, message) => ({
|
|
264
|
+
hookSpecificOutput: {
|
|
265
|
+
hookEventName,
|
|
266
|
+
status: "skipped",
|
|
267
|
+
message
|
|
268
|
+
},
|
|
269
|
+
suppressOutput: true
|
|
270
|
+
}),
|
|
271
|
+
BLOCKED: (reason) => ({
|
|
272
|
+
decision: "block",
|
|
273
|
+
reason
|
|
274
|
+
}),
|
|
275
|
+
CONTINUE: (hookEventName, additionalContext) => ({
|
|
276
|
+
continue: true,
|
|
277
|
+
...(additionalContext && {
|
|
278
|
+
hookSpecificOutput: {
|
|
279
|
+
hookEventName,
|
|
280
|
+
additionalContext
|
|
281
|
+
}
|
|
282
|
+
})
|
|
283
|
+
}),
|
|
284
|
+
ERROR: (reason) => ({
|
|
285
|
+
decision: "block",
|
|
286
|
+
reason
|
|
287
|
+
})
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* Pre-defined hook messages
|
|
291
|
+
*/
|
|
292
|
+
export const HOOK_MESSAGES = {
|
|
293
|
+
COMPRESSION_SUCCESS: "Memory compression completed successfully",
|
|
294
|
+
COMPRESSION_SKIPPED: "Compression skipped - Claude SDK not available in this context",
|
|
295
|
+
COMPRESSION_FAILED: (stderr) => `Compression failed: ${stderr}`,
|
|
296
|
+
CONTEXT_LOADED: "Project context loaded successfully",
|
|
297
|
+
CONTEXT_SKIPPED: "Continuing session - context loading skipped",
|
|
298
|
+
NO_TRANSCRIPT: "No transcript path provided",
|
|
299
|
+
HOOK_ERROR: (error) => `Hook error: ${error}`
|
|
300
|
+
};
|
|
301
|
+
// =============================================================================
|
|
302
|
+
// CONFIGURATION TEMPLATES
|
|
303
|
+
// =============================================================================
|
|
304
|
+
/**
|
|
305
|
+
* MCP server configuration template
|
|
306
|
+
*/
|
|
307
|
+
export const MCP_CONFIG_TEMPLATE = {
|
|
308
|
+
"claude-mem": {
|
|
309
|
+
command: "npx",
|
|
310
|
+
args: ["-y", "@modelcontextprotocol/server-memory"]
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
/**
|
|
314
|
+
* Hook configuration templates for Claude settings
|
|
315
|
+
*/
|
|
316
|
+
export const HOOK_CONFIG_TEMPLATES = {
|
|
317
|
+
PRE_COMPACT: (scriptPath) => ({
|
|
318
|
+
pattern: "*",
|
|
319
|
+
hooks: [{
|
|
320
|
+
type: "command",
|
|
321
|
+
command: scriptPath,
|
|
322
|
+
timeout: 180000
|
|
323
|
+
}]
|
|
324
|
+
}),
|
|
325
|
+
SESSION_START: (scriptPath) => ({
|
|
326
|
+
pattern: "*",
|
|
327
|
+
hooks: [{
|
|
328
|
+
type: "command",
|
|
329
|
+
command: scriptPath,
|
|
330
|
+
timeout: 30000
|
|
331
|
+
}]
|
|
332
|
+
}),
|
|
333
|
+
SESSION_END: (scriptPath) => ({
|
|
334
|
+
pattern: "*",
|
|
335
|
+
hooks: [{
|
|
336
|
+
type: "command",
|
|
337
|
+
command: scriptPath,
|
|
338
|
+
timeout: 180000
|
|
339
|
+
}]
|
|
340
|
+
})
|
|
341
|
+
};
|
|
342
|
+
// =============================================================================
|
|
343
|
+
// CLI MESSAGES AND STATUS TEMPLATES
|
|
344
|
+
// =============================================================================
|
|
345
|
+
/**
|
|
346
|
+
* Command-line interface messages
|
|
347
|
+
*/
|
|
348
|
+
export const CLI_MESSAGES = {
|
|
349
|
+
INSTALLATION: {
|
|
350
|
+
STARTING: '🚀 Installing Claude Memory System with embedded Weaviate...',
|
|
351
|
+
SUCCESS: '🎉 Installation complete! Embedded vector database ready.',
|
|
352
|
+
HOOKS_INSTALLED: '✅ Installed hooks to ~/.claude-mem/hooks/',
|
|
353
|
+
MCP_CONFIGURED: (path) => `✅ Configured MCP memory server in ${path}`,
|
|
354
|
+
EMBEDDED_READY: '🧠 Embedded Weaviate initialized for persistent semantic memory',
|
|
355
|
+
ALREADY_INSTALLED: '⚠️ Claude Memory hooks are already installed.',
|
|
356
|
+
USE_FORCE: ' Use --force to overwrite existing installation.',
|
|
357
|
+
SETTINGS_WRITTEN: (type, path) => `✅ Installed hooks in ${type} settings\n Settings file: ${path}`
|
|
358
|
+
},
|
|
359
|
+
NEXT_STEPS: [
|
|
360
|
+
'1. Restart Claude Code to load the new hooks',
|
|
361
|
+
'2. Use `/clear` and `/compact` in Claude Code to save and compress session memories',
|
|
362
|
+
'3. New sessions will automatically load relevant context'
|
|
363
|
+
],
|
|
364
|
+
ERRORS: {
|
|
365
|
+
HOOKS_NOT_FOUND: '❌ Hook source files not found',
|
|
366
|
+
SETTINGS_WRITE_FAILED: (path, error) => `❌ Failed to write settings file: ${error}\n Path: ${path}`,
|
|
367
|
+
MCP_CONFIG_PARSE_FAILED: (error) => `⚠️ Warning: Could not parse existing MCP config: ${error}`,
|
|
368
|
+
MCP_CONFIG_WRITE_FAILED: (error) => `⚠️ Warning: Could not write MCP config: ${error}`,
|
|
369
|
+
COMPRESSION_FAILED: (error) => `❌ Compression failed: ${error}`,
|
|
370
|
+
CONTEXT_LOAD_FAILED: (error) => `❌ Failed to load context: ${error}`
|
|
371
|
+
},
|
|
372
|
+
STATUS: {
|
|
373
|
+
NO_INDEX: '📚 No memory index found. Starting fresh session.',
|
|
374
|
+
NO_MATCHES: '📚 No matching memories found in index.',
|
|
375
|
+
RECENT_MEMORIES: '🧠 Recent memories from previous sessions:',
|
|
376
|
+
MEMORY_COUNT: (count) => `📚 Showing ${count} most recent memories`,
|
|
377
|
+
FULL_CONTEXT_AVAILABLE: '💡 Full context available via MCP memory tools'
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
// =============================================================================
|
|
381
|
+
// DEBUG AND LOGGING TEMPLATES
|
|
382
|
+
// =============================================================================
|
|
383
|
+
/**
|
|
384
|
+
* Debug logging message templates
|
|
385
|
+
*/
|
|
386
|
+
export const DEBUG_MESSAGES = {
|
|
387
|
+
COMPRESSION_STARTED: '🚀 COMPRESSION STARTED',
|
|
388
|
+
TRANSCRIPT_PATH: (path) => `📁 Transcript Path: ${path}`,
|
|
389
|
+
SESSION_ID: (id) => `🔍 Session ID: ${id}`,
|
|
390
|
+
PROJECT_NAME: (name) => `📝 PROJECT NAME: ${name}`,
|
|
391
|
+
CLAUDE_SDK_CALL: '🤖 Calling Claude SDK to analyze and populate knowledge graph...',
|
|
392
|
+
TRANSCRIPT_STATS: (size, count) => `📊 Transcript size: ${size} characters, ${count} messages`,
|
|
393
|
+
COMPRESSION_COMPLETE: (count) => `✅ COMPRESSION COMPLETE\n Total summaries extracted: ${count}`,
|
|
394
|
+
CLAUDE_PATH_FOUND: (path) => `🎯 Found Claude Code at: ${path}`,
|
|
395
|
+
MCP_CONFIG_USED: (path) => `📋 Using MCP config: ${path}`
|
|
396
|
+
};
|
|
397
|
+
// =============================================================================
|
|
398
|
+
// SEARCH AND QUERY TEMPLATES
|
|
399
|
+
// =============================================================================
|
|
400
|
+
/**
|
|
401
|
+
* Knowledge graph search templates
|
|
402
|
+
*/
|
|
403
|
+
export const SEARCH_TEMPLATES = {
|
|
404
|
+
SEARCH_SCRIPT: (query) => `
|
|
405
|
+
import { query } from "@anthropic-ai/claude-code";
|
|
406
|
+
|
|
407
|
+
const searchQuery = process.env.SEARCH_QUERY || '';
|
|
408
|
+
|
|
409
|
+
const result = await query({
|
|
410
|
+
prompt: "Search for: " + searchQuery,
|
|
411
|
+
options: {
|
|
412
|
+
mcpConfig: "~/.claude/.mcp.json",
|
|
413
|
+
allowedTools: ["mcp__memory__search_nodes"],
|
|
414
|
+
outputFormat: "json"
|
|
415
|
+
}
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
console.log(JSON.stringify(result));
|
|
419
|
+
`,
|
|
420
|
+
SEARCH_PREFIX: "Search for: "
|
|
421
|
+
};
|
|
422
|
+
// =============================================================================
|
|
423
|
+
// WEAVIATE INTEGRATION CONSTANTS
|
|
424
|
+
// =============================================================================
|
|
425
|
+
/**
|
|
426
|
+
* Weaviate MCP server configuration template
|
|
427
|
+
*/
|
|
428
|
+
export const WEAVIATE_MCP_CONFIG = {
|
|
429
|
+
"claude-mem": {
|
|
430
|
+
command: process.platform === 'win32'
|
|
431
|
+
? "C:\\path\\to\\mcp-server.exe"
|
|
432
|
+
: "/usr/local/bin/mcp-server-weaviate"
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
/**
|
|
436
|
+
* Weaviate collection names for entities and relations
|
|
437
|
+
*/
|
|
438
|
+
export const WEAVIATE_COLLECTIONS = {
|
|
439
|
+
ENTITIES: 'claude_mem_entities',
|
|
440
|
+
RELATIONS: 'claude_mem_relations'
|
|
441
|
+
};
|
|
442
|
+
/**
|
|
443
|
+
* Default Weaviate configuration values
|
|
444
|
+
*/
|
|
445
|
+
export const WEAVIATE_DEFAULTS = {
|
|
446
|
+
HOST: 'localhost:8080',
|
|
447
|
+
SCHEME: 'http',
|
|
448
|
+
MCP_PATH: '/usr/local/bin/mcp-server-weaviate'
|
|
449
|
+
};
|
|
450
|
+
/**
|
|
451
|
+
* Weaviate-specific CLI messages
|
|
452
|
+
*/
|
|
453
|
+
export const WEAVIATE_MESSAGES = {
|
|
454
|
+
CONNECTION: {
|
|
455
|
+
CONNECTING: '🔗 Connecting to Weaviate server...',
|
|
456
|
+
CONNECTED: '✅ Connected to Weaviate successfully',
|
|
457
|
+
FAILED: (error) => `❌ Failed to connect to Weaviate: ${error}`,
|
|
458
|
+
DISCONNECTED: '👋 Disconnected from Weaviate'
|
|
459
|
+
},
|
|
460
|
+
MIGRATION: {
|
|
461
|
+
STARTING: '🚀 Starting migration to Weaviate backend...',
|
|
462
|
+
READING_INDEX: '📖 Reading existing memory index files...',
|
|
463
|
+
MIGRATING_ENTITIES: (count) => `🔄 Migrating ${count} entities to Weaviate...`,
|
|
464
|
+
MIGRATING_RELATIONS: (count) => `🔗 Migrating ${count} relations to Weaviate...`,
|
|
465
|
+
UPDATING_SETTINGS: '⚙️ Updating settings to use Weaviate backend...',
|
|
466
|
+
COMPLETED: '✅ Migration to Weaviate completed successfully',
|
|
467
|
+
FAILED: (error) => `❌ Migration failed: ${error}`,
|
|
468
|
+
NO_DATA: '💡 No existing data found to migrate'
|
|
469
|
+
},
|
|
470
|
+
SEARCH: {
|
|
471
|
+
SEMANTIC_SEARCH: '🧠 Using semantic search with Weaviate...',
|
|
472
|
+
KEYWORD_SEARCH: '🔍 Using keyword search with Weaviate...',
|
|
473
|
+
HYBRID_SEARCH: '🔬 Using hybrid search with Weaviate...',
|
|
474
|
+
NO_RESULTS: '📚 No results found in Weaviate database',
|
|
475
|
+
RESULTS_FOUND: (count) => `📊 Found ${count} results in Weaviate`
|
|
476
|
+
},
|
|
477
|
+
SETUP: {
|
|
478
|
+
STARTING_EMBEDDED: '🚀 Starting embedded Weaviate instance...',
|
|
479
|
+
EMBEDDED_READY: '✅ Embedded Weaviate is ready and accepting connections',
|
|
480
|
+
DOWNLOADING_BINARIES: '⬇️ Downloading Weaviate binaries (first time only)...',
|
|
481
|
+
INITIALIZING_SCHEMA: '📋 Initializing knowledge graph schema...'
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
/**
|
|
485
|
+
* Weaviate error messages
|
|
486
|
+
*/
|
|
487
|
+
export const WEAVIATE_ERRORS = {
|
|
488
|
+
CONNECTION_FAILED: 'Could not establish connection to Weaviate server',
|
|
489
|
+
MCP_SERVER_NOT_FOUND: 'Weaviate MCP server binary not found at specified path',
|
|
490
|
+
INVALID_COLLECTION: (collection) => `Invalid Weaviate collection: ${collection}`,
|
|
491
|
+
QUERY_FAILED: (query, error) => `Query failed for '${query}': ${error}`,
|
|
492
|
+
ENTITY_CREATION_FAILED: (name) => `Failed to create entity '${name}' in Weaviate`,
|
|
493
|
+
RELATION_CREATION_FAILED: (from, to) => `Failed to create relation '${from}' -> '${to}' in Weaviate`,
|
|
494
|
+
MIGRATION_INCOMPLETE: 'Migration was incomplete - some data may not have been transferred',
|
|
495
|
+
EMBEDDED_START_FAILED: 'Failed to start embedded Weaviate instance - check disk space and permissions',
|
|
496
|
+
SCHEMA_MISMATCH: 'Weaviate schema does not match expected structure'
|
|
497
|
+
};
|
|
498
|
+
/**
|
|
499
|
+
* Export all constants for easy importing
|
|
500
|
+
*/
|
|
501
|
+
export const CONSTANTS = {
|
|
502
|
+
ENTITY_NAMING_PATTERNS,
|
|
503
|
+
ENTITY_TYPES,
|
|
504
|
+
OBSERVATION_FIELDS,
|
|
505
|
+
RELATIONSHIP_TYPES,
|
|
506
|
+
CONTEXT_TEMPLATES,
|
|
507
|
+
SESSION_START_TEMPLATES,
|
|
508
|
+
TIME_FORMATS,
|
|
509
|
+
HOOK_RESPONSES,
|
|
510
|
+
HOOK_MESSAGES,
|
|
511
|
+
MCP_CONFIG_TEMPLATE,
|
|
512
|
+
HOOK_CONFIG_TEMPLATES,
|
|
513
|
+
CLI_MESSAGES,
|
|
514
|
+
DEBUG_MESSAGES,
|
|
515
|
+
SEARCH_TEMPLATES,
|
|
516
|
+
// Weaviate constants
|
|
517
|
+
WEAVIATE_MCP_CONFIG,
|
|
518
|
+
WEAVIATE_COLLECTIONS,
|
|
519
|
+
WEAVIATE_DEFAULTS,
|
|
520
|
+
WEAVIATE_MESSAGES,
|
|
521
|
+
WEAVIATE_ERRORS
|
|
522
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class ErrorHandler {
|
|
2
|
+
private logger;
|
|
3
|
+
private logDir;
|
|
4
|
+
constructor(enableDebug?: boolean);
|
|
5
|
+
private ensureLogDirectory;
|
|
6
|
+
handleHookError(error: Error, hookType: string, payload?: unknown): never;
|
|
7
|
+
handleCompressionError(error: Error, transcriptPath: string, stage: string): never;
|
|
8
|
+
handleValidationError(message: string, context?: Record<string, unknown>): never;
|
|
9
|
+
logSuccess(operation: string, details?: Record<string, unknown>): void;
|
|
10
|
+
logWarning(message: string, details?: Record<string, unknown>): void;
|
|
11
|
+
logDebug(message: string, details?: Record<string, unknown>): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function parseStdinJson<T = unknown>(input: string): T;
|
|
14
|
+
export declare function safeExecute<T>(operation: () => Promise<T>, errorHandler: ErrorHandler, context: string): Promise<T>;
|
|
15
|
+
export declare function validateFileExists(filePath: string, errorHandler: ErrorHandler): void;
|
|
16
|
+
export declare function createHookResponse(success: boolean, data?: Record<string, unknown>): string;
|
|
17
|
+
export declare const globalErrorHandler: ErrorHandler;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { HookError, CompressionError, FileLogger } from './types.js';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
export class ErrorHandler {
|
|
8
|
+
logger;
|
|
9
|
+
logDir;
|
|
10
|
+
constructor(enableDebug = false) {
|
|
11
|
+
this.logDir = join(__dirname, '..', 'logs');
|
|
12
|
+
this.ensureLogDirectory();
|
|
13
|
+
const logFile = join(this.logDir, `claude-mem-${new Date().toISOString().slice(0, 10)}.log`);
|
|
14
|
+
this.logger = new FileLogger(logFile, enableDebug);
|
|
15
|
+
}
|
|
16
|
+
ensureLogDirectory() {
|
|
17
|
+
if (!existsSync(this.logDir)) {
|
|
18
|
+
mkdirSync(this.logDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
handleHookError(error, hookType, payload) {
|
|
22
|
+
const hookError = error instanceof HookError
|
|
23
|
+
? error
|
|
24
|
+
: new HookError(error.message, hookType, payload, 'HOOK_EXECUTION_ERROR');
|
|
25
|
+
this.logger.error(`Hook execution failed in ${hookType}`, hookError, {
|
|
26
|
+
hookType,
|
|
27
|
+
payload: payload ? JSON.stringify(payload) : undefined,
|
|
28
|
+
});
|
|
29
|
+
console.log(JSON.stringify({
|
|
30
|
+
continue: false,
|
|
31
|
+
stopReason: `Hook error: ${hookError.message}`,
|
|
32
|
+
error: {
|
|
33
|
+
type: hookError.name,
|
|
34
|
+
message: hookError.message,
|
|
35
|
+
code: hookError.code,
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
handleCompressionError(error, transcriptPath, stage) {
|
|
41
|
+
const compressionError = error instanceof CompressionError
|
|
42
|
+
? error
|
|
43
|
+
: new CompressionError(error.message, transcriptPath, stage);
|
|
44
|
+
this.logger.error(`Compression failed during ${stage}`, compressionError, {
|
|
45
|
+
transcriptPath,
|
|
46
|
+
stage,
|
|
47
|
+
});
|
|
48
|
+
console.error(`Compression error: ${compressionError.message}`);
|
|
49
|
+
console.error(`Stage: ${stage}`);
|
|
50
|
+
console.error(`Transcript: ${transcriptPath}`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
handleValidationError(message, context) {
|
|
54
|
+
this.logger.error('Validation error', undefined, { message, context });
|
|
55
|
+
console.error(`Validation error: ${message}`);
|
|
56
|
+
if (context) {
|
|
57
|
+
console.error('Context:', JSON.stringify(context, null, 2));
|
|
58
|
+
}
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
logSuccess(operation, details) {
|
|
62
|
+
this.logger.info(`Operation successful: ${operation}`, details);
|
|
63
|
+
}
|
|
64
|
+
logWarning(message, details) {
|
|
65
|
+
this.logger.warn(message, details);
|
|
66
|
+
}
|
|
67
|
+
logDebug(message, details) {
|
|
68
|
+
this.logger.debug(message, details);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function parseStdinJson(input) {
|
|
72
|
+
try {
|
|
73
|
+
return JSON.parse(input);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`Failed to parse JSON input: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export async function safeExecute(operation, errorHandler, context) {
|
|
80
|
+
try {
|
|
81
|
+
return await operation();
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const message = `Safe execution failed in ${context}: ${error instanceof Error ? error.message : String(error)}`;
|
|
85
|
+
errorHandler.handleValidationError(message, { context, error });
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function validateFileExists(filePath, errorHandler) {
|
|
90
|
+
if (!existsSync(filePath)) {
|
|
91
|
+
errorHandler.handleValidationError(`File not found: ${filePath}`, {
|
|
92
|
+
filePath,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function createHookResponse(success, data) {
|
|
97
|
+
const response = {
|
|
98
|
+
continue: success,
|
|
99
|
+
...data,
|
|
100
|
+
};
|
|
101
|
+
return JSON.stringify(response);
|
|
102
|
+
}
|
|
103
|
+
export const globalErrorHandler = new ErrorHandler(process.env.DEBUG === 'true');
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 🔒 LOCKED by @docs-agent | Change to 🔑 to allow @docs-agent edits
|
|
4
|
+
*
|
|
5
|
+
* OFFICIAL DOCS: @modelcontextprotocol/sdk v1.0.0
|
|
6
|
+
* Last Verified: 2025-09-01
|
|
7
|
+
*
|
|
8
|
+
* Claude-mem MCP Server CLI Entry Point
|
|
9
|
+
*
|
|
10
|
+
* This module provides the standalone entry point for running the claude-mem MCP server
|
|
11
|
+
* that communicates with Claude Code via stdio transport.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node dist/mcp-server-cli.js
|
|
15
|
+
* claude-mem-server
|
|
16
|
+
*
|
|
17
|
+
* Communication:
|
|
18
|
+
* - Stdin/Stdout: MCP protocol messages with Claude Code
|
|
19
|
+
* - Stderr: Logging and diagnostic output
|
|
20
|
+
*
|
|
21
|
+
* Architecture:
|
|
22
|
+
* This CLI connects the MCP server to Claude Code via stdio transport,
|
|
23
|
+
* enabling Claude Code to access the embedded Weaviate knowledge graph
|
|
24
|
+
* through standard MCP memory tools.
|
|
25
|
+
*
|
|
26
|
+
* Implementation follows official MCP SDK patterns:
|
|
27
|
+
* - StdioServerTransport for stdin/stdout communication (SDK README.md#_snippet_16)
|
|
28
|
+
* - Server initialization before transport connection
|
|
29
|
+
* - Graceful shutdown handlers for SIGINT/SIGTERM
|
|
30
|
+
* - Error handling for uncaught exceptions
|
|
31
|
+
*
|
|
32
|
+
* @see docs/mcp-sdk/stdio-transport.md for transport patterns
|
|
33
|
+
*/
|
|
34
|
+
export {};
|