memory-engineering
Version:
Advanced Memory-Aware Code Context System with claude-flow-inspired architecture, showcasing MongoDB + Voyage AI strategic positioning
178 lines (152 loc) • 4.88 kB
text/typescript
/**
* Memory Manager Implementation
* Following claude-flow-main proven patterns for robust memory orchestration
*/
import { EventEmitter } from 'events';
import { IMemoryBackend, MemoryEntry, MemoryQuery, MemoryBackendConfig, MemoryBackendError } from './backend-interface.js';
import { MongoDBBackend } from './mongodb-backend.js';
import { generateId } from '../utils/id-generator.js';
export interface IMemoryManager {
initialize(): Promise<void>;
shutdown(): Promise<void>;
store(entry: Partial<MemoryEntry>): Promise<string>;
retrieve(id: string): Promise<MemoryEntry | undefined>;
query(query: MemoryQuery): Promise<MemoryEntry[]>;
update(id: string, updates: Partial<MemoryEntry>): Promise<void>;
delete(id: string): Promise<void>;
getHealthStatus(): Promise<{
healthy: boolean;
error?: string;
metrics?: Record<string, number>;
}>;
}
export class MemoryManager extends EventEmitter implements IMemoryManager {
private backend: IMemoryBackend;
private initialized = false;
constructor(config: MemoryBackendConfig) {
super();
this.backend = new MongoDBBackend(config);
}
async initialize(): Promise<void> {
if (this.initialized) return;
try {
await this.backend.initialize();
this.initialized = true;
this.emit('initialized');
} catch (error) {
throw new MemoryBackendError('Memory manager initialization failed', { error });
}
}
async shutdown(): Promise<void> {
if (!this.initialized) return;
try {
await this.backend.shutdown();
this.initialized = false;
this.emit('shutdown');
} catch (error) {
throw new MemoryBackendError('Memory manager shutdown failed', { error });
}
}
async store(entry: Partial<MemoryEntry>): Promise<string> {
this.ensureInitialized();
const id = entry.id || generateId();
const completeEntry: MemoryEntry = {
id,
projectPath: entry.projectPath || '',
memoryType: entry.memoryType || 'unknown',
content: entry.content || {},
context: entry.context || {},
timestamp: entry.timestamp || new Date(),
tags: entry.tags || [],
version: entry.version || 1,
metadata: entry.metadata || {},
searchableText: entry.searchableText,
embedding: entry.embedding
};
try {
await this.backend.store(completeEntry);
this.emit('stored', { id, entry: completeEntry });
return id;
} catch (error) {
this.emit('error', { operation: 'store', id, error });
throw error;
}
}
async retrieve(id: string): Promise<MemoryEntry | undefined> {
this.ensureInitialized();
try {
const entry = await this.backend.retrieve(id);
if (entry) {
this.emit('retrieved', { id, entry });
}
return entry;
} catch (error) {
this.emit('error', { operation: 'retrieve', id, error });
throw error;
}
}
async query(query: MemoryQuery): Promise<MemoryEntry[]> {
this.ensureInitialized();
try {
const entries = await this.backend.query(query);
this.emit('queried', { query, resultCount: entries.length });
return entries;
} catch (error) {
this.emit('error', { operation: 'query', query, error });
throw error;
}
}
async update(id: string, updates: Partial<MemoryEntry>): Promise<void> {
this.ensureInitialized();
try {
const existing = await this.backend.retrieve(id);
if (!existing) {
throw new MemoryBackendError('Entry not found for update', { id });
}
const updatedEntry: MemoryEntry = {
...existing,
...updates,
id,
version: (existing.version || 0) + 1,
timestamp: new Date()
};
await this.backend.update(id, updatedEntry);
this.emit('updated', { id, entry: updatedEntry, previousVersion: existing.version });
} catch (error) {
this.emit('error', { operation: 'update', id, error });
throw error;
}
}
async delete(id: string): Promise<void> {
this.ensureInitialized();
try {
await this.backend.delete(id);
this.emit('deleted', { id });
} catch (error) {
this.emit('error', { operation: 'delete', id, error });
throw error;
}
}
async getHealthStatus(): Promise<{
healthy: boolean;
error?: string;
metrics?: Record<string, number>;
}> {
if (!this.initialized) {
return { healthy: false, error: 'Memory manager not initialized' };
}
try {
return await this.backend.getHealthStatus();
} catch (error) {
return {
healthy: false,
error: error instanceof Error ? error.message : 'Unknown error'
};
}
}
private ensureInitialized(): void {
if (!this.initialized) {
throw new MemoryBackendError('Memory manager not initialized');
}
}
}