@memextend/claude-code 0.1.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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=session-start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.d.ts","sourceRoot":"","sources":["../../src/hooks/session-start.ts"],"names":[],"mappings":""}
@@ -0,0 +1,205 @@
1
+ // packages/adapters/claude-code/src/hooks/session-start.ts
2
+ // Copyright (c) 2026 ZodTTD LLC. MIT License.
3
+ import { createHash } from 'crypto';
4
+ import { existsSync } from 'fs';
5
+ import { readFile } from 'fs/promises';
6
+ import { join, basename } from 'path';
7
+ import { homedir } from 'os';
8
+ import { execSync } from 'child_process';
9
+ import { SQLiteStorage, LanceDBStorage, MemoryRetriever, formatContextForInjection, createEmbedFunction, deduplicateMemories, getDeduplicationStats } from '@memextend/core';
10
+ import { log, logError } from './logger.js';
11
+ const MEMEXTEND_DIR = join(homedir(), '.memextend');
12
+ const CONFIG_PATH = join(MEMEXTEND_DIR, 'config.json');
13
+ const DB_PATH = join(MEMEXTEND_DIR, 'memextend.db');
14
+ const VECTORS_PATH = join(MEMEXTEND_DIR, 'vectors');
15
+ const MODELS_PATH = join(MEMEXTEND_DIR, 'models');
16
+ async function main() {
17
+ // Read input from stdin
18
+ const chunks = [];
19
+ for await (const chunk of process.stdin) {
20
+ chunks.push(chunk);
21
+ }
22
+ const input = JSON.parse(Buffer.concat(chunks).toString());
23
+ log('SessionStart', 'Hook fired', {
24
+ source: input.source,
25
+ session_id: input.session_id,
26
+ cwd: input.cwd
27
+ });
28
+ try {
29
+ // Check if memextend is initialized
30
+ if (!existsSync(DB_PATH)) {
31
+ log('SessionStart', 'DB not found, skipping');
32
+ outputResult({});
33
+ return;
34
+ }
35
+ // Load config
36
+ const config = await loadConfig();
37
+ if (!config.retrieval?.autoInject) {
38
+ log('SessionStart', 'Auto-inject disabled in config');
39
+ outputResult({});
40
+ return;
41
+ }
42
+ // Get project ID
43
+ const projectId = getProjectId(input.cwd);
44
+ // Initialize storage
45
+ const sqlite = new SQLiteStorage(DB_PATH);
46
+ const lancedb = await LanceDBStorage.create(VECTORS_PATH);
47
+ // Create embedding function (uses real model if available, fallback otherwise)
48
+ const embedder = await createEmbedFunction(MODELS_PATH);
49
+ const retriever = new MemoryRetriever(sqlite, lancedb, embedder.embedQuery, {
50
+ defaultLimit: config.retrieval?.maxMemories ?? 0,
51
+ defaultRecentDays: config.retrieval?.recentDays ?? 0,
52
+ });
53
+ // Ensure project is registered
54
+ const project = sqlite.getProject(projectId);
55
+ if (!project) {
56
+ sqlite.insertProject({
57
+ id: projectId,
58
+ name: basename(input.cwd),
59
+ path: input.cwd,
60
+ createdAt: new Date().toISOString()
61
+ });
62
+ }
63
+ // Determine if this is a post-compaction injection
64
+ const isPostCompact = input.source === 'compact';
65
+ if (isPostCompact) {
66
+ log('SessionStart', 'POST-COMPACT INJECTION - restoring context after compaction');
67
+ }
68
+ // Get context for session
69
+ // After compaction, we may want to inject more context since the previous context was lost
70
+ // 0 = unlimited, so use a high number for "unlimited"
71
+ const configLimit = config.retrieval?.maxMemories ?? 0;
72
+ const effectiveLimit = configLimit === 0 ? 1000 : configLimit; // 0 means unlimited, use high limit
73
+ const maxMemories = isPostCompact
74
+ ? Math.min(effectiveLimit * 2, configLimit === 0 ? 1000 : 100) // Double after compact
75
+ : effectiveLimit;
76
+ log('SessionStart', 'Retrieving memories', { maxMemories, isPostCompact, configLimit });
77
+ const context = await retriever.getContextForSession(projectId, {
78
+ includeGlobal: config.retrieval?.includeGlobal ?? true,
79
+ limit: maxMemories,
80
+ recentDays: config.retrieval?.recentDays ?? 0
81
+ });
82
+ // Combine all memories for deduplication
83
+ const allMemories = [
84
+ ...context.recentMemories,
85
+ ...context.relevantMemories.map(r => r.memory)
86
+ ];
87
+ // Deduplicate memories (newest wins for similar content)
88
+ const deduplicationThreshold = config.retrieval?.deduplicationThreshold ?? 0.85;
89
+ let deduplicatedMemories = allMemories;
90
+ if (allMemories.length > 1) {
91
+ // Fetch vectors for all memories
92
+ const memoryIds = allMemories.map(m => m.id);
93
+ const vectors = await lancedb.getVectorsByIds(memoryIds);
94
+ if (vectors.size > 0) {
95
+ deduplicatedMemories = deduplicateMemories(allMemories, vectors, {
96
+ similarityThreshold: deduplicationThreshold
97
+ });
98
+ const stats = getDeduplicationStats(allMemories.length, deduplicatedMemories.length);
99
+ if (stats.removed > 0) {
100
+ log('SessionStart', 'Deduplication removed similar memories', {
101
+ original: allMemories.length,
102
+ deduplicated: deduplicatedMemories.length,
103
+ removed: stats.removed,
104
+ percentage: stats.percentage
105
+ });
106
+ }
107
+ }
108
+ }
109
+ // Close storage and embedder
110
+ sqlite.close();
111
+ await lancedb.close();
112
+ await embedder.close();
113
+ // Check if there's anything to inject
114
+ if (deduplicatedMemories.length === 0 && context.globalProfile.length === 0) {
115
+ log('SessionStart', 'No memories to inject');
116
+ outputResult({});
117
+ return;
118
+ }
119
+ // Rebuild context with deduplicated memories
120
+ // Split deduplicated memories back into recent and relevant based on original categorization
121
+ const recentIds = new Set(context.recentMemories.map(m => m.id));
122
+ const deduplicatedContext = {
123
+ recentMemories: deduplicatedMemories.filter(m => recentIds.has(m.id)),
124
+ globalProfile: context.globalProfile,
125
+ relevantMemories: deduplicatedMemories
126
+ .filter(m => !recentIds.has(m.id))
127
+ .map(m => ({ memory: m, score: 0, source: 'hybrid' }))
128
+ };
129
+ log('SessionStart', 'Injecting memories', {
130
+ recentCount: deduplicatedContext.recentMemories.length,
131
+ globalCount: deduplicatedContext.globalProfile.length,
132
+ relevantCount: deduplicatedContext.relevantMemories.length,
133
+ totalOriginal: allMemories.length,
134
+ totalDeduplicated: deduplicatedMemories.length
135
+ });
136
+ // Use different character limits for compact vs session start
137
+ // Post-compact: minimal context since we just freed up space (~500 tokens at 2000 chars)
138
+ // Session start: richer context since we have a fresh 100K budget (~2500 tokens at 10000 chars)
139
+ const maxChars = isPostCompact
140
+ ? (config.retrieval?.compactMaxChars ?? 2000)
141
+ : (config.retrieval?.sessionMaxChars ?? 10000);
142
+ const previewLength = isPostCompact ? 100 : 200;
143
+ // Format and inject context with character limits
144
+ let formattedContext = formatContextForInjection(deduplicatedContext, {
145
+ maxChars,
146
+ previewLength
147
+ });
148
+ log('SessionStart', 'Formatted context', {
149
+ isPostCompact,
150
+ maxChars,
151
+ actualChars: formattedContext.length
152
+ });
153
+ // Add a note if this is post-compaction so Claude knows context was just restored
154
+ if (isPostCompact) {
155
+ formattedContext = `[Context restored after compaction - the following memories were preserved from your session]\n\n${formattedContext}`;
156
+ }
157
+ outputResult({
158
+ hookSpecificOutput: {
159
+ hookEventName: 'SessionStart',
160
+ additionalContext: formattedContext
161
+ }
162
+ });
163
+ }
164
+ catch (error) {
165
+ // Log error but don't fail the hook
166
+ logError('SessionStart', error);
167
+ console.error('[memextend] Session start error:', error);
168
+ outputResult({});
169
+ }
170
+ }
171
+ function getProjectId(cwd) {
172
+ // Try to get git root
173
+ try {
174
+ const gitRoot = execSync('git rev-parse --show-toplevel', {
175
+ cwd,
176
+ encoding: 'utf-8',
177
+ stdio: ['pipe', 'pipe', 'pipe']
178
+ }).trim();
179
+ return createHash('sha256').update(gitRoot).digest('hex').slice(0, 16);
180
+ }
181
+ catch {
182
+ // Not a git repo, use cwd
183
+ return createHash('sha256').update(cwd).digest('hex').slice(0, 16);
184
+ }
185
+ }
186
+ async function loadConfig() {
187
+ try {
188
+ if (existsSync(CONFIG_PATH)) {
189
+ const content = await readFile(CONFIG_PATH, 'utf-8');
190
+ return JSON.parse(content);
191
+ }
192
+ }
193
+ catch {
194
+ // Ignore config errors
195
+ }
196
+ return {};
197
+ }
198
+ function outputResult(result) {
199
+ console.log(JSON.stringify(result));
200
+ }
201
+ main().catch(error => {
202
+ console.error('[memextend] Fatal error:', error);
203
+ process.exit(0); // Exit cleanly to not block Claude Code
204
+ });
205
+ //# sourceMappingURL=session-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../src/hooks/session-start.ts"],"names":[],"mappings":"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"}