claude-memory-layer 1.0.1 → 1.0.3

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.
@@ -13,8 +13,12 @@ import { VectorStore } from '../core/vector-store.js';
13
13
  import { Embedder, getDefaultEmbedder } from '../core/embedder.js';
14
14
  import { VectorWorker, createVectorWorker } from '../core/vector-worker.js';
15
15
  import { Matcher, getDefaultMatcher } from '../core/matcher.js';
16
- import { Retriever, createRetriever, RetrievalResult } from '../core/retriever.js';
16
+ import { Retriever, createRetriever, RetrievalResult, UnifiedRetrievalResult } from '../core/retriever.js';
17
17
  import { GraduationPipeline, createGraduationPipeline } from '../core/graduation.js';
18
+ import { SharedEventStore, createSharedEventStore } from '../core/shared-event-store.js';
19
+ import { SharedStore, createSharedStore } from '../core/shared-store.js';
20
+ import { SharedVectorStore, createSharedVectorStore } from '../core/shared-vector-store.js';
21
+ import { SharedPromoter, createSharedPromoter, PromotionResult } from '../core/shared-promoter.js';
18
22
  import type {
19
23
  MemoryEventInput,
20
24
  AppendResult,
@@ -29,7 +33,9 @@ import type {
29
33
  ConsolidatedMemory,
30
34
  EndlessModeStatus,
31
35
  ContextSnapshot,
32
- ContinuityScore
36
+ ContinuityScore,
37
+ SharedStoreConfig,
38
+ Entry
33
39
  } from '../core/types.js';
34
40
  import { createToolObservationEmbedding } from '../core/metadata-extractor.js';
35
41
  import { WorkingSetStore, createWorkingSetStore } from '../core/working-set-store.js';
@@ -87,6 +93,7 @@ export function getProjectStoragePath(projectPath: string): string {
87
93
  // ============================================================
88
94
 
89
95
  const REGISTRY_PATH = path.join(os.homedir(), '.claude-code', 'memory', 'session-registry.json');
96
+ const SHARED_STORAGE_PATH = path.join(os.homedir(), '.claude-code', 'memory', 'shared');
90
97
 
91
98
  interface SessionRegistryEntry {
92
99
  projectPath: string;
@@ -172,7 +179,15 @@ export class MemoryService {
172
179
  private continuityManager: ContinuityManager | null = null;
173
180
  private endlessMode: MemoryMode = 'session';
174
181
 
175
- constructor(config: MemoryServiceConfig) {
182
+ // Shared Store components (cross-project knowledge)
183
+ private sharedEventStore: SharedEventStore | null = null;
184
+ private sharedStore: SharedStore | null = null;
185
+ private sharedVectorStore: SharedVectorStore | null = null;
186
+ private sharedPromoter: SharedPromoter | null = null;
187
+ private sharedStoreConfig: SharedStoreConfig | null = null;
188
+ private projectHash: string | null = null;
189
+
190
+ constructor(config: MemoryServiceConfig & { projectHash?: string; sharedStoreConfig?: SharedStoreConfig }) {
176
191
  const storagePath = this.expandPath(config.storagePath);
177
192
 
178
193
  // Ensure storage directory exists
@@ -180,6 +195,11 @@ export class MemoryService {
180
195
  fs.mkdirSync(storagePath, { recursive: true });
181
196
  }
182
197
 
198
+ // Store project hash for shared store operations
199
+ this.projectHash = config.projectHash || null;
200
+ // Default: shared store enabled
201
+ this.sharedStoreConfig = config.sharedStoreConfig ?? { enabled: true };
202
+
183
203
  // Initialize components
184
204
  this.eventStore = new EventStore(path.join(storagePath, 'events.duckdb'));
185
205
  this.vectorStore = new VectorStore(path.join(storagePath, 'vectors'));
@@ -221,9 +241,49 @@ export class MemoryService {
221
241
  await this.initializeEndlessMode();
222
242
  }
223
243
 
244
+ // Initialize shared store (enabled by default)
245
+ if (this.sharedStoreConfig?.enabled !== false) {
246
+ await this.initializeSharedStore();
247
+ }
248
+
224
249
  this.initialized = true;
225
250
  }
226
251
 
252
+ /**
253
+ * Initialize Shared Store components
254
+ */
255
+ private async initializeSharedStore(): Promise<void> {
256
+ const sharedPath = this.sharedStoreConfig?.sharedStoragePath
257
+ ? this.expandPath(this.sharedStoreConfig.sharedStoragePath)
258
+ : SHARED_STORAGE_PATH;
259
+
260
+ // Ensure shared directory exists
261
+ if (!fs.existsSync(sharedPath)) {
262
+ fs.mkdirSync(sharedPath, { recursive: true });
263
+ }
264
+
265
+ this.sharedEventStore = createSharedEventStore(
266
+ path.join(sharedPath, 'shared.duckdb')
267
+ );
268
+ await this.sharedEventStore.initialize();
269
+
270
+ this.sharedStore = createSharedStore(this.sharedEventStore);
271
+ this.sharedVectorStore = createSharedVectorStore(
272
+ path.join(sharedPath, 'vectors')
273
+ );
274
+ await this.sharedVectorStore.initialize();
275
+
276
+ this.sharedPromoter = createSharedPromoter(
277
+ this.sharedStore,
278
+ this.sharedVectorStore,
279
+ this.embedder,
280
+ this.sharedStoreConfig || undefined
281
+ );
282
+
283
+ // Connect shared stores to retriever
284
+ this.retriever.setSharedStores(this.sharedStore, this.sharedVectorStore);
285
+ }
286
+
227
287
  /**
228
288
  * Start a new session
229
289
  */
@@ -370,8 +430,9 @@ export class MemoryService {
370
430
  topK?: number;
371
431
  minScore?: number;
372
432
  sessionId?: string;
433
+ includeShared?: boolean;
373
434
  }
374
- ): Promise<RetrievalResult> {
435
+ ): Promise<UnifiedRetrievalResult> {
375
436
  await this.initialize();
376
437
 
377
438
  // Process any pending embeddings first
@@ -379,6 +440,15 @@ export class MemoryService {
379
440
  await this.vectorWorker.processAll();
380
441
  }
381
442
 
443
+ // Use unified retrieval if shared search is requested
444
+ if (options?.includeShared && this.sharedStore) {
445
+ return this.retriever.retrieveUnified(query, {
446
+ ...options,
447
+ includeShared: true,
448
+ projectHash: this.projectHash || undefined
449
+ });
450
+ }
451
+
382
452
  return this.retriever.retrieve(query, options);
383
453
  }
384
454
 
@@ -449,6 +519,62 @@ export class MemoryService {
449
519
  return header + result.context;
450
520
  }
451
521
 
522
+ // ============================================================
523
+ // Shared Store Methods (Cross-Project Knowledge)
524
+ // ============================================================
525
+
526
+ /**
527
+ * Check if shared store is enabled and initialized
528
+ */
529
+ isSharedStoreEnabled(): boolean {
530
+ return this.sharedStore !== null;
531
+ }
532
+
533
+ /**
534
+ * Promote an entry to shared storage
535
+ */
536
+ async promoteToShared(entry: Entry): Promise<PromotionResult> {
537
+ if (!this.sharedPromoter || !this.projectHash) {
538
+ return {
539
+ success: false,
540
+ error: 'Shared store not initialized or project hash not set'
541
+ };
542
+ }
543
+
544
+ return this.sharedPromoter.promoteEntry(entry, this.projectHash);
545
+ }
546
+
547
+ /**
548
+ * Get shared store statistics
549
+ */
550
+ async getSharedStoreStats(): Promise<{
551
+ total: number;
552
+ averageConfidence: number;
553
+ topTopics: Array<{ topic: string; count: number }>;
554
+ totalUsageCount: number;
555
+ } | null> {
556
+ if (!this.sharedStore) return null;
557
+ return this.sharedStore.getStats();
558
+ }
559
+
560
+ /**
561
+ * Search shared troubleshooting entries
562
+ */
563
+ async searchShared(
564
+ query: string,
565
+ options?: { topK?: number; minConfidence?: number }
566
+ ) {
567
+ if (!this.sharedStore) return [];
568
+ return this.sharedStore.search(query, options);
569
+ }
570
+
571
+ /**
572
+ * Get project hash for this service
573
+ */
574
+ getProjectHash(): string | null {
575
+ return this.projectHash;
576
+ }
577
+
452
578
  // ============================================================
453
579
  // Endless Mode Methods
454
580
  // ============================================================
@@ -708,6 +834,12 @@ export class MemoryService {
708
834
  if (this.vectorWorker) {
709
835
  this.vectorWorker.stop();
710
836
  }
837
+
838
+ // Close shared store
839
+ if (this.sharedEventStore) {
840
+ await this.sharedEventStore.close();
841
+ }
842
+
711
843
  await this.eventStore.close();
712
844
  }
713
845
 
@@ -747,12 +879,19 @@ export function getDefaultMemoryService(): MemoryService {
747
879
  * Get memory service for a specific project path
748
880
  * Creates isolated storage at ~/.claude-code/memory/projects/{hash}/
749
881
  */
750
- export function getMemoryServiceForProject(projectPath: string): MemoryService {
882
+ export function getMemoryServiceForProject(
883
+ projectPath: string,
884
+ sharedStoreConfig?: SharedStoreConfig
885
+ ): MemoryService {
751
886
  const hash = hashProjectPath(projectPath);
752
887
 
753
888
  if (!serviceCache.has(hash)) {
754
889
  const storagePath = getProjectStoragePath(projectPath);
755
- serviceCache.set(hash, new MemoryService({ storagePath }));
890
+ serviceCache.set(hash, new MemoryService({
891
+ storagePath,
892
+ projectHash: hash,
893
+ sharedStoreConfig
894
+ }));
756
895
  }
757
896
 
758
897
  return serviceCache.get(hash)!;