UNPKG

@sethdouglasford/claude-flow

Version:

Claude Code Flow - Advanced AI-powered development workflows with SPARC methodology

1,080 lines 37.5 kB
/** * Distributed Memory System with Cross-Agent Sharing */ import { EventEmitter } from "node:events"; import * as fs from "node:fs/promises"; import * as path from "node:path"; import * as crypto from "node:crypto"; import { Logger } from "../core/logger.js"; import { generateId } from "../utils/helpers.js"; export class SwarmMemoryManager extends EventEmitter { logger; config; memory; partitions = new Map(); entries = new Map(); index; cache; replication; persistence; encryption; isInitialized = false; // Background processes syncTimer; backupTimer; cleanupTimer; constructor(config = {}) { super(); // Configure logger based on config or default to quiet mode const logLevel = config.logging?.level || "error"; const logFormat = config.logging?.format || "text"; const logDestination = config.logging?.destination || "console"; this.logger = new Logger({ level: logLevel, format: logFormat, destination: logDestination }, { component: "SwarmMemoryManager" }); this.config = this.mergeWithDefaults(config); // Initialize memory structure this.memory = { namespace: this.config.namespace, partitions: [], permissions: { read: "swarm", write: "team", delete: "private", share: "team", }, persistent: true, backupEnabled: true, distributed: this.config.enableDistribution, consistency: this.config.consistencyLevel, cacheEnabled: this.config.enableCaching, compressionEnabled: this.config.enableCompression, }; // Initialize subsystems this.index = new MemoryIndex(); this.cache = new MemoryCache(this.config.cacheSize, this.config.cacheTtl); this.replication = new MemoryReplication(this.config); this.persistence = new MemoryPersistence(this.config); this.encryption = new MemoryEncryption(this.config); this.setupEventHandlers(); } async initialize() { if (this.isInitialized) { return; } this.logger.info("Initializing swarm memory manager..."); try { // Initialize subsystems await this.persistence.initialize(); await this.encryption.initialize(); await this.replication.initialize(); await this.index.initialize(); // Load existing data await this.loadMemoryState(); // Create default partitions await this.createDefaultPartitions(); // Start background processes this.startBackgroundProcesses(); this.isInitialized = true; this.emit("memory:initialized", { namespace: this.config.namespace, entriesLoaded: this.entries.size, partitionsLoaded: this.partitions.size, }); this.logger.info("Swarm memory manager initialized", { namespace: this.config.namespace, entries: this.entries.size, partitions: this.partitions.size, }); } catch (error) { this.logger.error("Failed to initialize memory manager", { error: error.message }); throw error; } } async shutdown() { if (!this.isInitialized) { return; } this.logger.info("Shutting down swarm memory manager..."); try { // Stop background processes this.stopBackgroundProcesses(); // Save final state await this.saveMemoryState(); // Shutdown subsystems await this.replication.shutdown(); await this.persistence.shutdown(); await this.encryption.shutdown(); this.isInitialized = false; this.emit("memory:shutdown"); this.logger.info("Swarm memory manager shut down"); } catch (error) { this.logger.error("Error during memory manager shutdown", { error: error.message }); } } // ===== MEMORY OPERATIONS ===== async store(key, value, options = {}) { this.ensureInitialized(); const entryId = generateId("mem"); const now = new Date(); // Validate access permissions if (options.owner) { await this.validateAccess(options.owner, "write", options.partition); } // Determine partition const partitionName = options.partition || "default"; const partition = await this.getOrCreatePartition(partitionName); // Create memory entry const entry = { id: entryId, key, value: await this.serializeValue(value), type: options.type || "knowledge", tags: options.tags ?? [], owner: options.owner || { id: "system", swarmId: "", type: "coordinator", instance: 0 }, accessLevel: options.accessLevel || "team", createdAt: now, updatedAt: now, expiresAt: options.ttl ? new Date(now.getTime() + options.ttl) : undefined, version: 1, references: [], dependencies: [], }; // Validate entry size const entrySize = this.calculateEntrySize(entry); if (entrySize > this.config.maxEntrySize) { throw new Error(`Entry size ${entrySize} exceeds maximum ${this.config.maxEntrySize}`); } // Check memory limits await this.enforceMemoryLimits(entrySize); // Store entry this.entries.set(entryId, entry); partition.entries.push(entry); // Update index await this.index.addEntry(entry); // Update cache if (this.config.enableCaching) { this.cache.set(key, entry); } // Replicate if enabled if (this.config.enableDistribution) { await this.replication.replicate(entry); } // Emit event this.emit("memory:stored", { entryId, key, partition: partitionName, type: entry.type, size: entrySize, }); this.logger.debug("Stored memory entry", { entryId, key, partition: partitionName, type: entry.type, size: entrySize, }); return entryId; } async retrieve(key, options = {}) { this.ensureInitialized(); // Try cache first if (this.config.enableCaching) { const cached = this.cache.get(key); if (cached && !this.isExpired(cached)) { if (options.requester) { await this.validateAccess(options.requester, "read", options.partition); } return options.includeMetadata ? cached : await this.deserializeValue(cached.value); } } // Find entry const entry = await this.findEntry(key, options.partition); if (!entry) { return null; } // Check expiration if (this.isExpired(entry)) { await this.deleteEntry(entry.id); return null; } // Validate access if (options.requester) { await this.validateAccess(options.requester, "read", options.partition); } // Update cache if (this.config.enableCaching) { this.cache.set(key, entry); } // Emit event this.emit("memory:retrieved", { entryId: entry.id, key, requester: options.requester?.id, }); return options.includeMetadata ? entry : await this.deserializeValue(entry.value); } async update(key, value, options = {}) { this.ensureInitialized(); const entry = await this.findEntry(key, options.partition); if (!entry) { return false; } // Validate access if (options.updater) { await this.validateAccess(options.updater, "write", options.partition); } // Create backup of old version if (options.incrementVersion !== false) { entry.previousVersions = entry.previousVersions ?? []; entry.previousVersions.push({ ...entry }); // Limit version history if (entry.previousVersions.length > 10) { entry.previousVersions = entry.previousVersions.slice(-10); } } // Update entry entry.value = await this.serializeValue(value); entry.updatedAt = new Date(); if (options.incrementVersion !== false) { entry.version++; } // Update index await this.index.updateEntry(entry); // Update cache if (this.config.enableCaching) { this.cache.set(key, entry); } // Replicate if enabled if (this.config.enableDistribution) { await this.replication.replicate(entry); } this.emit("memory:updated", { entryId: entry.id, key, version: entry.version, updater: options.updater?.id, }); return true; } async delete(key, options = {}) { this.ensureInitialized(); const entry = await this.findEntry(key, options.partition); if (!entry) { return false; } // Validate access if (options.deleter && !options.force) { await this.validateAccess(options.deleter, "delete", options.partition); } return await this.deleteEntry(entry.id); } async query(query) { this.ensureInitialized(); let results = Array.from(this.entries.values()); // Apply filters if (query.partition) { const partition = this.partitions.get(query.partition); if (partition) { const entryIds = new Set(partition.entries.map(e => e.id)); results = results.filter(e => entryIds.has(e.id)); } else { return []; } } if (query.key) { results = results.filter(e => e.key === query.key); } if (query.type) { results = results.filter(e => e.type === query.type); } if (query.owner) { results = results.filter(e => e.owner.id === query.owner.id); } if (query.accessLevel) { results = results.filter(e => e.accessLevel === query.accessLevel); } if (query.tags && query.tags.length > 0) { results = results.filter(e => query.tags.some(tag => e.tags.includes(tag))); } if (query.createdAfter) { results = results.filter(e => e.createdAt >= query.createdAfter); } if (query.createdBefore) { results = results.filter(e => e.createdAt <= query.createdBefore); } if (query.expiresAfter) { results = results.filter(e => e.expiresAt && e.expiresAt >= query.expiresAfter); } // Filter out expired entries results = results.filter(e => !this.isExpired(e)); // Sort results if (query.sortBy) { results.sort((a, b) => { let compareValue = 0; switch (query.sortBy) { case "createdAt": compareValue = a.createdAt.getTime() - b.createdAt.getTime(); break; case "updatedAt": compareValue = a.updatedAt.getTime() - b.updatedAt.getTime(); break; case "key": compareValue = a.key.localeCompare(b.key); break; default: compareValue = 0; } return query.sortOrder === "desc" ? -compareValue : compareValue; }); } // Apply pagination const offset = query.offset ?? 0; const limit = query.limit ?? results.length; results = results.slice(offset, offset + limit); return results; } async search(options) { this.ensureInitialized(); return await this.index.search(options); } // ===== SHARING AND COLLABORATION ===== async shareMemory(key, targetAgent, options = {}) { this.ensureInitialized(); const entry = await this.findEntry(key, options.partition); if (!entry) { throw new Error(`Memory entry not found: ${key}`); } // Validate sharing permissions if (options.sharer) { await this.validateAccess(options.sharer, "share", options.partition); } // Create shared copy const sharedEntryId = generateId("shared-mem"); const sharedEntry = { ...entry, id: sharedEntryId, owner: targetAgent, accessLevel: options.accessLevel || entry.accessLevel, createdAt: new Date(), updatedAt: new Date(), expiresAt: options.expiresAt, references: [...entry.references, entry.id], }; // Store shared entry this.entries.set(sharedEntryId, sharedEntry); await this.index.addEntry(sharedEntry); // Add to target agent's partition const targetPartition = await this.getOrCreatePartition(`agent_${targetAgent.id}`); targetPartition.entries.push(sharedEntry); this.emit("memory:shared", { originalId: entry.id, sharedId: sharedEntryId, key, sharer: options.sharer?.id, target: targetAgent.id, }); this.logger.info("Shared memory entry", { key, from: options.sharer?.id, to: targetAgent.id, sharedId: sharedEntryId, }); return sharedEntryId; } async broadcastMemory(key, targetAgents, options = {}) { this.ensureInitialized(); const sharedIds = []; for (const targetAgent of targetAgents) { try { const sharedId = await this.shareMemory(key, targetAgent, { ...options, sharer: options.broadcaster, }); sharedIds.push(sharedId); } catch (error) { this.logger.warn("Failed to share memory with agent", { key, targetAgent: targetAgent.id, error: error.message, }); } } this.emit("memory:broadcasted", { key, broadcaster: options.broadcaster?.id, targets: targetAgents.map(a => a.id), sharedCount: sharedIds.length, }); return sharedIds; } async synchronizeWith(targetNode, options = {}) { this.ensureInitialized(); if (!this.config.enableDistribution) { throw new Error("Distribution not enabled"); } await this.replication.synchronizeWith(targetNode, options); this.emit("memory:synchronized", { targetNode, direction: options.direction || "bidirectional", partition: options.partition, }); } // ===== PARTITION MANAGEMENT ===== async createPartition(name, options = {}, skipInitCheck = false) { if (!skipInitCheck) { this.ensureInitialized(); } if (this.partitions.has(name)) { throw new Error(`Partition already exists: ${name}`); } const partition = { id: generateId("partition"), name, type: options.type || "knowledge", entries: [], maxSize: options.maxSize || this.config.maxMemorySize, ttl: options.ttl, readOnly: options.readOnly || false, shared: options.shared || true, indexed: options.indexed !== false, compressed: options.compressed || this.config.enableCompression, }; this.partitions.set(name, partition); this.memory.partitions.push(partition); this.emit("memory:partition-created", { partitionId: partition.id, name, type: partition.type, }); this.logger.info("Created memory partition", { name, type: partition.type, maxSize: partition.maxSize, }); return partition.id; } async deletePartition(name, force = false) { this.ensureInitialized(); const partition = this.partitions.get(name); if (!partition) { return false; } if (partition.entries.length > 0 && !force) { throw new Error(`Partition ${name} contains entries. Use force=true to delete.`); } // Delete all entries in partition for (const entry of partition.entries) { await this.deleteEntry(entry.id); } this.partitions.delete(name); this.memory.partitions = this.memory.partitions.filter(p => p.id !== partition.id); this.emit("memory:partition-deleted", { partitionId: partition.id, name, }); return true; } getPartition(name) { return this.partitions.get(name); } getPartitions() { return Array.from(this.partitions.values()); } // ===== BACKUP AND RECOVERY ===== async createBackup() { this.ensureInitialized(); const backup = { timestamp: new Date(), version: "1.0.0", checksum: "", metadata: { namespace: this.config.namespace, entryCount: this.entries.size, partitionCount: this.partitions.size, }, entries: Array.from(this.entries.values()), partitions: Array.from(this.partitions.values()), }; // Calculate checksum backup.checksum = this.calculateChecksum(backup); const backupId = generateId("backup"); await this.persistence.saveBackup(backupId, backup); this.emit("memory:backup-created", { backupId, entryCount: backup.entries.length, size: JSON.stringify(backup).length, }); return backupId; } async restoreFromBackup(backupId) { this.ensureInitialized(); const backup = await this.persistence.loadBackup(backupId); if (!backup) { throw new Error(`Backup not found: ${backupId}`); } // Verify checksum const calculatedChecksum = this.calculateChecksum(backup); if (calculatedChecksum !== backup.checksum) { throw new Error("Backup checksum verification failed"); } // Clear current state this.entries.clear(); this.partitions.clear(); await this.index.clear(); // Restore entries for (const entry of backup.entries) { this.entries.set(entry.id, entry); await this.index.addEntry(entry); } // Restore partitions for (const partition of backup.partitions) { this.partitions.set(partition.name, partition); } this.memory.partitions = backup.partitions; this.emit("memory:backup-restored", { backupId, entryCount: backup.entries.length, partitionCount: backup.partitions.length, }); this.logger.info("Restored from backup", { backupId, entries: backup.entries.length, partitions: backup.partitions.length, }); } // ===== STATISTICS AND MONITORING ===== getStatistics() { const entries = Array.from(this.entries.values()); const validEntries = entries.filter(e => !this.isExpired(e)); const entriesByType = { knowledge: 0, state: 0, cache: 0, logs: 0, results: 0, communication: 0, configuration: 0, metrics: 0, }; const entriesByAccess = { private: 0, team: 0, swarm: 0, public: 0, system: 0, }; let totalSize = 0; let oldestEntry = new Date(); let newestEntry = new Date(0); let expiringEntries = 0; for (const entry of validEntries) { if (entry.type in entriesByType) { entriesByType[entry.type]++; } if (entry.accessLevel in entriesByAccess) { entriesByAccess[entry.accessLevel]++; } const entrySize = this.calculateEntrySize(entry); totalSize += entrySize; if (entry.createdAt < oldestEntry) { oldestEntry = entry.createdAt; } if (entry.createdAt > newestEntry) { newestEntry = entry.createdAt; } if (entry.expiresAt && entry.expiresAt.getTime() - Date.now() < 24 * 60 * 60 * 1000) { expiringEntries++; } } return { totalEntries: validEntries.length, totalSize, partitionCount: this.partitions.size, entriesByType, entriesByAccess, averageSize: validEntries.length > 0 ? totalSize / validEntries.length : 0, oldestEntry, newestEntry, expiringEntries, }; } async exportMemory(options = {}) { this.ensureInitialized(); let entries = Array.from(this.entries.values()); if (!options.includeExpired) { entries = entries.filter(e => !this.isExpired(e)); } if (options.filter) { const filteredResults = await this.query(options.filter); const filteredIds = new Set(filteredResults.map(e => e.id)); entries = entries.filter(e => filteredIds.has(e.id)); } if (options.format === "csv") { return this.entriesToCSV(entries); } else { return JSON.stringify({ exported: new Date().toISOString(), namespace: this.config.namespace, entryCount: entries.length, entries: entries.map(e => ({ ...e, value: e.value, // Value is already serialized })), }, null, 2); } } // ===== PRIVATE METHODS ===== ensureInitialized() { if (!this.isInitialized) { throw new Error("Memory manager not initialized"); } } async findEntry(key, partition) { for (const entry of this.entries.values()) { if (entry.key === key) { if (partition) { const part = this.partitions.get(partition); if (part?.entries.find(e => e.id === entry.id)) { return entry; } } else { return entry; } } } return null; } async deleteEntry(entryId) { const entry = this.entries.get(entryId); if (!entry) { return false; } // Remove from entries this.entries.delete(entryId); // Remove from partitions for (const partition of this.partitions.values()) { partition.entries = partition.entries.filter(e => e.id !== entryId); } // Remove from index await this.index.removeEntry(entryId); // Remove from cache if (this.config.enableCaching) { this.cache.delete(entry.key); } this.emit("memory:deleted", { entryId, key: entry.key, }); return true; } isExpired(entry) { return entry.expiresAt ? entry.expiresAt <= new Date() : false; } async validateAccess(agent, operation, partition) { // Implement access control logic here // For now, allow all operations return; } async getOrCreatePartition(name) { let partition = this.partitions.get(name); if (!partition) { await this.createPartition(name, {}, !this.isInitialized); partition = this.partitions.get(name); if (!partition) { throw new Error(`Failed to create partition: ${name}`); } } return partition; } async serializeValue(value) { // Apply compression and encryption if enabled let serialized = JSON.stringify(value); if (this.config.enableCompression) { // Compression would be implemented here // For now, just return the serialized value } if (this.config.enableEncryption) { serialized = await this.encryption.encrypt(serialized); } return serialized; } async deserializeValue(value) { let deserialized = value; if (this.config.enableEncryption) { deserialized = await this.encryption.decrypt(deserialized); } if (this.config.enableCompression) { // Decompression would be implemented here // For now, just use the deserialized value } return JSON.parse(deserialized); } calculateEntrySize(entry) { return JSON.stringify(entry).length; } async enforceMemoryLimits(newEntrySize) { const stats = this.getStatistics(); const projectedSize = stats.totalSize + newEntrySize; if (projectedSize > this.config.maxMemorySize) { // Remove expired entries first await this.cleanupExpiredEntries(); // If still over limit, remove oldest entries const updatedStats = this.getStatistics(); if (updatedStats.totalSize + newEntrySize > this.config.maxMemorySize) { await this.evictOldEntries(newEntrySize); } } } async cleanupExpiredEntries() { const expiredEntries = Array.from(this.entries.values()) .filter(e => this.isExpired(e)); for (const entry of expiredEntries) { await this.deleteEntry(entry.id); } if (expiredEntries.length > 0) { this.logger.info("Cleaned up expired entries", { count: expiredEntries.length }); } } async evictOldEntries(requiredSpace) { const entries = Array.from(this.entries.values()) .filter(e => !this.isExpired(e)) .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime()); let freedSpace = 0; let evictedCount = 0; for (const entry of entries) { if (freedSpace >= requiredSpace) { break; } if (entry.accessLevel !== "system") { // Don't evict system entries const entrySize = this.calculateEntrySize(entry); await this.deleteEntry(entry.id); freedSpace += entrySize; evictedCount++; } } this.logger.warn("Evicted old entries for space", { evictedCount, freedSpace, requiredSpace, }); } calculateChecksum(backup) { const content = JSON.stringify({ entries: backup.entries, partitions: backup.partitions, }); return crypto.createHash("sha256").update(content).digest("hex"); } entriesToCSV(entries) { const headers = ["id", "key", "type", "accessLevel", "createdAt", "updatedAt", "owner", "tags"]; const rows = entries.map(entry => [ entry.id, entry.key, entry.type, entry.accessLevel, entry.createdAt.toISOString(), entry.updatedAt.toISOString(), entry.owner.id, entry.tags.join(";"), ]); return [headers, ...rows].map(row => row.join(",")).join("\n"); } async loadMemoryState() { try { const state = await this.persistence.loadState(); if (state) { // Load entries for (const entry of state.entries ?? []) { this.entries.set(entry.id, entry); await this.index.addEntry(entry); } // Load partitions for (const partition of state.partitions ?? []) { this.partitions.set(partition.name, partition); } this.memory.partitions = state.partitions ?? []; this.logger.info("Loaded memory state", { entries: this.entries.size, partitions: this.partitions.size, }); } } catch (error) { this.logger.warn("Failed to load memory state", { error: error.message }); } } async saveMemoryState() { try { const state = { namespace: this.config.namespace, timestamp: new Date(), entries: Array.from(this.entries.values()), partitions: Array.from(this.partitions.values()), }; await this.persistence.saveState(state); } catch (error) { this.logger.error("Failed to save memory state", { error: error.message }); } } async createDefaultPartitions() { const defaultPartitions = [ { name: "default", type: "knowledge" }, { name: "system", type: "configuration" }, { name: "cache", type: "cache" }, { name: "logs", type: "logs" }, ]; for (const partition of defaultPartitions) { if (!this.partitions.has(partition.name)) { await this.createPartition(partition.name, { type: partition.type }, true); } } } mergeWithDefaults(config) { return { namespace: "default", persistencePath: "./swarm-memory", maxMemorySize: 100 * 1024 * 1024, // 100MB maxEntrySize: 10 * 1024 * 1024, // 10MB defaultTtl: 24 * 60 * 60 * 1000, // 24 hours enableCompression: false, enableEncryption: false, consistencyLevel: "eventual", syncInterval: 60000, // 1 minute backupInterval: 3600000, // 1 hour maxBackups: 24, enableDistribution: false, distributionNodes: [], replicationFactor: 1, enableCaching: true, cacheSize: 1000, cacheTtl: 300000, // 5 minutes ...config, }; } startBackgroundProcesses() { // Sync process if (this.config.syncInterval > 0) { this.syncTimer = setInterval(() => { this.performSync(); }, this.config.syncInterval); } // Backup process if (this.config.backupInterval > 0) { this.backupTimer = setInterval(() => { this.createBackup().catch(error => { this.logger.error("Background backup failed", { error: error.message }); }); }, this.config.backupInterval); } // Cleanup process this.cleanupTimer = setInterval(() => { this.cleanupExpiredEntries(); }, 60000); // Every minute } stopBackgroundProcesses() { if (this.syncTimer) { clearInterval(this.syncTimer); this.syncTimer = undefined; } if (this.backupTimer) { clearInterval(this.backupTimer); this.backupTimer = undefined; } if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = undefined; } } async performSync() { try { await this.saveMemoryState(); if (this.config.enableDistribution) { await this.replication.sync(); } } catch (error) { this.logger.error("Background sync failed", { error: error.message }); } } setupEventHandlers() { // Handle replication events this.replication.on("entry-received", async (data) => { const entry = data.entry; this.entries.set(entry.id, entry); await this.index.addEntry(entry); this.emit("memory:replicated", { entryId: entry.id, key: entry.key, source: data.source, }); }); } } // ===== SUPPORTING CLASSES ===== class MemoryIndex { index = new Map(); async initialize() { // Initialize search index } async addEntry(entry) { // Add entry to search index this.indexTerms(entry.id, [entry.key, ...entry.tags, entry.type]); } async updateEntry(entry) { await this.removeEntry(entry.id); await this.addEntry(entry); } async removeEntry(entryId) { // Remove from all index terms for (const termSet of this.index.values()) { termSet.delete(entryId); } } async search(options) { // Implement search logic return []; } async clear() { this.index.clear(); } indexTerms(entryId, terms) { for (const term of terms) { const normalizedTerm = term.toLowerCase(); if (!this.index.has(normalizedTerm)) { this.index.set(normalizedTerm, new Set()); } const termSet = this.index.get(normalizedTerm); if (termSet) { termSet.add(entryId); } } } } class MemoryCache { cache = new Map(); maxSize; ttl; constructor(maxSize, ttl) { this.maxSize = maxSize; this.ttl = ttl; } set(key, entry) { // Evict if at capacity if (this.cache.size >= this.maxSize) { const oldestKey = this.cache.keys().next().value; if (oldestKey !== undefined) { this.cache.delete(oldestKey); } } this.cache.set(key, { entry, expiry: Date.now() + this.ttl, }); } get(key) { const cached = this.cache.get(key); if (!cached) { return null; } if (Date.now() > cached.expiry) { this.cache.delete(key); return null; } return cached.entry; } delete(key) { this.cache.delete(key); } } class MemoryReplication extends EventEmitter { config; constructor(config) { super(); this.config = config; } async initialize() { // Initialize replication } async shutdown() { // Shutdown replication } async replicate(entry) { // Replicate entry to other nodes } async synchronizeWith(targetNode, options) { // Synchronize with target node } async sync() { // Perform background sync } } class MemoryPersistence { config; constructor(config) { this.config = config; } async initialize() { await fs.mkdir(this.config.persistencePath, { recursive: true }); } async shutdown() { // Shutdown persistence } async saveState(state) { const statePath = path.join(this.config.persistencePath, "state.json"); await fs.writeFile(statePath, JSON.stringify(state, null, 2)); } async loadState() { try { const statePath = path.join(this.config.persistencePath, "state.json"); const content = await fs.readFile(statePath, "utf-8"); return JSON.parse(content); } catch (error) { return null; } } async saveBackup(backupId, backup) { const backupPath = path.join(this.config.persistencePath, "backups", `${backupId}.json`); await fs.mkdir(path.dirname(backupPath), { recursive: true }); await fs.writeFile(backupPath, JSON.stringify(backup, null, 2)); } async loadBackup(backupId) { try { const backupPath = path.join(this.config.persistencePath, "backups", `${backupId}.json`); const content = await fs.readFile(backupPath, "utf-8"); return JSON.parse(content); } catch (error) { return null; } } } class MemoryEncryption { config; constructor(config) { this.config = config; } async initialize() { // Initialize encryption } async shutdown() { // Shutdown encryption } async encrypt(data) { // Implement encryption return data; } async decrypt(data) { // Implement decryption return data; } } export default SwarmMemoryManager; //# sourceMappingURL=memory.js.map