claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
607 lines (529 loc) • 16.4 kB
text/typescript
/**
* @claude-flow/memory - V3 Unified Memory System
*
* Provides a unified memory interface backed by AgentDB with HNSW indexing
* for 150x-12,500x faster vector search compared to brute-force approaches.
*
* @module @claude-flow/memory
*
* @example
* ```typescript
* import { UnifiedMemoryService, query, QueryTemplates } from '@claude-flow/memory';
*
* // Initialize the memory service
* const memory = new UnifiedMemoryService({
* dimensions: 1536,
* cacheEnabled: true,
* embeddingGenerator: async (text) => embeddings.embed(text),
* });
*
* await memory.initialize();
*
* // Store entries
* await memory.store({
* key: 'auth-patterns',
* content: 'OAuth 2.0 implementation patterns for secure authentication',
* tags: ['auth', 'security', 'patterns'],
* });
*
* // Semantic search
* const results = await memory.semanticSearch('user authentication best practices', 5);
*
* // Query with fluent builder
* const entries = await memory.query(
* query()
* .semantic('security vulnerabilities')
* .inNamespace('security')
* .withTags(['critical'])
* .threshold(0.8)
* .limit(10)
* .build()
* );
* ```
*/
// ===== Core Types =====
export type {
// Memory Entry Types
MemoryType,
AccessLevel,
ConsistencyLevel,
DistanceMetric,
MemoryEntry,
MemoryEntryInput,
MemoryEntryUpdate,
// Query Types
QueryType,
MemoryQuery,
SearchResult,
SearchOptions,
// HNSW Types
HNSWConfig,
HNSWStats,
QuantizationConfig,
// Backend Types
IMemoryBackend,
BackendStats,
HealthCheckResult,
ComponentHealth,
// Cache Types
CacheConfig,
CacheStats,
CachedEntry,
// Migration Types
MigrationSource,
MigrationConfig,
MigrationProgress,
MigrationResult,
MigrationError,
// Event Types
MemoryEventType,
MemoryEvent,
MemoryEventHandler,
// SONA Types
SONAMode,
LearningPattern,
// Utility Types
EmbeddingGenerator,
} from './types.js';
// Utility Functions and Constants (runtime values)
export {
generateMemoryId,
createDefaultEntry,
PERFORMANCE_TARGETS,
} from './types.js';
// ===== Auto Memory Bridge (ADR-048) =====
export { AutoMemoryBridge, resolveAutoMemoryDir, findGitRoot } from './auto-memory-bridge.js';
export type {
AutoMemoryBridgeConfig,
MemoryInsight,
InsightCategory,
SyncDirection,
SyncMode,
PruneStrategy,
SyncResult,
ImportResult,
} from './auto-memory-bridge.js';
// ===== Learning Bridge =====
export { LearningBridge } from './learning-bridge.js';
export type {
LearningBridgeConfig,
LearningStats,
ConsolidateResult,
PatternMatch,
} from './learning-bridge.js';
// ===== RVF Learning Persistence (ADR-057 Phase 6) =====
export { RvfLearningStore } from './rvf-learning-store.js';
export type {
RvfLearningStoreConfig,
PatternRecord,
LoraRecord,
EwcRecord,
TrajectoryRecord,
} from './rvf-learning-store.js';
export { PersistentSonaCoordinator } from './persistent-sona.js';
export type { PersistentSonaConfig } from './persistent-sona.js';
// ===== RVF Migration (Bidirectional) =====
export { RvfMigrator } from './rvf-migration.js';
export type { RvfMigrationOptions, RvfMigrationResult } from './rvf-migration.js';
// ===== Knowledge Graph =====
export { MemoryGraph } from './memory-graph.js';
export type {
MemoryGraphConfig,
GraphNode,
GraphEdge,
GraphStats,
RankedResult,
EdgeType,
} from './memory-graph.js';
// ===== Agent-Scoped Memory =====
export {
resolveAgentMemoryDir,
createAgentBridge,
transferKnowledge,
listAgentScopes,
} from './agent-memory-scope.js';
export type {
AgentMemoryScope,
AgentScopedConfig,
TransferOptions,
TransferResult,
} from './agent-memory-scope.js';
// ===== Controller Registry (ADR-053) =====
export { ControllerRegistry, INIT_LEVELS } from './controller-registry.js';
export type {
AgentDBControllerName,
CLIControllerName,
ControllerName,
InitLevel,
ControllerHealth,
RegistryHealthReport,
RuntimeConfig,
} from './controller-registry.js';
// ===== Core Components =====
export { AgentDBAdapter } from './agentdb-adapter.js';
export type { AgentDBAdapterConfig } from './agentdb-adapter.js';
export { AgentDBBackend } from './agentdb-backend.js';
export type { AgentDBBackendConfig } from './agentdb-backend.js';
export { SQLiteBackend } from './sqlite-backend.js';
export type { SQLiteBackendConfig } from './sqlite-backend.js';
export { SqlJsBackend } from './sqljs-backend.js';
export type { SqlJsBackendConfig } from './sqljs-backend.js';
export { HybridBackend } from './hybrid-backend.js';
export type {
HybridBackendConfig,
StructuredQuery,
SemanticQuery,
HybridQuery,
} from './hybrid-backend.js';
export { RvfBackend } from './rvf-backend.js';
export type { RvfBackendConfig } from './rvf-backend.js';
export { HnswLite, cosineSimilarity } from './hnsw-lite.js';
export type { HnswSearchResult } from './hnsw-lite.js';
export { HNSWIndex } from './hnsw-index.js';
export { CacheManager, TieredCacheManager } from './cache-manager.js';
export { QueryBuilder, query, QueryTemplates } from './query-builder.js';
export type { SortDirection, SortField } from './query-builder.js';
export { MemoryMigrator, createMigrator, migrateMultipleSources } from './migration.js';
export { createDatabase, getPlatformInfo, getAvailableProviders } from './database-provider.js';
export type { DatabaseProvider, DatabaseOptions } from './database-provider.js';
// ===== Smart Retrieval (ADR-090) =====
export { smartSearch, defaultQueryExpansions } from './smart-retrieval.js';
export type {
SearchCandidate,
RawSearchRequest,
RawSearchResponse,
SearchFn,
SmartSearchOptions,
SmartSearchStats,
SmartSearchResult,
} from './smart-retrieval.js';
// ===== Unified Memory Service =====
import { EventEmitter } from 'node:events';
import {
IMemoryBackend,
MemoryEntry,
MemoryEntryInput,
MemoryEntryUpdate,
MemoryQuery,
SearchResult,
SearchOptions,
BackendStats,
HealthCheckResult,
EmbeddingGenerator,
MigrationSource,
MigrationConfig,
MigrationResult,
} from './types.js';
import { AgentDBAdapter, AgentDBAdapterConfig } from './agentdb-adapter.js';
import { MemoryMigrator } from './migration.js';
/**
* Configuration for UnifiedMemoryService
*/
export interface UnifiedMemoryServiceConfig extends Partial<AgentDBAdapterConfig> {
/** Enable automatic embedding generation */
autoEmbed?: boolean;
/** Default embedding dimensions */
dimensions?: number;
/** Embedding generator function */
embeddingGenerator?: EmbeddingGenerator;
}
/**
* Unified Memory Service
*
* High-level interface for the V3 memory system that provides:
* - Simple API for common operations
* - Automatic embedding generation
* - Cross-agent memory sharing
* - SONA integration for learning
* - Event-driven notifications
* - Performance monitoring
*/
export class UnifiedMemoryService extends EventEmitter implements IMemoryBackend {
private adapter: AgentDBAdapter;
private config: UnifiedMemoryServiceConfig;
private initialized: boolean = false;
constructor(config: UnifiedMemoryServiceConfig = {}) {
super();
this.config = {
dimensions: 1536,
cacheEnabled: true,
autoEmbed: true,
...config,
};
this.adapter = new AgentDBAdapter({
dimensions: this.config.dimensions,
cacheEnabled: this.config.cacheEnabled,
cacheSize: this.config.cacheSize,
cacheTtl: this.config.cacheTtl,
hnswM: this.config.hnswM,
hnswEfConstruction: this.config.hnswEfConstruction,
defaultNamespace: this.config.defaultNamespace,
embeddingGenerator: this.config.embeddingGenerator,
persistenceEnabled: this.config.persistenceEnabled,
persistencePath: this.config.persistencePath,
maxEntries: this.config.maxEntries,
});
// Forward adapter events
this.adapter.on('entry:stored', (data) => this.emit('entry:stored', data));
this.adapter.on('entry:updated', (data) => this.emit('entry:updated', data));
this.adapter.on('entry:deleted', (data) => this.emit('entry:deleted', data));
this.adapter.on('cache:hit', (data) => this.emit('cache:hit', data));
this.adapter.on('cache:miss', (data) => this.emit('cache:miss', data));
this.adapter.on('index:added', (data) => this.emit('index:added', data));
}
// ===== Lifecycle =====
async initialize(): Promise<void> {
if (this.initialized) return;
await this.adapter.initialize();
this.initialized = true;
this.emit('initialized');
}
async shutdown(): Promise<void> {
if (!this.initialized) return;
await this.adapter.shutdown();
this.initialized = false;
this.emit('shutdown');
}
// ===== IMemoryBackend Implementation =====
async store(entry: MemoryEntry): Promise<void> {
return this.adapter.store(entry);
}
async get(id: string): Promise<MemoryEntry | null> {
return this.adapter.get(id);
}
async getByKey(namespace: string, key: string): Promise<MemoryEntry | null> {
return this.adapter.getByKey(namespace, key);
}
async update(id: string, update: MemoryEntryUpdate): Promise<MemoryEntry | null> {
return this.adapter.update(id, update);
}
async delete(id: string): Promise<boolean> {
return this.adapter.delete(id);
}
async query(query: MemoryQuery): Promise<MemoryEntry[]> {
return this.adapter.query(query);
}
async search(embedding: Float32Array, options: SearchOptions): Promise<SearchResult[]> {
return this.adapter.search(embedding, options);
}
async bulkInsert(entries: MemoryEntry[]): Promise<void> {
return this.adapter.bulkInsert(entries);
}
async bulkDelete(ids: string[]): Promise<number> {
return this.adapter.bulkDelete(ids);
}
async count(namespace?: string): Promise<number> {
return this.adapter.count(namespace);
}
async listNamespaces(): Promise<string[]> {
return this.adapter.listNamespaces();
}
async clearNamespace(namespace: string): Promise<number> {
return this.adapter.clearNamespace(namespace);
}
async getStats(): Promise<BackendStats> {
return this.adapter.getStats();
}
async healthCheck(): Promise<HealthCheckResult> {
return this.adapter.healthCheck();
}
// ===== Convenience Methods =====
/**
* Store an entry from simple input
*/
async storeEntry(input: MemoryEntryInput): Promise<MemoryEntry> {
return this.adapter.storeEntry(input);
}
/**
* Semantic search by content string
*/
async semanticSearch(
content: string,
k: number = 10,
threshold?: number
): Promise<SearchResult[]> {
return this.adapter.semanticSearch(content, k, threshold);
}
/**
* Find similar entries to a given entry
*/
async findSimilar(id: string, k: number = 5): Promise<SearchResult[]> {
const entry = await this.get(id);
if (!entry || !entry.embedding) {
return [];
}
const results = await this.search(entry.embedding, { k: k + 1 });
// Filter out the source entry
return results.filter((r) => r.entry.id !== id).slice(0, k);
}
/**
* Get or create an entry
*/
async getOrCreate(
namespace: string,
key: string,
creator: () => MemoryEntryInput | Promise<MemoryEntryInput>
): Promise<MemoryEntry> {
const existing = await this.getByKey(namespace, key);
if (existing) return existing;
const input = await creator();
return this.storeEntry({ ...input, namespace, key });
}
/**
* Append content to an existing entry
*/
async appendContent(id: string, content: string): Promise<MemoryEntry | null> {
const entry = await this.get(id);
if (!entry) return null;
return this.update(id, {
content: entry.content + '\n' + content,
});
}
/**
* Add tags to an existing entry
*/
async addTags(id: string, tags: string[]): Promise<MemoryEntry | null> {
const entry = await this.get(id);
if (!entry) return null;
const newTags = [...new Set([...entry.tags, ...tags])];
return this.update(id, { tags: newTags });
}
/**
* Remove tags from an existing entry
*/
async removeTags(id: string, tags: string[]): Promise<MemoryEntry | null> {
const entry = await this.get(id);
if (!entry) return null;
const newTags = entry.tags.filter((t) => !tags.includes(t));
return this.update(id, { tags: newTags });
}
// ===== Migration =====
/**
* Migrate from a legacy memory source
*/
async migrateFrom(
source: MigrationSource,
sourcePath: string,
options: Partial<MigrationConfig> = {}
): Promise<MigrationResult> {
const migrator = new MemoryMigrator(
this.adapter,
{ source, sourcePath, ...options },
this.config.embeddingGenerator
);
// Forward migration events
migrator.on('migration:started', (data) => this.emit('migration:started', data));
migrator.on('migration:progress', (data) => this.emit('migration:progress', data));
migrator.on('migration:completed', (data) => this.emit('migration:completed', data));
migrator.on('migration:failed', (data) => this.emit('migration:failed', data));
migrator.on('migration:error', (data) => this.emit('migration:error', data));
migrator.on('migration:warning', (data) => this.emit('migration:warning', data));
return migrator.migrate();
}
// ===== Cross-Agent Memory Sharing =====
/**
* Share an entry with another agent
*/
async shareWith(id: string, agentId: string): Promise<MemoryEntry | null> {
const entry = await this.get(id);
if (!entry) return null;
const sharedWith = (entry.metadata.sharedWith as string[]) || [];
if (!sharedWith.includes(agentId)) {
sharedWith.push(agentId);
}
return this.update(id, {
metadata: { ...entry.metadata, sharedWith },
});
}
/**
* Get entries shared with a specific agent
*/
async getSharedWith(agentId: string): Promise<MemoryEntry[]> {
const all = await this.query({ type: 'hybrid', limit: 10000 });
return all.filter((entry) => {
const sharedWith = (entry.metadata.sharedWith as string[]) || [];
return sharedWith.includes(agentId);
});
}
// ===== Utility =====
/**
* Get the underlying adapter for advanced operations
*/
getAdapter(): AgentDBAdapter {
return this.adapter;
}
/**
* Check if the service is initialized
*/
isInitialized(): boolean {
return this.initialized;
}
}
// ===== Factory Functions =====
/**
* Create a simple in-memory service (for testing)
*/
export function createInMemoryService(): UnifiedMemoryService {
return new UnifiedMemoryService({
persistenceEnabled: false,
cacheEnabled: true,
});
}
/**
* Create a persistent memory service
*/
export function createPersistentService(path: string): UnifiedMemoryService {
return new UnifiedMemoryService({
persistenceEnabled: true,
persistencePath: path,
cacheEnabled: true,
});
}
/**
* Create a memory service with embedding support
*/
export function createEmbeddingService(
embeddingGenerator: EmbeddingGenerator,
dimensions: number = 1536
): UnifiedMemoryService {
return new UnifiedMemoryService({
embeddingGenerator,
dimensions,
autoEmbed: true,
cacheEnabled: true,
});
}
/**
* Create a hybrid memory service (SQLite + AgentDB)
* This is the DEFAULT recommended configuration per ADR-009
*
* @example
* ```typescript
* const memory = createHybridService('./data/memory.db', embeddingFn);
* await memory.initialize();
*
* // Structured queries go to SQLite
* const user = await memory.getByKey('users', 'john@example.com');
*
* // Semantic queries go to AgentDB
* const similar = await memory.semanticSearch('authentication patterns', 10);
* ```
*/
export function createHybridService(
databasePath: string,
embeddingGenerator: EmbeddingGenerator,
dimensions: number = 1536
): UnifiedMemoryService {
return new UnifiedMemoryService({
embeddingGenerator,
dimensions,
autoEmbed: true,
cacheEnabled: true,
// Note: This would require extending UnifiedMemoryService to support HybridBackend
// For now, this creates an AgentDB service with persistence
persistenceEnabled: true,
persistencePath: databasePath,
});
}
// Default export
export default UnifiedMemoryService;