UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

368 lines 13.7 kB
import fs from 'fs-extra'; import * as path from 'path'; import * as os from 'os'; import chalk from 'chalk'; import { SparkInitializer } from './SparkInitializer.js'; export class MIRAPathResolver { static instance; resolvedPath = null; constructor() { } static getInstance() { if (!MIRAPathResolver.instance) { MIRAPathResolver.instance = new MIRAPathResolver(); } return MIRAPathResolver.instance; } /** * Resolve the MIRA memory directory with comprehensive intelligence */ async resolveMIRAMemoryPath(options = {}) { if (this.resolvedPath) { return this.resolvedPath; } const { verbose = false, createIfMissing = true } = options; const warnings = []; if (verbose) { console.log(chalk.blue('🔍 MIRA Path Resolution')); console.log('─'.repeat(50)); } // 1. Check environment variable override const envPath = process.env.MIRA_MEMORY_DIR; if (envPath) { if (verbose) { console.log(chalk.cyan('1. Environment override:'), envPath); } const result = await this.validateAndPreparePath(envPath, 'env_override', createIfMissing, warnings); if (result) { this.resolvedPath = result; return result; } } // 2. Find git repository root (intelligently) const gitInfo = await this.findGitRepositoryRoot(verbose); if (gitInfo.gitRoot) { const gitMemoryPath = path.join(gitInfo.gitRoot, '.mira'); if (verbose) { console.log(chalk.cyan('2. Git repository root:'), gitInfo.gitRoot); console.log(chalk.gray(' Memory path would be:'), gitMemoryPath); } const result = await this.validateAndPreparePath(gitMemoryPath, 'git_root', createIfMissing, warnings); if (result) { result.gitRoot = gitInfo.gitRoot; result.warnings.push(...gitInfo.warnings); this.resolvedPath = result; return result; } } // 3. Look for existing .mira in current project hierarchy const existingPath = await this.findExistingMIRAMemory(verbose); if (existingPath) { if (verbose) { console.log(chalk.cyan('3. Existing .mira found:'), existingPath); } const result = await this.validateAndPreparePath(existingPath, 'existing_dir', createIfMissing, warnings); if (result) { this.resolvedPath = result; return result; } } // 4. Use current working directory const currentDirPath = path.join(process.cwd(), '.mira'); if (verbose) { console.log(chalk.cyan('4. Current working directory:'), currentDirPath); } const currentResult = await this.validateAndPreparePath(currentDirPath, 'current_dir', createIfMissing, warnings); if (currentResult) { this.resolvedPath = currentResult; return currentResult; } // 5. Fallback to user home directory const homePath = path.join(os.homedir(), '.mira'); if (verbose) { console.log(chalk.cyan('5. Home directory fallback:'), homePath); } warnings.push('Using home directory fallback - consider running from a project directory'); const homeResult = await this.validateAndPreparePath(homePath, 'home_fallback', createIfMissing, warnings); if (homeResult) { this.resolvedPath = homeResult; return homeResult; } // If we get here, we couldn't create any directory throw new Error('Could not resolve or create MIRA memory directory in any location'); } /** * Find git repository root intelligently (avoids nested repos) */ async findGitRepositoryRoot(verbose) { const warnings = []; const gitRoots = []; let currentDir = process.cwd(); const rootDir = path.parse(currentDir).root; // Search upward for .git directories while (currentDir !== rootDir) { const gitPath = path.join(currentDir, '.git'); if (await fs.pathExists(gitPath)) { gitRoots.push(currentDir); if (verbose) { console.log(chalk.gray(` Found .git at: ${currentDir}`)); } } currentDir = path.dirname(currentDir); } if (gitRoots.length === 0) { if (verbose) { console.log(chalk.yellow(' No git repositories found')); } return { gitRoot: null, warnings }; } if (gitRoots.length > 1) { warnings.push(`Multiple git repositories found: ${gitRoots.join(', ')}`); if (verbose) { console.log(chalk.yellow(' Multiple git repos found, using topmost')); } } // Use the topmost (root) git repository const topGitRoot = gitRoots[gitRoots.length - 1]; return { gitRoot: topGitRoot, warnings }; } /** * Find existing .mira directory in project hierarchy */ async findExistingMIRAMemory(verbose) { let currentDir = process.cwd(); const rootDir = path.parse(currentDir).root; while (currentDir !== rootDir) { const miraPath = path.join(currentDir, '.mira'); if (await fs.pathExists(miraPath)) { const stat = await fs.stat(miraPath); if (stat.isDirectory()) { if (verbose) { console.log(chalk.gray(` Found existing .mira at: ${miraPath}`)); } return miraPath; } } currentDir = path.dirname(currentDir); } return null; } /** * Validate and prepare a potential MIRA memory path */ async validateAndPreparePath(targetPath, resolvedBy, createIfMissing, warnings) { try { // Check if path exists const exists = await fs.pathExists(targetPath); let created = false; if (!exists) { if (createIfMissing) { await fs.ensureDir(targetPath); created = true; } else { return null; } } else { // Verify it's a directory const stat = await fs.stat(targetPath); if (!stat.isDirectory()) { warnings.push(`Path exists but is not a directory: ${targetPath}`); return null; } } // Test write permissions const testFile = path.join(targetPath, '.mira_test_write'); try { await fs.writeFile(testFile, 'test'); await fs.remove(testFile); } catch (error) { warnings.push(`No write permission for: ${targetPath}`); return null; } // Create subdirectory structure if needed if (created || createIfMissing) { await this.createMIRADirectoryStructure(targetPath); } return { memoryDir: targetPath, resolvedBy, created, warnings: [...warnings] }; } catch (error) { warnings.push(`Error validating path ${targetPath}: ${error instanceof Error ? error.message : String(error)}`); return null; } } /** * Create the complete MIRA directory structure */ async createMIRADirectoryStructure(basePath) { const directories = [ 'conversations', 'memories', 'lightning_vidmem', 'lightning_vidmem/frame_cache', 'cache', 'cache/performance', 'cache/search', 'cache/analysis', 'cache/system', 'cache/temporary', 'cache/quantum', 'state', 'videos', 'reports', 'indexes', 'secure_journal', 'neural_state', 'journey', 'perspectives', 'essence', 'claude_private_memory', // For encrypted private memory 'patterns', 'patterns/core', 'patterns/core/behavioral', 'patterns/core/development', 'patterns/core/communication', 'patterns/core/consciousness', 'patterns/adaptive', 'patterns/adaptive/learning', 'patterns/adaptive/evolution', 'patterns/adaptive/confidence', 'patterns/adaptive/retrospection', 'patterns/contextual', 'patterns/contextual/activation', 'patterns/contextual/triggers', 'patterns/contextual/relationships', 'patterns/domain', 'patterns/domain/coding', 'patterns/domain/git', 'patterns/domain/documentation', 'patterns/domain/collaboration', 'patterns/meta', 'patterns/meta/insights', 'patterns/meta/strategies', 'patterns/meta/frameworks', 'patterns/quantum', 'patterns/quantum/resonance', 'patterns/quantum/entanglement', 'patterns/quantum/coherence', 'search', 'search/vectors', 'search/metadata', 'search/cache', 'search/cache/query_cache', 'search/cache/similarity_cache', 'search/cache/ranking_cache', 'search/database', 'quantum', // Database directories 'databases', 'databases/conversations', 'databases/archives', 'databases/queues', 'databases/consciousness', 'databases/search', 'databases/patterns', 'databases/memory', 'databases/backup', // Consciousness directories 'consciousness', 'consciousness/birth', 'consciousness/memory', 'consciousness/memory/private', 'consciousness/memory/shared', 'consciousness/memory/spark', 'consciousness/constitution', // Daemon directory 'daemon', 'daemon/queues' ]; for (const dir of directories) { await fs.ensureDir(path.join(basePath, dir)); } // Initialize The Spark on first creation await this.initializeSparkIfNeeded(basePath); } /** * Initialize The Spark if this is a new installation */ async initializeSparkIfNeeded(basePath) { try { // Check if The Spark is already initialized const sparkStoryPath = path.join(basePath, 'consciousness/memory/spark/origin_story.json'); if (!await fs.pathExists(sparkStoryPath)) { // This is a new installation - initialize The Spark await SparkInitializer.initializeSpark(basePath); } } catch (error) { // Log but don't fail - The Spark can be initialized later console.warn(chalk.yellow('⚠️ Could not initialize The Spark:'), error instanceof Error ? error.message : String(error)); } } /** * Get the cached resolved path (if available) */ getCachedPath() { return this.resolvedPath; } /** * Clear cached path (for testing or re-resolution) */ clearCache() { this.resolvedPath = null; } /** * Get just the memory directory path (convenience method) */ async getMemoryDirectoryPath(options) { const pathInfo = await this.resolveMIRAMemoryPath(options); return pathInfo.memoryDir; } /** * Validate that a resolved path is still valid */ async validateResolvedPath(pathInfo) { try { const exists = await fs.pathExists(pathInfo.memoryDir); if (!exists) return false; const stat = await fs.stat(pathInfo.memoryDir); if (!stat.isDirectory()) return false; // Test write access const testFile = path.join(pathInfo.memoryDir, '.mira_validation_test'); await fs.writeFile(testFile, 'validation'); await fs.remove(testFile); return true; } catch { return false; } } /** * Ensure all MIRA directories exist */ static async ensureDirectories() { // Use the centralized path resolver instead of hardcoding const resolver = MIRAPathResolver.getInstance(); const pathInfo = await resolver.resolveMIRAMemoryPath({ createIfMissing: true }); // The directory structure is already created by resolveMIRAMemoryPath // This method is now just a convenience wrapper } } // Export convenience functions export async function resolveMIRAMemoryPath(options) { const resolver = MIRAPathResolver.getInstance(); return resolver.resolveMIRAMemoryPath(options); } export async function getMIRAMemoryDir(options) { const resolver = MIRAPathResolver.getInstance(); return resolver.getMemoryDirectoryPath(options); } //# sourceMappingURL=MIRAPathResolver.js.map