minimem 0.0.3 → 0.0.4
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.
- package/dist/chunk-ARZQHOJI.js +239 -0
- package/dist/chunk-ARZQHOJI.js.map +1 -0
- package/dist/chunk-GVWPZRF7.js +260 -0
- package/dist/chunk-GVWPZRF7.js.map +1 -0
- package/dist/cli/index.js +1411 -612
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +375 -109
- package/dist/index.js +1330 -370
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +65 -0
- package/dist/internal.js +33 -0
- package/dist/internal.js.map +1 -0
- package/dist/session.d.ts +96 -0
- package/dist/session.js +15 -0
- package/dist/session.js.map +1 -0
- package/package.json +10 -2
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/config.ts","../../src/cli/commands/search.ts","../../src/minimem.ts","../../src/internal.ts","../../src/search/hybrid.ts","../../src/search/search.ts","../../src/db/schema.ts","../../src/db/sqlite-vec.ts","../../src/embeddings/embeddings.ts","../../src/embeddings/batch-openai.ts","../../src/embeddings/batch-gemini.ts","../../src/cli/commands/sync.ts","../../src/cli/commands/status.ts","../../src/cli/commands/append.ts","../../src/cli/commands/upsert.ts","../../src/session.ts","../../src/cli/commands/mcp.ts","../../src/server/mcp.ts","../../src/server/tools.ts","../../src/cli/commands/config.ts","../../src/cli/commands/sync-init.ts","../../src/cli/sync/central.ts","../../src/cli/sync/registry.ts","../../src/cli/sync/detection.ts","../../src/cli/sync/operations.ts","../../src/cli/sync/state.ts","../../src/cli/sync/conflicts.ts","../../src/cli/commands/conflicts.ts","../../src/cli/commands/push-pull.ts","../../src/cli/commands/daemon.ts","../../src/cli/sync/daemon.ts","../../src/cli/sync/watcher.ts","../../src/cli/sync/validation.ts"],"sourcesContent":["/**\n * Minimem CLI\n *\n * A file-based memory system with vector search for AI agents.\n */\n\nimport { program } from \"commander\";\n\nimport { init } from \"./commands/init.js\";\nimport { search } from \"./commands/search.js\";\nimport { sync } from \"./commands/sync.js\";\nimport { status } from \"./commands/status.js\";\nimport { append } from \"./commands/append.js\";\nimport { upsert } from \"./commands/upsert.js\";\nimport { mcp } from \"./commands/mcp.js\";\nimport { config } from \"./commands/config.js\";\nimport { syncInit, syncInitCentral, syncList, syncRemove } from \"./commands/sync-init.js\";\nimport { pushCommand, pullCommand, syncStatusCommand } from \"./commands/push-pull.js\";\nimport { conflictsCommand, resolveCommand, cleanupCommand, logCommand } from \"./commands/conflicts.js\";\nimport { daemonCommand, daemonStopCommand, daemonStatusCommand, daemonLogsCommand } from \"./commands/daemon.js\";\nimport { validateRegistry, formatValidationResult } from \"./sync/validation.js\";\n\n// Read version from package.json at runtime would require fs\n// For simplicity, hardcode it (update during releases)\nconst VERSION = \"0.0.2\";\n\nprogram\n .name(\"minimem\")\n .description(\"File-based memory system with vector search for AI agents\")\n .version(VERSION);\n\n// minimem init [dir]\nprogram\n .command(\"init [dir]\")\n .description(\"Initialize a memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem as global memory directory\")\n .option(\"-f, --force\", \"Reinitialize even if already initialized\")\n .action(init);\n\n// minimem search <query>\nprogram\n .command(\"search <query>\")\n .description(\"Semantic search through memory files\")\n .option(\"-d, --dir <path...>\", \"Memory directories (can specify multiple)\")\n .option(\"-g, --global\", \"Include ~/.minimem in search\")\n .option(\"-n, --max <number>\", \"Maximum results (default: 10)\")\n .option(\"-s, --min-score <number>\", \"Minimum score threshold 0-1 (default: 0.3)\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"--json\", \"Output results as JSON\")\n .action(search);\n\n// minimem sync\nprogram\n .command(\"sync\")\n .description(\"Force re-index memory files\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --force\", \"Force full re-index\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .action(sync);\n\n// minimem status\nprogram\n .command(\"status\")\n .description(\"Show index stats and provider info\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"--json\", \"Output as JSON\")\n .action(status);\n\n// minimem append <text>\nprogram\n .command(\"append <text>\")\n .description(\"Append text to today's daily log (memory/YYYY-MM-DD.md)\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --file <path>\", \"Append to specific file instead of today's log\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"-s, --session <id>\", \"Session ID to associate with this memory\")\n .option(\"--session-source <name>\", \"Session source (claude-code, vscode, etc.)\")\n .action(append);\n\n// minimem upsert <file> [content]\nprogram\n .command(\"upsert <file> [content]\")\n .description(\"Create or update a memory file\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"--stdin\", \"Read content from stdin\")\n .option(\"-s, --session <id>\", \"Session ID to associate with this memory\")\n .option(\"--session-source <name>\", \"Session source (claude-code, vscode, etc.)\")\n .action(upsert);\n\n// minimem mcp\nprogram\n .command(\"mcp\")\n .description(\"Run as MCP server over stdio (for Claude Desktop, Cursor, etc.)\")\n .option(\"-d, --dir <path...>\", \"Memory directories (can specify multiple)\")\n .option(\"-g, --global\", \"Include ~/.minimem\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .action(mcp);\n\n// minimem config\nprogram\n .command(\"config\")\n .description(\"View or modify configuration\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"--xdg-global\", \"Modify ~/.config/minimem/config.json (for sync settings)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--set <key=value>\", \"Set a config value (e.g., embedding.provider=openai)\")\n .option(\"--unset <key>\", \"Remove a config value\")\n .action(config);\n\n// minimem sync init-central <path>\nprogram\n .command(\"sync:init-central <path>\")\n .description(\"Initialize a central repository for syncing memories\")\n .option(\"-f, --force\", \"Force creation even if directory exists\")\n .action(syncInitCentral);\n\n// minimem sync init\nprogram\n .command(\"sync:init\")\n .description(\"Initialize sync for a memory directory\")\n .option(\"-d, --local <path>\", \"Memory directory to sync\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-p, --path <path>\", \"Path in central repo (e.g., myproject/)\")\n .action(syncInit);\n\n// minimem sync list\nprogram\n .command(\"sync:list\")\n .description(\"List all sync mappings\")\n .action(syncList);\n\n// minimem sync remove\nprogram\n .command(\"sync:remove\")\n .description(\"Remove sync mapping for a directory\")\n .option(\"-d, --local <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .action(syncRemove);\n\n// minimem push\nprogram\n .command(\"push\")\n .description(\"Push local changes to central repository\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --force\", \"Force push (overwrite remote on conflicts)\")\n .option(\"--dry-run\", \"Show what would be pushed without making changes\")\n .action(pushCommand);\n\n// minimem pull\nprogram\n .command(\"pull\")\n .description(\"Pull changes from central repository\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --force\", \"Force pull (overwrite local on conflicts)\")\n .option(\"--dry-run\", \"Show what would be pulled without making changes\")\n .action(pullCommand);\n\n// minimem sync:status\nprogram\n .command(\"sync:status\")\n .description(\"Show sync status for a directory\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .action(syncStatusCommand);\n\n// minimem sync:conflicts\nprogram\n .command(\"sync:conflicts\")\n .description(\"List quarantined conflicts\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"--json\", \"Output as JSON\")\n .action(conflictsCommand);\n\n// minimem sync:resolve <timestamp>\nprogram\n .command(\"sync:resolve <timestamp>\")\n .description(\"Resolve a quarantined conflict using merge tool\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-t, --tool <name>\", \"Merge tool (code, meld, kdiff3, vimdiff)\")\n .action(resolveCommand);\n\n// minimem sync:cleanup\nprogram\n .command(\"sync:cleanup\")\n .description(\"Clean up old quarantined conflicts\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"--days <number>\", \"Remove conflicts older than N days (default: 30)\")\n .option(\"--dry-run\", \"Show what would be removed without removing\")\n .action(cleanupCommand);\n\n// minimem sync:log\nprogram\n .command(\"sync:log\")\n .description(\"Show sync history\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-n, --limit <number>\", \"Number of entries to show (default: 20)\")\n .option(\"--json\", \"Output as JSON\")\n .action(logCommand);\n\n// minimem daemon\nprogram\n .command(\"daemon\")\n .description(\"Start the sync daemon\")\n .option(\"-b, --background\", \"Run in background\")\n .option(\"--foreground\", \"Run in foreground (internal use)\")\n .action(daemonCommand);\n\n// minimem daemon:stop\nprogram\n .command(\"daemon:stop\")\n .description(\"Stop the sync daemon\")\n .action(daemonStopCommand);\n\n// minimem daemon:status\nprogram\n .command(\"daemon:status\")\n .description(\"Show daemon status\")\n .action(daemonStatusCommand);\n\n// minimem daemon:logs\nprogram\n .command(\"daemon:logs\")\n .description(\"Show daemon logs\")\n .option(\"-n, --lines <number>\", \"Number of lines to show (default: 50)\")\n .option(\"-f, --follow\", \"Follow log output\")\n .action(daemonLogsCommand);\n\n// minimem sync:validate\nprogram\n .command(\"sync:validate\")\n .description(\"Validate registry for collisions and stale mappings\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: { json?: boolean }) => {\n try {\n const result = await validateRegistry();\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatValidationResult(result));\n }\n\n if (!result.valid) {\n process.exit(1);\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n\n// Parse and run\nprogram.parse();\n","/**\n * minimem init - Initialize memory directory\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n resolveMemoryDir,\n saveConfig,\n getInitConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nconst MEMORY_TEMPLATE = `# Memory\n\nThis is your memory file. Add notes, decisions, and context here.\n\n## Quick Start\n\n- Add daily logs in the \\`memory/\\` directory (e.g., \\`memory/2024-01-15.md\\`)\n- Use \\`minimem search <query>\\` to find relevant memories\n- Use \\`minimem append <text>\\` to quickly add to today's log\n\n## Notes\n\n`;\n\nexport type InitOptions = {\n global?: boolean;\n force?: boolean;\n};\n\nexport async function init(\n dir: string | undefined,\n options: InitOptions,\n): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir, global: options.global });\n const displayPath = formatPath(memoryDir);\n\n // Check if already initialized\n if (!options.force && (await isInitialized(memoryDir))) {\n console.log(`Already initialized: ${displayPath}`);\n console.log(\"Use --force to reinitialize\");\n return;\n }\n\n console.log(`Initializing minimem in ${displayPath}...`);\n\n // Create directories\n await fs.mkdir(memoryDir, { recursive: true });\n await fs.mkdir(path.join(memoryDir, \"memory\"), { recursive: true });\n await fs.mkdir(path.join(memoryDir, \".minimem\"), { recursive: true });\n\n // Create MEMORY.md if it doesn't exist\n const memoryFilePath = path.join(memoryDir, \"MEMORY.md\");\n try {\n await fs.access(memoryFilePath);\n console.log(\" MEMORY.md already exists, skipping\");\n } catch {\n await fs.writeFile(memoryFilePath, MEMORY_TEMPLATE, \"utf-8\");\n console.log(\" Created MEMORY.md\");\n }\n\n // Create config\n const config = getInitConfig();\n await saveConfig(memoryDir, config);\n console.log(\" Created .minimem/config.json\");\n\n // Create .gitignore for .minimem directory\n const gitignorePath = path.join(memoryDir, \".minimem\", \".gitignore\");\n await fs.writeFile(gitignorePath, \"index.db\\nindex.db-*\\n\", \"utf-8\");\n console.log(\" Created .minimem/.gitignore\");\n\n console.log();\n console.log(\"Done! Your memory directory is ready.\");\n console.log();\n console.log(\"Next steps:\");\n console.log(` 1. Set your embedding API key:`);\n console.log(` export OPENAI_API_KEY=your-key`);\n console.log(` # or: export GOOGLE_API_KEY=your-key`);\n console.log();\n console.log(` 2. Add some memories to MEMORY.md or memory/*.md`);\n console.log();\n console.log(` 3. Search your memories:`);\n console.log(` minimem search \"your query\"${dir ? ` --dir ${dir}` : \"\"}`);\n}\n","/**\n * CLI configuration loading and directory resolution\n *\n * Config resolution order (later overrides earlier):\n * 1. Built-in defaults\n * 2. Global config (~/.minimem/config.json)\n * 3. Local config (.minimem/config.json in memory directory)\n * 4. CLI flags and environment variables\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport crypto from \"node:crypto\";\n\nimport type { MinimemConfig } from \"../minimem.js\";\nimport type { EmbeddingProviderOptions } from \"../embeddings/embeddings.js\";\n\nconst CONFIG_FILENAME = \"config.json\";\nconst CONFIG_DIR = \".minimem\";\nconst GLOBAL_DIR = \".minimem\";\n// XDG-style global config directory for sync settings\nconst XDG_CONFIG_DIR = \".config/minimem\";\n\nexport type CliConfig = {\n embedding?: {\n /** Embedding provider: \"auto\", \"openai\", \"gemini\", \"local\", \"none\" */\n provider?: EmbeddingProviderOptions[\"provider\"];\n /** Model name (provider-specific) */\n model?: string;\n /** Fallback provider if primary fails */\n fallback?: EmbeddingProviderOptions[\"fallback\"];\n /** OpenAI-specific settings */\n openai?: {\n apiKey?: string;\n baseUrl?: string;\n model?: string;\n };\n /** Gemini-specific settings */\n gemini?: {\n apiKey?: string;\n baseUrl?: string;\n model?: string;\n };\n /** Local embedding settings */\n local?: {\n modelPath?: string;\n modelCacheDir?: string;\n };\n };\n hybrid?: {\n /** Enable hybrid search (vector + BM25) */\n enabled?: boolean;\n /** Weight for vector search results (0-1) */\n vectorWeight?: number;\n /** Weight for text/BM25 search results (0-1) */\n textWeight?: number;\n };\n query?: {\n /** Default max results */\n maxResults?: number;\n /** Default min score threshold (0-1) */\n minScore?: number;\n };\n watch?: {\n /** Enable file watching */\n enabled?: boolean;\n /** Debounce delay in ms */\n debounceMs?: number;\n };\n chunking?: {\n /** Target tokens per chunk */\n tokens?: number;\n /** Overlap tokens between chunks */\n overlap?: number;\n };\n /** Sync configuration (for git-based syncing) */\n sync?: {\n /** Enable sync for this directory */\n enabled?: boolean;\n /** Path in central repo for this directory's memories */\n path?: string;\n /** Glob patterns for files to include in sync */\n include?: string[];\n /** Glob patterns for files to exclude from sync */\n exclude?: string[];\n };\n};\n\n/**\n * Global config stored at ~/.config/minimem/config.json\n * Contains settings that apply across all memory directories\n */\nexport type GlobalConfig = {\n /** Path to central repository for syncing */\n centralRepo?: string;\n /** Unique machine identifier for registry */\n machineId?: string;\n /** Global sync settings */\n sync?: {\n /** Default conflict resolution strategy */\n conflictStrategy?: \"keep-both\" | \"merge\" | \"manual\" | \"last-write-wins\";\n /** Enable automatic sync when daemon is running */\n autoSync?: boolean;\n /** Automatically commit changes to central repo */\n autoCommit?: boolean;\n /** External merge resolver command */\n mergeResolver?: string;\n };\n /** Embedding and other settings can be inherited */\n embedding?: CliConfig[\"embedding\"];\n hybrid?: CliConfig[\"hybrid\"];\n query?: CliConfig[\"query\"];\n chunking?: CliConfig[\"chunking\"];\n};\n\nexport type ResolvedConfig = {\n memoryDir: string;\n config: CliConfig;\n};\n\n/**\n * Resolve the memory directory based on options\n *\n * Priority:\n * 1. --dir flag\n * 2. MEMORY_DIR environment variable\n * 3. --global flag → ~/.minimem\n * 4. Current working directory\n */\nexport function resolveMemoryDir(options: {\n dir?: string;\n global?: boolean;\n}): string {\n if (options.dir) {\n return path.resolve(options.dir);\n }\n\n const envDir = process.env.MEMORY_DIR;\n if (envDir) {\n return path.resolve(envDir);\n }\n\n if (options.global) {\n return path.join(os.homedir(), \".minimem\");\n }\n\n return process.cwd();\n}\n\n/**\n * Get the global config directory path (~/.minimem)\n */\nexport function getGlobalDir(): string {\n return path.join(os.homedir(), GLOBAL_DIR);\n}\n\n/**\n * Get the global config file path (~/.minimem/.minimem/config.json)\n * Note: Global directory follows same structure as other memory directories\n */\nexport function getGlobalConfigPath(): string {\n return path.join(getGlobalDir(), CONFIG_DIR, CONFIG_FILENAME);\n}\n\n/**\n * Get the config file path for a memory directory\n */\nexport function getConfigPath(memoryDir: string): string {\n return path.join(memoryDir, CONFIG_DIR, CONFIG_FILENAME);\n}\n\n/**\n * Get the XDG-style global config directory (~/.config/minimem)\n */\nexport function getXdgConfigDir(): string {\n return path.join(os.homedir(), XDG_CONFIG_DIR);\n}\n\n/**\n * Get the XDG-style global config file path (~/.config/minimem/config.json)\n */\nexport function getXdgConfigPath(): string {\n return path.join(getXdgConfigDir(), CONFIG_FILENAME);\n}\n\n/**\n * Expand ~ to home directory in paths\n */\nexport function expandPath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filePath.slice(2));\n }\n if (filePath === \"~\") {\n return os.homedir();\n }\n return filePath;\n}\n\n/**\n * Load XDG global config from ~/.config/minimem/config.json\n */\nexport async function loadXdgConfig(): Promise<GlobalConfig> {\n try {\n const content = await fs.readFile(getXdgConfigPath(), \"utf-8\");\n return JSON.parse(content) as GlobalConfig;\n } catch {\n return {};\n }\n}\n\n/**\n * Save XDG global config to ~/.config/minimem/config.json\n */\nexport async function saveXdgConfig(config: GlobalConfig): Promise<void> {\n const configDir = getXdgConfigDir();\n const configPath = getXdgConfigPath();\n\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Get or generate a unique machine ID\n * Format: {hostname}-{random4hex}\n * Stored in XDG global config\n */\nexport async function getMachineId(): Promise<string> {\n const globalConfig = await loadXdgConfig();\n\n if (globalConfig.machineId) {\n return globalConfig.machineId;\n }\n\n // Generate new machine ID\n const hostname = os.hostname().toLowerCase().replace(/[^a-z0-9-]/g, \"-\");\n const suffix = crypto.randomBytes(2).toString(\"hex\");\n const machineId = `${hostname}-${suffix}`;\n\n // Save to global config\n await saveXdgConfig({ ...globalConfig, machineId });\n\n return machineId;\n}\n\n/**\n * Get the central repo path from global config (expanded)\n */\nexport async function getCentralRepo(): Promise<string | undefined> {\n const globalConfig = await loadXdgConfig();\n if (globalConfig.centralRepo) {\n return expandPath(globalConfig.centralRepo);\n }\n return undefined;\n}\n\n/**\n * Set the central repo path in global config\n */\nexport async function setCentralRepo(repoPath: string): Promise<void> {\n const globalConfig = await loadXdgConfig();\n globalConfig.centralRepo = repoPath;\n await saveXdgConfig(globalConfig);\n}\n\n/**\n * Load config from a specific file path\n */\nasync function loadConfigFile(configPath: string): Promise<CliConfig> {\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as CliConfig;\n } catch {\n return {};\n }\n}\n\n/**\n * Load global config from ~/.minimem/config.json\n */\nexport async function loadGlobalConfig(): Promise<CliConfig> {\n return loadConfigFile(getGlobalConfigPath());\n}\n\n/**\n * Load config from a memory directory, layered on top of global config\n *\n * Resolution order:\n * 1. Built-in defaults\n * 2. Global config (~/.minimem/config.json)\n * 3. Local config (.minimem/config.json in memory directory)\n */\nexport async function loadConfig(memoryDir: string): Promise<CliConfig> {\n const globalDir = getGlobalDir();\n const isGlobalDir = path.resolve(memoryDir) === globalDir;\n\n // Load global config (unless we're loading the global dir itself)\n const globalConfig = isGlobalDir ? {} : await loadGlobalConfig();\n\n // Load local config\n const localConfig = await loadConfigFile(getConfigPath(memoryDir));\n\n // Deep merge: local overrides global\n return deepMergeConfig(globalConfig, localConfig);\n}\n\n/**\n * Deep merge two configs (source overrides target)\n */\nfunction deepMergeConfig(target: CliConfig, source: CliConfig): CliConfig {\n const result: CliConfig = { ...target };\n\n if (source.embedding) {\n result.embedding = {\n ...target.embedding,\n ...source.embedding,\n openai: source.embedding.openai\n ? { ...target.embedding?.openai, ...source.embedding.openai }\n : target.embedding?.openai,\n gemini: source.embedding.gemini\n ? { ...target.embedding?.gemini, ...source.embedding.gemini }\n : target.embedding?.gemini,\n local: source.embedding.local\n ? { ...target.embedding?.local, ...source.embedding.local }\n : target.embedding?.local,\n };\n }\n\n if (source.hybrid) {\n result.hybrid = { ...target.hybrid, ...source.hybrid };\n }\n\n if (source.query) {\n result.query = { ...target.query, ...source.query };\n }\n\n if (source.watch) {\n result.watch = { ...target.watch, ...source.watch };\n }\n\n if (source.chunking) {\n result.chunking = { ...target.chunking, ...source.chunking };\n }\n\n if (source.sync) {\n result.sync = { ...target.sync, ...source.sync };\n // Arrays should be replaced, not merged\n if (source.sync.include) {\n result.sync.include = source.sync.include;\n }\n if (source.sync.exclude) {\n result.sync.exclude = source.sync.exclude;\n }\n }\n\n return result;\n}\n\n/**\n * Save config to a memory directory\n */\nexport async function saveConfig(\n memoryDir: string,\n config: CliConfig,\n): Promise<void> {\n const configDir = path.join(memoryDir, CONFIG_DIR);\n const configPath = getConfigPath(memoryDir);\n\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Get default config with all settings\n */\nexport function getDefaultConfig(): CliConfig {\n return {\n embedding: {\n provider: \"auto\",\n // model is provider-specific, so no default here\n // fallback: \"none\" is implicit\n },\n hybrid: {\n enabled: true,\n vectorWeight: 0.7,\n textWeight: 0.3,\n },\n query: {\n maxResults: 10,\n minScore: 0.3,\n },\n chunking: {\n tokens: 256,\n overlap: 32,\n },\n };\n}\n\n/**\n * Get default sync configuration\n */\nexport function getDefaultSyncConfig(): NonNullable<CliConfig[\"sync\"]> {\n return {\n enabled: false,\n include: [\"MEMORY.md\", \"memory/**/*.md\"],\n exclude: [],\n };\n}\n\n/**\n * Get default global sync settings\n */\nexport function getDefaultGlobalSyncConfig(): NonNullable<GlobalConfig[\"sync\"]> {\n return {\n conflictStrategy: \"keep-both\",\n autoSync: false,\n autoCommit: false,\n };\n}\n\n/**\n * Load full config including XDG global settings\n * Resolution order:\n * 1. Built-in defaults\n * 2. XDG global config (~/.config/minimem/config.json)\n * 3. Legacy global config (~/.minimem/.minimem/config.json)\n * 4. Local config (.minimem/config.json in memory directory)\n */\nexport async function loadFullConfig(memoryDir: string): Promise<{\n local: CliConfig;\n global: GlobalConfig;\n merged: CliConfig;\n}> {\n const globalDir = getGlobalDir();\n const isGlobalDir = path.resolve(memoryDir) === globalDir;\n\n // Load XDG global config\n const xdgConfig = await loadXdgConfig();\n\n // Load legacy global config (unless we're loading the global dir itself)\n const legacyGlobalConfig = isGlobalDir ? {} : await loadGlobalConfig();\n\n // Load local config\n const localConfig = await loadConfigFile(getConfigPath(memoryDir));\n\n // Merge: XDG → legacy global → local\n const merged = deepMergeConfig(\n deepMergeConfig(xdgConfig as CliConfig, legacyGlobalConfig),\n localConfig\n );\n\n return {\n local: localConfig,\n global: xdgConfig,\n merged,\n };\n}\n\n/**\n * Get sync config for a directory with defaults applied\n */\nexport async function getSyncConfig(memoryDir: string): Promise<{\n enabled: boolean;\n path?: string;\n include: string[];\n exclude: string[];\n centralRepo?: string;\n conflictStrategy: NonNullable<GlobalConfig[\"sync\"]>[\"conflictStrategy\"];\n autoSync: boolean;\n autoCommit: boolean;\n mergeResolver?: string;\n}> {\n const { merged, global: xdgConfig } = await loadFullConfig(memoryDir);\n const defaults = getDefaultSyncConfig();\n const globalDefaults = getDefaultGlobalSyncConfig();\n\n return {\n enabled: merged.sync?.enabled ?? defaults.enabled ?? false,\n path: merged.sync?.path,\n include: merged.sync?.include ?? defaults.include,\n exclude: merged.sync?.exclude ?? defaults.exclude,\n centralRepo: xdgConfig.centralRepo ? expandPath(xdgConfig.centralRepo) : undefined,\n conflictStrategy: xdgConfig.sync?.conflictStrategy ?? globalDefaults.conflictStrategy,\n autoSync: xdgConfig.sync?.autoSync ?? globalDefaults.autoSync,\n autoCommit: xdgConfig.sync?.autoCommit ?? globalDefaults.autoCommit,\n mergeResolver: xdgConfig.sync?.mergeResolver,\n };\n}\n\n/**\n * Get a minimal config for new directories (doesn't include all defaults)\n * This is what gets written to config.json on init\n */\nexport function getInitConfig(): CliConfig {\n return {\n embedding: {\n provider: \"auto\",\n },\n hybrid: {\n enabled: true,\n vectorWeight: 0.7,\n textWeight: 0.3,\n },\n query: {\n maxResults: 10,\n minScore: 0.3,\n },\n };\n}\n\n/**\n * Merge configs with defaults\n */\nexport function mergeConfig(config: CliConfig): CliConfig {\n const defaults = getDefaultConfig();\n return deepMergeConfig(defaults, config);\n}\n\n/**\n * Build MinimemConfig from CLI config and options\n */\nexport function buildMinimemConfig(\n memoryDir: string,\n cliConfig: CliConfig,\n options?: {\n provider?: string;\n watch?: boolean;\n },\n): MinimemConfig {\n const merged = mergeConfig(cliConfig);\n\n // Resolve embedding provider (CLI flag > config > default)\n const embeddingProvider = (options?.provider ||\n merged.embedding?.provider ||\n \"auto\") as EmbeddingProviderOptions[\"provider\"];\n\n // Build embedding options, using provider-specific model if set\n const providerModel =\n embeddingProvider === \"openai\"\n ? merged.embedding?.openai?.model\n : embeddingProvider === \"gemini\"\n ? merged.embedding?.gemini?.model\n : undefined;\n\n const embedding: EmbeddingProviderOptions = {\n provider: embeddingProvider,\n model: merged.embedding?.model || providerModel,\n fallback: merged.embedding?.fallback,\n openai: merged.embedding?.openai,\n gemini: merged.embedding?.gemini,\n local: merged.embedding?.local,\n };\n\n return {\n memoryDir,\n embedding,\n hybrid: merged.hybrid,\n query: merged.query,\n chunking: merged.chunking,\n watch: {\n enabled: options?.watch ?? false, // Disable watching by default in CLI\n },\n };\n}\n\n/**\n * Check if a directory is initialized as a minimem memory directory\n */\nexport async function isInitialized(memoryDir: string): Promise<boolean> {\n const configPath = getConfigPath(memoryDir);\n try {\n await fs.access(configPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Format a path for display (use ~ for home directory)\n */\nexport function formatPath(filePath: string): string {\n const home = os.homedir();\n if (filePath.startsWith(home)) {\n return \"~\" + filePath.slice(home.length);\n }\n return filePath;\n}\n","/**\n * minimem search - Semantic search through memory\n *\n * Supports searching across multiple memory directories in a single query.\n */\n\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { Minimem, type SearchResult } from \"../../minimem.js\";\nimport {\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type SearchOptions = {\n dir?: string[];\n global?: boolean;\n max?: string;\n minScore?: string;\n provider?: string;\n json?: boolean;\n};\n\ntype SearchResultWithSource = SearchResult & {\n memoryDir: string;\n};\n\nexport async function search(\n query: string,\n options: SearchOptions,\n): Promise<void> {\n // Collect all directories to search\n const directories = resolveSearchDirectories(options);\n\n if (directories.length === 0) {\n console.error(\"Error: No memory directories specified.\");\n console.error(\"Use --dir <path> or --global to specify directories to search.\");\n process.exit(1);\n }\n\n // Validate all directories are initialized\n const validDirs: string[] = [];\n for (const dir of directories) {\n if (await isInitialized(dir)) {\n validDirs.push(dir);\n } else {\n console.error(`Warning: ${formatPath(dir)} is not initialized, skipping.`);\n }\n }\n\n if (validDirs.length === 0) {\n console.error(\"Error: No valid initialized memory directories found.\");\n process.exit(1);\n }\n\n const maxResults = options.max ? parseInt(options.max, 10) : 10;\n const minScore = options.minScore ? parseFloat(options.minScore) : undefined;\n\n // Search each directory and collect results\n const allResults: SearchResultWithSource[] = [];\n const instances: Minimem[] = [];\n\n let warnedBm25 = false;\n\n try {\n for (const memoryDir of validDirs) {\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n const minimem = await Minimem.create(config);\n instances.push(minimem);\n\n // Warn once if running in BM25-only mode\n if (!warnedBm25) {\n const status = await minimem.status();\n if (status.bm25Only) {\n console.error(\"Note: Running in BM25-only mode (no embedding API configured).\");\n console.error(\" Results are based on keyword matching only.\\n\");\n warnedBm25 = true;\n }\n }\n\n // Get more results per directory, then merge and trim\n const perDirMax = Math.ceil(maxResults * 1.5);\n const results = await minimem.search(query, { maxResults: perDirMax, minScore });\n\n // Add source directory to each result\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir,\n });\n }\n }\n\n // Sort by score descending and limit to maxResults\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n console.log(\"No results found.\");\n return;\n }\n\n if (options.json) {\n console.log(JSON.stringify(topResults, null, 2));\n return;\n }\n\n // Format results for terminal\n const showSource = validDirs.length > 1;\n\n for (const result of topResults) {\n const score = (result.score * 100).toFixed(1);\n const location = `${result.path}:${result.startLine}-${result.endLine}`;\n\n if (showSource) {\n console.log(`[${score}%] ${formatPath(result.memoryDir)}`);\n console.log(` ${location}`);\n } else {\n console.log(`[${score}%] ${location}`);\n }\n console.log(formatSnippet(result.snippet));\n console.log();\n }\n\n const dirSummary = validDirs.length > 1\n ? ` across ${validDirs.length} directories`\n : \"\";\n console.log(`Found ${topResults.length} result${topResults.length === 1 ? \"\" : \"s\"}${dirSummary}`);\n } finally {\n // Clean up all instances\n for (const instance of instances) {\n instance.close();\n }\n }\n}\n\n/**\n * Resolve all directories to search based on options\n */\nfunction resolveSearchDirectories(options: SearchOptions): string[] {\n const dirs: string[] = [];\n\n // Add explicit directories\n if (options.dir && options.dir.length > 0) {\n for (const dir of options.dir) {\n dirs.push(path.resolve(dir));\n }\n }\n\n // Add global directory if --global flag is set\n if (options.global) {\n const globalDir = path.join(os.homedir(), \".minimem\");\n if (!dirs.includes(globalDir)) {\n dirs.push(globalDir);\n }\n }\n\n // If no directories specified, use current directory\n if (dirs.length === 0) {\n dirs.push(process.cwd());\n }\n\n return dirs;\n}\n\n/**\n * Format snippet for terminal display\n */\nfunction formatSnippet(snippet: string): string {\n const lines = snippet.split(\"\\n\");\n const formatted = lines.map((line) => ` ${line}`).join(\"\\n\");\n\n // Truncate if too long\n if (formatted.length > 500) {\n return formatted.slice(0, 497) + \"...\";\n }\n\n return formatted;\n}\n","import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\n\nimport {\n buildFileEntry,\n chunkMarkdown,\n ensureDir,\n hashText,\n listMemoryFiles,\n type MemoryChunk,\n type MemoryFileEntry,\n parseEmbedding,\n} from \"./internal.js\";\nimport { bm25RankToScore, buildFtsQuery, mergeHybridResults } from \"./search/hybrid.js\";\nimport { searchKeyword, searchVector } from \"./search/search.js\";\nimport { ensureMemoryIndexSchema } from \"./db/schema.js\";\nimport { loadSqliteVecExtension } from \"./db/sqlite-vec.js\";\nimport {\n createEmbeddingProvider,\n type EmbeddingProvider,\n type EmbeddingProviderOptions,\n type OpenAiEmbeddingClient,\n type GeminiEmbeddingClient,\n} from \"./embeddings/embeddings.js\";\nimport { runOpenAiEmbeddingBatches, type OpenAiBatchRequest, OPENAI_BATCH_ENDPOINT } from \"./embeddings/batch-openai.js\";\nimport { runGeminiEmbeddingBatches, type GeminiBatchRequest } from \"./embeddings/batch-gemini.js\";\n\nconst META_KEY = \"memory_index_meta_v1\";\nconst SNIPPET_MAX_CHARS = 700;\nconst VECTOR_TABLE = \"chunks_vec\";\nconst FTS_TABLE = \"chunks_fts\";\nconst EMBEDDING_CACHE_TABLE = \"embedding_cache\";\nconst EMBEDDING_BATCH_MAX_TOKENS = 8000;\nconst EMBEDDING_APPROX_CHARS_PER_TOKEN = 1;\nconst EMBEDDING_INDEX_CONCURRENCY = 4;\nconst EMBEDDING_RETRY_MAX_ATTEMPTS = 3;\nconst EMBEDDING_RETRY_BASE_DELAY_MS = 500;\nconst EMBEDDING_RETRY_MAX_DELAY_MS = 8000;\nconst VECTOR_LOAD_TIMEOUT_MS = 30_000;\nconst EMBEDDING_QUERY_TIMEOUT_REMOTE_MS = 60_000;\nconst EMBEDDING_QUERY_TIMEOUT_LOCAL_MS = 5 * 60_000;\n\nconst vectorToBlob = (embedding: number[]): Buffer =>\n Buffer.from(new Float32Array(embedding).buffer);\n\nexport type MinimemConfig = {\n /** Directory containing memory files (MEMORY.md, memory/*.md) */\n memoryDir: string;\n /** Path to SQLite database. Defaults to memoryDir/.minimem/index.db */\n dbPath?: string;\n /** Embedding provider options */\n embedding: EmbeddingProviderOptions;\n /** Chunking configuration */\n chunking?: {\n /** Tokens per chunk (default: 256) */\n tokens?: number;\n /** Overlap tokens between chunks (default: 32) */\n overlap?: number;\n };\n /** Embedding cache configuration */\n cache?: {\n /** Enable embedding cache (default: true) */\n enabled?: boolean;\n /** Max cache entries before LRU pruning (default: 10000) */\n maxEntries?: number;\n };\n /** Hybrid search configuration */\n hybrid?: {\n /** Enable hybrid search (default: true) */\n enabled?: boolean;\n /** Weight for vector search (default: 0.7) */\n vectorWeight?: number;\n /** Weight for keyword search (default: 0.3) */\n textWeight?: number;\n /** Candidate multiplier for search (default: 2.0) */\n candidateMultiplier?: number;\n };\n /** Query configuration */\n query?: {\n /** Max results (default: 10) */\n maxResults?: number;\n /** Min score threshold (default: 0.3) */\n minScore?: number;\n };\n /** File watching configuration */\n watch?: {\n /** Enable file watching (default: true) */\n enabled?: boolean;\n /** Debounce delay in ms (default: 1000) */\n debounceMs?: number;\n };\n /** Batch embedding configuration */\n batch?: {\n /** Enable batch embedding API (default: false) */\n enabled?: boolean;\n /** Wait for batch completion (default: true) */\n wait?: boolean;\n /** Concurrent batch requests (default: 2) */\n concurrency?: number;\n /** Poll interval in ms (default: 2000) */\n pollIntervalMs?: number;\n /** Timeout in ms (default: 60 minutes) */\n timeoutMs?: number;\n };\n /** sqlite-vec extension path (optional) */\n vectorExtensionPath?: string;\n /** Debug logging function */\n debug?: (message: string, data?: Record<string, unknown>) => void;\n};\n\nexport type MinimemSearchResult = {\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n};\n\ntype MemoryIndexMeta = {\n model: string;\n provider: string;\n providerKey?: string;\n chunkTokens: number;\n chunkOverlap: number;\n vectorDims?: number;\n};\n\nexport class Minimem {\n private readonly memoryDir: string;\n private readonly dbPath: string;\n private readonly chunking: { tokens: number; overlap: number };\n private readonly cache: { enabled: boolean; maxEntries: number };\n private readonly hybrid: {\n enabled: boolean;\n vectorWeight: number;\n textWeight: number;\n candidateMultiplier: number;\n };\n private readonly queryConfig: { maxResults: number; minScore: number };\n private readonly watchConfig: { enabled: boolean; debounceMs: number };\n private readonly batchConfig: {\n enabled: boolean;\n wait: boolean;\n concurrency: number;\n pollIntervalMs: number;\n timeoutMs: number;\n };\n private readonly vectorExtensionPath?: string;\n private readonly debug?: (message: string, data?: Record<string, unknown>) => void;\n\n private provider!: EmbeddingProvider;\n private openAi?: OpenAiEmbeddingClient;\n private gemini?: GeminiEmbeddingClient;\n private providerKey: string = \"\";\n private providerFallbackReason?: string;\n private db!: DatabaseSync;\n\n private readonly vector: {\n enabled: boolean;\n available: boolean | null;\n extensionPath?: string;\n loadError?: string;\n dims?: number;\n };\n private readonly fts: {\n enabled: boolean;\n available: boolean;\n loadError?: string;\n };\n\n private vectorReady: Promise<boolean> | null = null;\n private watcher: FSWatcher | null = null;\n private watchTimer: NodeJS.Timeout | null = null;\n private closed = false;\n private dirty = true;\n private syncing: Promise<void> | null = null;\n private embeddingOptions: EmbeddingProviderOptions;\n\n private constructor(config: MinimemConfig) {\n this.memoryDir = path.resolve(config.memoryDir);\n this.dbPath = config.dbPath ?? path.join(this.memoryDir, \".minimem\", \"index.db\");\n this.chunking = {\n tokens: config.chunking?.tokens ?? 256,\n overlap: config.chunking?.overlap ?? 32,\n };\n this.cache = {\n enabled: config.cache?.enabled ?? true,\n maxEntries: config.cache?.maxEntries ?? 10000,\n };\n this.hybrid = {\n enabled: config.hybrid?.enabled ?? true,\n vectorWeight: config.hybrid?.vectorWeight ?? 0.7,\n textWeight: config.hybrid?.textWeight ?? 0.3,\n candidateMultiplier: config.hybrid?.candidateMultiplier ?? 2.0,\n };\n this.queryConfig = {\n maxResults: config.query?.maxResults ?? 10,\n minScore: config.query?.minScore ?? 0.3,\n };\n this.watchConfig = {\n enabled: config.watch?.enabled ?? true,\n debounceMs: config.watch?.debounceMs ?? 1000,\n };\n this.batchConfig = {\n enabled: config.batch?.enabled ?? false,\n wait: config.batch?.wait ?? true,\n concurrency: config.batch?.concurrency ?? 2,\n pollIntervalMs: config.batch?.pollIntervalMs ?? 2000,\n timeoutMs: config.batch?.timeoutMs ?? 60 * 60 * 1000,\n };\n this.vectorExtensionPath = config.vectorExtensionPath;\n this.debug = config.debug;\n this.embeddingOptions = config.embedding;\n\n this.vector = {\n enabled: true,\n available: null,\n extensionPath: this.vectorExtensionPath,\n };\n this.fts = { enabled: this.hybrid.enabled, available: false };\n }\n\n static async create(config: MinimemConfig): Promise<Minimem> {\n const instance = new Minimem(config);\n await instance.initialize();\n return instance;\n }\n\n private async initialize(): Promise<void> {\n // Create embedding provider\n const providerResult = await createEmbeddingProvider(this.embeddingOptions);\n this.provider = providerResult.provider;\n this.openAi = providerResult.openAi;\n this.gemini = providerResult.gemini;\n this.providerKey = this.computeProviderKey();\n this.providerFallbackReason = providerResult.fallbackReason;\n\n // Log warning if in BM25-only fallback mode\n if (this.provider.id === \"none\") {\n this.debug?.(\"Running in BM25-only mode (no embedding API available)\");\n }\n\n // Open database\n this.db = this.openDatabase();\n this.ensureSchema();\n\n // Check for existing vector dims\n const meta = this.readMeta();\n if (meta?.vectorDims) {\n this.vector.dims = meta.vectorDims;\n }\n\n // Start file watcher\n if (this.watchConfig.enabled) {\n this.ensureWatcher();\n }\n }\n\n private openDatabase(): DatabaseSync {\n const dbDir = path.dirname(this.dbPath);\n ensureDir(dbDir);\n return new DatabaseSync(this.dbPath);\n }\n\n private ensureSchema(): void {\n const result = ensureMemoryIndexSchema({\n db: this.db,\n embeddingCacheTable: EMBEDDING_CACHE_TABLE,\n ftsTable: FTS_TABLE,\n ftsEnabled: this.fts.enabled,\n });\n this.fts.available = result.ftsAvailable;\n if (result.ftsError) {\n this.fts.loadError = result.ftsError;\n }\n }\n\n private computeProviderKey(): string {\n const parts: string[] = [this.provider.id, this.provider.model];\n if (this.openAi) {\n parts.push(this.openAi.baseUrl);\n }\n if (this.gemini) {\n parts.push(this.gemini.baseUrl);\n }\n return hashText(parts.join(\":\"));\n }\n\n private readMeta(): MemoryIndexMeta | null {\n try {\n const row = this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(META_KEY) as\n | { value: string }\n | undefined;\n if (!row?.value) return null;\n return JSON.parse(row.value) as MemoryIndexMeta;\n } catch {\n return null;\n }\n }\n\n private writeMeta(meta: MemoryIndexMeta): void {\n this.db\n .prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)`)\n .run(META_KEY, JSON.stringify(meta));\n }\n\n private ensureWatcher(): void {\n if (this.watcher) return;\n const memorySubDir = path.join(this.memoryDir, \"memory\");\n const memoryFile = path.join(this.memoryDir, \"MEMORY.md\");\n\n this.watcher = chokidar.watch([memoryFile, memorySubDir], {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },\n });\n\n const scheduleSync = () => {\n this.dirty = true;\n if (this.watchTimer) clearTimeout(this.watchTimer);\n this.watchTimer = setTimeout(() => {\n void this.sync({ reason: \"watch\" }).catch((err) => {\n this.debug?.(`memory sync failed (watch): ${String(err)}`);\n });\n }, this.watchConfig.debounceMs);\n };\n\n this.watcher.on(\"add\", scheduleSync);\n this.watcher.on(\"change\", scheduleSync);\n this.watcher.on(\"unlink\", scheduleSync);\n }\n\n /**\n * Check if the index is stale by comparing file mtimes against stored values.\n * This is a lightweight check (stat calls only, no file reads).\n */\n private async isStale(): Promise<boolean> {\n try {\n const files = await listMemoryFiles(this.memoryDir);\n\n // Get stored file records\n const stored = this.db\n .prepare(`SELECT path, mtime FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string; mtime: number }>;\n\n // Quick check: different file count means stale\n if (files.length !== stored.length) {\n this.debug?.(`Stale: file count changed (${stored.length} -> ${files.length})`);\n return true;\n }\n\n // Build lookup map of stored mtimes\n const storedMap = new Map(stored.map((f) => [f.path, f.mtime]));\n\n // Check each file's mtime against stored value\n for (const absPath of files) {\n const relPath = path.relative(this.memoryDir, absPath).replace(/\\\\/g, \"/\");\n const storedMtime = storedMap.get(relPath);\n\n // File not in index = stale\n if (storedMtime === undefined) {\n this.debug?.(`Stale: new file ${relPath}`);\n return true;\n }\n\n // Check mtime\n const stat = await fs.stat(absPath);\n const currentMtime = Math.floor(stat.mtimeMs);\n if (currentMtime !== storedMtime) {\n this.debug?.(`Stale: mtime changed for ${relPath}`);\n return true;\n }\n }\n\n return false;\n } catch (err) {\n // On error, assume stale to be safe\n this.debug?.(`Stale check failed: ${String(err)}`);\n return true;\n }\n }\n\n async search(\n query: string,\n opts?: { maxResults?: number; minScore?: number },\n ): Promise<MinimemSearchResult[]> {\n // Check staleness: use dirty flag if watcher is on, otherwise check mtimes\n if (this.dirty || (!this.watchConfig.enabled && (await this.isStale()))) {\n await this.sync({ reason: \"search\" });\n }\n\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.queryConfig.minScore;\n const maxResults = opts?.maxResults ?? this.queryConfig.maxResults;\n const candidates = Math.min(\n 200,\n Math.max(1, Math.floor(maxResults * this.hybrid.candidateMultiplier)),\n );\n\n const sourceFilter = { sql: \"\", params: [] as string[] };\n\n const keywordResults = this.hybrid.enabled && this.fts.available\n ? await searchKeyword({\n db: this.db,\n ftsTable: FTS_TABLE,\n providerModel: this.provider.model,\n query: cleaned,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n sourceFilter,\n buildFtsQuery,\n bm25RankToScore,\n }).catch(() => [])\n : [];\n\n const queryVec = await this.embedQueryWithTimeout(cleaned);\n const hasVector = queryVec.some((v) => v !== 0);\n const vectorResults = hasVector\n ? await searchVector({\n db: this.db,\n vectorTable: VECTOR_TABLE,\n providerModel: this.provider.model,\n queryVec,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n ensureVectorReady: (dims) => this.ensureVectorReady(dims),\n sourceFilterVec: sourceFilter,\n sourceFilterChunks: sourceFilter,\n }).catch(() => [])\n : [];\n\n if (!this.hybrid.enabled) {\n return vectorResults\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n const merged = mergeHybridResults({\n vector: vectorResults.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.score,\n })),\n keyword: keywordResults.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n textScore: r.textScore,\n })),\n vectorWeight: this.hybrid.vectorWeight,\n textWeight: this.hybrid.textWeight,\n });\n\n return merged\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n async sync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n if (this.syncing) {\n await this.syncing;\n return;\n }\n\n this.syncing = this.runSync(opts);\n try {\n await this.syncing;\n } finally {\n this.syncing = null;\n }\n }\n\n private async runSync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n this.debug?.(`memory sync starting`, { reason: opts?.reason });\n\n await this.ensureVectorReady();\n const meta = this.readMeta();\n const needsFullReindex =\n opts?.force ||\n !meta ||\n meta.model !== this.provider.model ||\n meta.provider !== this.provider.id ||\n meta.providerKey !== this.providerKey ||\n meta.chunkTokens !== this.chunking.tokens ||\n meta.chunkOverlap !== this.chunking.overlap ||\n (this.vector.available && !meta?.vectorDims);\n\n const files = await listMemoryFiles(this.memoryDir);\n const activePaths = new Set<string>();\n\n for (const absPath of files) {\n const entry = await buildFileEntry(absPath, this.memoryDir);\n activePaths.add(entry.path);\n\n const record = this.db\n .prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`)\n .get(entry.path, \"memory\") as { hash: string } | undefined;\n\n if (!needsFullReindex && record?.hash === entry.hash) {\n continue;\n }\n\n await this.indexFile(entry);\n }\n\n // Delete stale entries\n const staleRows = this.db\n .prepare(`SELECT path FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string }>;\n\n for (const stale of staleRows) {\n if (activePaths.has(stale.path)) continue;\n this.db.prepare(`DELETE FROM files WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(stale.path, \"memory\");\n } catch {}\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(stale.path, \"memory\", this.provider.model);\n } catch {}\n }\n }\n\n // Write meta\n this.writeMeta({\n model: this.provider.model,\n provider: this.provider.id,\n providerKey: this.providerKey,\n chunkTokens: this.chunking.tokens,\n chunkOverlap: this.chunking.overlap,\n vectorDims: this.vector.dims,\n });\n\n // Prune embedding cache\n this.pruneEmbeddingCacheIfNeeded();\n\n this.dirty = false;\n this.debug?.(`memory sync complete`, { files: files.length });\n }\n\n private async indexFile(entry: MemoryFileEntry): Promise<void> {\n const content = await fs.readFile(entry.absPath, \"utf-8\");\n const chunks = chunkMarkdown(content, this.chunking);\n\n // Get embeddings\n const embeddings = await this.embedChunks(chunks);\n\n // Update files table\n this.db\n .prepare(\n `INSERT OR REPLACE INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`,\n )\n .run(entry.path, \"memory\", entry.hash, Math.floor(entry.mtimeMs), entry.size);\n\n // Delete old chunks for this file\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(entry.path, \"memory\");\n } catch {}\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(entry.path, \"memory\");\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(entry.path, \"memory\", this.provider.model);\n } catch {}\n }\n\n // Insert new chunks\n const now = Date.now();\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = embeddings[i] ?? [];\n const chunkId = randomUUID();\n\n this.db\n .prepare(\n `INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunkId,\n entry.path,\n \"memory\",\n chunk.startLine,\n chunk.endLine,\n chunk.hash,\n this.provider.model,\n chunk.text,\n JSON.stringify(embedding),\n now,\n );\n\n // Insert into vector table if available\n if (this.vector.available && embedding.length > 0) {\n if (!this.vector.dims) {\n this.vector.dims = embedding.length;\n this.ensureVectorTable(embedding.length);\n }\n try {\n this.db\n .prepare(`INSERT INTO ${VECTOR_TABLE} (id, embedding) VALUES (?, ?)`)\n .run(chunkId, vectorToBlob(embedding));\n } catch {}\n }\n\n // Insert into FTS table if available\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(\n `INSERT INTO ${FTS_TABLE} (text, id, path, source, model, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunk.text,\n chunkId,\n entry.path,\n \"memory\",\n this.provider.model,\n chunk.startLine,\n chunk.endLine,\n );\n } catch {}\n }\n }\n }\n\n private async embedChunks(chunks: MemoryChunk[]): Promise<number[][]> {\n if (chunks.length === 0) return [];\n\n const hashes = chunks.map((c) => c.hash);\n const cached = this.loadEmbeddingCache(hashes);\n const missing: Array<{ index: number; chunk: MemoryChunk }> = [];\n\n for (let i = 0; i < chunks.length; i++) {\n if (!cached.has(hashes[i])) {\n missing.push({ index: i, chunk: chunks[i] });\n }\n }\n\n if (missing.length > 0) {\n const texts = missing.map((m) => m.chunk.text);\n const newEmbeddings = await this.embedBatchWithRetry(texts);\n\n for (let i = 0; i < missing.length; i++) {\n const hash = missing[i].chunk.hash;\n const embedding = newEmbeddings[i] ?? [];\n cached.set(hash, embedding);\n this.upsertEmbeddingCache(hash, embedding);\n }\n }\n\n return hashes.map((h) => cached.get(h) ?? []);\n }\n\n private async embedBatchWithRetry(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n // Try batch API first if enabled\n if (this.batchConfig.enabled) {\n try {\n return await this.embedWithBatchApi(texts);\n } catch (err) {\n this.debug?.(`batch embedding failed, falling back to direct: ${String(err)}`);\n }\n }\n\n // Fall back to direct embedding\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < EMBEDDING_RETRY_MAX_ATTEMPTS; attempt++) {\n try {\n return await this.provider.embedBatch(texts);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < EMBEDDING_RETRY_MAX_ATTEMPTS - 1) {\n const delay = Math.min(\n EMBEDDING_RETRY_MAX_DELAY_MS,\n EMBEDDING_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n }\n\n private async embedWithBatchApi(texts: string[]): Promise<number[][]> {\n if (this.openAi) {\n const requests: OpenAiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n method: \"POST\",\n url: OPENAI_BATCH_ENDPOINT,\n body: { model: this.openAi!.model, input: text },\n }));\n\n const results = await runOpenAiEmbeddingBatches({\n openAi: this.openAi,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n if (this.gemini) {\n const requests: GeminiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n\n const results = await runGeminiEmbeddingBatches({\n gemini: this.gemini,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n throw new Error(\"Batch API not available for local embeddings\");\n }\n\n private async embedQueryWithTimeout(text: string): Promise<number[]> {\n const timeout =\n this.provider.id === \"local\" ? EMBEDDING_QUERY_TIMEOUT_LOCAL_MS : EMBEDDING_QUERY_TIMEOUT_REMOTE_MS;\n\n return Promise.race([\n this.provider.embedQuery(text),\n new Promise<number[]>((_, reject) =>\n setTimeout(() => reject(new Error(\"embedding query timeout\")), timeout),\n ),\n ]);\n }\n\n private loadEmbeddingCache(hashes: string[]): Map<string, number[]> {\n const result = new Map<string, number[]>();\n if (!this.cache.enabled || hashes.length === 0) return result;\n\n const placeholders = hashes.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT hash, embedding FROM ${EMBEDDING_CACHE_TABLE}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${placeholders})`,\n )\n .all(this.provider.id, this.provider.model, this.providerKey, ...hashes) as Array<{\n hash: string;\n embedding: string;\n }>;\n\n const now = Date.now();\n for (const row of rows) {\n result.set(row.hash, parseEmbedding(row.embedding));\n // Touch for LRU\n this.db\n .prepare(\n `UPDATE ${EMBEDDING_CACHE_TABLE} SET updated_at = ?\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash = ?`,\n )\n .run(now, this.provider.id, this.provider.model, this.providerKey, row.hash);\n }\n\n return result;\n }\n\n private upsertEmbeddingCache(hash: string, embedding: number[]): void {\n if (!this.cache.enabled) return;\n const now = Date.now();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO ${EMBEDDING_CACHE_TABLE}\n (provider, model, provider_key, hash, embedding, dims, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n this.provider.id,\n this.provider.model,\n this.providerKey,\n hash,\n JSON.stringify(embedding),\n embedding.length,\n now,\n );\n }\n\n private pruneEmbeddingCacheIfNeeded(): void {\n if (!this.cache.enabled) return;\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n if (row.count <= this.cache.maxEntries) return;\n\n const excess = row.count - this.cache.maxEntries;\n this.db\n .prepare(\n `DELETE FROM ${EMBEDDING_CACHE_TABLE}\n WHERE rowid IN (\n SELECT rowid FROM ${EMBEDDING_CACHE_TABLE}\n ORDER BY updated_at ASC\n LIMIT ?\n )`,\n )\n .run(excess);\n }\n\n private async ensureVectorReady(dimensions?: number): Promise<boolean> {\n if (this.vector.available === true) return true;\n if (this.vector.available === false) return false;\n\n if (!this.vectorReady) {\n this.vectorReady = this.loadVectorExtension();\n }\n\n const ready = await this.vectorReady;\n if (ready && dimensions && !this.vector.dims) {\n this.vector.dims = dimensions;\n this.ensureVectorTable(dimensions);\n }\n return ready;\n }\n\n private async loadVectorExtension(): Promise<boolean> {\n const result = await loadSqliteVecExtension({\n db: this.db,\n extensionPath: this.vectorExtensionPath,\n });\n\n this.vector.available = result.ok;\n if (result.error) {\n this.vector.loadError = result.error;\n this.debug?.(`sqlite-vec load failed: ${result.error}`);\n }\n if (result.extensionPath) {\n this.vector.extensionPath = result.extensionPath;\n }\n\n return result.ok;\n }\n\n private ensureVectorTable(dimensions: number): void {\n if (!this.vector.available) return;\n try {\n this.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${VECTOR_TABLE} USING vec0(\n id TEXT PRIMARY KEY,\n embedding FLOAT[${dimensions}]\n )`,\n );\n } catch (err) {\n this.debug?.(`vector table creation failed: ${String(err)}`);\n }\n }\n\n async readFile(relativePath: string): Promise<string | null> {\n const absPath = path.join(this.memoryDir, relativePath);\n try {\n return await fs.readFile(absPath, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n /**\n * Read specific lines from a memory file\n */\n async readLines(\n relativePath: string,\n opts?: { from?: number; lines?: number },\n ): Promise<{ content: string; startLine: number; endLine: number } | null> {\n const content = await this.readFile(relativePath);\n if (content === null) return null;\n\n const allLines = content.split(\"\\n\");\n const from = Math.max(1, opts?.from ?? 1);\n const lines = opts?.lines ?? allLines.length;\n\n const startIdx = from - 1;\n const endIdx = Math.min(startIdx + lines, allLines.length);\n const selectedLines = allLines.slice(startIdx, endIdx);\n\n return {\n content: selectedLines.join(\"\\n\"),\n startLine: from,\n endLine: startIdx + selectedLines.length,\n };\n }\n\n /**\n * Write content to a memory file (creates or overwrites)\n */\n async writeFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absPath, content, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory write: ${relativePath}`);\n }\n\n /**\n * Append content to a memory file (creates if doesn't exist)\n */\n async appendFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n\n // Ensure newline separation\n let toAppend = content;\n try {\n const existing = await fs.readFile(absPath, \"utf-8\");\n if (existing.length > 0 && !existing.endsWith(\"\\n\")) {\n toAppend = \"\\n\" + content;\n }\n } catch {\n // File doesn't exist, will be created\n }\n\n await fs.appendFile(absPath, toAppend, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory append: ${relativePath}`);\n }\n\n /**\n * Append content to today's daily log (memory/YYYY-MM-DD.md)\n */\n async appendToday(content: string): Promise<string> {\n const today = new Date().toISOString().split(\"T\")[0]; // YYYY-MM-DD\n const relativePath = `memory/${today}.md`;\n await this.appendFile(relativePath, content);\n return relativePath;\n }\n\n /**\n * List all memory files\n */\n async listFiles(): Promise<string[]> {\n const files = await listMemoryFiles(this.memoryDir);\n return files.map((f) => path.relative(this.memoryDir, f).replace(/\\\\/g, \"/\"));\n }\n\n /**\n * Validate that a path is within allowed memory locations\n */\n private validateMemoryPath(relativePath: string): void {\n const normalized = relativePath.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n\n // Allow MEMORY.md at root\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") {\n return;\n }\n\n // Allow anything under memory/\n if (normalized.startsWith(\"memory/\") && normalized.endsWith(\".md\")) {\n // Prevent path traversal\n if (normalized.includes(\"..\")) {\n throw new Error(`Invalid memory path: ${relativePath} (path traversal not allowed)`);\n }\n return;\n }\n\n throw new Error(\n `Invalid memory path: ${relativePath}. Must be MEMORY.md or memory/*.md`,\n );\n }\n\n async status(): Promise<{\n memoryDir: string;\n dbPath: string;\n provider: string;\n model: string;\n vectorAvailable: boolean;\n ftsAvailable: boolean;\n bm25Only: boolean;\n fallbackReason?: string;\n fileCount: number;\n chunkCount: number;\n cacheCount: number;\n }> {\n const fileRow = this.db.prepare(`SELECT COUNT(*) as count FROM files`).get() as { count: number };\n const chunkRow = this.db.prepare(`SELECT COUNT(*) as count FROM chunks`).get() as { count: number };\n const cacheRow = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n\n return {\n memoryDir: this.memoryDir,\n dbPath: this.dbPath,\n provider: this.provider.id,\n model: this.provider.model,\n vectorAvailable: this.vector.available === true,\n ftsAvailable: this.fts.available,\n bm25Only: this.provider.id === \"none\",\n fallbackReason: this.providerFallbackReason,\n fileCount: fileRow.count,\n chunkCount: chunkRow.count,\n cacheCount: cacheRow.count,\n };\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n if (this.watchTimer) {\n clearTimeout(this.watchTimer);\n this.watchTimer = null;\n }\n\n if (this.watcher) {\n void this.watcher.close();\n this.watcher = null;\n }\n\n try {\n this.db.close();\n } catch {}\n }\n}\n","import crypto from \"node:crypto\";\nimport fsSync from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport type MemoryFileEntry = {\n path: string;\n absPath: string;\n mtimeMs: number;\n size: number;\n hash: string;\n};\n\nexport type MemoryChunk = {\n startLine: number;\n endLine: number;\n text: string;\n hash: string;\n};\n\nexport function ensureDir(dir: string): string {\n try {\n fsSync.mkdirSync(dir, { recursive: true });\n } catch {}\n return dir;\n}\n\nexport function normalizeRelPath(value: string): string {\n const trimmed = value.trim().replace(/^[./]+/, \"\");\n return trimmed.replace(/\\\\/g, \"/\");\n}\n\nexport function isMemoryPath(relPath: string): boolean {\n const normalized = normalizeRelPath(relPath);\n if (!normalized) return false;\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") return true;\n return normalized.startsWith(\"memory/\");\n}\n\nasync function exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function walkDir(dir: string, files: string[]) {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await walkDir(full, files);\n continue;\n }\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith(\".md\")) continue;\n files.push(full);\n }\n}\n\nexport async function listMemoryFiles(memoryDir: string): Promise<string[]> {\n const result: string[] = [];\n const memoryFile = path.join(memoryDir, \"MEMORY.md\");\n const altMemoryFile = path.join(memoryDir, \"memory.md\");\n if (await exists(memoryFile)) result.push(memoryFile);\n if (await exists(altMemoryFile)) result.push(altMemoryFile);\n const memorySubDir = path.join(memoryDir, \"memory\");\n if (await exists(memorySubDir)) {\n await walkDir(memorySubDir, result);\n }\n if (result.length <= 1) return result;\n const seen = new Set<string>();\n const deduped: string[] = [];\n for (const entry of result) {\n let key = entry;\n try {\n key = await fs.realpath(entry);\n } catch {}\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(entry);\n }\n return deduped;\n}\n\nexport function hashText(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport async function buildFileEntry(\n absPath: string,\n memoryDir: string,\n): Promise<MemoryFileEntry> {\n const stat = await fs.stat(absPath);\n const content = await fs.readFile(absPath, \"utf-8\");\n const hash = hashText(content);\n return {\n path: path.relative(memoryDir, absPath).replace(/\\\\/g, \"/\"),\n absPath,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n hash,\n };\n}\n\nexport function chunkMarkdown(\n content: string,\n chunking: { tokens: number; overlap: number },\n): MemoryChunk[] {\n const lines = content.split(\"\\n\");\n if (lines.length === 0) return [];\n const maxChars = Math.max(32, chunking.tokens * 4);\n const overlapChars = Math.max(0, chunking.overlap * 4);\n const chunks: MemoryChunk[] = [];\n\n let current: Array<{ line: string; lineNo: number }> = [];\n let currentChars = 0;\n\n const flush = () => {\n if (current.length === 0) return;\n const firstEntry = current[0];\n const lastEntry = current[current.length - 1];\n if (!firstEntry || !lastEntry) return;\n const text = current.map((entry) => entry.line).join(\"\\n\");\n const startLine = firstEntry.lineNo;\n const endLine = lastEntry.lineNo;\n chunks.push({\n startLine,\n endLine,\n text,\n hash: hashText(text),\n });\n };\n\n const carryOverlap = () => {\n if (overlapChars <= 0 || current.length === 0) {\n current = [];\n currentChars = 0;\n return;\n }\n let acc = 0;\n const kept: Array<{ line: string; lineNo: number }> = [];\n for (let i = current.length - 1; i >= 0; i -= 1) {\n const entry = current[i];\n if (!entry) continue;\n acc += entry.line.length + 1;\n kept.unshift(entry);\n if (acc >= overlapChars) break;\n }\n current = kept;\n currentChars = kept.reduce((sum, entry) => sum + entry.line.length + 1, 0);\n };\n\n for (let i = 0; i < lines.length; i += 1) {\n const line = lines[i] ?? \"\";\n const lineNo = i + 1;\n const segments: string[] = [];\n if (line.length === 0) {\n segments.push(\"\");\n } else {\n for (let start = 0; start < line.length; start += maxChars) {\n segments.push(line.slice(start, start + maxChars));\n }\n }\n for (const segment of segments) {\n const lineSize = segment.length + 1;\n if (currentChars + lineSize > maxChars && current.length > 0) {\n flush();\n carryOverlap();\n }\n current.push({ line: segment, lineNo });\n currentChars += lineSize;\n }\n }\n flush();\n return chunks;\n}\n\nexport function parseEmbedding(raw: string): number[] {\n try {\n const parsed = JSON.parse(raw) as number[];\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length === 0 || b.length === 0) return 0;\n const len = Math.min(a.length, b.length);\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < len; i += 1) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 0;\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n\nexport function truncateUtf16Safe(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars);\n}\n","export type HybridSource = string;\n\nexport type HybridVectorResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n};\n\nexport type HybridKeywordResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n textScore: number;\n};\n\nexport function buildFtsQuery(raw: string): string | null {\n const tokens =\n raw\n .match(/[A-Za-z0-9_]+/g)\n ?.map((t) => t.trim())\n .filter(Boolean) ?? [];\n if (tokens.length === 0) return null;\n const quoted = tokens.map((t) => `\"${t.replaceAll('\"', \"\")}\"`);\n return quoted.join(\" AND \");\n}\n\nexport function bm25RankToScore(rank: number): number {\n const normalized = Number.isFinite(rank) ? Math.max(0, rank) : 999;\n return 1 / (1 + normalized);\n}\n\nexport function mergeHybridResults(params: {\n vector: HybridVectorResult[];\n keyword: HybridKeywordResult[];\n vectorWeight: number;\n textWeight: number;\n}): Array<{\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: HybridSource;\n}> {\n const byId = new Map<\n string,\n {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n textScore: number;\n }\n >();\n\n for (const r of params.vector) {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.vectorScore,\n textScore: 0,\n });\n }\n\n for (const r of params.keyword) {\n const existing = byId.get(r.id);\n if (existing) {\n existing.textScore = r.textScore;\n if (r.snippet && r.snippet.length > 0) existing.snippet = r.snippet;\n } else {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: 0,\n textScore: r.textScore,\n });\n }\n }\n\n const merged = Array.from(byId.values()).map((entry) => {\n const score = params.vectorWeight * entry.vectorScore + params.textWeight * entry.textScore;\n return {\n path: entry.path,\n startLine: entry.startLine,\n endLine: entry.endLine,\n score,\n snippet: entry.snippet,\n source: entry.source,\n };\n });\n\n return merged.sort((a, b) => b.score - a.score);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nimport { cosineSimilarity, parseEmbedding, truncateUtf16Safe } from \"../internal.js\";\n\nconst vectorToBlob = (embedding: number[]): Buffer =>\n Buffer.from(new Float32Array(embedding).buffer);\n\nexport type SearchSource = string;\n\nexport type SearchRowResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: SearchSource;\n};\n\nexport async function searchVector(params: {\n db: DatabaseSync;\n vectorTable: string;\n providerModel: string;\n queryVec: number[];\n limit: number;\n snippetMaxChars: number;\n ensureVectorReady: (dimensions: number) => Promise<boolean>;\n sourceFilterVec: { sql: string; params: SearchSource[] };\n sourceFilterChunks: { sql: string; params: SearchSource[] };\n}): Promise<SearchRowResult[]> {\n if (params.queryVec.length === 0 || params.limit <= 0) return [];\n if (await params.ensureVectorReady(params.queryVec.length)) {\n const rows = params.db\n .prepare(\n `SELECT c.id, c.path, c.start_line, c.end_line, c.text,\\n` +\n ` c.source,\\n` +\n ` vec_distance_cosine(v.embedding, ?) AS dist\\n` +\n ` FROM ${params.vectorTable} v\\n` +\n ` JOIN chunks c ON c.id = v.id\\n` +\n ` WHERE c.model = ?${params.sourceFilterVec.sql}\\n` +\n ` ORDER BY dist ASC\\n` +\n ` LIMIT ?`,\n )\n .all(\n vectorToBlob(params.queryVec),\n params.providerModel,\n ...params.sourceFilterVec.params,\n params.limit,\n ) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n source: SearchSource;\n dist: number;\n }>;\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: 1 - row.dist,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n }));\n }\n\n const candidates = listChunks({\n db: params.db,\n providerModel: params.providerModel,\n sourceFilter: params.sourceFilterChunks,\n });\n const scored = candidates\n .map((chunk) => ({\n chunk,\n score: cosineSimilarity(params.queryVec, chunk.embedding),\n }))\n .filter((entry) => Number.isFinite(entry.score));\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, params.limit)\n .map((entry) => ({\n id: entry.chunk.id,\n path: entry.chunk.path,\n startLine: entry.chunk.startLine,\n endLine: entry.chunk.endLine,\n score: entry.score,\n snippet: truncateUtf16Safe(entry.chunk.text, params.snippetMaxChars),\n source: entry.chunk.source,\n }));\n}\n\nexport function listChunks(params: {\n db: DatabaseSync;\n providerModel: string;\n sourceFilter: { sql: string; params: SearchSource[] };\n}): Array<{\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n text: string;\n embedding: number[];\n source: SearchSource;\n}> {\n const rows = params.db\n .prepare(\n `SELECT id, path, start_line, end_line, text, embedding, source\\n` +\n ` FROM chunks\\n` +\n ` WHERE model = ?${params.sourceFilter.sql}`,\n )\n .all(params.providerModel, ...params.sourceFilter.params) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n embedding: string;\n source: SearchSource;\n }>;\n\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n text: row.text,\n embedding: parseEmbedding(row.embedding),\n source: row.source,\n }));\n}\n\nexport async function searchKeyword(params: {\n db: DatabaseSync;\n ftsTable: string;\n providerModel: string;\n query: string;\n limit: number;\n snippetMaxChars: number;\n sourceFilter: { sql: string; params: SearchSource[] };\n buildFtsQuery: (raw: string) => string | null;\n bm25RankToScore: (rank: number) => number;\n}): Promise<Array<SearchRowResult & { textScore: number }>> {\n if (params.limit <= 0) return [];\n const ftsQuery = params.buildFtsQuery(params.query);\n if (!ftsQuery) return [];\n\n const rows = params.db\n .prepare(\n `SELECT id, path, source, start_line, end_line, text,\\n` +\n ` bm25(${params.ftsTable}) AS rank\\n` +\n ` FROM ${params.ftsTable}\\n` +\n ` WHERE ${params.ftsTable} MATCH ? AND model = ?${params.sourceFilter.sql}\\n` +\n ` ORDER BY rank ASC\\n` +\n ` LIMIT ?`,\n )\n .all(ftsQuery, params.providerModel, ...params.sourceFilter.params, params.limit) as Array<{\n id: string;\n path: string;\n source: SearchSource;\n start_line: number;\n end_line: number;\n text: string;\n rank: number;\n }>;\n\n return rows.map((row) => {\n const textScore = params.bm25RankToScore(row.rank);\n return {\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: textScore,\n textScore,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n };\n });\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nexport function ensureMemoryIndexSchema(params: {\n db: DatabaseSync;\n embeddingCacheTable: string;\n ftsTable: string;\n ftsEnabled: boolean;\n}): { ftsAvailable: boolean; ftsError?: string } {\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS files (\n path TEXT PRIMARY KEY,\n source TEXT NOT NULL DEFAULT 'memory',\n hash TEXT NOT NULL,\n mtime INTEGER NOT NULL,\n size INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS chunks (\n id TEXT PRIMARY KEY,\n path TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'memory',\n start_line INTEGER NOT NULL,\n end_line INTEGER NOT NULL,\n hash TEXT NOT NULL,\n model TEXT NOT NULL,\n text TEXT NOT NULL,\n embedding TEXT NOT NULL,\n updated_at INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS ${params.embeddingCacheTable} (\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n provider_key TEXT NOT NULL,\n hash TEXT NOT NULL,\n embedding TEXT NOT NULL,\n dims INTEGER,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (provider, model, provider_key, hash)\n );\n `);\n params.db.exec(\n `CREATE INDEX IF NOT EXISTS idx_embedding_cache_updated_at ON ${params.embeddingCacheTable}(updated_at);`,\n );\n\n let ftsAvailable = false;\n let ftsError: string | undefined;\n if (params.ftsEnabled) {\n try {\n params.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${params.ftsTable} USING fts5(\\n` +\n ` text,\\n` +\n ` id UNINDEXED,\\n` +\n ` path UNINDEXED,\\n` +\n ` source UNINDEXED,\\n` +\n ` model UNINDEXED,\\n` +\n ` start_line UNINDEXED,\\n` +\n ` end_line UNINDEXED\\n` +\n `);`,\n );\n ftsAvailable = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n ftsAvailable = false;\n ftsError = message;\n }\n }\n\n ensureColumn(params.db, \"files\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n ensureColumn(params.db, \"chunks\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);`);\n\n return { ftsAvailable, ...(ftsError ? { ftsError } : {}) };\n}\n\nfunction ensureColumn(\n db: DatabaseSync,\n table: \"files\" | \"chunks\",\n column: string,\n definition: string,\n): void {\n const rows = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n if (rows.some((row) => row.name === column)) return;\n db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nexport async function loadSqliteVecExtension(params: {\n db: DatabaseSync;\n extensionPath?: string;\n}): Promise<{ ok: boolean; extensionPath?: string; error?: string }> {\n try {\n const sqliteVec = await import(\"sqlite-vec\");\n const resolvedPath = params.extensionPath?.trim() ? params.extensionPath.trim() : undefined;\n const extensionPath = resolvedPath ?? sqliteVec.getLoadablePath();\n\n params.db.enableLoadExtension(true);\n if (resolvedPath) {\n params.db.loadExtension(extensionPath);\n } else {\n sqliteVec.load(params.db);\n }\n\n return { ok: true, extensionPath };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n","import fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nimport type { Llama, LlamaEmbeddingContext, LlamaModel } from \"node-llama-cpp\";\n\nexport type EmbeddingProvider = {\n id: string;\n model: string;\n embedQuery: (text: string) => Promise<number[]>;\n embedBatch: (texts: string[]) => Promise<number[][]>;\n};\n\nexport type EmbeddingProviderResult = {\n provider: EmbeddingProvider;\n requestedProvider: \"openai\" | \"local\" | \"gemini\" | \"auto\";\n fallbackFrom?: \"openai\" | \"local\" | \"gemini\";\n fallbackReason?: string;\n openAi?: OpenAiEmbeddingClient;\n gemini?: GeminiEmbeddingClient;\n};\n\nexport type EmbeddingProviderOptions = {\n provider: \"openai\" | \"local\" | \"gemini\" | \"auto\" | \"none\";\n model?: string;\n fallback?: \"openai\" | \"gemini\" | \"local\" | \"none\";\n openai?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n gemini?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n local?: {\n modelPath?: string;\n modelCacheDir?: string;\n };\n};\n\nexport type OpenAiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n};\n\nexport type GeminiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n modelPath: string;\n};\n\nconst DEFAULT_LOCAL_MODEL = \"hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf\";\nconst DEFAULT_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst DEFAULT_OPENAI_BASE_URL = \"https://api.openai.com/v1\";\nconst DEFAULT_GEMINI_EMBEDDING_MODEL = \"gemini-embedding-001\";\nconst DEFAULT_GEMINI_BASE_URL = \"https://generativelanguage.googleapis.com/v1beta\";\n\n/**\n * Creates a no-op embedding provider that returns empty vectors.\n * Used for BM25-only mode when no embedding API is available.\n */\nfunction createNoOpEmbeddingProvider(): EmbeddingProvider {\n return {\n id: \"none\",\n model: \"bm25-only\",\n embedQuery: async () => [],\n embedBatch: async (texts) => texts.map(() => []),\n };\n}\n\nfunction resolveUserPath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filePath.slice(2));\n }\n return filePath;\n}\n\nfunction canAutoSelectLocal(options: EmbeddingProviderOptions): boolean {\n const modelPath = options.local?.modelPath?.trim();\n if (!modelPath) return false;\n if (/^(hf:|https?:)/i.test(modelPath)) return false;\n const resolved = resolveUserPath(modelPath);\n try {\n return fsSync.statSync(resolved).isFile();\n } catch {\n return false;\n }\n}\n\nfunction isMissingApiKeyError(err: unknown): boolean {\n const message = formatError(err);\n return message.includes(\"API key\") || message.includes(\"apiKey\");\n}\n\nasync function importNodeLlamaCpp() {\n const llama = await import(\"node-llama-cpp\");\n return llama;\n}\n\nasync function createLocalEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProvider> {\n const modelPath = options.local?.modelPath?.trim() || DEFAULT_LOCAL_MODEL;\n const modelCacheDir = options.local?.modelCacheDir?.trim();\n\n const { getLlama, resolveModelFile, LlamaLogLevel } = await importNodeLlamaCpp();\n\n let llama: Llama | null = null;\n let embeddingModel: LlamaModel | null = null;\n let embeddingContext: LlamaEmbeddingContext | null = null;\n\n const ensureContext = async () => {\n if (!llama) {\n llama = await getLlama({ logLevel: LlamaLogLevel.error });\n }\n if (!embeddingModel) {\n const resolved = await resolveModelFile(modelPath, modelCacheDir || undefined);\n embeddingModel = await llama.loadModel({ modelPath: resolved });\n }\n if (!embeddingContext) {\n embeddingContext = await embeddingModel.createEmbeddingContext();\n }\n return embeddingContext;\n };\n\n return {\n id: \"local\",\n model: modelPath,\n embedQuery: async (text) => {\n const ctx = await ensureContext();\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n },\n embedBatch: async (texts) => {\n const ctx = await ensureContext();\n const embeddings = await Promise.all(\n texts.map(async (text) => {\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n }),\n );\n return embeddings;\n },\n };\n}\n\nfunction normalizeOpenAiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_OPENAI_EMBEDDING_MODEL;\n if (trimmed.startsWith(\"openai/\")) return trimmed.slice(\"openai/\".length);\n return trimmed;\n}\n\nfunction resolveOpenAiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.openai?.apiKey?.trim();\n if (apiKey) return apiKey;\n const envKey = process.env.OPENAI_API_KEY?.trim();\n if (envKey) return envKey;\n throw new Error(\"OpenAI API key not found. Set OPENAI_API_KEY env var or pass openai.apiKey option.\");\n}\n\nexport async function createOpenAiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: OpenAiEmbeddingClient }> {\n const apiKey = resolveOpenAiApiKey(options);\n const baseUrl = options.openai?.baseUrl?.trim() || DEFAULT_OPENAI_BASE_URL;\n const headerOverrides = options.openai?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headerOverrides,\n };\n const model = normalizeOpenAiModel(options.model || \"\");\n const client: OpenAiEmbeddingClient = { baseUrl, headers, model };\n const url = `${baseUrl.replace(/\\/$/, \"\")}/embeddings`;\n\n const embed = async (input: string[]): Promise<number[][]> => {\n if (input.length === 0) return [];\n const res = await fetch(url, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ model: client.model, input }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai embeddings failed: ${res.status} ${text}`);\n }\n const payload = (await res.json()) as {\n data?: Array<{ embedding?: number[] }>;\n };\n const data = payload.data ?? [];\n return data.map((entry) => entry.embedding ?? []);\n };\n\n return {\n provider: {\n id: \"openai\",\n model: client.model,\n embedQuery: async (text) => {\n const [vec] = await embed([text]);\n return vec ?? [];\n },\n embedBatch: embed,\n },\n client,\n };\n}\n\nfunction normalizeGeminiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_GEMINI_EMBEDDING_MODEL;\n const withoutPrefix = trimmed.replace(/^models\\//, \"\");\n if (withoutPrefix.startsWith(\"gemini/\")) return withoutPrefix.slice(\"gemini/\".length);\n if (withoutPrefix.startsWith(\"google/\")) return withoutPrefix.slice(\"google/\".length);\n return withoutPrefix;\n}\n\nfunction normalizeGeminiBaseUrl(raw: string): string {\n const trimmed = raw.replace(/\\/+$/, \"\");\n const openAiIndex = trimmed.indexOf(\"/openai\");\n if (openAiIndex > -1) return trimmed.slice(0, openAiIndex);\n return trimmed;\n}\n\nfunction buildGeminiModelPath(model: string): string {\n return model.startsWith(\"models/\") ? model : `models/${model}`;\n}\n\nfunction resolveGeminiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.gemini?.apiKey?.trim();\n if (apiKey) return apiKey;\n const googleKey = process.env.GOOGLE_API_KEY?.trim();\n if (googleKey) return googleKey;\n const geminiKey = process.env.GEMINI_API_KEY?.trim();\n if (geminiKey) return geminiKey;\n throw new Error(\"Gemini API key not found. Set GOOGLE_API_KEY or GEMINI_API_KEY env var or pass gemini.apiKey option.\");\n}\n\nexport async function createGeminiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: GeminiEmbeddingClient }> {\n const apiKey = resolveGeminiApiKey(options);\n const rawBaseUrl = options.gemini?.baseUrl?.trim() || DEFAULT_GEMINI_BASE_URL;\n const baseUrl = normalizeGeminiBaseUrl(rawBaseUrl);\n const headerOverrides = options.gemini?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n ...headerOverrides,\n };\n const model = normalizeGeminiModel(options.model || \"\");\n const modelPath = buildGeminiModelPath(model);\n const client: GeminiEmbeddingClient = { baseUrl, headers, model, modelPath };\n\n const embedUrl = `${baseUrl}/${modelPath}:embedContent`;\n const batchUrl = `${baseUrl}/${modelPath}:batchEmbedContents`;\n\n const embedQuery = async (text: string): Promise<number[]> => {\n if (!text.trim()) return [];\n const res = await fetch(embedUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_QUERY\",\n }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embedding?: { values?: number[] } };\n return payload.embedding?.values ?? [];\n };\n\n const embedBatch = async (texts: string[]): Promise<number[][]> => {\n if (texts.length === 0) return [];\n const requests = texts.map((text) => ({\n model: modelPath,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n const res = await fetch(batchUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ requests }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embeddings?: Array<{ values?: number[] }> };\n const embeddings = Array.isArray(payload.embeddings) ? payload.embeddings : [];\n return texts.map((_, index) => embeddings[index]?.values ?? []);\n };\n\n return {\n provider: {\n id: \"gemini\",\n model: client.model,\n embedQuery,\n embedBatch,\n },\n client,\n };\n}\n\nexport async function createEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProviderResult> {\n const requestedProvider = options.provider;\n const fallback = options.fallback ?? \"none\";\n\n // Handle explicit \"none\" provider (BM25-only mode)\n if (requestedProvider === \"none\") {\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider: \"none\" as \"auto\", // Type coercion for compatibility\n };\n }\n\n const createProvider = async (id: \"openai\" | \"local\" | \"gemini\") => {\n if (id === \"local\") {\n const provider = await createLocalEmbeddingProvider(options);\n return { provider };\n }\n if (id === \"gemini\") {\n const { provider, client } = await createGeminiEmbeddingProvider(options);\n return { provider, gemini: client };\n }\n const { provider, client } = await createOpenAiEmbeddingProvider(options);\n return { provider, openAi: client };\n };\n\n const formatPrimaryError = (err: unknown, provider: \"openai\" | \"local\" | \"gemini\") =>\n provider === \"local\" ? formatLocalSetupError(err) : formatError(err);\n\n if (requestedProvider === \"auto\") {\n const missingKeyErrors: string[] = [];\n let localError: string | null = null;\n\n if (canAutoSelectLocal(options)) {\n try {\n const local = await createProvider(\"local\");\n return { ...local, requestedProvider };\n } catch (err) {\n localError = formatLocalSetupError(err);\n }\n }\n\n for (const provider of [\"openai\", \"gemini\"] as const) {\n try {\n const result = await createProvider(provider);\n return { ...result, requestedProvider };\n } catch (err) {\n const message = formatPrimaryError(err, provider);\n if (isMissingApiKeyError(err)) {\n missingKeyErrors.push(message);\n continue;\n }\n throw new Error(message);\n }\n }\n\n // Fall back to BM25-only mode instead of throwing\n // This allows the system to work without any API keys using full-text search only\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider,\n fallbackFrom: \"auto\" as \"openai\", // Indicate this is a fallback\n fallbackReason: \"No embedding API available. Using BM25 full-text search only.\",\n };\n }\n\n try {\n const primary = await createProvider(requestedProvider);\n return { ...primary, requestedProvider };\n } catch (primaryErr) {\n const reason = formatPrimaryError(primaryErr, requestedProvider);\n if (fallback && fallback !== \"none\" && fallback !== requestedProvider) {\n try {\n const fallbackResult = await createProvider(fallback);\n return {\n ...fallbackResult,\n requestedProvider,\n fallbackFrom: requestedProvider,\n fallbackReason: reason,\n };\n } catch (fallbackErr) {\n throw new Error(`${reason}\\n\\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`);\n }\n }\n throw new Error(reason);\n }\n}\n\nfunction formatError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction isNodeLlamaCppMissing(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const code = (err as Error & { code?: unknown }).code;\n if (code === \"ERR_MODULE_NOT_FOUND\") {\n return err.message.includes(\"node-llama-cpp\");\n }\n return false;\n}\n\nfunction formatLocalSetupError(err: unknown): string {\n const detail = formatError(err);\n const missing = isNodeLlamaCppMissing(err);\n return [\n \"Local embeddings unavailable.\",\n missing\n ? \"Reason: optional dependency node-llama-cpp is missing (or failed to install).\"\n : detail\n ? `Reason: ${detail}`\n : undefined,\n missing && detail ? `Detail: ${detail}` : null,\n \"To enable local embeddings:\",\n \"1) Use Node 22 LTS (recommended for installs/updates)\",\n missing ? \"2) Install node-llama-cpp: npm install node-llama-cpp\" : null,\n \"3) If you use pnpm: pnpm approve-builds (select node-llama-cpp), then pnpm rebuild node-llama-cpp\",\n 'Or set provider = \"openai\" or \"gemini\" (remote).',\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import type { OpenAiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type OpenAiBatchRequest = {\n custom_id: string;\n method: \"POST\";\n url: \"/v1/embeddings\";\n body: {\n model: string;\n input: string;\n };\n};\n\nexport type OpenAiBatchStatus = {\n id?: string;\n status?: string;\n output_file_id?: string | null;\n error_file_id?: string | null;\n};\n\nexport type OpenAiBatchOutputLine = {\n custom_id?: string;\n response?: {\n status_code?: number;\n body?: {\n data?: Array<{ embedding?: number[]; index?: number }>;\n error?: { message?: string };\n };\n };\n error?: { message?: string };\n};\n\nexport const OPENAI_BATCH_ENDPOINT = \"/v1/embeddings\";\nconst OPENAI_BATCH_COMPLETION_WINDOW = \"24h\";\nconst OPENAI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getOpenAiBaseUrl(openAi: OpenAiEmbeddingClient): string {\n return openAi.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getOpenAiHeaders(\n openAi: OpenAiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = openAi.headers ? { ...openAi.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction splitOpenAiBatchRequests(requests: OpenAiBatchRequest[]): OpenAiBatchRequest[][] {\n if (requests.length <= OPENAI_BATCH_MAX_REQUESTS) return [requests];\n const groups: OpenAiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += OPENAI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + OPENAI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nasync function retryAsync<T>(\n fn: () => Promise<T>,\n opts: {\n attempts: number;\n minDelayMs: number;\n maxDelayMs: number;\n jitter: number;\n shouldRetry: (err: unknown) => boolean;\n },\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt < opts.attempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (!opts.shouldRetry(err) || attempt === opts.attempts - 1) {\n throw err;\n }\n const delay = Math.min(\n opts.maxDelayMs,\n opts.minDelayMs * Math.pow(2, attempt) * (1 + Math.random() * opts.jitter),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n throw lastError;\n}\n\nasync function submitOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n requests: OpenAiBatchRequest[];\n source: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const jsonl = params.requests.map((request) => JSON.stringify(request)).join(\"\\n\");\n const form = new FormData();\n form.append(\"purpose\", \"batch\");\n form.append(\n \"file\",\n new Blob([jsonl], { type: \"application/jsonl\" }),\n `memory-embeddings.${hashText(String(Date.now()))}.jsonl`,\n );\n\n const fileRes = await fetch(`${baseUrl}/files`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: false }),\n body: form,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`openai batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { id?: string };\n if (!filePayload.id) {\n throw new Error(\"openai batch file upload failed: missing file id\");\n }\n\n const batchRes = await retryAsync(\n async () => {\n const res = await fetch(`${baseUrl}/batches`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n body: JSON.stringify({\n input_file_id: filePayload.id,\n endpoint: OPENAI_BATCH_ENDPOINT,\n completion_window: OPENAI_BATCH_COMPLETION_WINDOW,\n metadata: {\n source: params.source,\n },\n }),\n });\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`openai batch create failed: ${res.status} ${text}`) as Error & {\n status?: number;\n };\n err.status = res.status;\n throw err;\n }\n return res;\n },\n {\n attempts: 3,\n minDelayMs: 300,\n maxDelayMs: 2000,\n jitter: 0.2,\n shouldRetry: (err) => {\n const status = (err as { status?: number }).status;\n return status === 429 || (typeof status === \"number\" && status >= 500);\n },\n },\n );\n return (await batchRes.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiBatchStatus(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/batches/${params.batchId}`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiFileContent(params: {\n openAi: OpenAiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/files/${params.fileId}/content`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseOpenAiBatchOutput(text: string): OpenAiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as OpenAiBatchOutputLine);\n}\n\nasync function readOpenAiBatchError(params: {\n openAi: OpenAiEmbeddingClient;\n errorFileId: string;\n}): Promise<string | undefined> {\n try {\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: params.errorFileId,\n });\n const lines = parseOpenAiBatchOutput(content);\n const first = lines.find((line) => line.error?.message || line.response?.body?.error);\n const message =\n first?.error?.message ??\n (typeof first?.response?.body?.error?.message === \"string\"\n ? first?.response?.body?.error?.message\n : undefined);\n return message;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return message ? `error file unavailable: ${message}` : undefined;\n }\n}\n\nasync function waitForOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: OpenAiBatchStatus;\n}): Promise<{ outputFileId: string; errorFileId?: string }> {\n const start = Date.now();\n let current: OpenAiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchOpenAiBatchStatus({\n openAi: params.openAi,\n batchId: params.batchId,\n }));\n const state = status.status ?? \"unknown\";\n if (state === \"completed\") {\n if (!status.output_file_id) {\n throw new Error(`openai batch ${params.batchId} completed without output file`);\n }\n return {\n outputFileId: status.output_file_id,\n errorFileId: status.error_file_id ?? undefined,\n };\n }\n if ([\"failed\", \"expired\", \"cancelled\", \"canceled\"].includes(state)) {\n const detail = status.error_file_id\n ? await readOpenAiBatchError({ openAi: params.openAi, errorFileId: status.error_file_id })\n : undefined;\n const suffix = detail ? `: ${detail}` : \"\";\n throw new Error(`openai batch ${params.batchId} ${state}${suffix}`);\n }\n if (!params.wait) {\n throw new Error(`openai batch ${params.batchId} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`openai batch ${params.batchId} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`openai batch ${params.batchId} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runOpenAiEmbeddingBatches(params: {\n openAi: OpenAiEmbeddingClient;\n source: string;\n requests: OpenAiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitOpenAiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitOpenAiBatch({\n openAi: params.openAi,\n requests: group,\n source: params.source,\n });\n if (!batchInfo.id) {\n throw new Error(\"openai batch create failed: missing batch id\");\n }\n\n params.debug?.(\"memory embeddings: openai batch created\", {\n batchId: batchInfo.id,\n status: batchInfo.status,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (!params.wait && batchInfo.status !== \"completed\") {\n throw new Error(\n `openai batch ${batchInfo.id} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.status === \"completed\"\n ? {\n outputFileId: batchInfo.output_file_id ?? \"\",\n errorFileId: batchInfo.error_file_id ?? undefined,\n }\n : await waitForOpenAiBatch({\n openAi: params.openAi,\n batchId: batchInfo.id,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`openai batch ${batchInfo.id} completed without output file`);\n }\n\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: completed.outputFileId,\n });\n const outputLines = parseOpenAiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.custom_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n const response = line.response;\n const statusCode = response?.status_code ?? 0;\n if (statusCode >= 400) {\n const message =\n response?.body?.error?.message ??\n (typeof response?.body === \"string\" ? response.body : undefined) ??\n \"unknown error\";\n errors.push(`${customId}: ${message}`);\n continue;\n }\n const data = response?.body?.data ?? [];\n const embedding = data[0]?.embedding ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`openai batch ${batchInfo.id} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`openai batch ${batchInfo.id} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: openai batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","import type { GeminiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type GeminiBatchRequest = {\n custom_id: string;\n content: { parts: Array<{ text: string }> };\n taskType: \"RETRIEVAL_DOCUMENT\" | \"RETRIEVAL_QUERY\";\n};\n\nexport type GeminiBatchStatus = {\n name?: string;\n state?: string;\n outputConfig?: { file?: string; fileId?: string };\n metadata?: {\n output?: {\n responsesFile?: string;\n };\n };\n error?: { message?: string };\n};\n\nexport type GeminiBatchOutputLine = {\n key?: string;\n custom_id?: string;\n request_id?: string;\n embedding?: { values?: number[] };\n response?: {\n embedding?: { values?: number[] };\n error?: { message?: string };\n };\n error?: { message?: string };\n};\n\nconst GEMINI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getGeminiBaseUrl(gemini: GeminiEmbeddingClient): string {\n return gemini.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getGeminiHeaders(\n gemini: GeminiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = gemini.headers ? { ...gemini.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction getGeminiUploadUrl(baseUrl: string): string {\n if (baseUrl.includes(\"/v1beta\")) {\n return baseUrl.replace(/\\/v1beta\\/?$/, \"/upload/v1beta\");\n }\n return `${baseUrl.replace(/\\/$/, \"\")}/upload`;\n}\n\nfunction splitGeminiBatchRequests(requests: GeminiBatchRequest[]): GeminiBatchRequest[][] {\n if (requests.length <= GEMINI_BATCH_MAX_REQUESTS) return [requests];\n const groups: GeminiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += GEMINI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + GEMINI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nfunction buildGeminiUploadBody(params: { jsonl: string; displayName: string }): {\n body: Blob;\n contentType: string;\n} {\n const boundary = `minimem-${hashText(params.displayName)}`;\n const jsonPart = JSON.stringify({\n file: {\n displayName: params.displayName,\n mimeType: \"application/jsonl\",\n },\n });\n const delimiter = `--${boundary}\\r\\n`;\n const closeDelimiter = `--${boundary}--\\r\\n`;\n const parts = [\n `${delimiter}Content-Type: application/json; charset=UTF-8\\r\\n\\r\\n${jsonPart}\\r\\n`,\n `${delimiter}Content-Type: application/jsonl; charset=UTF-8\\r\\n\\r\\n${params.jsonl}\\r\\n`,\n closeDelimiter,\n ];\n const body = new Blob([parts.join(\"\")], { type: \"multipart/related\" });\n return {\n body,\n contentType: `multipart/related; boundary=${boundary}`,\n };\n}\n\nasync function submitGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n requests: GeminiBatchRequest[];\n source: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const jsonl = params.requests\n .map((request) =>\n JSON.stringify({\n key: request.custom_id,\n request: {\n content: request.content,\n task_type: request.taskType,\n },\n }),\n )\n .join(\"\\n\");\n const displayName = `memory-embeddings-${hashText(String(Date.now()))}`;\n const uploadPayload = buildGeminiUploadBody({ jsonl, displayName });\n\n const uploadUrl = `${getGeminiUploadUrl(baseUrl)}/files?uploadType=multipart`;\n const fileRes = await fetch(uploadUrl, {\n method: \"POST\",\n headers: {\n ...getGeminiHeaders(params.gemini, { json: false }),\n \"Content-Type\": uploadPayload.contentType,\n },\n body: uploadPayload.body,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`gemini batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { name?: string; file?: { name?: string } };\n const fileId = filePayload.name ?? filePayload.file?.name;\n if (!fileId) {\n throw new Error(\"gemini batch file upload failed: missing file id\");\n }\n\n const batchBody = {\n batch: {\n displayName: `memory-embeddings-${params.source}`,\n inputConfig: {\n file_name: fileId,\n },\n },\n };\n\n const batchEndpoint = `${baseUrl}/${params.gemini.modelPath}:asyncBatchEmbedContent`;\n const batchRes = await fetch(batchEndpoint, {\n method: \"POST\",\n headers: getGeminiHeaders(params.gemini, { json: true }),\n body: JSON.stringify(batchBody),\n });\n if (batchRes.ok) {\n return (await batchRes.json()) as GeminiBatchStatus;\n }\n const text = await batchRes.text();\n if (batchRes.status === 404) {\n throw new Error(\n \"gemini batch create failed: 404 (asyncBatchEmbedContent not available for this model/baseUrl). Disable batch.enabled or switch providers.\",\n );\n }\n throw new Error(`gemini batch create failed: ${batchRes.status} ${text}`);\n}\n\nasync function fetchGeminiBatchStatus(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const name = params.batchName.startsWith(\"batches/\")\n ? params.batchName\n : `batches/${params.batchName}`;\n const statusUrl = `${baseUrl}/${name}`;\n const res = await fetch(statusUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as GeminiBatchStatus;\n}\n\nasync function fetchGeminiFileContent(params: {\n gemini: GeminiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const file = params.fileId.startsWith(\"files/\") ? params.fileId : `files/${params.fileId}`;\n const downloadUrl = `${baseUrl}/${file}:download`;\n const res = await fetch(downloadUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseGeminiBatchOutput(text: string): GeminiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as GeminiBatchOutputLine);\n}\n\nasync function waitForGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: GeminiBatchStatus;\n}): Promise<{ outputFileId: string }> {\n const start = Date.now();\n let current: GeminiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchGeminiBatchStatus({\n gemini: params.gemini,\n batchName: params.batchName,\n }));\n const state = status.state ?? \"UNKNOWN\";\n if ([\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(state)) {\n const outputFileId =\n status.outputConfig?.file ??\n status.outputConfig?.fileId ??\n status.metadata?.output?.responsesFile;\n if (!outputFileId) {\n throw new Error(`gemini batch ${params.batchName} completed without output file`);\n }\n return { outputFileId };\n }\n if ([\"FAILED\", \"CANCELLED\", \"CANCELED\", \"EXPIRED\"].includes(state)) {\n const message = status.error?.message ?? \"unknown error\";\n throw new Error(`gemini batch ${params.batchName} ${state}: ${message}`);\n }\n if (!params.wait) {\n throw new Error(`gemini batch ${params.batchName} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`gemini batch ${params.batchName} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`gemini batch ${params.batchName} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runGeminiEmbeddingBatches(params: {\n gemini: GeminiEmbeddingClient;\n source: string;\n requests: GeminiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitGeminiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitGeminiBatch({\n gemini: params.gemini,\n requests: group,\n source: params.source,\n });\n const batchName = batchInfo.name ?? \"\";\n if (!batchName) {\n throw new Error(\"gemini batch create failed: missing batch name\");\n }\n\n params.debug?.(\"memory embeddings: gemini batch created\", {\n batchName,\n state: batchInfo.state,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (\n !params.wait &&\n batchInfo.state &&\n ![\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ) {\n throw new Error(\n `gemini batch ${batchName} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.state && [\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ? {\n outputFileId:\n batchInfo.outputConfig?.file ??\n batchInfo.outputConfig?.fileId ??\n batchInfo.metadata?.output?.responsesFile ??\n \"\",\n }\n : await waitForGeminiBatch({\n gemini: params.gemini,\n batchName,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`gemini batch ${batchName} completed without output file`);\n }\n\n const content = await fetchGeminiFileContent({\n gemini: params.gemini,\n fileId: completed.outputFileId,\n });\n const outputLines = parseGeminiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.key ?? line.custom_id ?? line.request_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n if (line.response?.error?.message) {\n errors.push(`${customId}: ${line.response.error.message}`);\n continue;\n }\n const embedding = line.embedding?.values ?? line.response?.embedding?.values ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`gemini batch ${batchName} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`gemini batch ${batchName} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: gemini batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","/**\n * minimem sync - Force re-index memory files\n */\n\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type SyncOptions = {\n dir?: string;\n global?: boolean;\n force?: boolean;\n provider?: string;\n};\n\nexport async function sync(options: SyncOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n console.error(`Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`);\n process.exit(1);\n }\n\n console.log(`Syncing ${formatPath(memoryDir)}...`);\n\n // Load config and create Minimem instance\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n // Add debug logging\n config.debug = (message, data) => {\n if (data) {\n console.log(` ${message}`, data);\n } else {\n console.log(` ${message}`);\n }\n };\n\n let minimem: Minimem | null = null;\n\n try {\n minimem = await Minimem.create(config);\n\n const startTime = Date.now();\n await minimem.sync({ force: options.force });\n const duration = Date.now() - startTime;\n\n const status = await minimem.status();\n\n console.log();\n console.log(`Sync complete in ${duration}ms`);\n console.log(` Files: ${status.fileCount}`);\n console.log(` Chunks: ${status.chunkCount}`);\n console.log(` Cache: ${status.cacheCount} embeddings`);\n } finally {\n minimem?.close();\n }\n}\n","/**\n * minimem status - Show index stats and provider info\n */\n\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type StatusOptions = {\n dir?: string;\n global?: boolean;\n json?: boolean;\n provider?: string;\n};\n\nexport async function status(options: StatusOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n console.error(`Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`);\n process.exit(1);\n }\n\n // Load config and create Minimem instance\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n let minimem: Minimem | null = null;\n\n try {\n minimem = await Minimem.create(config);\n const info = await minimem.status();\n\n if (options.json) {\n console.log(JSON.stringify(info, null, 2));\n return;\n }\n\n console.log(\"Minimem Status\");\n console.log(\"==============\");\n console.log();\n console.log(`Memory Dir: ${formatPath(info.memoryDir)}`);\n console.log(`Database: ${formatPath(info.dbPath)}`);\n console.log();\n console.log(\"Embedding Provider\");\n if (info.bm25Only) {\n console.log(` Provider: none (BM25-only mode)`);\n console.log(` Model: ${info.model}`);\n if (info.fallbackReason) {\n console.log(` Reason: ${info.fallbackReason}`);\n }\n } else {\n console.log(` Provider: ${info.provider}`);\n console.log(` Model: ${info.model}`);\n }\n console.log();\n console.log(\"Search Capabilities\");\n if (info.bm25Only) {\n console.log(` Vector: disabled (no embedding provider)`);\n } else {\n console.log(` Vector: ${info.vectorAvailable ? \"available\" : \"not available\"}`);\n }\n console.log(` FTS: ${info.ftsAvailable ? \"available\" : \"not available\"}`);\n console.log();\n console.log(\"Index Stats\");\n console.log(` Files: ${info.fileCount}`);\n console.log(` Chunks: ${info.chunkCount}`);\n console.log(` Cache: ${info.cacheCount} embeddings`);\n } finally {\n minimem?.close();\n }\n}\n","/**\n * minimem append - Quick append to today's daily log\n */\n\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type AppendOptions = {\n dir?: string;\n global?: boolean;\n file?: string;\n provider?: string;\n session?: string;\n sessionSource?: string;\n};\n\nexport async function append(\n text: string,\n options: AppendOptions,\n): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n console.error(`Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`);\n process.exit(1);\n }\n\n // Add session marker if explicit session provided\n let finalText = text;\n if (options.session) {\n const timestamp = new Date().toISOString();\n const sourceInfo = options.sessionSource ? ` source=${options.sessionSource}` : \"\";\n finalText = `<!-- ${timestamp} session=${options.session}${sourceInfo} -->\\n${text}`;\n }\n\n // Load config and create Minimem instance\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n let minimem: Minimem | null = null;\n\n try {\n minimem = await Minimem.create(config);\n\n let targetPath: string;\n\n if (options.file) {\n // Append to specific file\n targetPath = options.file;\n await minimem.appendFile(targetPath, finalText);\n } else {\n // Append to today's daily log\n targetPath = await minimem.appendToday(finalText);\n }\n\n console.log(`Appended to ${targetPath}`);\n if (options.session) {\n console.log(` Session: ${options.session}`);\n }\n } finally {\n minimem?.close();\n }\n}\n","/**\n * minimem upsert - Create or update a memory file\n *\n * Supports upserting memories across different memory directories.\n */\n\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { Minimem } from \"../../minimem.js\";\nimport {\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\nimport {\n addFrontmatter,\n parseFrontmatter,\n type SessionContext,\n} from \"../../session.js\";\n\nexport type UpsertOptions = {\n dir?: string;\n global?: boolean;\n provider?: string;\n stdin?: boolean;\n session?: string;\n sessionSource?: string;\n};\n\nexport async function upsert(\n file: string,\n content: string | undefined,\n options: UpsertOptions,\n): Promise<void> {\n // Resolve memory directory\n const memoryDir = resolveMemoryDir(options);\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n console.error(`Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`);\n process.exit(1);\n }\n\n // Get content from stdin if --stdin flag is set\n let finalContent = content;\n if (options.stdin) {\n finalContent = await readStdin();\n }\n\n if (!finalContent) {\n console.error(\"Error: No content provided. Use --stdin or provide content as argument.\");\n process.exit(1);\n }\n\n // Build session context from explicit options\n const session: SessionContext | undefined = options.session\n ? {\n id: options.session,\n source: options.sessionSource,\n project: process.cwd(),\n }\n : undefined;\n\n // Resolve file path relative to memory directory\n const filePath = resolveFilePath(file, memoryDir);\n\n // Ensure the file is within the memory directory\n const resolvedPath = path.resolve(filePath);\n const resolvedMemoryDir = path.resolve(memoryDir);\n if (!resolvedPath.startsWith(resolvedMemoryDir)) {\n console.error(`Error: File path must be within the memory directory.`);\n console.error(` Memory dir: ${formatPath(memoryDir)}`);\n console.error(` File path: ${formatPath(filePath)}`);\n process.exit(1);\n }\n\n // Ensure parent directory exists\n const parentDir = path.dirname(filePath);\n await fs.mkdir(parentDir, { recursive: true });\n\n // Check if file exists (for reporting)\n let isUpdate = false;\n let existingContent: string | undefined;\n try {\n await fs.access(filePath);\n isUpdate = true;\n existingContent = await fs.readFile(filePath, \"utf-8\");\n } catch {\n // File doesn't exist, this is a create\n }\n\n // Add session frontmatter if session context exists and file is markdown\n let contentToWrite = finalContent;\n if (session && filePath.endsWith(\".md\")) {\n if (isUpdate && existingContent) {\n // For updates, preserve existing frontmatter but update session\n const { frontmatter: existing, body } = parseFrontmatter(existingContent);\n // Check if the new content already has frontmatter\n const { frontmatter: newFm, body: newBody } = parseFrontmatter(finalContent);\n if (newFm) {\n // New content has frontmatter, merge with existing\n contentToWrite = addFrontmatter(newBody, {\n ...existing,\n ...newFm,\n session: { ...existing?.session, ...newFm.session, ...session },\n });\n } else {\n // New content has no frontmatter, add session to new content\n contentToWrite = addFrontmatter(finalContent, {\n ...existing,\n session: { ...existing?.session, ...session },\n });\n }\n } else {\n // New file - add frontmatter with session\n const { frontmatter: existingFm, body } = parseFrontmatter(finalContent);\n contentToWrite = addFrontmatter(body, {\n ...existingFm,\n session,\n });\n }\n }\n\n // Write content to file\n await fs.writeFile(filePath, contentToWrite, \"utf-8\");\n\n const relativePath = path.relative(memoryDir, filePath);\n const action = isUpdate ? \"Updated\" : \"Created\";\n console.log(`${action}: ${relativePath}`);\n console.log(` in ${formatPath(memoryDir)}`);\n if (options.session) {\n console.log(` Session: ${options.session}`);\n }\n\n // Try to sync the index (requires embedding provider)\n let minimem: Minimem | null = null;\n\n try {\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n minimem = await Minimem.create(config);\n await minimem.sync();\n console.log(\" Index synced.\");\n } catch (error) {\n // Sync failed, but file was written successfully\n console.log(\" Note: Index not synced (run 'minimem sync' with API key to index).\");\n } finally {\n minimem?.close();\n }\n}\n\n/**\n * Resolve memory directory from options\n */\nfunction resolveMemoryDir(options: UpsertOptions): string {\n if (options.dir) {\n return path.resolve(options.dir);\n }\n if (options.global) {\n return path.join(os.homedir(), \".minimem\");\n }\n return process.cwd();\n}\n\n/**\n * Resolve file path, handling both absolute and relative paths\n */\nfunction resolveFilePath(file: string, memoryDir: string): string {\n // If absolute path, use as-is\n if (path.isAbsolute(file)) {\n return file;\n }\n\n // If starts with memory/, use relative to memory dir\n if (file.startsWith(\"memory/\") || file.startsWith(\"memory\\\\\")) {\n return path.join(memoryDir, file);\n }\n\n // Otherwise, assume it's in the memory/ subdirectory\n // Unless it's MEMORY.md or similar root file\n if (file === \"MEMORY.md\" || file.endsWith(\".md\") && !file.includes(\"/\")) {\n return path.join(memoryDir, file);\n }\n\n return path.join(memoryDir, \"memory\", file);\n}\n\n/**\n * Read content from stdin\n */\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n\n return new Promise((resolve, reject) => {\n process.stdin.on(\"data\", (chunk) => chunks.push(chunk));\n process.stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n process.stdin.on(\"error\", reject);\n });\n}\n","/**\n * Session tracking for memory entries\n *\n * Captures context about the originating session (Claude Code, VS Code, etc.)\n * and stores it as YAML frontmatter in memory files.\n */\n\nimport * as os from \"node:os\";\n\n/**\n * Session metadata for memory entries\n */\nexport type SessionContext = {\n /** Session identifier (e.g., Claude Code session ID) */\n id?: string;\n /** Source application (claude-code, vscode, cursor, etc.) */\n source?: string;\n /** Project directory path */\n project?: string;\n /** Path to session transcript/log file */\n transcript?: string;\n};\n\n/**\n * Frontmatter structure for memory files\n */\nexport type MemoryFrontmatter = {\n session?: SessionContext;\n created?: string;\n updated?: string;\n tags?: string[];\n};\n\n/**\n * Parse YAML frontmatter from content\n *\n * Frontmatter is delimited by --- at the start and end:\n * ```\n * ---\n * session:\n * id: abc123\n * source: claude-code\n * created: 2024-01-27T14:30:00Z\n * ---\n * Actual content here...\n * ```\n */\nexport function parseFrontmatter(content: string): {\n frontmatter: MemoryFrontmatter | undefined;\n body: string;\n} {\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n/;\n const match = content.match(frontmatterRegex);\n\n if (!match) {\n return { frontmatter: undefined, body: content };\n }\n\n const yamlContent = match[1];\n const body = content.slice(match[0].length);\n\n try {\n const frontmatter = parseSimpleYaml(yamlContent);\n return { frontmatter, body };\n } catch {\n // If parsing fails, treat as no frontmatter\n return { frontmatter: undefined, body: content };\n }\n}\n\n/**\n * Simple YAML parser for frontmatter\n * Handles basic key-value pairs and nested objects\n */\nfunction parseSimpleYaml(yaml: string): MemoryFrontmatter {\n const result: MemoryFrontmatter = {};\n const lines = yaml.split(\"\\n\");\n let currentKey: string | null = null;\n let currentObject: Record<string, unknown> | null = null;\n\n for (const line of lines) {\n // Skip empty lines\n if (!line.trim()) continue;\n\n // Check indentation level\n const indentMatch = line.match(/^(\\s*)/);\n const indent = indentMatch ? indentMatch[1].length : 0;\n\n // Top-level key\n if (indent === 0) {\n const keyMatch = line.match(/^(\\w+):\\s*(.*)?$/);\n if (keyMatch) {\n const [, key, value] = keyMatch;\n if (value && value.trim()) {\n // Simple key: value\n (result as Record<string, unknown>)[key] = parseYamlValue(value.trim());\n currentKey = null;\n currentObject = null;\n } else {\n // Object start\n currentKey = key;\n currentObject = {};\n (result as Record<string, unknown>)[key] = currentObject;\n }\n }\n } else if (currentObject && indent >= 2) {\n // Nested key\n const nestedMatch = line.match(/^\\s+(\\w+):\\s*(.*)$/);\n if (nestedMatch) {\n const [, key, value] = nestedMatch;\n currentObject[key] = parseYamlValue(value.trim());\n }\n }\n }\n\n return result;\n}\n\n/**\n * Parse a YAML value (handles strings, numbers, booleans, arrays)\n */\nfunction parseYamlValue(value: string): unknown {\n // Remove quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n\n // Boolean\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Number\n const num = Number(value);\n if (!isNaN(num) && value !== \"\") return num;\n\n // Array (simple inline format)\n if (value.startsWith(\"[\") && value.endsWith(\"]\")) {\n const inner = value.slice(1, -1);\n return inner.split(\",\").map((s) => parseYamlValue(s.trim()));\n }\n\n // String\n return value;\n}\n\n/**\n * Serialize frontmatter to YAML string\n */\nexport function serializeFrontmatter(frontmatter: MemoryFrontmatter): string {\n const lines: string[] = [\"---\"];\n\n if (frontmatter.session) {\n lines.push(\"session:\");\n const session = frontmatter.session;\n if (session.id) lines.push(` id: ${session.id}`);\n if (session.source) lines.push(` source: ${session.source}`);\n if (session.project) lines.push(` project: ${formatPath(session.project)}`);\n if (session.transcript) lines.push(` transcript: ${formatPath(session.transcript)}`);\n }\n\n if (frontmatter.created) {\n lines.push(`created: ${frontmatter.created}`);\n }\n\n if (frontmatter.updated) {\n lines.push(`updated: ${frontmatter.updated}`);\n }\n\n if (frontmatter.tags && frontmatter.tags.length > 0) {\n lines.push(`tags: [${frontmatter.tags.join(\", \")}]`);\n }\n\n lines.push(\"---\");\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Add or update frontmatter in content\n */\nexport function addFrontmatter(\n content: string,\n frontmatter: MemoryFrontmatter,\n): string {\n const { frontmatter: existing, body } = parseFrontmatter(content);\n\n // Merge with existing frontmatter\n const merged: MemoryFrontmatter = {\n ...existing,\n ...frontmatter,\n session: {\n ...existing?.session,\n ...frontmatter.session,\n },\n };\n\n // Update timestamp\n if (!merged.created) {\n merged.created = new Date().toISOString();\n }\n merged.updated = new Date().toISOString();\n\n return serializeFrontmatter(merged) + body;\n}\n\n/**\n * Add session context as frontmatter to content\n */\nexport function addSessionToContent(\n content: string,\n session: SessionContext,\n): string {\n return addFrontmatter(content, { session });\n}\n\n/**\n * Format path for display (use ~ for home directory)\n */\nfunction formatPath(filePath: string): string {\n const home = os.homedir();\n if (filePath.startsWith(home)) {\n return \"~\" + filePath.slice(home.length);\n }\n return filePath;\n}\n\n/**\n * Extract session context from file content\n */\nexport function extractSession(content: string): SessionContext | undefined {\n const { frontmatter } = parseFrontmatter(content);\n return frontmatter?.session;\n}\n","/**\n * minimem mcp - Run as MCP server (stdio)\n *\n * Supports multiple memory directories for cross-directory search.\n * Auto-initializes global ~/.minimem directory as a fallback.\n */\n\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { Minimem } from \"../../minimem.js\";\nimport { createMcpServer, runMcpServer } from \"../../server/mcp.js\";\nimport type { MemoryInstance } from \"../../server/tools.js\";\nimport {\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n getInitConfig,\n saveConfig,\n} from \"../config.js\";\n\nexport type McpOptions = {\n dir?: string[];\n global?: boolean;\n provider?: string;\n};\n\nexport async function mcp(options: McpOptions): Promise<void> {\n // Collect all directories\n const directories = resolveDirectories(options);\n const globalDir = path.join(os.homedir(), \".minimem\");\n\n if (directories.length === 0) {\n console.error(\"Error: No memory directories specified.\");\n console.error(\"Use --dir <path> or --global to specify directories.\");\n process.exit(1);\n }\n\n // Auto-initialize global directory if it will be used\n const includesGlobal = directories.includes(globalDir);\n if (includesGlobal && !(await isInitialized(globalDir))) {\n await ensureGlobalInitialized(globalDir);\n }\n\n // Validate and create instances for each directory\n const instances: MemoryInstance[] = [];\n const minimemInstances: Minimem[] = [];\n\n for (const memoryDir of directories) {\n const isGlobal = memoryDir === globalDir;\n\n if (!(await isInitialized(memoryDir))) {\n // Write to stderr so it doesn't interfere with MCP JSON-RPC\n console.error(`Warning: ${formatPath(memoryDir)} is not initialized, skipping.`);\n\n // If current directory isn't initialized and global isn't already included,\n // add global as a fallback\n if (!isGlobal && !includesGlobal) {\n console.error(` Using global (~/.minimem) as fallback.`);\n if (!(await isInitialized(globalDir))) {\n await ensureGlobalInitialized(globalDir);\n }\n directories.push(globalDir);\n }\n continue;\n }\n\n try {\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: true, // Enable watching for MCP server\n });\n\n const minimem = await Minimem.create(config);\n minimemInstances.push(minimem);\n\n // Check if running in BM25-only mode\n const status = await minimem.status();\n if (status.bm25Only && instances.length === 0) {\n // Only warn once\n console.error(`Note: Running in BM25-only mode (no embedding API configured).`);\n console.error(` Search results will be based on keyword matching only.`);\n }\n\n // Create a friendly name for the directory\n const name = getDirName(memoryDir);\n\n instances.push({\n minimem,\n memoryDir,\n name,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`Warning: Failed to load ${formatPath(memoryDir)}: ${message}`);\n }\n }\n\n if (instances.length === 0) {\n console.error(\"Error: No valid memory directories found.\");\n process.exit(1);\n }\n\n // Log which directories are being served (to stderr)\n if (instances.length === 1) {\n console.error(`Serving: ${instances[0].name} (${formatPath(instances[0].memoryDir)})`);\n } else {\n console.error(`Serving ${instances.length} directories:`);\n for (const inst of instances) {\n console.error(` - ${inst.name} (${formatPath(inst.memoryDir)})`);\n }\n }\n\n const server = createMcpServer(instances);\n\n // Handle shutdown gracefully\n const shutdown = () => {\n for (const minimem of minimemInstances) {\n minimem.close();\n }\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Run the MCP server (this blocks)\n await runMcpServer(server);\n}\n\n/**\n * Resolve all directories from options\n */\nexport function resolveDirectories(options: McpOptions): string[] {\n const dirs: string[] = [];\n\n // Add explicit directories\n if (options.dir && options.dir.length > 0) {\n for (const dir of options.dir) {\n dirs.push(path.resolve(dir));\n }\n }\n\n // Add global directory if --global flag is set\n if (options.global) {\n const globalDir = path.join(os.homedir(), \".minimem\");\n if (!dirs.includes(globalDir)) {\n dirs.push(globalDir);\n }\n }\n\n // If no directories specified, use current directory\n if (dirs.length === 0) {\n dirs.push(process.cwd());\n }\n\n return dirs;\n}\n\n/**\n * Get a friendly name for a directory\n */\nexport function getDirName(memoryDir: string): string {\n const home = os.homedir();\n\n // Check if it's the global directory\n if (memoryDir === path.join(home, \".minimem\")) {\n return \"global\";\n }\n\n // Use the directory name\n const name = path.basename(memoryDir);\n\n // If it's a hidden directory, use parent + name\n if (name.startsWith(\".\")) {\n const parent = path.basename(path.dirname(memoryDir));\n return `${parent}/${name}`;\n }\n\n return name;\n}\n\n/**\n * Auto-initialize the global memory directory silently\n */\nexport async function ensureGlobalInitialized(globalDir: string): Promise<void> {\n console.error(`Auto-initializing global memory directory (~/.minimem)...`);\n\n // Create directories\n await fs.mkdir(globalDir, { recursive: true });\n await fs.mkdir(path.join(globalDir, \"memory\"), { recursive: true });\n await fs.mkdir(path.join(globalDir, \".minimem\"), { recursive: true });\n\n // Create MEMORY.md\n const memoryFilePath = path.join(globalDir, \"MEMORY.md\");\n try {\n await fs.access(memoryFilePath);\n } catch {\n const template = `# Global Memory\n\nThis is your global memory file. Add notes, decisions, and context here.\n\nNotes stored here are available across all projects.\n\n## Notes\n\n`;\n await fs.writeFile(memoryFilePath, template, \"utf-8\");\n }\n\n // Create config\n const config = getInitConfig();\n await saveConfig(globalDir, config);\n\n // Create .gitignore\n const gitignorePath = path.join(globalDir, \".minimem\", \".gitignore\");\n await fs.writeFile(gitignorePath, \"index.db\\nindex.db-*\\n\", \"utf-8\");\n\n console.error(` Created ~/.minimem with default configuration.`);\n}\n","/**\n * MCP (Model Context Protocol) Server for Minimem\n *\n * Provides memory tools via JSON-RPC 2.0 over stdio.\n * Compatible with Claude Desktop, Cursor, and other MCP clients.\n *\n * Usage:\n * import { Minimem } from \"minimem\";\n * import { createMcpServer, runMcpServer } from \"minimem/mcp\";\n *\n * const minimem = await Minimem.create({ ... });\n * const server = createMcpServer(minimem);\n * await runMcpServer(server); // Runs over stdio\n */\n\nimport * as readline from \"node:readline\";\nimport type { Minimem } from \"../minimem.js\";\nimport {\n MEMORY_TOOLS,\n type ToolDefinition,\n type ToolResult,\n type MemoryInstance,\n MemoryToolExecutor,\n} from \"./tools.js\";\n\nconst PROTOCOL_VERSION = \"2024-11-05\";\nconst SERVER_NAME = \"minimem\";\nconst SERVER_VERSION = \"0.1.0\";\n\n/**\n * JSON-RPC 2.0 request\n */\ntype JsonRpcRequest = {\n jsonrpc: \"2.0\";\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * JSON-RPC 2.0 response\n */\ntype JsonRpcResponse = {\n jsonrpc: \"2.0\";\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n};\n\n/**\n * JSON-RPC 2.0 notification (no id)\n */\ntype JsonRpcNotification = {\n jsonrpc: \"2.0\";\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * MCP Server capabilities\n */\ntype ServerCapabilities = {\n tools?: {\n listChanged?: boolean;\n };\n};\n\n/**\n * MCP Server info\n */\ntype ServerInfo = {\n name: string;\n version: string;\n};\n\n/**\n * MCP Initialize result\n */\ntype InitializeResult = {\n protocolVersion: string;\n capabilities: ServerCapabilities;\n serverInfo: ServerInfo;\n};\n\n/**\n * MCP Tool in list format\n */\ntype McpTool = {\n name: string;\n description: string;\n inputSchema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n};\n\n/**\n * MCP Server implementation\n */\nexport class McpServer {\n private executor: MemoryToolExecutor;\n private initialized = false;\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n this.executor = new MemoryToolExecutor(instances);\n }\n\n /**\n * Handle a JSON-RPC request and return a response\n */\n async handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n const result = await this.dispatch(request.method, request.params);\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const code = err instanceof McpError ? err.code : -32603;\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: { code, message },\n };\n }\n }\n\n /**\n * Dispatch a method call\n */\n private async dispatch(\n method: string,\n params?: Record<string, unknown>,\n ): Promise<unknown> {\n switch (method) {\n case \"initialize\":\n return this.initialize(params);\n case \"initialized\":\n // Notification, no response needed\n return {};\n case \"tools/list\":\n return this.listTools();\n case \"tools/call\":\n return this.callTool(params);\n case \"ping\":\n return {};\n default:\n throw new McpError(-32601, `Method not found: ${method}`);\n }\n }\n\n /**\n * Handle initialize request\n */\n private initialize(\n params?: Record<string, unknown>,\n ): InitializeResult {\n this.initialized = true;\n return {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {\n tools: {\n listChanged: false,\n },\n },\n serverInfo: {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n };\n }\n\n /**\n * List available tools\n */\n private listTools(): { tools: McpTool[] } {\n const tools: McpTool[] = MEMORY_TOOLS.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n return { tools };\n }\n\n /**\n * Call a tool\n */\n private async callTool(\n params?: Record<string, unknown>,\n ): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> {\n if (!params?.name || typeof params.name !== \"string\") {\n throw new McpError(-32602, \"Missing tool name\");\n }\n\n const toolName = params.name;\n const toolParams = (params.arguments ?? {}) as Record<string, unknown>;\n\n const result = await this.executor.execute(toolName, toolParams);\n return result;\n }\n}\n\n/**\n * Custom error class for MCP errors\n */\nclass McpError extends Error {\n constructor(\n public code: number,\n message: string,\n ) {\n super(message);\n this.name = \"McpError\";\n }\n}\n\n/**\n * Create an MCP server for the given Minimem instance(s)\n */\nexport function createMcpServer(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): McpServer {\n return new McpServer(instances);\n}\n\n/**\n * Run the MCP server over stdio\n */\nexport async function runMcpServer(server: McpServer): Promise<void> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n const send = (message: JsonRpcResponse | JsonRpcNotification) => {\n const json = JSON.stringify(message);\n process.stdout.write(json + \"\\n\");\n };\n\n rl.on(\"line\", async (line) => {\n if (!line.trim()) return;\n\n try {\n const request = JSON.parse(line) as JsonRpcRequest;\n\n if (request.jsonrpc !== \"2.0\") {\n send({\n jsonrpc: \"2.0\",\n id: request.id ?? null,\n error: { code: -32600, message: \"Invalid JSON-RPC version\" },\n });\n return;\n }\n\n // Handle notification (no id)\n if (request.id === undefined) {\n await server.handleRequest({ ...request, id: 0 });\n return;\n }\n\n const response = await server.handleRequest(request);\n send(response);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n send({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32700, message: `Parse error: ${message}` },\n });\n }\n });\n\n rl.on(\"close\", () => {\n process.exit(0);\n });\n\n // Keep the process alive\n await new Promise(() => {});\n}\n\n/**\n * MCP server configuration for claude_desktop_config.json\n *\n * Example:\n * {\n * \"mcpServers\": {\n * \"minimem\": {\n * \"command\": \"node\",\n * \"args\": [\"path/to/your/mcp-server.js\"],\n * \"env\": {\n * \"MEMORY_DIR\": \"/path/to/memory\"\n * }\n * }\n * }\n * }\n */\nexport type McpServerConfig = {\n command: string;\n args: string[];\n env?: Record<string, string>;\n};\n\n/**\n * Generate MCP server config for Claude Desktop\n */\nexport function generateMcpConfig(opts: {\n serverPath: string;\n memoryDir: string;\n embeddingProvider?: \"openai\" | \"gemini\" | \"local\" | \"auto\";\n}): McpServerConfig {\n return {\n command: \"node\",\n args: [opts.serverPath],\n env: {\n MEMORY_DIR: opts.memoryDir,\n ...(opts.embeddingProvider ? { EMBEDDING_PROVIDER: opts.embeddingProvider } : {}),\n },\n };\n}\n","/**\n * Tool definitions for memory operations\n *\n * These tools are compatible with:\n * - MCP (Model Context Protocol)\n * - Anthropic Claude tool use\n * - OpenAI function calling\n *\n * Note: Only memory_search is provided since the memory system is file-based.\n * Agents can use filesystem tools directly for read/write operations.\n */\n\nimport type { Minimem, MinimemSearchResult } from \"../minimem.js\";\n\n/**\n * JSON Schema for tool parameters (MCP/OpenAI/Anthropic compatible)\n */\nexport type ToolInputSchema = {\n type: \"object\";\n properties: Record<\n string,\n {\n type: string;\n description?: string;\n enum?: string[];\n items?: { type: string };\n default?: unknown;\n }\n >;\n required?: string[];\n};\n\n/**\n * Tool definition compatible with MCP, Anthropic, and OpenAI\n */\nexport type ToolDefinition = {\n name: string;\n description: string;\n inputSchema: ToolInputSchema;\n};\n\n/**\n * Tool execution result\n */\nexport type ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n/**\n * Memory search tool parameters\n */\nexport type MemorySearchParams = {\n query: string;\n maxResults?: number;\n minScore?: number;\n directories?: string[];\n};\n\n/**\n * Search result with source directory\n */\ntype SearchResultWithSource = MinimemSearchResult & {\n memoryDir: string;\n};\n\nexport const MEMORY_SEARCH_TOOL: ToolDefinition = {\n name: \"memory_search\",\n description:\n \"Semantically search through memory files (MEMORY.md and memory/*.md). \" +\n \"Use this to recall prior decisions, facts, preferences, people, dates, or context. \" +\n \"Returns ranked snippets with file paths and line numbers. \" +\n \"When multiple memory directories are configured, searches all by default.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Natural language search query\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 10)\",\n },\n minScore: {\n type: \"number\",\n description: \"Minimum relevance score threshold 0-1 (default: 0.3)\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional: filter to specific memory directories by name/path. \" +\n \"If omitted, searches all configured directories.\",\n },\n },\n required: [\"query\"],\n },\n};\n\n/**\n * All available memory tools\n */\nexport const MEMORY_TOOLS: ToolDefinition[] = [MEMORY_SEARCH_TOOL];\n\n/**\n * Get tool definitions for use with LLM APIs\n */\nexport function getToolDefinitions(): ToolDefinition[] {\n return MEMORY_TOOLS;\n}\n\n/**\n * Memory instance with its directory path\n */\nexport type MemoryInstance = {\n minimem: Minimem;\n memoryDir: string;\n name?: string;\n};\n\n/**\n * Tool executor that handles memory search across multiple directories\n */\nexport class MemoryToolExecutor {\n private instances: MemoryInstance[];\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n // Normalize to array of MemoryInstance\n if (Array.isArray(instances)) {\n this.instances = instances;\n } else if (\"minimem\" in instances) {\n this.instances = [instances];\n } else {\n // Legacy: single Minimem instance without directory info\n this.instances = [{ minimem: instances, memoryDir: \"default\" }];\n }\n }\n\n /**\n * Get list of configured directory names/paths\n */\n getDirectories(): string[] {\n return this.instances.map((i) => i.name ?? i.memoryDir);\n }\n\n /**\n * Execute a tool by name with given parameters\n */\n async execute(\n toolName: string,\n params: Record<string, unknown>,\n ): Promise<ToolResult> {\n try {\n switch (toolName) {\n case \"memory_search\":\n return await this.memorySearch(params as MemorySearchParams);\n default:\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${toolName}` }],\n isError: true,\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n isError: true,\n };\n }\n }\n\n private async memorySearch(params: MemorySearchParams): Promise<ToolResult> {\n const maxResults = params.maxResults ?? 10;\n const minScore = params.minScore;\n\n // Filter instances by directories param if provided\n let instancesToSearch = this.instances;\n if (params.directories && params.directories.length > 0) {\n const dirFilter = new Set(params.directories.map((d) => d.toLowerCase()));\n instancesToSearch = this.instances.filter((i) => {\n const name = (i.name ?? i.memoryDir).toLowerCase();\n const dir = i.memoryDir.toLowerCase();\n return (\n dirFilter.has(name) ||\n dirFilter.has(dir) ||\n // Also match partial paths\n [...dirFilter].some((f) => dir.includes(f) || name.includes(f))\n );\n });\n\n if (instancesToSearch.length === 0) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [\n {\n type: \"text\",\n text: `No matching directories found. Available: ${available}`,\n },\n ],\n isError: true,\n };\n }\n }\n\n // Search all matching instances\n const allResults: SearchResultWithSource[] = [];\n\n for (const instance of instancesToSearch) {\n // Get more results per directory, then merge and trim\n const perDirMax = Math.ceil(maxResults * 1.5);\n const results = await instance.minimem.search(params.query, {\n maxResults: perDirMax,\n minScore,\n });\n\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n // Sort by score and limit\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No results found.\" }],\n };\n }\n\n // Format results\n const showSource = instancesToSearch.length > 1;\n const formatted = topResults\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(1);\n const source = showSource ? ` [${r.memoryDir}]` : \"\";\n return `[${i + 1}] ${location}${source} (${score}% match)\\n${r.snippet}`;\n })\n .join(\"\\n\\n\");\n\n const dirSummary =\n instancesToSearch.length > 1\n ? `\\n\\n(Searched ${instancesToSearch.length} directories)`\n : \"\";\n\n return {\n content: [{ type: \"text\", text: formatted + dirSummary }],\n };\n }\n}\n\n/**\n * Create a tool executor for the given Minimem instance(s)\n */\nexport function createToolExecutor(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): MemoryToolExecutor {\n return new MemoryToolExecutor(instances);\n}\n","/**\n * minimem config - View and manage configuration\n */\n\nimport {\n resolveMemoryDir,\n loadConfig,\n loadGlobalConfig,\n loadXdgConfig,\n saveConfig,\n saveXdgConfig,\n getConfigPath,\n getGlobalConfigPath,\n getXdgConfigPath,\n mergeConfig,\n getDefaultConfig,\n getSyncConfig,\n isInitialized,\n formatPath,\n type CliConfig,\n type GlobalConfig,\n} from \"../config.js\";\n\nexport type ConfigOptions = {\n dir?: string;\n global?: boolean;\n xdgGlobal?: boolean;\n json?: boolean;\n set?: string;\n unset?: string;\n};\n\nexport async function config(options: ConfigOptions): Promise<void> {\n // Handle --set and --unset\n if (options.set || options.unset) {\n await handleConfigEdit(options);\n return;\n }\n\n // Show config\n await showConfig(options);\n}\n\nasync function showConfig(options: ConfigOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n // Load configs\n const globalConfig = await loadGlobalConfig();\n const xdgConfig = await loadXdgConfig();\n const localConfig = await loadConfig(memoryDir);\n const mergedConfig = mergeConfig(localConfig);\n const syncConfig = await getSyncConfig(memoryDir);\n const defaults = getDefaultConfig();\n\n if (options.json) {\n console.log(JSON.stringify({\n effective: mergedConfig,\n local: localConfig,\n global: globalConfig,\n xdgGlobal: xdgConfig,\n syncConfig,\n defaults,\n }, null, 2));\n return;\n }\n\n console.log(\"Minimem Configuration\");\n console.log(\"=====================\");\n console.log();\n\n console.log(\"Config Files:\");\n console.log(` XDG Global: ${formatPath(getXdgConfigPath())}`);\n console.log(` Legacy Global: ${formatPath(getGlobalConfigPath())}`);\n console.log(` Local: ${formatPath(getConfigPath(memoryDir))}`);\n console.log();\n\n console.log(\"Effective Configuration:\");\n console.log(\"(merged from defaults → xdg global → legacy global → local)\");\n console.log();\n\n printConfigSection(\"Embedding\", {\n \"provider\": mergedConfig.embedding?.provider,\n \"model\": mergedConfig.embedding?.model || \"(provider default)\",\n \"fallback\": mergedConfig.embedding?.fallback || \"none\",\n });\n\n printConfigSection(\"Hybrid Search\", {\n \"enabled\": mergedConfig.hybrid?.enabled,\n \"vectorWeight\": mergedConfig.hybrid?.vectorWeight,\n \"textWeight\": mergedConfig.hybrid?.textWeight,\n });\n\n printConfigSection(\"Query Defaults\", {\n \"maxResults\": mergedConfig.query?.maxResults,\n \"minScore\": mergedConfig.query?.minScore,\n });\n\n printConfigSection(\"Chunking\", {\n \"tokens\": mergedConfig.chunking?.tokens,\n \"overlap\": mergedConfig.chunking?.overlap,\n });\n\n printConfigSection(\"Sync (Local)\", {\n \"enabled\": syncConfig.enabled,\n \"path\": syncConfig.path || \"(not configured)\",\n \"include\": syncConfig.include.join(\", \"),\n \"exclude\": syncConfig.exclude.length > 0 ? syncConfig.exclude.join(\", \") : \"(none)\",\n });\n\n printConfigSection(\"Sync (Global)\", {\n \"centralRepo\": syncConfig.centralRepo || \"(not configured)\",\n \"conflictStrategy\": syncConfig.conflictStrategy,\n \"autoSync\": syncConfig.autoSync,\n \"autoCommit\": syncConfig.autoCommit,\n \"mergeResolver\": syncConfig.mergeResolver || \"(default)\",\n });\n\n console.log();\n console.log(\"To modify configuration:\");\n console.log(\" minimem config --set embedding.provider=openai\");\n console.log(\" minimem config --set sync.enabled=true\");\n console.log(\" minimem config --set sync.path=myproject/\");\n console.log();\n console.log(\"Global sync settings (use --xdg-global flag):\");\n console.log(\" minimem config --xdg-global --set centralRepo=~/memories-repo\");\n console.log(\" minimem config --xdg-global --set sync.conflictStrategy=merge\");\n}\n\nfunction printConfigSection(title: string, values: Record<string, unknown>): void {\n console.log(` ${title}:`);\n for (const [key, value] of Object.entries(values)) {\n const displayValue = value === undefined ? \"(default)\" : String(value);\n console.log(` ${key}: ${displayValue}`);\n }\n}\n\nasync function handleConfigEdit(options: ConfigOptions): Promise<void> {\n // Handle XDG global config edits\n if (options.xdgGlobal) {\n await handleXdgConfigEdit(options);\n return;\n }\n\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n const configPath = getConfigPath(memoryDir);\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n // Load current config (just the local file, not merged)\n const currentConfig = await loadConfigFile(configPath);\n\n if (options.set) {\n const [keyPath, value] = options.set.split(\"=\");\n if (!keyPath || value === undefined) {\n console.error(\"Error: --set requires format: key.path=value\");\n console.error(\"Example: --set embedding.provider=openai\");\n process.exit(1);\n }\n\n const newConfig = setConfigValue(currentConfig, keyPath, parseValue(value));\n await saveConfig(memoryDir, newConfig);\n console.log(`Set ${keyPath}=${value} in ${formatPath(configPath)}`);\n }\n\n if (options.unset) {\n const keyPath = options.unset;\n const newConfig = unsetConfigValue(currentConfig, keyPath);\n await saveConfig(memoryDir, newConfig);\n console.log(`Unset ${keyPath} in ${formatPath(configPath)}`);\n }\n}\n\nasync function handleXdgConfigEdit(options: ConfigOptions): Promise<void> {\n const configPath = getXdgConfigPath();\n const currentConfig = await loadXdgConfig();\n\n if (options.set) {\n const [keyPath, value] = options.set.split(\"=\");\n if (!keyPath || value === undefined) {\n console.error(\"Error: --set requires format: key.path=value\");\n console.error(\"Example: --set centralRepo=~/memories-repo\");\n process.exit(1);\n }\n\n const newConfig = setConfigValue(currentConfig as Record<string, unknown>, keyPath, parseValue(value)) as GlobalConfig;\n await saveXdgConfig(newConfig);\n console.log(`Set ${keyPath}=${value} in ${formatPath(configPath)}`);\n }\n\n if (options.unset) {\n const keyPath = options.unset;\n const newConfig = unsetConfigValue(currentConfig as Record<string, unknown>, keyPath) as GlobalConfig;\n await saveXdgConfig(newConfig);\n console.log(`Unset ${keyPath} in ${formatPath(configPath)}`);\n }\n}\n\nasync function loadConfigFile(configPath: string): Promise<CliConfig> {\n const fs = await import(\"node:fs/promises\");\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as CliConfig;\n } catch {\n return {};\n }\n}\n\nfunction parseValue(value: string): unknown {\n // Try to parse as JSON (for booleans, numbers, etc.)\n try {\n return JSON.parse(value);\n } catch {\n // Return as string\n return value;\n }\n}\n\nfunction setConfigValue<T extends Record<string, unknown>>(config: T, keyPath: string, value: unknown): T {\n const parts = keyPath.split(\".\");\n const result = { ...config } as Record<string, unknown>;\n let current: Record<string, unknown> = result;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n if (!(key in current) || typeof current[key] !== \"object\") {\n current[key] = {};\n } else {\n current[key] = { ...(current[key] as Record<string, unknown>) };\n }\n current = current[key] as Record<string, unknown>;\n }\n\n current[parts[parts.length - 1]] = value;\n return result as T;\n}\n\nfunction unsetConfigValue<T extends Record<string, unknown>>(config: T, keyPath: string): T {\n const parts = keyPath.split(\".\");\n const result = { ...config } as Record<string, unknown>;\n let current: Record<string, unknown> = result;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n if (!(key in current) || typeof current[key] !== \"object\") {\n return result as T; // Path doesn't exist\n }\n current[key] = { ...(current[key] as Record<string, unknown>) };\n current = current[key] as Record<string, unknown>;\n }\n\n delete current[parts[parts.length - 1]];\n return result as T;\n}\n","/**\n * minimem sync init - Initialize sync for a memory directory\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n resolveMemoryDir,\n loadConfig,\n saveConfig,\n isInitialized,\n formatPath,\n getMachineId,\n expandPath,\n getDefaultSyncConfig,\n} from \"../config.js\";\nimport {\n getCentralRepoPath,\n initCentralRepo,\n validateCentralRepo,\n} from \"../sync/central.js\";\nimport {\n readRegistry,\n writeRegistry,\n checkCollision,\n addMapping,\n} from \"../sync/registry.js\";\nimport { detectDirectoryType } from \"../sync/detection.js\";\n\nexport type SyncInitOptions = {\n /** Memory directory to initialize sync for */\n local?: string;\n /** Path in central repo */\n path?: string;\n /** Use global ~/.minimem directory */\n global?: boolean;\n};\n\nexport type SyncInitCentralOptions = {\n /** Force creation even if directory exists */\n force?: boolean;\n};\n\n/**\n * Initialize a central repository\n */\nexport async function syncInitCentral(\n repoPath: string,\n options: SyncInitCentralOptions = {}\n): Promise<void> {\n console.log(`Initializing central repository at ${formatPath(repoPath)}...`);\n\n const result = await initCentralRepo(repoPath);\n\n if (!result.success) {\n console.error(`Error: ${result.message}`);\n process.exit(1);\n }\n\n if (result.created) {\n console.log(\" Created new git repository\");\n console.log(\" Created .gitignore\");\n console.log(\" Created .minimem-registry.json\");\n console.log(\" Created README.md\");\n } else {\n console.log(\" Configured existing directory\");\n }\n\n console.log();\n console.log(\"Central repository is ready!\");\n console.log(`Set as centralRepo in ~/.config/minimem/config.json`);\n console.log();\n console.log(\"Next steps:\");\n console.log(\" 1. Initialize sync for a memory directory:\");\n console.log(\" minimem sync init --path myproject/\");\n console.log();\n console.log(\" 2. Or from a different directory:\");\n console.log(\" minimem sync init --local ~/my-memories --path mymemories/\");\n}\n\n/**\n * Initialize sync for a memory directory\n */\nexport async function syncInit(options: SyncInitOptions): Promise<void> {\n // Resolve the memory directory\n const memoryDir = resolveMemoryDir({\n dir: options.local,\n global: options.global,\n });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n console.error(\"Run 'minimem init' first.\");\n process.exit(1);\n }\n\n // Check if --path is provided\n if (!options.path) {\n console.error(\"Error: --path is required.\");\n console.error(\"Example: minimem sync init --path myproject/\");\n process.exit(1);\n }\n\n const centralPath = options.path;\n\n // Get central repo\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n console.error(\"Error: No central repository configured.\");\n console.error(\"First initialize a central repository:\");\n console.error(\" minimem sync init-central ~/memories-repo\");\n process.exit(1);\n }\n\n // Validate central repo\n const validation = await validateCentralRepo(centralRepo);\n if (!validation.valid) {\n console.error(`Error: Central repository is invalid:`);\n for (const error of validation.errors) {\n console.error(` - ${error}`);\n }\n process.exit(1);\n }\n\n if (validation.warnings.length > 0) {\n console.log(\"Warnings about central repository:\");\n for (const warning of validation.warnings) {\n console.log(` - ${warning}`);\n }\n console.log();\n }\n\n // Get machine ID\n const machineId = await getMachineId();\n\n // Check for collisions\n const registry = await readRegistry(centralRepo);\n const collisionResult = checkCollision(registry, centralPath, memoryDir, machineId);\n\n if (collisionResult === \"collision\") {\n const existingMapping = registry.mappings.find(\n (m) => m.path === centralPath || m.path === `${centralPath}/`\n );\n console.error(`Error: Path '${centralPath}' is already mapped by another machine.`);\n if (existingMapping) {\n console.error(` Machine: ${existingMapping.machineId}`);\n console.error(` Local path: ${existingMapping.localPath}`);\n console.error(` Last sync: ${existingMapping.lastSync}`);\n }\n console.error();\n console.error(\"Choose a different path or remove the existing mapping.\");\n process.exit(1);\n }\n\n // Detect directory type\n const dirType = await detectDirectoryType(memoryDir);\n\n console.log(`Initializing sync for ${formatPath(memoryDir)}...`);\n console.log(` Directory type: ${dirType}`);\n console.log(` Central path: ${centralPath}`);\n console.log(` Machine ID: ${machineId}`);\n console.log();\n\n // Update local config\n const localConfig = await loadConfig(memoryDir);\n const syncDefaults = getDefaultSyncConfig();\n\n localConfig.sync = {\n enabled: true,\n path: centralPath,\n include: localConfig.sync?.include ?? syncDefaults.include,\n exclude: localConfig.sync?.exclude ?? syncDefaults.exclude,\n };\n\n await saveConfig(memoryDir, localConfig);\n console.log(\" Updated .minimem/config.json with sync settings\");\n\n // Update registry\n const updatedRegistry = addMapping(registry, {\n path: centralPath,\n localPath: memoryDir,\n machineId,\n lastSync: new Date().toISOString(),\n });\n\n await writeRegistry(centralRepo, updatedRegistry);\n console.log(\" Registered mapping in central repository\");\n\n // Create central path directory if it doesn't exist\n const centralDir = path.join(centralRepo, centralPath);\n try {\n await fs.mkdir(centralDir, { recursive: true });\n } catch {\n // Directory might already exist\n }\n\n console.log();\n console.log(\"Sync initialized successfully!\");\n console.log();\n console.log(\"Next steps:\");\n console.log(\" Push local files to central:\");\n console.log(\" minimem push\");\n console.log();\n console.log(\" Or pull from central:\");\n console.log(\" minimem pull\");\n}\n\n/**\n * List all sync mappings\n */\nexport async function syncList(): Promise<void> {\n const centralRepo = await getCentralRepoPath();\n\n if (!centralRepo) {\n console.log(\"No central repository configured.\");\n console.log(\"Run: minimem sync init-central <path>\");\n return;\n }\n\n const machineId = await getMachineId();\n const registry = await readRegistry(centralRepo);\n\n console.log(`Central Repository: ${formatPath(centralRepo)}`);\n console.log(`Machine ID: ${machineId}`);\n console.log();\n\n if (registry.mappings.length === 0) {\n console.log(\"No sync mappings registered.\");\n console.log(\"Run: minimem sync init --path <name>/\");\n return;\n }\n\n console.log(\"Registered Mappings:\");\n console.log(\"-\".repeat(80));\n\n for (const mapping of registry.mappings) {\n const isCurrentMachine = mapping.machineId === machineId;\n const marker = isCurrentMachine ? \" *\" : \" \";\n const lastSync = new Date(mapping.lastSync).toLocaleString();\n\n console.log(`${marker}Path: ${mapping.path}`);\n console.log(` Local: ${mapping.localPath}`);\n console.log(` Machine: ${mapping.machineId}`);\n console.log(` Last Sync: ${lastSync}`);\n console.log();\n }\n\n console.log(\"* = this machine\");\n}\n\n/**\n * Remove sync mapping for a directory\n */\nexport async function syncRemove(options: { local?: string; global?: boolean }): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.local,\n global: options.global,\n });\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n console.error(\"Error: No central repository configured.\");\n process.exit(1);\n }\n\n const localConfig = await loadConfig(memoryDir);\n if (!localConfig.sync?.path) {\n console.error(`Error: ${formatPath(memoryDir)} is not configured for sync.`);\n process.exit(1);\n }\n\n const centralPath = localConfig.sync.path;\n const machineId = await getMachineId();\n\n // Update local config\n delete localConfig.sync;\n await saveConfig(memoryDir, localConfig);\n console.log(`Removed sync config from ${formatPath(memoryDir)}`);\n\n // Update registry\n const registry = await readRegistry(centralRepo);\n const updatedRegistry = {\n ...registry,\n mappings: registry.mappings.filter(\n (m) => !(m.path === centralPath && m.machineId === machineId)\n ),\n };\n await writeRegistry(centralRepo, updatedRegistry);\n console.log(`Removed mapping from central registry`);\n\n console.log();\n console.log(\"Note: Files in the central repository were NOT deleted.\");\n console.log(`They remain at: ${formatPath(path.join(centralRepo, centralPath))}`);\n}\n","/**\n * Central repository initialization and management\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\nimport { expandPath, saveXdgConfig, loadXdgConfig } from \"../config.js\";\nimport {\n createEmptyRegistry,\n writeRegistry,\n readRegistry,\n getRegistryPath,\n} from \"./registry.js\";\nimport { isInsideGitRepo } from \"./detection.js\";\n\nconst GITIGNORE_CONTENT = `# Minimem sync - ignore database files and temp directories\n*.db\n*.db-journal\n*.db-wal\n*.db-shm\nstaging/\nconflicts/\nshadows/\n.DS_Store\n`;\n\nconst README_CONTENT = `# Minimem Central Repository\n\nThis repository contains synchronized memory files from minimem.\n\n## Structure\n\nEach directory represents a mapped memory location:\n\n\\`\\`\\`\nmemories-repo/\n├── global/ # ~/.minimem/\n├── work/ # ~/work/memories/\n└── projects/\n └── myproject/ # ~/projects/myproject/\n\\`\\`\\`\n\n## Registry\n\nThe \\`.minimem-registry.json\\` file tracks which local directories are mapped to which paths.\nThis prevents path collisions when multiple machines sync to the same repository.\n\n## Usage\n\nTo sync a local memory directory to this repo:\n\n\\`\\`\\`bash\nminimem config --xdg-global --set centralRepo=<path-to-this-repo>\nminimem sync init --path <directory-name>/\n\\`\\`\\`\n\n## Files\n\n- \\`.minimem-registry.json\\` - Tracks sync mappings\n- \\`.gitignore\\` - Ignores database and temp files\n- \\`*/MEMORY.md\\` - Main memory files\n- \\`*/memory/*.md\\` - Additional memory files\n`;\n\nexport type InitCentralResult = {\n success: boolean;\n path: string;\n created: boolean;\n message: string;\n};\n\n/**\n * Check if a path is writable\n */\nasync function isWritable(dirPath: string): Promise<boolean> {\n try {\n const testFile = path.join(dirPath, `.minimem-write-test-${Date.now()}`);\n await fs.writeFile(testFile, \"test\");\n await fs.unlink(testFile);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if git is available\n */\nfunction isGitAvailable(): boolean {\n try {\n execSync(\"git --version\", { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Initialize a git repository\n */\nasync function initGitRepo(dirPath: string): Promise<void> {\n execSync(\"git init\", { cwd: dirPath, stdio: \"pipe\" });\n}\n\n/**\n * Initialize a new central repository or configure an existing one\n */\nexport async function initCentralRepo(\n repoPath: string\n): Promise<InitCentralResult> {\n const expandedPath = expandPath(repoPath);\n const resolvedPath = path.resolve(expandedPath);\n\n // Check if git is available\n if (!isGitAvailable()) {\n return {\n success: false,\n path: resolvedPath,\n created: false,\n message: \"Git is not installed or not available in PATH\",\n };\n }\n\n // Check if directory exists\n let dirExists = false;\n try {\n const stat = await fs.stat(resolvedPath);\n dirExists = stat.isDirectory();\n } catch {\n dirExists = false;\n }\n\n let created = false;\n\n if (!dirExists) {\n // Create new directory\n try {\n await fs.mkdir(resolvedPath, { recursive: true });\n created = true;\n } catch (error) {\n return {\n success: false,\n path: resolvedPath,\n created: false,\n message: `Failed to create directory: ${error}`,\n };\n }\n }\n\n // Check if writable\n if (!(await isWritable(resolvedPath))) {\n return {\n success: false,\n path: resolvedPath,\n created,\n message: \"Directory is not writable\",\n };\n }\n\n // Initialize git repo if not already\n const isGitRepo = await isInsideGitRepo(resolvedPath);\n if (!isGitRepo) {\n try {\n await initGitRepo(resolvedPath);\n } catch (error) {\n return {\n success: false,\n path: resolvedPath,\n created,\n message: `Failed to initialize git repository: ${error}`,\n };\n }\n }\n\n // Create .gitignore if not exists\n const gitignorePath = path.join(resolvedPath, \".gitignore\");\n try {\n await fs.access(gitignorePath);\n } catch {\n await fs.writeFile(gitignorePath, GITIGNORE_CONTENT, \"utf-8\");\n }\n\n // Create registry if not exists\n const registryPath = getRegistryPath(resolvedPath);\n try {\n await fs.access(registryPath);\n } catch {\n await writeRegistry(resolvedPath, createEmptyRegistry());\n }\n\n // Create README if not exists\n const readmePath = path.join(resolvedPath, \"README.md\");\n try {\n await fs.access(readmePath);\n } catch {\n await fs.writeFile(readmePath, README_CONTENT, \"utf-8\");\n }\n\n // Update global config with central repo path\n const globalConfig = await loadXdgConfig();\n globalConfig.centralRepo = repoPath; // Store original (possibly with ~)\n await saveXdgConfig(globalConfig);\n\n return {\n success: true,\n path: resolvedPath,\n created,\n message: created\n ? \"Created new central repository\"\n : \"Configured existing directory as central repository\",\n };\n}\n\n/**\n * Validate an existing central repository\n */\nexport async function validateCentralRepo(repoPath: string): Promise<{\n valid: boolean;\n warnings: string[];\n errors: string[];\n}> {\n const expandedPath = expandPath(repoPath);\n const resolvedPath = path.resolve(expandedPath);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n // Check directory exists\n try {\n const stat = await fs.stat(resolvedPath);\n if (!stat.isDirectory()) {\n errors.push(\"Path is not a directory\");\n return { valid: false, warnings, errors };\n }\n } catch {\n errors.push(\"Directory does not exist\");\n return { valid: false, warnings, errors };\n }\n\n // Check if git repo\n const isGitRepo = await isInsideGitRepo(resolvedPath);\n if (!isGitRepo) {\n warnings.push(\"Not a git repository - sync features may be limited\");\n }\n\n // Check for registry\n const registryPath = getRegistryPath(resolvedPath);\n try {\n await fs.access(registryPath);\n // Validate registry content\n const registry = await readRegistry(resolvedPath);\n if (!registry.mappings) {\n warnings.push(\"Registry file is malformed\");\n }\n } catch {\n warnings.push(\"Registry file is missing - will be created on first sync\");\n }\n\n // Check for .gitignore\n const gitignorePath = path.join(resolvedPath, \".gitignore\");\n try {\n const gitignore = await fs.readFile(gitignorePath, \"utf-8\");\n if (!gitignore.includes(\"*.db\")) {\n warnings.push(\".gitignore does not exclude database files\");\n }\n } catch {\n warnings.push(\".gitignore is missing\");\n }\n\n // Check if writable\n if (!(await isWritable(resolvedPath))) {\n errors.push(\"Directory is not writable\");\n }\n\n return {\n valid: errors.length === 0,\n warnings,\n errors,\n };\n}\n\n/**\n * Get the configured central repo path\n */\nexport async function getCentralRepoPath(): Promise<string | undefined> {\n const globalConfig = await loadXdgConfig();\n if (globalConfig.centralRepo) {\n return path.resolve(expandPath(globalConfig.centralRepo));\n }\n return undefined;\n}\n","/**\n * Registry system for sync path collision prevention\n *\n * The registry is stored in the central repo as .minimem-registry.json\n * and tracks which local directories are mapped to which paths.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport crypto from \"node:crypto\";\n\nconst REGISTRY_FILENAME = \".minimem-registry.json\";\n\nexport type RegistryMapping = {\n /** Path in central repo (e.g., \"global/\", \"work/\") */\n path: string;\n /** Local directory path (with ~ for home) */\n localPath: string;\n /** Machine identifier */\n machineId: string;\n /** Last sync timestamp (ISO format) */\n lastSync: string;\n};\n\nexport type Registry = {\n version: number;\n mappings: RegistryMapping[];\n};\n\nexport type CollisionCheckResult = \"none\" | \"same-machine\" | \"collision\";\n\n/**\n * Get the registry file path for a central repo\n */\nexport function getRegistryPath(centralRepo: string): string {\n return path.join(centralRepo, REGISTRY_FILENAME);\n}\n\n/**\n * Create an empty registry\n */\nexport function createEmptyRegistry(): Registry {\n return {\n version: 1,\n mappings: [],\n };\n}\n\n/**\n * Read registry from central repo\n * Returns empty registry if file doesn't exist\n */\nexport async function readRegistry(centralRepo: string): Promise<Registry> {\n const registryPath = getRegistryPath(centralRepo);\n\n try {\n const content = await fs.readFile(registryPath, \"utf-8\");\n const registry = JSON.parse(content) as Registry;\n\n // Validate basic structure\n if (!registry.mappings || !Array.isArray(registry.mappings)) {\n return createEmptyRegistry();\n }\n\n return registry;\n } catch (error) {\n // File doesn't exist or is invalid\n return createEmptyRegistry();\n }\n}\n\n/**\n * Write registry to central repo atomically\n * Writes to temp file then renames to avoid corruption\n */\nexport async function writeRegistry(\n centralRepo: string,\n registry: Registry\n): Promise<void> {\n const registryPath = getRegistryPath(centralRepo);\n const tempPath = `${registryPath}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n\n // Ensure version is set\n registry.version = registry.version || 1;\n\n // Write to temp file\n await fs.writeFile(tempPath, JSON.stringify(registry, null, 2), \"utf-8\");\n\n // Atomic rename\n await fs.rename(tempPath, registryPath);\n}\n\n/**\n * Normalize a path for comparison\n * Expands ~ and resolves to absolute path\n */\nexport function normalizePath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.resolve(os.homedir(), filePath.slice(2));\n }\n if (filePath === \"~\") {\n return os.homedir();\n }\n return path.resolve(filePath);\n}\n\n/**\n * Compress a path for storage\n * Replaces home directory with ~\n */\nexport function compressPath(filePath: string): string {\n const home = os.homedir();\n const resolved = path.resolve(filePath);\n if (resolved.startsWith(home)) {\n return \"~\" + resolved.slice(home.length);\n }\n return resolved;\n}\n\n/**\n * Normalize central repo path (remove trailing slash, etc.)\n */\nexport function normalizeRepoPath(repoPath: string): string {\n // Remove trailing slashes but keep at least one char\n let normalized = repoPath.replace(/\\/+$/, \"\");\n if (normalized === \"\") {\n normalized = \"/\";\n }\n // Ensure it ends with / for directory paths (except root)\n if (!normalized.endsWith(\"/\") && normalized !== \"/\") {\n normalized += \"/\";\n }\n return normalized;\n}\n\n/**\n * Check if a path mapping would collide with existing mappings\n *\n * Returns:\n * - \"none\": path is free, can be used\n * - \"same-machine\": same machine already has this path, can update\n * - \"collision\": different machine has this path, blocked\n */\nexport function checkCollision(\n registry: Registry,\n centralPath: string,\n localPath: string,\n machineId: string\n): CollisionCheckResult {\n const normalizedCentralPath = normalizeRepoPath(centralPath);\n const normalizedLocalPath = normalizePath(localPath);\n\n for (const mapping of registry.mappings) {\n const mappingCentralPath = normalizeRepoPath(mapping.path);\n const mappingLocalPath = normalizePath(mapping.localPath);\n\n // Check if central path matches\n if (mappingCentralPath === normalizedCentralPath) {\n // Same machine, same or different local path - can update\n if (mapping.machineId === machineId) {\n return \"same-machine\";\n }\n\n // Different machine - collision\n return \"collision\";\n }\n }\n\n return \"none\";\n}\n\n/**\n * Add or update a mapping in the registry\n */\nexport function addMapping(\n registry: Registry,\n mapping: RegistryMapping\n): Registry {\n const normalizedPath = normalizeRepoPath(mapping.path);\n const normalizedLocalPath = compressPath(mapping.localPath);\n\n // Remove existing mapping for this path+machine combination\n const filteredMappings = registry.mappings.filter(\n (m) =>\n !(\n normalizeRepoPath(m.path) === normalizedPath &&\n m.machineId === mapping.machineId\n )\n );\n\n // Add new mapping\n filteredMappings.push({\n ...mapping,\n path: normalizedPath,\n localPath: normalizedLocalPath,\n });\n\n return {\n ...registry,\n mappings: filteredMappings,\n };\n}\n\n/**\n * Remove a mapping from the registry\n */\nexport function removeMapping(\n registry: Registry,\n centralPath: string,\n machineId: string\n): Registry {\n const normalizedPath = normalizeRepoPath(centralPath);\n\n const filteredMappings = registry.mappings.filter(\n (m) =>\n !(normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId)\n );\n\n return {\n ...registry,\n mappings: filteredMappings,\n };\n}\n\n/**\n * Find a mapping by central path and machine ID\n */\nexport function findMapping(\n registry: Registry,\n centralPath: string,\n machineId: string\n): RegistryMapping | undefined {\n const normalizedPath = normalizeRepoPath(centralPath);\n\n return registry.mappings.find(\n (m) =>\n normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId\n );\n}\n\n/**\n * Get all mappings for a specific machine\n */\nexport function getMachineMappings(\n registry: Registry,\n machineId: string\n): RegistryMapping[] {\n return registry.mappings.filter((m) => m.machineId === machineId);\n}\n\n/**\n * Update the lastSync timestamp for a mapping\n */\nexport function updateLastSync(\n registry: Registry,\n centralPath: string,\n machineId: string\n): Registry {\n const normalizedPath = normalizeRepoPath(centralPath);\n\n const mappings = registry.mappings.map((m) => {\n if (\n normalizeRepoPath(m.path) === normalizedPath &&\n m.machineId === machineId\n ) {\n return {\n ...m,\n lastSync: new Date().toISOString(),\n };\n }\n return m;\n });\n\n return {\n ...registry,\n mappings,\n };\n}\n","/**\n * Directory type detection for sync system\n *\n * Detects whether a memory directory is:\n * - project-bound: inside git repo, no sync config\n * - standalone: has sync config, not inside git repo\n * - hybrid: inside git repo AND has sync config\n * - unmanaged: no git repo, no sync config\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getConfigPath } from \"../config.js\";\n\nexport type DirectoryType = \"project-bound\" | \"standalone\" | \"hybrid\" | \"unmanaged\";\n\n/**\n * Check if a directory is inside a git repository\n * Walks up the directory tree looking for .git\n */\nexport async function isInsideGitRepo(dir: string): Promise<boolean> {\n let current = path.resolve(dir);\n const root = path.parse(current).root;\n\n while (current !== root) {\n try {\n const gitPath = path.join(current, \".git\");\n const stat = await fs.stat(gitPath);\n if (stat.isDirectory() || stat.isFile()) {\n // .git can be a file in worktrees\n return true;\n }\n } catch {\n // .git doesn't exist at this level, continue up\n }\n current = path.dirname(current);\n }\n\n return false;\n}\n\n/**\n * Get the root of the git repository containing a directory\n * Returns undefined if not inside a git repo\n */\nexport async function getGitRoot(dir: string): Promise<string | undefined> {\n let current = path.resolve(dir);\n const root = path.parse(current).root;\n\n while (current !== root) {\n try {\n const gitPath = path.join(current, \".git\");\n const stat = await fs.stat(gitPath);\n if (stat.isDirectory() || stat.isFile()) {\n return current;\n }\n } catch {\n // Continue up\n }\n current = path.dirname(current);\n }\n\n return undefined;\n}\n\n/**\n * Check if a directory has sync configuration enabled\n */\nexport async function hasSyncConfig(dir: string): Promise<boolean> {\n const configPath = getConfigPath(dir);\n\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n const config = JSON.parse(content);\n // Check if sync is explicitly enabled or has a path configured\n return config.sync?.enabled === true || typeof config.sync?.path === \"string\";\n } catch {\n return false;\n }\n}\n\n/**\n * Detect the directory type based on git repo presence and sync config\n *\n * Decision matrix:\n * | Sync Config | In Git Repo | Result |\n * |-------------|-------------|---------------|\n * | Yes | Yes | hybrid |\n * | Yes | No | standalone |\n * | No | Yes | project-bound |\n * | No | No | unmanaged |\n */\nexport async function detectDirectoryType(dir: string): Promise<DirectoryType> {\n const [hasSync, inGit] = await Promise.all([\n hasSyncConfig(dir),\n isInsideGitRepo(dir),\n ]);\n\n if (hasSync && inGit) {\n return \"hybrid\";\n } else if (hasSync && !inGit) {\n return \"standalone\";\n } else if (!hasSync && inGit) {\n return \"project-bound\";\n } else {\n return \"unmanaged\";\n }\n}\n\n/**\n * Get detailed directory info including type and git root\n */\nexport async function getDirectoryInfo(dir: string): Promise<{\n type: DirectoryType;\n gitRoot?: string;\n hasSyncConfig: boolean;\n}> {\n const [hasSync, gitRoot] = await Promise.all([\n hasSyncConfig(dir),\n getGitRoot(dir),\n ]);\n\n const inGit = gitRoot !== undefined;\n\n let type: DirectoryType;\n if (hasSync && inGit) {\n type = \"hybrid\";\n } else if (hasSync && !inGit) {\n type = \"standalone\";\n } else if (!hasSync && inGit) {\n type = \"project-bound\";\n } else {\n type = \"unmanaged\";\n }\n\n return {\n type,\n gitRoot,\n hasSyncConfig: hasSync,\n };\n}\n","/**\n * Sync operations - push and pull\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\nimport { getSyncConfig, expandPath } from \"../config.js\";\nimport { getCentralRepoPath } from \"./central.js\";\nimport {\n loadSyncState,\n saveSyncState,\n listSyncableFiles,\n computeFileHash,\n getFileSyncStatus,\n type SyncState,\n} from \"./state.js\";\nimport { detectConflicts, quarantineConflict, type FileConflict } from \"./conflicts.js\";\nimport { readRegistry, writeRegistry, updateLastSync } from \"./registry.js\";\nimport { getMachineId } from \"../config.js\";\nimport { appendSyncLog, type SyncLogEntry } from \"../commands/conflicts.js\";\n\nexport type SyncResult = {\n success: boolean;\n pushed: string[];\n pulled: string[];\n conflicts: string[];\n errors: string[];\n skipped: string[];\n};\n\n/**\n * Ensure a directory exists\n */\nasync function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Copy a file atomically via temp file\n */\nasync function copyFileAtomic(src: string, dest: string): Promise<void> {\n const destDir = path.dirname(dest);\n await ensureDir(destDir);\n\n const tempDest = `${dest}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n\n try {\n await fs.copyFile(src, tempDest);\n await fs.rename(tempDest, dest);\n } catch (error) {\n // Clean up temp file on error\n try {\n await fs.unlink(tempDest);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n}\n\n/**\n * Apply keep-both merge strategy\n */\nfunction keepBothMerge(\n localContent: string,\n remoteContent: string,\n localTimestamp: string,\n remoteTimestamp: string\n): string {\n return `<<<<<<< LOCAL (${localTimestamp})\n${localContent}\n=======\n${remoteContent}\n>>>>>>> REMOTE (${remoteTimestamp})\n`;\n}\n\n/**\n * Push local changes to central repository\n */\nexport async function push(\n memoryDir: string,\n options: {\n force?: boolean;\n dryRun?: boolean;\n } = {}\n): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n pushed: [],\n pulled: [],\n conflicts: [],\n errors: [],\n skipped: [],\n };\n\n // Get config\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.enabled || !syncConfig.path) {\n result.success = false;\n result.errors.push(\"Sync not configured for this directory\");\n return result;\n }\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n result.success = false;\n result.errors.push(\"No central repository configured\");\n return result;\n }\n\n const remotePath = path.join(centralRepo, syncConfig.path);\n\n // Detect conflicts\n const detection = await detectConflicts(memoryDir);\n\n // Load state\n const state = await loadSyncState(memoryDir, syncConfig.path);\n\n // Process changes\n for (const change of detection.changes) {\n const localPath = path.join(memoryDir, change.file);\n const remoteFilePath = path.join(remotePath, change.file);\n\n try {\n switch (change.status) {\n case \"local-only\":\n case \"new-local\":\n // Push local to remote\n if (!options.dryRun) {\n await copyFileAtomic(localPath, remoteFilePath);\n const hash = await computeFileHash(localPath);\n state.files[change.file] = {\n localHash: hash,\n remoteHash: hash,\n lastSyncedHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pushed.push(change.file);\n break;\n\n case \"deleted-remote\":\n // Local file was deleted remotely, skip (don't push deletion)\n result.skipped.push(change.file);\n break;\n\n case \"conflict\":\n if (options.force) {\n // Force push - overwrite remote\n if (!options.dryRun) {\n await copyFileAtomic(localPath, remoteFilePath);\n const hash = await computeFileHash(localPath);\n state.files[change.file] = {\n localHash: hash,\n remoteHash: hash,\n lastSyncedHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pushed.push(change.file);\n } else {\n // Handle conflict with keep-both strategy\n if (!options.dryRun && syncConfig.conflictStrategy === \"keep-both\") {\n const localContent = await fs.readFile(localPath, \"utf-8\");\n const remoteContent = await fs.readFile(remoteFilePath, \"utf-8\");\n const merged = keepBothMerge(\n localContent,\n remoteContent,\n new Date().toISOString(),\n new Date().toISOString()\n );\n await fs.writeFile(localPath, merged);\n await fs.writeFile(remoteFilePath, merged);\n const hash = computeFileHash(localPath);\n result.pushed.push(change.file);\n } else {\n result.conflicts.push(change.file);\n result.success = false;\n }\n }\n break;\n\n default:\n // remote-only, new-remote, deleted-local - skip on push\n result.skipped.push(change.file);\n break;\n }\n } catch (error) {\n result.errors.push(`${change.file}: ${error}`);\n result.success = false;\n }\n }\n\n // Save state and update registry\n if (!options.dryRun && result.pushed.length > 0) {\n state.lastSync = new Date().toISOString();\n await saveSyncState(memoryDir, state);\n\n // Update registry lastSync\n const machineId = await getMachineId();\n const registry = await readRegistry(centralRepo);\n const updatedRegistry = updateLastSync(registry, syncConfig.path, machineId);\n await writeRegistry(centralRepo, updatedRegistry);\n }\n\n // Log the sync operation\n if (!options.dryRun) {\n const logEntry: SyncLogEntry = {\n timestamp: new Date().toISOString(),\n operation: \"push\",\n result: result.success ? (result.conflicts.length > 0 ? \"partial\" : \"success\") : \"failure\",\n pushed: result.pushed.length,\n conflicts: result.conflicts.length,\n errors: result.errors.length > 0 ? result.errors : undefined,\n };\n await appendSyncLog(memoryDir, logEntry);\n }\n\n return result;\n}\n\n/**\n * Pull changes from central repository\n */\nexport async function pull(\n memoryDir: string,\n options: {\n force?: boolean;\n dryRun?: boolean;\n } = {}\n): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n pushed: [],\n pulled: [],\n conflicts: [],\n errors: [],\n skipped: [],\n };\n\n // Get config\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.enabled || !syncConfig.path) {\n result.success = false;\n result.errors.push(\"Sync not configured for this directory\");\n return result;\n }\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n result.success = false;\n result.errors.push(\"No central repository configured\");\n return result;\n }\n\n const remotePath = path.join(centralRepo, syncConfig.path);\n\n // Detect conflicts\n const detection = await detectConflicts(memoryDir);\n\n // Load state\n const state = await loadSyncState(memoryDir, syncConfig.path);\n\n // Process changes\n for (const change of detection.changes) {\n const localPath = path.join(memoryDir, change.file);\n const remoteFilePath = path.join(remotePath, change.file);\n\n try {\n switch (change.status) {\n case \"remote-only\":\n case \"new-remote\":\n // Pull remote to local\n if (!options.dryRun) {\n await copyFileAtomic(remoteFilePath, localPath);\n const hash = await computeFileHash(localPath);\n state.files[change.file] = {\n localHash: hash,\n remoteHash: hash,\n lastSyncedHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pulled.push(change.file);\n break;\n\n case \"deleted-local\":\n // Remote file was deleted locally, skip (don't pull deletion)\n result.skipped.push(change.file);\n break;\n\n case \"conflict\":\n if (options.force) {\n // Force pull - overwrite local\n if (!options.dryRun) {\n await copyFileAtomic(remoteFilePath, localPath);\n const hash = await computeFileHash(localPath);\n state.files[change.file] = {\n localHash: hash,\n remoteHash: hash,\n lastSyncedHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pulled.push(change.file);\n } else {\n // Handle conflict with keep-both strategy\n if (!options.dryRun && syncConfig.conflictStrategy === \"keep-both\") {\n const localContent = await fs.readFile(localPath, \"utf-8\");\n const remoteContent = await fs.readFile(remoteFilePath, \"utf-8\");\n const merged = keepBothMerge(\n localContent,\n remoteContent,\n new Date().toISOString(),\n new Date().toISOString()\n );\n await fs.writeFile(localPath, merged);\n await fs.writeFile(remoteFilePath, merged);\n result.pulled.push(change.file);\n } else {\n result.conflicts.push(change.file);\n result.success = false;\n }\n }\n break;\n\n default:\n // local-only, new-local, deleted-remote - skip on pull\n result.skipped.push(change.file);\n break;\n }\n } catch (error) {\n result.errors.push(`${change.file}: ${error}`);\n result.success = false;\n }\n }\n\n // Save state and update registry\n if (!options.dryRun && result.pulled.length > 0) {\n state.lastSync = new Date().toISOString();\n await saveSyncState(memoryDir, state);\n\n // Update registry lastSync\n const machineId = await getMachineId();\n const registry = await readRegistry(centralRepo);\n const updatedRegistry = updateLastSync(registry, syncConfig.path, machineId);\n await writeRegistry(centralRepo, updatedRegistry);\n }\n\n // Log the sync operation\n if (!options.dryRun) {\n const logEntry: SyncLogEntry = {\n timestamp: new Date().toISOString(),\n operation: \"pull\",\n result: result.success ? (result.conflicts.length > 0 ? \"partial\" : \"success\") : \"failure\",\n pulled: result.pulled.length,\n conflicts: result.conflicts.length,\n errors: result.errors.length > 0 ? result.errors : undefined,\n };\n await appendSyncLog(memoryDir, logEntry);\n }\n\n return result;\n}\n\n/**\n * Bidirectional sync - push local changes, pull remote changes\n */\nexport async function bidirectionalSync(\n memoryDir: string,\n options: {\n force?: boolean;\n dryRun?: boolean;\n } = {}\n): Promise<SyncResult> {\n // First push, then pull\n const pushResult = await push(memoryDir, options);\n const pullResult = await pull(memoryDir, options);\n\n return {\n success: pushResult.success && pullResult.success,\n pushed: pushResult.pushed,\n pulled: pullResult.pulled,\n conflicts: [...new Set([...pushResult.conflicts, ...pullResult.conflicts])],\n errors: [...pushResult.errors, ...pullResult.errors],\n skipped: [...new Set([...pushResult.skipped, ...pullResult.skipped])],\n };\n}\n","/**\n * Sync state tracking with content hashing\n *\n * Tracks file hashes to detect changes and conflicts between\n * local directories and the central repository.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { minimatch } from \"minimatch\";\n\nconst STATE_FILENAME = \"sync-state.json\";\nconst STATE_DIR = \".minimem\";\n\nexport type FileHashInfo = {\n /** SHA-256 hash of local file content */\n localHash: string;\n /** SHA-256 hash of remote file content */\n remoteHash: string;\n /** Hash at last successful sync (the common base) */\n lastSyncedHash: string;\n /** Last modified timestamp (ISO) */\n lastModified: string;\n};\n\nexport type SyncState = {\n /** Version for future migrations */\n version: number;\n /** Last sync timestamp (ISO) */\n lastSync: string | null;\n /** Central repo path this directory syncs to */\n centralPath: string;\n /** File hashes keyed by relative path */\n files: Record<string, FileHashInfo>;\n};\n\n/**\n * Get the sync state file path for a directory\n */\nexport function getSyncStatePath(dir: string): string {\n return path.join(dir, STATE_DIR, STATE_FILENAME);\n}\n\n/**\n * Create an empty sync state\n */\nexport function createEmptySyncState(centralPath: string): SyncState {\n return {\n version: 1,\n lastSync: null,\n centralPath,\n files: {},\n };\n}\n\n/**\n * Load sync state from a directory\n * Returns empty state if file doesn't exist\n */\nexport async function loadSyncState(\n dir: string,\n centralPath: string\n): Promise<SyncState> {\n const statePath = getSyncStatePath(dir);\n\n try {\n const content = await fs.readFile(statePath, \"utf-8\");\n const state = JSON.parse(content) as SyncState;\n\n // Validate basic structure\n if (!state.files || typeof state.files !== \"object\") {\n return createEmptySyncState(centralPath);\n }\n\n // Update centralPath if it changed\n state.centralPath = centralPath;\n\n return state;\n } catch {\n return createEmptySyncState(centralPath);\n }\n}\n\n/**\n * Save sync state atomically\n */\nexport async function saveSyncState(\n dir: string,\n state: SyncState\n): Promise<void> {\n const statePath = getSyncStatePath(dir);\n const stateDir = path.dirname(statePath);\n const tempPath = `${statePath}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n\n // Ensure directory exists\n await fs.mkdir(stateDir, { recursive: true });\n\n // Ensure version is set\n state.version = state.version || 1;\n\n // Write to temp file\n await fs.writeFile(tempPath, JSON.stringify(state, null, 2), \"utf-8\");\n\n // Atomic rename\n await fs.rename(tempPath, statePath);\n}\n\n/**\n * Compute SHA-256 hash of a file's content\n */\nexport async function computeFileHash(filePath: string): Promise<string> {\n const content = await fs.readFile(filePath);\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/**\n * Compute hash of string content\n */\nexport function computeContentHash(content: string | Buffer): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/**\n * List files matching include/exclude patterns\n */\nexport async function listSyncableFiles(\n dir: string,\n include: string[],\n exclude: string[]\n): Promise<string[]> {\n const files: string[] = [];\n\n async function walkDir(currentDir: string, relativePath: string = \"\") {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(currentDir, entry.name);\n const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;\n\n // Skip .minimem directory\n if (entry.name === \".minimem\") continue;\n\n if (entry.isDirectory()) {\n await walkDir(entryPath, relPath);\n } else if (entry.isFile()) {\n // Check include patterns\n const matchesInclude = include.some((pattern) =>\n minimatch(relPath, pattern)\n );\n\n // Check exclude patterns\n const matchesExclude = exclude.some((pattern) =>\n minimatch(relPath, pattern)\n );\n\n if (matchesInclude && !matchesExclude) {\n files.push(relPath);\n }\n }\n }\n }\n\n try {\n await walkDir(dir);\n } catch (error) {\n // Directory might not exist yet\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n return files.sort();\n}\n\n/**\n * Get file hash info, computing hash if file exists\n */\nexport async function getFileHashInfo(\n filePath: string\n): Promise<{ exists: boolean; hash?: string; mtime?: string }> {\n try {\n const stat = await fs.stat(filePath);\n const hash = await computeFileHash(filePath);\n return {\n exists: true,\n hash,\n mtime: stat.mtime.toISOString(),\n };\n } catch {\n return { exists: false };\n }\n}\n\n/**\n * Compare local and remote files to determine sync status\n */\nexport type FileSyncStatus =\n | \"unchanged\" // Both same, matches last sync\n | \"local-only\" // Only local changed\n | \"remote-only\" // Only remote changed\n | \"conflict\" // Both changed differently\n | \"new-local\" // New file locally\n | \"new-remote\" // New file on remote\n | \"deleted-local\" // Deleted locally\n | \"deleted-remote\"; // Deleted on remote\n\nexport function getFileSyncStatus(\n localHash: string | null,\n remoteHash: string | null,\n lastSyncedHash: string | null\n): FileSyncStatus {\n // Both exist and are the same\n if (localHash && remoteHash && localHash === remoteHash) {\n return \"unchanged\";\n }\n\n // New files (no last sync record)\n if (!lastSyncedHash) {\n if (localHash && !remoteHash) return \"new-local\";\n if (!localHash && remoteHash) return \"new-remote\";\n if (localHash && remoteHash && localHash !== remoteHash) return \"conflict\";\n }\n\n // Deletions\n if (lastSyncedHash && !localHash && remoteHash === lastSyncedHash) {\n return \"deleted-local\";\n }\n if (lastSyncedHash && !remoteHash && localHash === lastSyncedHash) {\n return \"deleted-remote\";\n }\n\n // Changes since last sync\n if (lastSyncedHash) {\n const localChanged = localHash !== lastSyncedHash;\n const remoteChanged = remoteHash !== lastSyncedHash;\n\n if (localChanged && !remoteChanged) return \"local-only\";\n if (!localChanged && remoteChanged) return \"remote-only\";\n if (localChanged && remoteChanged) {\n // Both changed - conflict if they're different\n if (localHash !== remoteHash) return \"conflict\";\n // Both changed to same value - unchanged\n return \"unchanged\";\n }\n }\n\n return \"unchanged\";\n}\n\n/**\n * Update sync state after a successful sync\n */\nexport function updateSyncStateAfterSync(\n state: SyncState,\n filePath: string,\n hash: string\n): SyncState {\n return {\n ...state,\n lastSync: new Date().toISOString(),\n files: {\n ...state.files,\n [filePath]: {\n localHash: hash,\n remoteHash: hash,\n lastSyncedHash: hash,\n lastModified: new Date().toISOString(),\n },\n },\n };\n}\n\n/**\n * Remove a file from sync state\n */\nexport function removeFileFromSyncState(\n state: SyncState,\n filePath: string\n): SyncState {\n const { [filePath]: _, ...remainingFiles } = state.files;\n return {\n ...state,\n files: remainingFiles,\n };\n}\n\n/**\n * Build a complete sync state by scanning files\n */\nexport async function buildSyncState(\n localDir: string,\n remoteDir: string,\n centralPath: string,\n include: string[],\n exclude: string[],\n existingState?: SyncState\n): Promise<{\n state: SyncState;\n changes: Array<{\n file: string;\n status: FileSyncStatus;\n localHash: string | null;\n remoteHash: string | null;\n }>;\n}> {\n const state = existingState || createEmptySyncState(centralPath);\n const changes: Array<{\n file: string;\n status: FileSyncStatus;\n localHash: string | null;\n remoteHash: string | null;\n }> = [];\n\n // Get all files from both sides\n const [localFiles, remoteFiles] = await Promise.all([\n listSyncableFiles(localDir, include, exclude),\n listSyncableFiles(remoteDir, include, exclude),\n ]);\n\n const allFiles = new Set([...localFiles, ...remoteFiles]);\n\n for (const file of allFiles) {\n const localPath = path.join(localDir, file);\n const remotePath = path.join(remoteDir, file);\n\n const [localInfo, remoteInfo] = await Promise.all([\n getFileHashInfo(localPath),\n getFileHashInfo(remotePath),\n ]);\n\n const existingEntry = state.files[file];\n const lastSyncedHash = existingEntry?.lastSyncedHash ?? null;\n\n const status = getFileSyncStatus(\n localInfo.hash ?? null,\n remoteInfo.hash ?? null,\n lastSyncedHash\n );\n\n if (status !== \"unchanged\") {\n changes.push({\n file,\n status,\n localHash: localInfo.hash ?? null,\n remoteHash: remoteInfo.hash ?? null,\n });\n }\n\n // Update state with current hashes\n state.files[file] = {\n localHash: localInfo.hash ?? existingEntry?.localHash ?? \"\",\n remoteHash: remoteInfo.hash ?? existingEntry?.remoteHash ?? \"\",\n lastSyncedHash: existingEntry?.lastSyncedHash ?? \"\",\n lastModified: localInfo.mtime ?? remoteInfo.mtime ?? new Date().toISOString(),\n };\n }\n\n return { state, changes };\n}\n","/**\n * Conflict detection and resolution\n *\n * Detects when files have changed on both local and remote since the last sync,\n * and provides mechanisms to resolve conflicts.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { getSyncConfig } from \"../config.js\";\nimport {\n loadSyncState,\n saveSyncState,\n listSyncableFiles,\n getFileHashInfo,\n getFileSyncStatus,\n type FileSyncStatus,\n type SyncState,\n} from \"./state.js\";\nimport { getCentralRepoPath } from \"./central.js\";\n\nconst SHADOWS_DIR = \"shadows\";\nconst CONFLICTS_DIR = \"conflicts\";\n\nexport type FileConflict = {\n /** Relative file path */\n file: string;\n /** Sync status */\n status: FileSyncStatus;\n /** Local file hash (null if deleted/missing) */\n localHash: string | null;\n /** Remote file hash (null if deleted/missing) */\n remoteHash: string | null;\n /** Last synced hash (null if new file) */\n baseHash: string | null;\n};\n\nexport type ConflictDetectionResult = {\n /** Files that need action */\n changes: FileConflict[];\n /** Files with no changes */\n unchanged: string[];\n /** Summary counts */\n summary: {\n unchanged: number;\n localOnly: number;\n remoteOnly: number;\n conflicts: number;\n newLocal: number;\n newRemote: number;\n deletedLocal: number;\n deletedRemote: number;\n };\n};\n\n/**\n * Get the shadows directory path\n */\nexport function getShadowsDir(memoryDir: string): string {\n return path.join(memoryDir, \".minimem\", SHADOWS_DIR);\n}\n\n/**\n * Get the conflicts directory path\n */\nexport function getConflictsDir(memoryDir: string): string {\n return path.join(memoryDir, \".minimem\", CONFLICTS_DIR);\n}\n\n/**\n * Get shadow file path for a given file\n */\nexport function getShadowPath(memoryDir: string, filePath: string): string {\n // Flatten path for shadow storage\n const flatName = filePath.replace(/\\//g, \"_\");\n return path.join(getShadowsDir(memoryDir), `${flatName}.base`);\n}\n\n/**\n * Create a shadow copy of a file's content\n */\nexport async function createShadowCopy(\n memoryDir: string,\n filePath: string,\n content: string | Buffer\n): Promise<void> {\n const shadowPath = getShadowPath(memoryDir, filePath);\n await fs.mkdir(path.dirname(shadowPath), { recursive: true });\n await fs.writeFile(shadowPath, content);\n}\n\n/**\n * Read a shadow copy if it exists\n */\nexport async function readShadowCopy(\n memoryDir: string,\n filePath: string\n): Promise<string | null> {\n const shadowPath = getShadowPath(memoryDir, filePath);\n try {\n return await fs.readFile(shadowPath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Delete a shadow copy\n */\nexport async function deleteShadowCopy(\n memoryDir: string,\n filePath: string\n): Promise<void> {\n const shadowPath = getShadowPath(memoryDir, filePath);\n try {\n await fs.unlink(shadowPath);\n } catch {\n // File might not exist\n }\n}\n\n/**\n * Clean up all shadow copies\n */\nexport async function cleanShadows(memoryDir: string): Promise<void> {\n const shadowsDir = getShadowsDir(memoryDir);\n try {\n await fs.rm(shadowsDir, { recursive: true, force: true });\n } catch {\n // Directory might not exist\n }\n}\n\n/**\n * Quarantine a conflicted file\n * Saves local, remote, and base versions to conflicts directory\n */\nexport async function quarantineConflict(\n memoryDir: string,\n filePath: string,\n localContent: string | Buffer | null,\n remoteContent: string | Buffer | null,\n baseContent: string | Buffer | null\n): Promise<string> {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const conflictDir = path.join(getConflictsDir(memoryDir), timestamp);\n const flatName = filePath.replace(/\\//g, \"_\");\n\n await fs.mkdir(conflictDir, { recursive: true });\n\n if (localContent !== null) {\n await fs.writeFile(path.join(conflictDir, `${flatName}.local`), localContent);\n }\n if (remoteContent !== null) {\n await fs.writeFile(path.join(conflictDir, `${flatName}.remote`), remoteContent);\n }\n if (baseContent !== null) {\n await fs.writeFile(path.join(conflictDir, `${flatName}.base`), baseContent);\n }\n\n return conflictDir;\n}\n\n/**\n * List all quarantined conflicts\n */\nexport async function listQuarantinedConflicts(\n memoryDir: string\n): Promise<Array<{ timestamp: string; files: string[] }>> {\n const conflictsDir = getConflictsDir(memoryDir);\n const conflicts: Array<{ timestamp: string; files: string[] }> = [];\n\n try {\n const entries = await fs.readdir(conflictsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const dirPath = path.join(conflictsDir, entry.name);\n const files = await fs.readdir(dirPath);\n\n // Extract unique file names (remove .local, .remote, .base suffixes)\n const uniqueFiles = new Set<string>();\n for (const file of files) {\n const baseName = file.replace(/\\.(local|remote|base)$/, \"\");\n uniqueFiles.add(baseName.replace(/_/g, \"/\"));\n }\n\n conflicts.push({\n timestamp: entry.name,\n files: Array.from(uniqueFiles),\n });\n }\n }\n } catch {\n // Directory might not exist\n }\n\n return conflicts.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n}\n\n/**\n * Detect conflicts between local and remote\n */\nexport async function detectConflicts(\n memoryDir: string,\n centralPath?: string\n): Promise<ConflictDetectionResult> {\n // Get central repo path\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n throw new Error(\"No central repository configured\");\n }\n\n // Get sync config\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.path) {\n throw new Error(\"Directory is not configured for sync\");\n }\n\n const remotePath = path.join(centralRepo, syncConfig.path);\n const effectiveCentralPath = centralPath ?? syncConfig.path;\n\n // Load sync state\n const state = await loadSyncState(memoryDir, effectiveCentralPath);\n\n // Get file lists\n const [localFiles, remoteFiles] = await Promise.all([\n listSyncableFiles(memoryDir, syncConfig.include, syncConfig.exclude),\n listSyncableFiles(remotePath, syncConfig.include, syncConfig.exclude),\n ]);\n\n const allFiles = new Set([...localFiles, ...remoteFiles]);\n\n const changes: FileConflict[] = [];\n const unchanged: string[] = [];\n const summary = {\n unchanged: 0,\n localOnly: 0,\n remoteOnly: 0,\n conflicts: 0,\n newLocal: 0,\n newRemote: 0,\n deletedLocal: 0,\n deletedRemote: 0,\n };\n\n for (const file of allFiles) {\n const localPath = path.join(memoryDir, file);\n const remoteFilePath = path.join(remotePath, file);\n\n const [localInfo, remoteInfo] = await Promise.all([\n getFileHashInfo(localPath),\n getFileHashInfo(remoteFilePath),\n ]);\n\n const existingEntry = state.files[file];\n const baseHash = existingEntry?.lastSyncedHash ?? null;\n\n const status = getFileSyncStatus(\n localInfo.hash ?? null,\n remoteInfo.hash ?? null,\n baseHash\n );\n\n if (status === \"unchanged\") {\n unchanged.push(file);\n summary.unchanged++;\n } else {\n changes.push({\n file,\n status,\n localHash: localInfo.hash ?? null,\n remoteHash: remoteInfo.hash ?? null,\n baseHash,\n });\n\n // Update summary\n switch (status) {\n case \"local-only\":\n summary.localOnly++;\n break;\n case \"remote-only\":\n summary.remoteOnly++;\n break;\n case \"conflict\":\n summary.conflicts++;\n break;\n case \"new-local\":\n summary.newLocal++;\n break;\n case \"new-remote\":\n summary.newRemote++;\n break;\n case \"deleted-local\":\n summary.deletedLocal++;\n break;\n case \"deleted-remote\":\n summary.deletedRemote++;\n break;\n }\n }\n }\n\n return { changes, unchanged, summary };\n}\n\n/**\n * Create shadow copies for all conflicts\n * This preserves the base version for 3-way merge\n */\nexport async function createShadowsForConflicts(\n memoryDir: string,\n conflicts: FileConflict[],\n state: SyncState\n): Promise<void> {\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) return;\n\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.path) return;\n\n for (const conflict of conflicts) {\n if (conflict.status === \"conflict\" && conflict.baseHash) {\n // We need the base content - try to get it from the state's recorded hash\n // Since we don't store content, we'd need to have saved it before\n // For now, create an empty shadow to mark that a conflict occurred\n const shadowPath = getShadowPath(memoryDir, conflict.file);\n await fs.mkdir(path.dirname(shadowPath), { recursive: true });\n\n // Write a marker file indicating we need the base content\n // In practice, the shadow should have been created during the last sync\n try {\n await fs.access(shadowPath);\n } catch {\n // Shadow doesn't exist - write a placeholder\n await fs.writeFile(\n shadowPath,\n `# Shadow for ${conflict.file}\\n# Base hash: ${conflict.baseHash}\\n# Created during conflict detection\\n`\n );\n }\n }\n }\n}\n","/**\n * minimem sync:conflicts - Conflict management commands\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { spawn } from \"node:child_process\";\n\nimport {\n resolveMemoryDir,\n isInitialized,\n formatPath,\n getSyncConfig,\n} from \"../config.js\";\nimport {\n listQuarantinedConflicts,\n getConflictsDir,\n getShadowsDir,\n} from \"../sync/conflicts.js\";\nimport { getSyncStatePath, loadSyncState } from \"../sync/state.js\";\n\nexport type ConflictsOptions = {\n dir?: string;\n global?: boolean;\n json?: boolean;\n};\n\n/**\n * List all quarantined conflicts\n */\nexport async function conflictsCommand(options: ConflictsOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n try {\n const conflicts = await listQuarantinedConflicts(memoryDir);\n\n if (options.json) {\n console.log(JSON.stringify(conflicts, null, 2));\n return;\n }\n\n if (conflicts.length === 0) {\n console.log(\"No quarantined conflicts.\");\n return;\n }\n\n console.log(`Quarantined conflicts in ${formatPath(memoryDir)}`);\n console.log(\"-\".repeat(50));\n\n for (const conflict of conflicts) {\n console.log(`\\n${conflict.timestamp}:`);\n for (const file of conflict.files) {\n console.log(` - ${file}`);\n }\n }\n\n console.log(`\\nTotal: ${conflicts.length} conflict set(s)`);\n console.log(\"\\nUse 'minimem sync:resolve <timestamp>' to resolve a conflict.\");\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n\nexport type ResolveOptions = {\n dir?: string;\n global?: boolean;\n tool?: string;\n};\n\n/**\n * Resolve a quarantined conflict\n */\nexport async function resolveCommand(\n timestamp: string,\n options: ResolveOptions\n): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n const conflictDir = path.join(getConflictsDir(memoryDir), timestamp);\n\n try {\n await fs.access(conflictDir);\n } catch {\n console.error(`Error: Conflict '${timestamp}' not found.`);\n console.error(\"Use 'minimem sync:conflicts' to list available conflicts.\");\n process.exit(1);\n }\n\n try {\n const files = await fs.readdir(conflictDir);\n\n // Group files by base name\n const fileGroups = new Map<string, { local?: string; remote?: string; base?: string }>();\n for (const file of files) {\n const match = file.match(/^(.+)\\.(local|remote|base)$/);\n if (match) {\n const [, baseName, type] = match;\n if (!fileGroups.has(baseName)) {\n fileGroups.set(baseName, {});\n }\n const group = fileGroups.get(baseName)!;\n group[type as \"local\" | \"remote\" | \"base\"] = path.join(conflictDir, file);\n }\n }\n\n if (fileGroups.size === 0) {\n console.error(\"No conflict files found in this directory.\");\n process.exit(1);\n }\n\n // Determine merge tool\n const mergeTool = options.tool || process.env.MERGE_TOOL || await detectMergeTool();\n\n if (!mergeTool) {\n console.log(\"No merge tool detected. Available conflict files:\");\n for (const [baseName, group] of fileGroups) {\n console.log(`\\n${baseName.replace(/_/g, \"/\")}:`);\n if (group.local) console.log(` Local: ${group.local}`);\n if (group.remote) console.log(` Remote: ${group.remote}`);\n if (group.base) console.log(` Base: ${group.base}`);\n }\n console.log(\"\\nManually edit the files or set MERGE_TOOL environment variable.\");\n return;\n }\n\n console.log(`Using merge tool: ${mergeTool}`);\n\n for (const [baseName, group] of fileGroups) {\n const fileName = baseName.replace(/_/g, \"/\");\n console.log(`\\nResolving: ${fileName}`);\n\n if (group.local && group.remote) {\n // Launch merge tool\n const args = group.base\n ? [group.local, group.base, group.remote]\n : [group.local, group.remote];\n\n const child = spawn(mergeTool, args, { stdio: \"inherit\" });\n\n await new Promise<void>((resolve, reject) => {\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Merge tool exited with code ${code}`));\n }\n });\n child.on(\"error\", reject);\n });\n }\n }\n\n console.log(\"\\nMerge complete. Remove conflict directory when satisfied:\");\n console.log(` rm -rf \"${conflictDir}\"`);\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n\n/**\n * Detect available merge tool\n */\nasync function detectMergeTool(): Promise<string | null> {\n const tools = [\"code\", \"meld\", \"kdiff3\", \"vimdiff\", \"opendiff\"];\n\n for (const tool of tools) {\n try {\n const { execSync } = await import(\"node:child_process\");\n execSync(`which ${tool}`, { stdio: \"ignore\" });\n return tool;\n } catch {\n continue;\n }\n }\n\n return null;\n}\n\nexport type CleanupOptions = {\n dir?: string;\n global?: boolean;\n days?: number;\n dryRun?: boolean;\n};\n\n/**\n * Clean up old quarantined conflicts\n */\nexport async function cleanupCommand(options: CleanupOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n const maxAgeDays = options.days ?? 30;\n const cutoffDate = new Date(Date.now() - maxAgeDays * 24 * 60 * 60 * 1000);\n\n try {\n const conflictsDir = getConflictsDir(memoryDir);\n let entries: string[] = [];\n\n try {\n entries = await fs.readdir(conflictsDir);\n } catch {\n console.log(\"No conflicts directory found.\");\n return;\n }\n\n let cleaned = 0;\n let kept = 0;\n\n for (const entry of entries) {\n // Timestamps are in ISO format with : and . replaced with -\n // e.g., 2026-02-03T07-20-56-704Z\n const timestamp = entry.replace(/-(\\d{2})-(\\d{2})-(\\d{3})Z$/, \":$1:$2.$3Z\");\n const entryDate = new Date(timestamp);\n\n if (isNaN(entryDate.getTime())) {\n console.log(` Skipping invalid timestamp: ${entry}`);\n continue;\n }\n\n const entryPath = path.join(conflictsDir, entry);\n\n if (entryDate < cutoffDate) {\n if (options.dryRun) {\n console.log(` Would remove: ${entry}`);\n } else {\n await fs.rm(entryPath, { recursive: true, force: true });\n console.log(` Removed: ${entry}`);\n }\n cleaned++;\n } else {\n kept++;\n }\n }\n\n if (options.dryRun) {\n console.log(`\\nWould remove ${cleaned} conflict(s), keep ${kept}`);\n } else {\n console.log(`\\nRemoved ${cleaned} conflict(s), kept ${kept}`);\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n\n/**\n * Sync logging\n */\nconst SYNC_LOG_FILE = \"sync.log\";\nconst MAX_LOG_ENTRIES = 1000;\n\nexport type SyncLogEntry = {\n timestamp: string;\n operation: \"push\" | \"pull\" | \"sync\";\n result: \"success\" | \"partial\" | \"failure\";\n pushed?: number;\n pulled?: number;\n conflicts?: number;\n errors?: string[];\n};\n\n/**\n * Get sync log path\n */\nexport function getSyncLogPath(memoryDir: string): string {\n return path.join(memoryDir, \".minimem\", SYNC_LOG_FILE);\n}\n\n/**\n * Append to sync log\n */\nexport async function appendSyncLog(\n memoryDir: string,\n entry: SyncLogEntry\n): Promise<void> {\n const logPath = getSyncLogPath(memoryDir);\n\n try {\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n\n // Read existing log\n let entries: SyncLogEntry[] = [];\n try {\n const content = await fs.readFile(logPath, \"utf-8\");\n entries = content\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line));\n } catch {\n // No existing log\n }\n\n // Add new entry and trim if needed\n entries.push(entry);\n if (entries.length > MAX_LOG_ENTRIES) {\n entries = entries.slice(-MAX_LOG_ENTRIES);\n }\n\n // Write back\n const content = entries.map((e) => JSON.stringify(e)).join(\"\\n\") + \"\\n\";\n await fs.writeFile(logPath, content);\n } catch (error) {\n // Log failures are non-fatal\n console.error(`Warning: Failed to write sync log: ${error}`);\n }\n}\n\n/**\n * Read sync log\n */\nexport async function readSyncLog(memoryDir: string): Promise<SyncLogEntry[]> {\n const logPath = getSyncLogPath(memoryDir);\n\n try {\n const content = await fs.readFile(logPath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line));\n } catch {\n return [];\n }\n}\n\nexport type LogOptions = {\n dir?: string;\n global?: boolean;\n limit?: number;\n json?: boolean;\n};\n\n/**\n * Show sync log\n */\nexport async function logCommand(options: LogOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n try {\n let entries = await readSyncLog(memoryDir);\n\n const limit = options.limit ?? 20;\n entries = entries.slice(-limit);\n\n if (options.json) {\n console.log(JSON.stringify(entries, null, 2));\n return;\n }\n\n if (entries.length === 0) {\n console.log(\"No sync history.\");\n return;\n }\n\n console.log(`Sync history for ${formatPath(memoryDir)}`);\n console.log(\"-\".repeat(60));\n\n for (const entry of entries) {\n const time = new Date(entry.timestamp).toLocaleString();\n const status =\n entry.result === \"success\" ? \"OK\" :\n entry.result === \"partial\" ? \"PARTIAL\" : \"FAILED\";\n\n let details = \"\";\n if (entry.pushed) details += ` +${entry.pushed}`;\n if (entry.pulled) details += ` -${entry.pulled}`;\n if (entry.conflicts) details += ` !${entry.conflicts}`;\n\n console.log(`${time} ${entry.operation.padEnd(6)} ${status.padEnd(8)}${details}`);\n\n if (entry.errors && entry.errors.length > 0) {\n for (const error of entry.errors.slice(0, 3)) {\n console.log(` Error: ${error}`);\n }\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n","/**\n * minimem push/pull - Sync commands\n */\n\nimport {\n resolveMemoryDir,\n isInitialized,\n formatPath,\n} from \"../config.js\";\nimport { push, pull, bidirectionalSync } from \"../sync/operations.js\";\nimport { detectConflicts } from \"../sync/conflicts.js\";\n\nexport type PushPullOptions = {\n dir?: string;\n global?: boolean;\n force?: boolean;\n dryRun?: boolean;\n};\n\n/**\n * Push local changes to central repository\n */\nexport async function pushCommand(options: PushPullOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n console.log(`Pushing from ${formatPath(memoryDir)}...`);\n\n if (options.dryRun) {\n console.log(\"(dry run - no changes will be made)\");\n }\n\n try {\n const result = await push(memoryDir, {\n force: options.force,\n dryRun: options.dryRun,\n });\n\n if (result.pushed.length > 0) {\n console.log(`\\nPushed ${result.pushed.length} file(s):`);\n for (const file of result.pushed) {\n console.log(` + ${file}`);\n }\n }\n\n if (result.skipped.length > 0) {\n console.log(`\\nSkipped ${result.skipped.length} file(s) (no local changes)`);\n }\n\n if (result.conflicts.length > 0) {\n console.log(`\\nConflicts (${result.conflicts.length}):`);\n for (const file of result.conflicts) {\n console.log(` ! ${file}`);\n }\n console.log(\"\\nResolve conflicts or use --force to overwrite\");\n }\n\n if (result.errors.length > 0) {\n console.error(`\\nErrors:`);\n for (const error of result.errors) {\n console.error(` ${error}`);\n }\n }\n\n if (!result.success) {\n process.exit(1);\n }\n\n if (result.pushed.length === 0 && result.conflicts.length === 0) {\n console.log(\"Nothing to push - already in sync\");\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n\n/**\n * Pull changes from central repository\n */\nexport async function pullCommand(options: PushPullOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n console.log(`Pulling to ${formatPath(memoryDir)}...`);\n\n if (options.dryRun) {\n console.log(\"(dry run - no changes will be made)\");\n }\n\n try {\n const result = await pull(memoryDir, {\n force: options.force,\n dryRun: options.dryRun,\n });\n\n if (result.pulled.length > 0) {\n console.log(`\\nPulled ${result.pulled.length} file(s):`);\n for (const file of result.pulled) {\n console.log(` + ${file}`);\n }\n }\n\n if (result.skipped.length > 0) {\n console.log(`\\nSkipped ${result.skipped.length} file(s) (no remote changes)`);\n }\n\n if (result.conflicts.length > 0) {\n console.log(`\\nConflicts (${result.conflicts.length}):`);\n for (const file of result.conflicts) {\n console.log(` ! ${file}`);\n }\n console.log(\"\\nResolve conflicts or use --force to overwrite\");\n }\n\n if (result.errors.length > 0) {\n console.error(`\\nErrors:`);\n for (const error of result.errors) {\n console.error(` ${error}`);\n }\n }\n\n if (!result.success) {\n process.exit(1);\n }\n\n if (result.pulled.length === 0 && result.conflicts.length === 0) {\n console.log(\"Nothing to pull - already in sync\");\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n\n/**\n * Show sync status\n */\nexport async function syncStatusCommand(options: { dir?: string; global?: boolean }): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n console.error(`Error: ${formatPath(memoryDir)} is not initialized.`);\n process.exit(1);\n }\n\n try {\n const detection = await detectConflicts(memoryDir);\n const { summary } = detection;\n\n console.log(`Sync status for ${formatPath(memoryDir)}`);\n console.log(\"-\".repeat(50));\n\n if (summary.unchanged > 0) {\n console.log(` Unchanged: ${summary.unchanged}`);\n }\n if (summary.localOnly > 0) {\n console.log(` Local changes: ${summary.localOnly} (push to sync)`);\n }\n if (summary.remoteOnly > 0) {\n console.log(` Remote changes: ${summary.remoteOnly} (pull to sync)`);\n }\n if (summary.newLocal > 0) {\n console.log(` New local: ${summary.newLocal}`);\n }\n if (summary.newRemote > 0) {\n console.log(` New remote: ${summary.newRemote}`);\n }\n if (summary.deletedLocal > 0) {\n console.log(` Deleted local: ${summary.deletedLocal}`);\n }\n if (summary.deletedRemote > 0) {\n console.log(` Deleted remote: ${summary.deletedRemote}`);\n }\n if (summary.conflicts > 0) {\n console.log(` CONFLICTS: ${summary.conflicts}`);\n }\n\n const totalChanges =\n summary.localOnly +\n summary.remoteOnly +\n summary.newLocal +\n summary.newRemote +\n summary.conflicts;\n\n if (totalChanges === 0) {\n console.log(\"\\n All files in sync!\");\n } else {\n console.log(`\\n Total changes: ${totalChanges}`);\n if (summary.conflicts > 0) {\n console.log(\" Run 'minimem push --force' or 'minimem pull --force' to resolve\");\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n}\n","/**\n * minimem daemon - Background sync daemon commands\n */\n\nimport fs from \"node:fs/promises\";\n\nimport {\n startDaemon,\n startDaemonBackground,\n stopDaemon,\n getDaemonStatus,\n isDaemonRunning,\n getDaemonLogPath,\n} from \"../sync/daemon.js\";\n\nexport type DaemonOptions = {\n background?: boolean;\n foreground?: boolean;\n};\n\n/**\n * Start the daemon\n */\nexport async function daemonCommand(options: DaemonOptions): Promise<void> {\n // If --foreground is specified, run in foreground (used by background spawn)\n if (options.foreground) {\n console.log(\"Starting daemon in foreground...\");\n try {\n await startDaemon();\n } catch (error) {\n console.error(`Daemon error: ${error}`);\n process.exit(1);\n }\n return;\n }\n\n // Check if already running\n if (await isDaemonRunning()) {\n console.log(\"Daemon is already running.\");\n console.log(\"Use 'minimem daemon:stop' to stop it.\");\n return;\n }\n\n if (options.background) {\n console.log(\"Starting daemon in background...\");\n try {\n const pid = await startDaemonBackground();\n console.log(`Daemon started with PID ${pid}`);\n console.log(`Log file: ${getDaemonLogPath()}`);\n } catch (error) {\n console.error(`Failed to start daemon: ${error}`);\n process.exit(1);\n }\n } else {\n console.log(\"Starting daemon in foreground...\");\n console.log(\"Press Ctrl+C to stop.\");\n console.log(\"\");\n try {\n await startDaemon();\n } catch (error) {\n console.error(`Daemon error: ${error}`);\n process.exit(1);\n }\n }\n}\n\n/**\n * Stop the daemon\n */\nexport async function daemonStopCommand(): Promise<void> {\n const status = await getDaemonStatus();\n\n if (!status.running) {\n console.log(\"Daemon is not running.\");\n return;\n }\n\n console.log(`Stopping daemon (PID ${status.pid})...`);\n\n const stopped = await stopDaemon();\n\n if (stopped) {\n console.log(\"Daemon stopped.\");\n } else {\n console.error(\"Failed to stop daemon.\");\n process.exit(1);\n }\n}\n\n/**\n * Show daemon status\n */\nexport async function daemonStatusCommand(): Promise<void> {\n const status = await getDaemonStatus();\n\n if (status.running) {\n console.log(\"Daemon status: running\");\n console.log(` PID: ${status.pid}`);\n console.log(` Log: ${getDaemonLogPath()}`);\n } else {\n console.log(\"Daemon status: stopped\");\n }\n}\n\nexport type LogOptions = {\n lines?: number;\n follow?: boolean;\n};\n\n/**\n * Show daemon logs\n */\nexport async function daemonLogsCommand(options: LogOptions): Promise<void> {\n const logPath = getDaemonLogPath();\n\n try {\n const content = await fs.readFile(logPath, \"utf-8\");\n const lines = content.split(\"\\n\").filter(Boolean);\n\n const numLines = options.lines ?? 50;\n const displayLines = lines.slice(-numLines);\n\n for (const line of displayLines) {\n console.log(line);\n }\n\n if (options.follow) {\n console.log(\"\\n--- Following log (Ctrl+C to stop) ---\\n\");\n\n // Simple follow implementation using polling\n let lastSize = (await fs.stat(logPath)).size;\n\n const poll = async () => {\n try {\n const stats = await fs.stat(logPath);\n if (stats.size > lastSize) {\n const fd = await fs.open(logPath, \"r\");\n const buffer = Buffer.alloc(stats.size - lastSize);\n await fd.read(buffer, 0, buffer.length, lastSize);\n await fd.close();\n\n process.stdout.write(buffer.toString());\n lastSize = stats.size;\n }\n } catch {\n // File may have been rotated\n lastSize = 0;\n }\n };\n\n const interval = setInterval(poll, 1000);\n\n process.on(\"SIGINT\", () => {\n clearInterval(interval);\n process.exit(0);\n });\n\n // Keep running\n await new Promise(() => {});\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n console.log(\"No daemon log found.\");\n } else {\n console.error(`Error reading log: ${error}`);\n process.exit(1);\n }\n }\n}\n","/**\n * Sync daemon - watches directories and syncs automatically\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nimport { createFileWatcher, type WatcherInstance, type FileChange } from \"./watcher.js\";\nimport { push, pull } from \"./operations.js\";\nimport { readRegistry, type Registry } from \"./registry.js\";\nimport { getCentralRepoPath } from \"./central.js\";\nimport { loadXdgConfig, getSyncConfig } from \"../config.js\";\nimport { validateRegistry, type ValidationResult } from \"./validation.js\";\n\nconst DAEMON_LOG_FILE = \"daemon.log\";\nconst PID_FILE = \"daemon.pid\";\nconst MAX_LOG_SIZE = 1024 * 1024; // 1MB\n\nexport type DaemonOptions = {\n /** Run in background (detach from terminal) */\n background?: boolean;\n /** Sync interval in milliseconds (for central repo polling) */\n pollInterval?: number;\n /** Validation interval in milliseconds (default: 5 minutes) */\n validationInterval?: number;\n /** Log level */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n};\n\nexport type DaemonStatus = {\n running: boolean;\n pid?: number;\n startTime?: string;\n watchedDirs?: string[];\n};\n\n/**\n * Get the daemon directory path\n */\nexport function getDaemonDir(): string {\n return path.join(os.homedir(), \".minimem\");\n}\n\n/**\n * Get PID file path\n */\nexport function getPidFilePath(): string {\n return path.join(getDaemonDir(), PID_FILE);\n}\n\n/**\n * Get daemon log path\n */\nexport function getDaemonLogPath(): string {\n return path.join(getDaemonDir(), DAEMON_LOG_FILE);\n}\n\n/**\n * Check if daemon is running\n */\nexport async function isDaemonRunning(): Promise<boolean> {\n const pidFile = getPidFilePath();\n\n try {\n const content = await fs.readFile(pidFile, \"utf-8\");\n const pid = parseInt(content.trim(), 10);\n\n if (isNaN(pid)) {\n return false;\n }\n\n // Check if process is running\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n // Process not running, clean up stale PID file\n await fs.unlink(pidFile).catch(() => {});\n return false;\n }\n } catch {\n return false;\n }\n}\n\n/**\n * Get daemon status\n */\nexport async function getDaemonStatus(): Promise<DaemonStatus> {\n const running = await isDaemonRunning();\n\n if (!running) {\n return { running: false };\n }\n\n const pidFile = getPidFilePath();\n const content = await fs.readFile(pidFile, \"utf-8\");\n const pid = parseInt(content.trim(), 10);\n\n return {\n running: true,\n pid,\n };\n}\n\n/**\n * Write to daemon log\n */\nasync function writeLog(\n message: string,\n level: \"debug\" | \"info\" | \"warn\" | \"error\" = \"info\"\n): Promise<void> {\n const logPath = getDaemonLogPath();\n const timestamp = new Date().toISOString();\n const line = `[${timestamp}] [${level.toUpperCase()}] ${message}\\n`;\n\n try {\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n\n // Rotate log if too large\n try {\n const stats = await fs.stat(logPath);\n if (stats.size > MAX_LOG_SIZE) {\n await fs.rename(logPath, `${logPath}.old`);\n }\n } catch {\n // File doesn't exist\n }\n\n await fs.appendFile(logPath, line);\n } catch (error) {\n console.error(`Failed to write log: ${error}`);\n }\n}\n\n/**\n * Stop the daemon\n */\nexport async function stopDaemon(): Promise<boolean> {\n const status = await getDaemonStatus();\n\n if (!status.running || !status.pid) {\n return false;\n }\n\n try {\n process.kill(status.pid, \"SIGTERM\");\n\n // Wait for process to exit\n let attempts = 0;\n while (attempts < 10) {\n await new Promise((r) => setTimeout(r, 500));\n if (!(await isDaemonRunning())) {\n return true;\n }\n attempts++;\n }\n\n // Force kill if still running\n try {\n process.kill(status.pid, \"SIGKILL\");\n } catch {\n // Process may have already exited\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Start the daemon\n */\nexport async function startDaemon(options: DaemonOptions = {}): Promise<void> {\n const pollInterval = options.pollInterval ?? 30000; // 30 seconds\n\n // Check if already running\n if (await isDaemonRunning()) {\n throw new Error(\"Daemon is already running\");\n }\n\n // Write PID file\n const daemonDir = getDaemonDir();\n await fs.mkdir(daemonDir, { recursive: true });\n await fs.writeFile(getPidFilePath(), String(process.pid));\n\n await writeLog(\"Daemon starting\");\n\n // Get central repo path\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n await writeLog(\"No central repository configured\", \"warn\");\n }\n\n // Get all directories with sync enabled from registry\n const watchedDirs: Map<string, WatcherInstance> = new Map();\n let running = true;\n\n // Load directories from registry\n async function loadWatchedDirs(): Promise<void> {\n if (!centralRepo) return;\n\n try {\n const registry = await readRegistry(centralRepo);\n\n // Get local directories that should be watched\n const xdgConfig = await loadXdgConfig();\n const machineId = xdgConfig.machineId;\n\n for (const mapping of registry.mappings) {\n if (mapping.machineId !== machineId) continue;\n\n const localPath = mapping.localPath;\n\n // Skip if already watching\n if (watchedDirs.has(localPath)) continue;\n\n // Check if sync is enabled for this directory\n try {\n const syncConfig = await getSyncConfig(localPath);\n if (!syncConfig.enabled) continue;\n\n // Start watcher\n const watcher = createFileWatcher(localPath, {\n debounceMs: 2000,\n });\n\n watcher.on(\"changes\", async (changes: FileChange[]) => {\n await handleLocalChanges(localPath, changes);\n });\n\n watchedDirs.set(localPath, watcher);\n await writeLog(`Watching directory: ${localPath}`);\n } catch (error) {\n await writeLog(`Failed to watch ${localPath}: ${error}`, \"error\");\n }\n }\n } catch (error) {\n await writeLog(`Failed to load registry: ${error}`, \"error\");\n }\n }\n\n // Handle local file changes\n async function handleLocalChanges(\n memoryDir: string,\n changes: FileChange[]\n ): Promise<void> {\n await writeLog(`Local changes in ${memoryDir}: ${changes.map((c) => c.file).join(\", \")}`);\n\n try {\n const syncConfig = await getSyncConfig(memoryDir);\n\n if (syncConfig.autoSync) {\n await writeLog(`Auto-pushing changes from ${memoryDir}`);\n const result = await push(memoryDir, { dryRun: false });\n\n if (result.success) {\n await writeLog(`Pushed ${result.pushed.length} files from ${memoryDir}`);\n } else {\n await writeLog(\n `Push failed for ${memoryDir}: ${result.errors.join(\", \")}`,\n \"error\"\n );\n }\n }\n } catch (error) {\n await writeLog(`Failed to handle changes in ${memoryDir}: ${error}`, \"error\");\n }\n }\n\n // Poll central repo for changes\n async function pollCentralRepo(): Promise<void> {\n if (!centralRepo) return;\n\n try {\n // Check for changes in central repo that need to be pulled\n for (const [localPath] of watchedDirs) {\n try {\n const syncConfig = await getSyncConfig(localPath);\n\n if (syncConfig.autoSync) {\n const result = await pull(localPath, { dryRun: true });\n\n if (result.pulled.length > 0) {\n await writeLog(`Remote changes detected for ${localPath}, pulling...`);\n await pull(localPath, { dryRun: false });\n }\n }\n } catch (error) {\n await writeLog(`Failed to check/pull for ${localPath}: ${error}`, \"error\");\n }\n }\n } catch (error) {\n await writeLog(`Failed to poll central repo: ${error}`, \"error\");\n }\n }\n\n // Cleanup function\n async function cleanup(): Promise<void> {\n running = false;\n await writeLog(\"Daemon stopping\");\n\n // Close all watchers\n for (const [dir, watcher] of watchedDirs) {\n try {\n await watcher.close();\n await writeLog(`Stopped watching: ${dir}`);\n } catch (error) {\n await writeLog(`Error closing watcher for ${dir}: ${error}`, \"error\");\n }\n }\n watchedDirs.clear();\n\n // Remove PID file\n try {\n await fs.unlink(getPidFilePath());\n } catch {\n // Ignore\n }\n\n await writeLog(\"Daemon stopped\");\n }\n\n // Handle signals\n process.on(\"SIGTERM\", async () => {\n await cleanup();\n process.exit(0);\n });\n\n process.on(\"SIGINT\", async () => {\n await cleanup();\n process.exit(0);\n });\n\n // Validate registry on startup\n async function runValidation(): Promise<void> {\n try {\n const result = await validateRegistry();\n\n if (result.issues.length > 0) {\n for (const issue of result.issues) {\n const level = issue.severity === \"error\" ? \"error\" : \"warn\";\n await writeLog(`Validation: ${issue.message}`, level);\n }\n }\n } catch (error) {\n await writeLog(`Validation failed: ${error}`, \"error\");\n }\n }\n\n // Initial load and validation\n await runValidation();\n await loadWatchedDirs();\n\n // Validation interval tracking\n const validationInterval = options.validationInterval ?? 5 * 60 * 1000; // 5 minutes\n let lastValidation = Date.now();\n\n // Main loop\n while (running) {\n await new Promise((r) => setTimeout(r, pollInterval));\n\n if (!running) break;\n\n // Reload directories in case new ones were added\n await loadWatchedDirs();\n\n // Poll central repo for changes\n await pollCentralRepo();\n\n // Periodic validation\n if (Date.now() - lastValidation > validationInterval) {\n await runValidation();\n lastValidation = Date.now();\n }\n }\n}\n\n/**\n * Run daemon in background (fork process)\n */\nexport async function startDaemonBackground(): Promise<number> {\n const { spawn } = await import(\"node:child_process\");\n\n // Get the path to the CLI\n const cliPath = process.argv[1];\n\n const child = spawn(process.execPath, [cliPath, \"daemon\", \"--foreground\"], {\n detached: true,\n stdio: \"ignore\",\n });\n\n child.unref();\n\n if (child.pid) {\n // Wait a moment and verify it started\n await new Promise((r) => setTimeout(r, 1000));\n\n if (await isDaemonRunning()) {\n return child.pid;\n }\n }\n\n throw new Error(\"Failed to start daemon in background\");\n}\n","/**\n * File watcher with debouncing for memory directories\n */\n\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport path from \"node:path\";\nimport { EventEmitter } from \"node:events\";\n\nimport { listSyncableFiles } from \"./state.js\";\n\nexport type WatcherEvent = \"add\" | \"change\" | \"unlink\";\n\nexport type FileChange = {\n event: WatcherEvent;\n file: string; // Relative path\n};\n\nexport type WatcherOptions = {\n /** Debounce interval in milliseconds (default: 2000) */\n debounceMs?: number;\n /** Patterns to include (default: MEMORY.md, memory/*.md) */\n include?: string[];\n /** Patterns to exclude */\n exclude?: string[];\n /** Use polling instead of native events (for network drives) */\n usePolling?: boolean;\n /** Polling interval in milliseconds (default: 1000) */\n pollInterval?: number;\n};\n\nexport type WatcherInstance = {\n /** Stop watching and clean up */\n close: () => Promise<void>;\n /** Add event listener */\n on: (event: \"changes\", listener: (changes: FileChange[]) => void) => void;\n /** Remove event listener */\n off: (event: \"changes\", listener: (changes: FileChange[]) => void) => void;\n /** Whether the watcher is ready */\n ready: boolean;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 2000;\nconst DEFAULT_POLL_INTERVAL = 1000;\n\nconst DEFAULT_INCLUDE = [\"MEMORY.md\", \"memory/**/*.md\"];\nconst DEFAULT_EXCLUDE = [\".minimem/**\", \"node_modules/**\", \".git/**\"];\n\n/**\n * Create a file watcher for a memory directory\n */\nexport function createFileWatcher(\n memoryDir: string,\n options: WatcherOptions = {}\n): WatcherInstance {\n const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n const include = options.include ?? DEFAULT_INCLUDE;\n const exclude = options.exclude ?? DEFAULT_EXCLUDE;\n\n const emitter = new EventEmitter();\n let watcher: FSWatcher | null = null;\n let ready = false;\n\n // Pending changes for debouncing\n let pendingChanges: Map<string, FileChange> = new Map();\n let debounceTimer: NodeJS.Timeout | null = null;\n\n /**\n * Flush pending changes\n */\n const flushChanges = () => {\n if (pendingChanges.size > 0) {\n const changes = Array.from(pendingChanges.values());\n pendingChanges = new Map();\n emitter.emit(\"changes\", changes);\n }\n debounceTimer = null;\n };\n\n /**\n * Schedule a debounced flush\n */\n const scheduleFlush = () => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(flushChanges, debounceMs);\n };\n\n /**\n * Handle a file event\n */\n const handleEvent = (event: WatcherEvent, filePath: string) => {\n // Get relative path\n const relativePath = path.relative(memoryDir, filePath);\n\n // Skip files in .minimem\n if (relativePath.startsWith(\".minimem\")) {\n return;\n }\n\n // Check if file matches include patterns\n const isIncluded = include.some((pattern) => {\n if (pattern.includes(\"*\")) {\n // Simple glob matching\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*\\*/g, \".*\").replace(/\\*/g, \"[^/]*\") + \"$\"\n );\n return regex.test(relativePath);\n }\n return relativePath === pattern || relativePath.startsWith(pattern + \"/\");\n });\n\n if (!isIncluded) {\n return;\n }\n\n // Check if file matches exclude patterns\n const isExcluded = exclude.some((pattern) => {\n if (pattern.includes(\"*\")) {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*\\*/g, \".*\").replace(/\\*/g, \"[^/]*\") + \"$\"\n );\n return regex.test(relativePath);\n }\n return relativePath === pattern || relativePath.startsWith(pattern);\n });\n\n if (isExcluded) {\n return;\n }\n\n // Add to pending changes (later events override earlier for same file)\n pendingChanges.set(relativePath, { event, file: relativePath });\n scheduleFlush();\n };\n\n // Create watcher\n const watchPaths = include.map((pattern) => path.join(memoryDir, pattern));\n\n watcher = chokidar.watch(watchPaths, {\n ignored: exclude.map((pattern) => path.join(memoryDir, pattern)),\n persistent: true,\n ignoreInitial: true,\n usePolling: options.usePolling ?? false,\n interval: options.pollInterval ?? DEFAULT_POLL_INTERVAL,\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 100,\n },\n });\n\n watcher\n .on(\"add\", (filePath) => handleEvent(\"add\", filePath))\n .on(\"change\", (filePath) => handleEvent(\"change\", filePath))\n .on(\"unlink\", (filePath) => handleEvent(\"unlink\", filePath))\n .on(\"ready\", () => {\n ready = true;\n })\n .on(\"error\", (error) => {\n console.error(`Watcher error: ${error}`);\n });\n\n return {\n close: async () => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n debounceTimer = null;\n }\n if (watcher) {\n await watcher.close();\n watcher = null;\n }\n emitter.removeAllListeners();\n },\n\n on: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.on(event, listener);\n },\n\n off: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.off(event, listener);\n },\n\n get ready() {\n return ready;\n },\n };\n}\n\n/**\n * Watch multiple directories\n */\nexport function createMultiDirWatcher(\n memoryDirs: string[],\n options: WatcherOptions = {}\n): WatcherInstance {\n const watchers = memoryDirs.map((dir) => ({\n dir,\n watcher: createFileWatcher(dir, options),\n }));\n\n const emitter = new EventEmitter();\n\n // Forward events from all watchers\n for (const { dir, watcher } of watchers) {\n watcher.on(\"changes\", (changes) => {\n // Add directory info to changes\n const changesWithDir = changes.map((c) => ({\n ...c,\n file: path.join(dir, c.file),\n }));\n emitter.emit(\"changes\", changesWithDir);\n });\n }\n\n return {\n close: async () => {\n await Promise.all(watchers.map(({ watcher }) => watcher.close()));\n emitter.removeAllListeners();\n },\n\n on: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.on(event, listener);\n },\n\n off: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.off(event, listener);\n },\n\n get ready() {\n return watchers.every(({ watcher }) => watcher.ready);\n },\n };\n}\n","/**\n * Registry validation\n *\n * Validates registry for path collisions, stale mappings, and missing directories.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readRegistry, type Registry, type RegistryMapping } from \"./registry.js\";\nimport { getCentralRepoPath } from \"./central.js\";\nimport { loadXdgConfig } from \"../config.js\";\n\nexport type ValidationIssue = {\n type: \"collision\" | \"stale\" | \"missing\" | \"orphan\";\n severity: \"warning\" | \"error\";\n message: string;\n path?: string;\n machineId?: string;\n details?: Record<string, unknown>;\n};\n\nexport type ValidationResult = {\n valid: boolean;\n issues: ValidationIssue[];\n stats: {\n totalMappings: number;\n activeMappings: number;\n staleMappings: number;\n collisions: number;\n missingDirs: number;\n };\n};\n\nconst STALE_THRESHOLD_DAYS = 30;\n\n/**\n * Validate the registry\n */\nexport async function validateRegistry(): Promise<ValidationResult> {\n const result: ValidationResult = {\n valid: true,\n issues: [],\n stats: {\n totalMappings: 0,\n activeMappings: 0,\n staleMappings: 0,\n collisions: 0,\n missingDirs: 0,\n },\n };\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n result.issues.push({\n type: \"missing\",\n severity: \"warning\",\n message: \"No central repository configured\",\n });\n return result;\n }\n\n let registry: Registry;\n try {\n registry = await readRegistry(centralRepo);\n } catch (error) {\n result.issues.push({\n type: \"missing\",\n severity: \"error\",\n message: `Failed to read registry: ${error}`,\n });\n result.valid = false;\n return result;\n }\n\n const xdgConfig = await loadXdgConfig();\n const currentMachineId = xdgConfig.machineId;\n const now = new Date();\n const staleThreshold = new Date(now.getTime() - STALE_THRESHOLD_DAYS * 24 * 60 * 60 * 1000);\n\n result.stats.totalMappings = registry.mappings.length;\n\n // Group mappings by central path to detect collisions\n const pathToMappings = new Map<string, RegistryMapping[]>();\n\n for (const mapping of registry.mappings) {\n const existing = pathToMappings.get(mapping.path) || [];\n existing.push(mapping);\n pathToMappings.set(mapping.path, existing);\n }\n\n // Check for collisions\n for (const [centralPath, mappings] of pathToMappings) {\n if (mappings.length > 1) {\n // Multiple machines mapping to same path\n const machineIds = mappings.map((m) => m.machineId);\n const uniqueMachines = new Set(machineIds);\n\n if (uniqueMachines.size > 1) {\n result.issues.push({\n type: \"collision\",\n severity: \"error\",\n message: `Path '${centralPath}' is mapped by multiple machines: ${Array.from(uniqueMachines).join(\", \")}`,\n path: centralPath,\n details: { machines: Array.from(uniqueMachines) },\n });\n result.stats.collisions++;\n result.valid = false;\n }\n }\n }\n\n // Check each mapping\n for (const mapping of registry.mappings) {\n // Check for stale mappings\n const lastSyncDate = new Date(mapping.lastSync);\n if (lastSyncDate < staleThreshold) {\n const daysSinceSync = Math.floor(\n (now.getTime() - lastSyncDate.getTime()) / (24 * 60 * 60 * 1000)\n );\n\n result.issues.push({\n type: \"stale\",\n severity: \"warning\",\n message: `Mapping '${mapping.path}' by '${mapping.machineId}' is stale (last sync: ${daysSinceSync} days ago)`,\n path: mapping.path,\n machineId: mapping.machineId,\n details: { lastSync: mapping.lastSync, daysSinceSync },\n });\n result.stats.staleMappings++;\n } else {\n result.stats.activeMappings++;\n }\n\n // Check if local directory exists (only for current machine)\n if (mapping.machineId === currentMachineId) {\n const localPath = expandPath(mapping.localPath);\n try {\n await fs.access(localPath);\n } catch {\n result.issues.push({\n type: \"missing\",\n severity: \"warning\",\n message: `Local directory no longer exists: ${mapping.localPath}`,\n path: mapping.path,\n machineId: mapping.machineId,\n details: { localPath: mapping.localPath },\n });\n result.stats.missingDirs++;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Expand path (handle ~ for home directory)\n */\nfunction expandPath(p: string): string {\n if (p.startsWith(\"~/\")) {\n return path.join(process.env.HOME || \"\", p.slice(2));\n }\n return p;\n}\n\n/**\n * Format validation result for display\n */\nexport function formatValidationResult(result: ValidationResult): string {\n const lines: string[] = [];\n\n lines.push(\"Registry Validation Results\");\n lines.push(\"-\".repeat(40));\n\n lines.push(`Total mappings: ${result.stats.totalMappings}`);\n lines.push(`Active mappings: ${result.stats.activeMappings}`);\n\n if (result.stats.staleMappings > 0) {\n lines.push(`Stale mappings: ${result.stats.staleMappings}`);\n }\n if (result.stats.collisions > 0) {\n lines.push(`Collisions: ${result.stats.collisions}`);\n }\n if (result.stats.missingDirs > 0) {\n lines.push(`Missing directories: ${result.stats.missingDirs}`);\n }\n\n if (result.issues.length > 0) {\n lines.push(\"\");\n lines.push(\"Issues:\");\n\n for (const issue of result.issues) {\n const prefix = issue.severity === \"error\" ? \"ERROR\" : \"WARN\";\n lines.push(` [${prefix}] ${issue.message}`);\n }\n } else {\n lines.push(\"\");\n lines.push(\"No issues found.\");\n }\n\n lines.push(\"\");\n lines.push(result.valid ? \"Registry is valid.\" : \"Registry has errors that need attention.\");\n\n return lines.join(\"\\n\");\n}\n"],"mappings":"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","names":["fs","path","config","config","fs","path","config","path","os","fs","path","crypto","fs","path","fs","path","crypto","fsSync","path","os","payload","provider","client","resolve","status","text","status","resolve","runWithConcurrency","vectorToBlob","config","path","fs","resolve","config","status","config","status","config","config","fs","path","os","os","formatPath","formatPath","resolveMemoryDir","config","resolve","fs","path","os","config","status","loadConfigFile","fs","config","fs","path","fs","path","fs","path","os","crypto","fs","path","path","fs","fs","config","path","fs","path","fs","fs","path","crypto","fs","path","crypto","walkDir","fs","path","fs","path","path","fs","path","status","fs","path","path","fs","resolve","execSync","content","status","ensureDir","fs","path","crypto","fs","fs","path","os","chokidar","path","fs","path","expandPath","fs","path","path","os","fs","status","spawn","status","fs"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/config.ts","../../src/cli/shared.ts","../../src/minimem.ts","../../src/internal.ts","../../src/search/hybrid.ts","../../src/search/search.ts","../../src/db/schema.ts","../../src/session.ts","../../src/search/graph.ts","../../src/db/sqlite-vec.ts","../../src/embeddings/embeddings.ts","../../src/embeddings/batch-openai.ts","../../src/embeddings/batch-gemini.ts","../../src/cli/commands/search.ts","../../src/cli/commands/sync.ts","../../src/cli/commands/status.ts","../../src/cli/commands/append.ts","../../src/cli/commands/upsert.ts","../../src/cli/commands/mcp.ts","../../src/server/mcp.ts","../../src/server/tools.ts","../../src/cli/commands/config.ts","../../src/cli/commands/sync-init.ts","../../src/cli/sync/central.ts","../../src/cli/sync/registry.ts","../../src/cli/sync/detection.ts","../../src/cli/sync/operations.ts","../../src/cli/sync/state.ts","../../src/cli/commands/conflicts.ts","../../src/cli/sync/conflicts.ts","../../src/cli/commands/push-pull.ts","../../src/cli/commands/daemon.ts","../../src/cli/sync/daemon.ts","../../src/cli/sync/watcher.ts","../../src/cli/sync/validation.ts","../../src/cli/version.ts"],"sourcesContent":["/**\n * Minimem CLI\n *\n * A file-based memory system with vector search for AI agents.\n */\n\nimport { program } from \"commander\";\n\nimport { init } from \"./commands/init.js\";\nimport { search } from \"./commands/search.js\";\nimport { sync } from \"./commands/sync.js\";\nimport { status } from \"./commands/status.js\";\nimport { append } from \"./commands/append.js\";\nimport { upsert } from \"./commands/upsert.js\";\nimport { mcp } from \"./commands/mcp.js\";\nimport { config } from \"./commands/config.js\";\nimport { syncInit, syncInitCentral, syncList, syncRemove } from \"./commands/sync-init.js\";\nimport { pushCommand, pullCommand, syncStatusCommand } from \"./commands/push-pull.js\";\nimport { conflictsCommand, resolveCommand, cleanupCommand, logCommand } from \"./commands/conflicts.js\";\nimport { daemonCommand, daemonStopCommand, daemonStatusCommand, daemonLogsCommand } from \"./commands/daemon.js\";\nimport { validateRegistry, formatValidationResult } from \"./sync/validation.js\";\nimport { VERSION } from \"./version.js\";\nimport { exitWithError } from \"./config.js\";\n\nprogram\n .name(\"minimem\")\n .description(\"File-based memory system with vector search for AI agents\")\n .version(VERSION);\n\n// minimem init [dir]\nprogram\n .command(\"init [dir]\")\n .description(\"Initialize a memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem as global memory directory\")\n .option(\"-f, --force\", \"Reinitialize even if already initialized\")\n .action(init);\n\n// minimem search <query>\nprogram\n .command(\"search <query>\")\n .description(\"Semantic search through memory files\")\n .option(\"-d, --dir <path...>\", \"Memory directories (can specify multiple)\")\n .option(\"-g, --global\", \"Include ~/.minimem in search\")\n .option(\"-n, --max <number>\", \"Maximum results (default: 10)\")\n .option(\"-s, --min-score <number>\", \"Minimum score threshold 0-1 (default: 0.3)\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"--json\", \"Output results as JSON\")\n .action(search);\n\n// minimem sync\nprogram\n .command(\"sync\")\n .description(\"Force re-index memory files\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --force\", \"Force full re-index\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .action(sync);\n\n// minimem status\nprogram\n .command(\"status\")\n .description(\"Show index stats and provider info\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"--json\", \"Output as JSON\")\n .action(status);\n\n// minimem append <text>\nprogram\n .command(\"append <text>\")\n .description(\"Append text to today's daily log (memory/YYYY-MM-DD.md)\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --file <path>\", \"Append to specific file instead of today's log\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"-s, --session <id>\", \"Session ID to associate with this memory\")\n .option(\"--session-source <name>\", \"Session source (claude-code, vscode, etc.)\")\n .action(append);\n\n// minimem upsert <file> [content]\nprogram\n .command(\"upsert <file> [content]\")\n .description(\"Create or update a memory file (file path relative to memory dir)\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .option(\"--stdin\", \"Read content from stdin\")\n .option(\"-s, --session <id>\", \"Session ID to associate with this memory\")\n .option(\"--session-source <name>\", \"Session source (claude-code, vscode, etc.)\")\n .action(upsert);\n\n// minimem mcp\nprogram\n .command(\"mcp\")\n .description(\"Run as MCP server over stdio (for Claude Desktop, Cursor, etc.)\")\n .option(\"-d, --dir <path...>\", \"Memory directories (can specify multiple)\")\n .option(\"-g, --global\", \"Include ~/.minimem\")\n .option(\"-p, --provider <name>\", \"Embedding provider (openai, gemini, local, auto)\")\n .action(mcp);\n\n// minimem config\nprogram\n .command(\"config\")\n .description(\"View or modify configuration\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"--xdg-global\", \"Modify ~/.config/minimem/config.json (for sync settings)\")\n .option(\"--json\", \"Output as JSON\")\n .option(\"--set <key=value>\", \"Set a config value (e.g., embedding.provider=openai)\")\n .option(\"--unset <key>\", \"Remove a config value\")\n .action(config);\n\n// minimem sync init-central <path>\nprogram\n .command(\"sync:init-central <path>\")\n .description(\"Initialize a central repository for syncing memories\")\n .option(\"-f, --force\", \"Force creation even if directory exists\")\n .action(syncInitCentral);\n\n// minimem sync init\nprogram\n .command(\"sync:init\")\n .description(\"Initialize sync for a memory directory\")\n .option(\"-d, --local <path>\", \"Memory directory to sync\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-p, --path <path>\", \"Path in central repo (e.g., myproject/)\")\n .action(syncInit);\n\n// minimem sync list\nprogram\n .command(\"sync:list\")\n .description(\"List all sync mappings\")\n .action(syncList);\n\n// minimem sync remove\nprogram\n .command(\"sync:remove\")\n .description(\"Remove sync mapping for a directory\")\n .option(\"-d, --local <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .action(syncRemove);\n\n// minimem push\nprogram\n .command(\"push\")\n .description(\"Push local changes to central repository\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --force\", \"Force push (overwrite remote on conflicts)\")\n .option(\"--dry-run\", \"Show what would be pushed without making changes\")\n .action(pushCommand);\n\n// minimem pull\nprogram\n .command(\"pull\")\n .description(\"Pull changes from central repository\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-f, --force\", \"Force pull (overwrite local on conflicts)\")\n .option(\"--dry-run\", \"Show what would be pulled without making changes\")\n .action(pullCommand);\n\n// minimem sync:status\nprogram\n .command(\"sync:status\")\n .description(\"Show sync status for a directory\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .action(syncStatusCommand);\n\n// minimem sync:conflicts\nprogram\n .command(\"sync:conflicts\")\n .description(\"List quarantined conflicts\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"--json\", \"Output as JSON\")\n .action(conflictsCommand);\n\n// minimem sync:resolve <timestamp>\nprogram\n .command(\"sync:resolve <timestamp>\")\n .description(\"Resolve a quarantined conflict using merge tool\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-t, --tool <name>\", \"Merge tool (code, meld, kdiff3, vimdiff)\")\n .action(resolveCommand);\n\n// minimem sync:cleanup\nprogram\n .command(\"sync:cleanup\")\n .description(\"Clean up old quarantined conflicts\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"--days <number>\", \"Remove conflicts older than N days (default: 30)\")\n .option(\"--dry-run\", \"Show what would be removed without removing\")\n .action(cleanupCommand);\n\n// minimem sync:log\nprogram\n .command(\"sync:log\")\n .description(\"Show sync history\")\n .option(\"-d, --dir <path>\", \"Memory directory\")\n .option(\"-g, --global\", \"Use ~/.minimem\")\n .option(\"-n, --limit <number>\", \"Number of entries to show (default: 20)\")\n .option(\"--json\", \"Output as JSON\")\n .action(logCommand);\n\n// minimem daemon\nprogram\n .command(\"daemon\")\n .description(\"Start the sync daemon\")\n .option(\"-b, --background\", \"Run in background\")\n .option(\"--foreground\", \"Run in foreground (internal use)\")\n .action(daemonCommand);\n\n// minimem daemon:stop\nprogram\n .command(\"daemon:stop\")\n .description(\"Stop the sync daemon\")\n .action(daemonStopCommand);\n\n// minimem daemon:status\nprogram\n .command(\"daemon:status\")\n .description(\"Show daemon status\")\n .action(daemonStatusCommand);\n\n// minimem daemon:logs\nprogram\n .command(\"daemon:logs\")\n .description(\"Show daemon logs\")\n .option(\"-n, --lines <number>\", \"Number of lines to show (default: 50)\")\n .option(\"-f, --follow\", \"Follow log output\")\n .action(daemonLogsCommand);\n\n// minimem sync:validate\nprogram\n .command(\"sync:validate\")\n .description(\"Validate registry for collisions and stale mappings\")\n .option(\"--json\", \"Output as JSON\")\n .action(async (options: { json?: boolean }) => {\n try {\n const result = await validateRegistry();\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log(formatValidationResult(result));\n }\n\n if (!result.valid) {\n process.exit(1);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n });\n\n// Parse and run\nprogram.parse();\n","/**\n * minimem init - Initialize memory directory\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n resolveMemoryDir,\n saveConfig,\n getInitConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nconst MEMORY_TEMPLATE = `# Memory\n\nThis is your memory file. Add notes, decisions, and context here.\n\n## Quick Start\n\n- Add daily logs in the \\`memory/\\` directory (e.g., \\`memory/2024-01-15.md\\`)\n- Use \\`minimem search <query>\\` to find relevant memories\n- Use \\`minimem append <text>\\` to quickly add to today's log\n\n## Notes\n\n`;\n\nexport type InitOptions = {\n global?: boolean;\n force?: boolean;\n};\n\nexport async function init(\n dir: string | undefined,\n options: InitOptions,\n): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir, global: options.global });\n const displayPath = formatPath(memoryDir);\n\n // Check if already initialized\n if (!options.force && (await isInitialized(memoryDir))) {\n console.log(`Already initialized: ${displayPath}`);\n console.log(\"Use --force to reinitialize\");\n return;\n }\n\n console.log(`Initializing minimem in ${displayPath}...`);\n\n // Create directories\n await fs.mkdir(memoryDir, { recursive: true });\n await fs.mkdir(path.join(memoryDir, \"memory\"), { recursive: true });\n await fs.mkdir(path.join(memoryDir, \".minimem\"), { recursive: true });\n\n // Create MEMORY.md if it doesn't exist\n const memoryFilePath = path.join(memoryDir, \"MEMORY.md\");\n try {\n await fs.access(memoryFilePath);\n console.log(\" MEMORY.md already exists, skipping\");\n } catch {\n await fs.writeFile(memoryFilePath, MEMORY_TEMPLATE, \"utf-8\");\n console.log(\" Created MEMORY.md\");\n }\n\n // Create config\n const config = getInitConfig();\n await saveConfig(memoryDir, config);\n console.log(\" Created .minimem/config.json\");\n\n // Create .gitignore for .minimem directory\n const gitignorePath = path.join(memoryDir, \".minimem\", \".gitignore\");\n await fs.writeFile(gitignorePath, \"index.db\\nindex.db-*\\n\", \"utf-8\");\n console.log(\" Created .minimem/.gitignore\");\n\n console.log();\n console.log(\"Done! Your memory directory is ready.\");\n console.log();\n console.log(\"Next steps:\");\n console.log(` 1. Set your embedding API key:`);\n console.log(` export OPENAI_API_KEY=your-key`);\n console.log(` # or: export GOOGLE_API_KEY=your-key`);\n console.log();\n console.log(` 2. Add some memories to MEMORY.md or memory/*.md`);\n console.log();\n console.log(` 3. Search your memories:`);\n console.log(` minimem search \"your query\"${dir ? ` --dir ${dir}` : \"\"}`);\n}\n","/**\n * CLI configuration loading and directory resolution\n *\n * Config resolution order (later overrides earlier):\n * 1. Built-in defaults\n * 2. Global config (~/.minimem/config.json)\n * 3. Local config (.minimem/config.json in memory directory)\n * 4. CLI flags and environment variables\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport crypto from \"node:crypto\";\n\nimport type { MinimemConfig } from \"../minimem.js\";\nimport type { EmbeddingProviderOptions } from \"../embeddings/embeddings.js\";\n\n// Re-export shared utilities for backward compatibility\nexport {\n resolveMemoryDir,\n resolveMemoryDirs,\n getGlobalMemoryDir,\n exitWithError,\n warn,\n note,\n logError,\n getDirName,\n type DirOptions,\n} from \"./shared.js\";\n\nconst CONFIG_FILENAME = \"config.json\";\nconst CONFIG_DIR = \".minimem\";\nconst GLOBAL_DIR = \".minimem\";\n// XDG-style global config directory for sync settings\nconst XDG_CONFIG_DIR = \".config/minimem\";\n\nexport type CliConfig = {\n embedding?: {\n /** Embedding provider: \"auto\", \"openai\", \"gemini\", \"local\", \"none\" */\n provider?: EmbeddingProviderOptions[\"provider\"];\n /** Model name (provider-specific) */\n model?: string;\n /** Fallback provider if primary fails */\n fallback?: EmbeddingProviderOptions[\"fallback\"];\n /** OpenAI-specific settings */\n openai?: {\n apiKey?: string;\n baseUrl?: string;\n model?: string;\n };\n /** Gemini-specific settings */\n gemini?: {\n apiKey?: string;\n baseUrl?: string;\n model?: string;\n };\n /** Local embedding settings */\n local?: {\n modelPath?: string;\n modelCacheDir?: string;\n };\n };\n hybrid?: {\n /** Enable hybrid search (vector + BM25) */\n enabled?: boolean;\n /** Weight for vector search results (0-1) */\n vectorWeight?: number;\n /** Weight for text/BM25 search results (0-1) */\n textWeight?: number;\n };\n query?: {\n /** Default max results */\n maxResults?: number;\n /** Default min score threshold (0-1) */\n minScore?: number;\n };\n watch?: {\n /** Enable file watching */\n enabled?: boolean;\n /** Debounce delay in ms */\n debounceMs?: number;\n };\n chunking?: {\n /** Target tokens per chunk */\n tokens?: number;\n /** Overlap tokens between chunks */\n overlap?: number;\n };\n hooks?: {\n /** Enable session-start hook (injects recent memories). Defaults to false. */\n sessionStart?: boolean;\n /** Enable session-end hook (appends session summary). Defaults to false. */\n sessionEnd?: boolean;\n };\n /** Sync configuration (for git-based syncing) */\n sync?: {\n /** Enable sync for this directory */\n enabled?: boolean;\n /** Path in central repo for this directory's memories */\n path?: string;\n /** Glob patterns for files to include in sync */\n include?: string[];\n /** Glob patterns for files to exclude from sync */\n exclude?: string[];\n };\n};\n\n/**\n * Global config stored at ~/.config/minimem/config.json\n * Contains settings that apply across all memory directories\n */\nexport type GlobalConfig = {\n /** Path to central repository for syncing */\n centralRepo?: string;\n /** Unique machine identifier for registry */\n machineId?: string;\n /** Global sync settings */\n sync?: {\n /** Default conflict resolution strategy */\n conflictStrategy?: \"keep-both\" | \"merge\" | \"manual\" | \"last-write-wins\";\n /** Enable automatic sync when daemon is running */\n autoSync?: boolean;\n /** Automatically commit changes to central repo */\n autoCommit?: boolean;\n /** External merge resolver command */\n mergeResolver?: string;\n };\n /** Embedding and other settings can be inherited */\n embedding?: CliConfig[\"embedding\"];\n hybrid?: CliConfig[\"hybrid\"];\n query?: CliConfig[\"query\"];\n chunking?: CliConfig[\"chunking\"];\n};\n\nexport type ResolvedConfig = {\n memoryDir: string;\n config: CliConfig;\n};\n\n// Note: resolveMemoryDir is now imported from ./shared.js and re-exported above\n\n/**\n * Get the global config directory path (~/.minimem)\n */\nexport function getGlobalDir(): string {\n return path.join(os.homedir(), GLOBAL_DIR);\n}\n\n/**\n * Get the global config file path (~/.minimem/.minimem/config.json)\n * Note: Global directory follows same structure as other memory directories\n */\nexport function getGlobalConfigPath(): string {\n return path.join(getGlobalDir(), CONFIG_DIR, CONFIG_FILENAME);\n}\n\n/**\n * Get the config file path for a memory directory\n */\nexport function getConfigPath(memoryDir: string): string {\n return path.join(memoryDir, CONFIG_DIR, CONFIG_FILENAME);\n}\n\n/**\n * Get the XDG-style global config directory (~/.config/minimem)\n */\nexport function getXdgConfigDir(): string {\n return path.join(os.homedir(), XDG_CONFIG_DIR);\n}\n\n/**\n * Get the XDG-style global config file path (~/.config/minimem/config.json)\n */\nexport function getXdgConfigPath(): string {\n return path.join(getXdgConfigDir(), CONFIG_FILENAME);\n}\n\n/**\n * Expand ~ to home directory in paths\n */\nexport function expandPath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filePath.slice(2));\n }\n if (filePath === \"~\") {\n return os.homedir();\n }\n return filePath;\n}\n\n/**\n * Load XDG global config from ~/.config/minimem/config.json\n */\nexport async function loadXdgConfig(): Promise<GlobalConfig> {\n try {\n const content = await fs.readFile(getXdgConfigPath(), \"utf-8\");\n return JSON.parse(content) as GlobalConfig;\n } catch {\n return {};\n }\n}\n\n/**\n * Save XDG global config to ~/.config/minimem/config.json\n */\nexport async function saveXdgConfig(config: GlobalConfig): Promise<void> {\n const configDir = getXdgConfigDir();\n const configPath = getXdgConfigPath();\n\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Get or generate a unique machine ID\n * Format: {hostname}-{random4hex}\n * Stored in XDG global config\n */\nexport async function getMachineId(): Promise<string> {\n const globalConfig = await loadXdgConfig();\n\n if (globalConfig.machineId) {\n return globalConfig.machineId;\n }\n\n // Generate new machine ID\n const hostname = os.hostname().toLowerCase().replace(/[^a-z0-9-]/g, \"-\");\n const suffix = crypto.randomBytes(2).toString(\"hex\");\n const machineId = `${hostname}-${suffix}`;\n\n // Save to global config\n await saveXdgConfig({ ...globalConfig, machineId });\n\n return machineId;\n}\n\n/**\n * Get the central repo path from global config (expanded)\n */\nexport async function getCentralRepo(): Promise<string | undefined> {\n const globalConfig = await loadXdgConfig();\n if (globalConfig.centralRepo) {\n return expandPath(globalConfig.centralRepo);\n }\n return undefined;\n}\n\n/**\n * Set the central repo path in global config\n */\nexport async function setCentralRepo(repoPath: string): Promise<void> {\n const globalConfig = await loadXdgConfig();\n globalConfig.centralRepo = repoPath;\n await saveXdgConfig(globalConfig);\n}\n\n/**\n * Load config from a specific file path\n */\nasync function loadConfigFile(configPath: string): Promise<CliConfig> {\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as CliConfig;\n } catch {\n return {};\n }\n}\n\n/**\n * Load global config from ~/.minimem/config.json\n */\nexport async function loadGlobalConfig(): Promise<CliConfig> {\n return loadConfigFile(getGlobalConfigPath());\n}\n\n/**\n * Load config from a memory directory, layered on top of global config\n *\n * Resolution order:\n * 1. Built-in defaults\n * 2. Global config (~/.minimem/config.json)\n * 3. Local config (.minimem/config.json in memory directory)\n */\nexport async function loadConfig(memoryDir: string): Promise<CliConfig> {\n const globalDir = getGlobalDir();\n const isGlobalDir = path.resolve(memoryDir) === globalDir;\n\n // Load global config (unless we're loading the global dir itself)\n const globalConfig = isGlobalDir ? {} : await loadGlobalConfig();\n\n // Load local config\n const localConfig = await loadConfigFile(getConfigPath(memoryDir));\n\n // Deep merge: local overrides global\n return deepMergeConfig(globalConfig, localConfig);\n}\n\n/**\n * Deep merge two configs (source overrides target)\n */\nfunction deepMergeConfig(target: CliConfig, source: CliConfig): CliConfig {\n const result: CliConfig = { ...target };\n\n if (source.embedding) {\n result.embedding = {\n ...target.embedding,\n ...source.embedding,\n openai: source.embedding.openai\n ? { ...target.embedding?.openai, ...source.embedding.openai }\n : target.embedding?.openai,\n gemini: source.embedding.gemini\n ? { ...target.embedding?.gemini, ...source.embedding.gemini }\n : target.embedding?.gemini,\n local: source.embedding.local\n ? { ...target.embedding?.local, ...source.embedding.local }\n : target.embedding?.local,\n };\n }\n\n if (source.hybrid) {\n result.hybrid = { ...target.hybrid, ...source.hybrid };\n }\n\n if (source.query) {\n result.query = { ...target.query, ...source.query };\n }\n\n if (source.watch) {\n result.watch = { ...target.watch, ...source.watch };\n }\n\n if (source.chunking) {\n result.chunking = { ...target.chunking, ...source.chunking };\n }\n\n if (source.hooks) {\n result.hooks = { ...target.hooks, ...source.hooks };\n }\n\n if (source.sync) {\n result.sync = { ...target.sync, ...source.sync };\n // Arrays should be replaced, not merged\n if (source.sync.include) {\n result.sync.include = source.sync.include;\n }\n if (source.sync.exclude) {\n result.sync.exclude = source.sync.exclude;\n }\n }\n\n return result;\n}\n\n/**\n * Save config to a memory directory\n */\nexport async function saveConfig(\n memoryDir: string,\n config: CliConfig,\n): Promise<void> {\n const configDir = path.join(memoryDir, CONFIG_DIR);\n const configPath = getConfigPath(memoryDir);\n\n await fs.mkdir(configDir, { recursive: true });\n await fs.writeFile(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\n/**\n * Get default config with all settings\n */\nexport function getDefaultConfig(): CliConfig {\n return {\n embedding: {\n provider: \"auto\",\n // model is provider-specific, so no default here\n // fallback: \"none\" is implicit\n },\n hybrid: {\n enabled: true,\n vectorWeight: 0.7,\n textWeight: 0.3,\n },\n query: {\n maxResults: 10,\n minScore: 0.3,\n },\n chunking: {\n tokens: 256,\n overlap: 32,\n },\n };\n}\n\n/**\n * Get default sync configuration\n */\nexport function getDefaultSyncConfig(): NonNullable<CliConfig[\"sync\"]> {\n return {\n enabled: false,\n include: [\"MEMORY.md\", \"memory/**/*.md\"],\n exclude: [],\n };\n}\n\n/**\n * Get default global sync settings\n */\nexport function getDefaultGlobalSyncConfig(): NonNullable<GlobalConfig[\"sync\"]> {\n return {\n conflictStrategy: \"keep-both\",\n autoSync: false,\n autoCommit: false,\n };\n}\n\n/**\n * Load full config including XDG global settings\n * Resolution order:\n * 1. Built-in defaults\n * 2. XDG global config (~/.config/minimem/config.json)\n * 3. Legacy global config (~/.minimem/.minimem/config.json)\n * 4. Local config (.minimem/config.json in memory directory)\n */\nexport async function loadFullConfig(memoryDir: string): Promise<{\n local: CliConfig;\n global: GlobalConfig;\n merged: CliConfig;\n}> {\n const globalDir = getGlobalDir();\n const isGlobalDir = path.resolve(memoryDir) === globalDir;\n\n // Load XDG global config\n const xdgConfig = await loadXdgConfig();\n\n // Load legacy global config (unless we're loading the global dir itself)\n const legacyGlobalConfig = isGlobalDir ? {} : await loadGlobalConfig();\n\n // Load local config\n const localConfig = await loadConfigFile(getConfigPath(memoryDir));\n\n // Merge: XDG → legacy global → local\n const merged = deepMergeConfig(\n deepMergeConfig(xdgConfig as CliConfig, legacyGlobalConfig),\n localConfig\n );\n\n return {\n local: localConfig,\n global: xdgConfig,\n merged,\n };\n}\n\n/**\n * Get sync config for a directory with defaults applied\n */\nexport async function getSyncConfig(memoryDir: string): Promise<{\n enabled: boolean;\n path?: string;\n include: string[];\n exclude: string[];\n centralRepo?: string;\n conflictStrategy: NonNullable<GlobalConfig[\"sync\"]>[\"conflictStrategy\"];\n autoSync: boolean;\n autoCommit: boolean;\n mergeResolver?: string;\n}> {\n const { merged, global: xdgConfig } = await loadFullConfig(memoryDir);\n const defaults = getDefaultSyncConfig();\n const globalDefaults = getDefaultGlobalSyncConfig();\n\n return {\n enabled: merged.sync?.enabled ?? defaults.enabled ?? false,\n path: merged.sync?.path,\n include: merged.sync?.include ?? defaults.include,\n exclude: merged.sync?.exclude ?? defaults.exclude,\n centralRepo: xdgConfig.centralRepo ? expandPath(xdgConfig.centralRepo) : undefined,\n conflictStrategy: xdgConfig.sync?.conflictStrategy ?? globalDefaults.conflictStrategy,\n autoSync: xdgConfig.sync?.autoSync ?? globalDefaults.autoSync,\n autoCommit: xdgConfig.sync?.autoCommit ?? globalDefaults.autoCommit,\n mergeResolver: xdgConfig.sync?.mergeResolver,\n };\n}\n\n/**\n * Get a minimal config for new directories (doesn't include all defaults)\n * This is what gets written to config.json on init\n */\nexport function getInitConfig(): CliConfig {\n return {\n embedding: {\n provider: \"auto\",\n },\n hybrid: {\n enabled: true,\n vectorWeight: 0.7,\n textWeight: 0.3,\n },\n query: {\n maxResults: 10,\n minScore: 0.3,\n },\n };\n}\n\n/**\n * Merge configs with defaults\n */\nexport function mergeConfig(config: CliConfig): CliConfig {\n const defaults = getDefaultConfig();\n return deepMergeConfig(defaults, config);\n}\n\n/**\n * Build MinimemConfig from CLI config and options\n */\nexport function buildMinimemConfig(\n memoryDir: string,\n cliConfig: CliConfig,\n options?: {\n provider?: string;\n watch?: boolean;\n },\n): MinimemConfig {\n const merged = mergeConfig(cliConfig);\n\n // Resolve embedding provider (CLI flag > config > default)\n const embeddingProvider = (options?.provider ||\n merged.embedding?.provider ||\n \"auto\") as EmbeddingProviderOptions[\"provider\"];\n\n // Build embedding options, using provider-specific model if set\n const providerModel =\n embeddingProvider === \"openai\"\n ? merged.embedding?.openai?.model\n : embeddingProvider === \"gemini\"\n ? merged.embedding?.gemini?.model\n : undefined;\n\n const embedding: EmbeddingProviderOptions = {\n provider: embeddingProvider,\n model: merged.embedding?.model || providerModel,\n fallback: merged.embedding?.fallback,\n openai: merged.embedding?.openai,\n gemini: merged.embedding?.gemini,\n local: merged.embedding?.local,\n };\n\n return {\n memoryDir,\n embedding,\n hybrid: merged.hybrid,\n query: merged.query,\n chunking: merged.chunking,\n watch: {\n enabled: options?.watch ?? false, // Disable watching by default in CLI\n },\n };\n}\n\n/**\n * Check if a directory is initialized as a minimem memory directory\n */\nexport async function isInitialized(memoryDir: string): Promise<boolean> {\n const configPath = getConfigPath(memoryDir);\n try {\n await fs.access(configPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Format a path for display (use ~ for home directory)\n */\nexport function formatPath(filePath: string): string {\n const home = os.homedir();\n if (filePath.startsWith(home)) {\n return \"~\" + filePath.slice(home.length);\n }\n return filePath;\n}\n","/**\n * Shared CLI utilities\n *\n * Centralized functions for directory resolution, error handling,\n * and other cross-cutting concerns used by all CLI commands.\n */\n\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\n\n/**\n * Options that affect directory resolution\n */\nexport type DirOptions = {\n dir?: string | string[];\n global?: boolean;\n};\n\n/**\n * Resolve a single memory directory from options.\n *\n * Priority:\n * 1. --dir flag (first element if array)\n * 2. MEMORY_DIR environment variable\n * 3. --global flag → ~/.minimem\n * 4. Current working directory\n *\n * Use this for commands that operate on a single directory.\n */\nexport function resolveMemoryDir(options: DirOptions): string {\n // Handle --dir flag (use first if array)\n const dir = Array.isArray(options.dir) ? options.dir[0] : options.dir;\n if (dir) {\n return path.resolve(dir);\n }\n\n // Check MEMORY_DIR environment variable\n const envDir = process.env.MEMORY_DIR;\n if (envDir) {\n return path.resolve(envDir);\n }\n\n // Handle --global flag\n if (options.global) {\n return path.join(os.homedir(), \".minimem\");\n }\n\n // Default to current working directory\n return process.cwd();\n}\n\n/**\n * Resolve multiple memory directories from options.\n *\n * Use this for commands that can search across multiple directories\n * (e.g., search, mcp).\n *\n * Returns deduplicated list of absolute paths.\n */\nexport function resolveMemoryDirs(options: DirOptions): string[] {\n const dirs: string[] = [];\n\n // Add explicit directories from --dir flag\n if (options.dir) {\n const dirList = Array.isArray(options.dir) ? options.dir : [options.dir];\n dirs.push(...dirList.map((d) => path.resolve(d)));\n }\n\n // If no explicit dirs, check MEMORY_DIR environment variable\n if (dirs.length === 0 && process.env.MEMORY_DIR) {\n dirs.push(path.resolve(process.env.MEMORY_DIR));\n }\n\n // Add global directory if --global flag is set\n if (options.global) {\n const globalDir = path.join(os.homedir(), \".minimem\");\n if (!dirs.includes(globalDir)) {\n dirs.push(globalDir);\n }\n }\n\n // Default to current directory if nothing specified\n if (dirs.length === 0) {\n dirs.push(process.cwd());\n }\n\n // Deduplicate\n return [...new Set(dirs)];\n}\n\n/**\n * Get the global memory directory path (~/.minimem)\n */\nexport function getGlobalMemoryDir(): string {\n return path.join(os.homedir(), \".minimem\");\n}\n\n/**\n * Exit with an error message and optional suggestion.\n *\n * All CLI errors should use this for consistent formatting.\n */\nexport function exitWithError(message: string, suggestion?: string): never {\n console.error(`Error: ${message}`);\n if (suggestion) {\n console.error(` Suggestion: ${suggestion}`);\n }\n process.exit(1);\n}\n\n/**\n * Print a warning message (non-fatal).\n */\nexport function warn(message: string): void {\n console.error(`Warning: ${message}`);\n}\n\n/**\n * Print a note/informational message.\n */\nexport function note(message: string): void {\n console.error(`Note: ${message}`);\n}\n\n/**\n * Log an error with context (for debugging).\n * Only logs if a debug function is provided.\n */\nexport function logError(\n context: string,\n error: unknown,\n debug?: (msg: string) => void\n): void {\n const message = error instanceof Error ? error.message : String(error);\n if (debug) {\n debug(`[${context}] Error: ${message}`);\n }\n}\n\n/**\n * Get a friendly display name for a directory.\n */\nexport function getDirName(memoryDir: string): string {\n const home = os.homedir();\n\n // Check if it's the global directory\n if (memoryDir === path.join(home, \".minimem\")) {\n return \"global\";\n }\n\n // Use the directory name\n const name = path.basename(memoryDir);\n\n // If it's a hidden directory, use parent + name\n if (name.startsWith(\".\")) {\n const parent = path.basename(path.dirname(memoryDir));\n return `${parent}/${name}`;\n }\n\n return name;\n}\n","import { randomUUID } from \"node:crypto\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\n\nimport {\n buildFileEntry,\n chunkMarkdown,\n ensureDir,\n extractChunkMetadata,\n hashText,\n listMemoryFiles,\n logError,\n type MemoryChunk,\n type MemoryFileEntry,\n parseEmbedding,\n vectorToBlob,\n} from \"./internal.js\";\nimport { bm25RankToScore, buildFtsQuery, mergeHybridResults } from \"./search/hybrid.js\";\nimport { searchKeyword, searchVector, buildKnowledgeFilterSql } from \"./search/search.js\";\nimport { ensureMemoryIndexSchema } from \"./db/schema.js\";\nimport { parseFrontmatter, type MemoryFrontmatter, type KnowledgeLink } from \"./session.js\";\nimport {\n getLinksFrom,\n getLinksTo,\n getNeighbors,\n getPathBetween,\n type GraphLink,\n type GraphNeighbor,\n} from \"./search/graph.js\";\nimport { loadSqliteVecExtension } from \"./db/sqlite-vec.js\";\nimport {\n createEmbeddingProvider,\n type EmbeddingProvider,\n type EmbeddingProviderOptions,\n type OpenAiEmbeddingClient,\n type GeminiEmbeddingClient,\n} from \"./embeddings/embeddings.js\";\nimport { runOpenAiEmbeddingBatches, type OpenAiBatchRequest, OPENAI_BATCH_ENDPOINT } from \"./embeddings/batch-openai.js\";\nimport { runGeminiEmbeddingBatches, type GeminiBatchRequest } from \"./embeddings/batch-gemini.js\";\n\nconst META_KEY = \"memory_index_meta_v1\";\nconst SNIPPET_MAX_CHARS = 700;\nconst VECTOR_TABLE = \"chunks_vec\";\nconst FTS_TABLE = \"chunks_fts\";\nconst EMBEDDING_CACHE_TABLE = \"embedding_cache\";\nconst EMBEDDING_BATCH_MAX_TOKENS = 8000;\nconst EMBEDDING_APPROX_CHARS_PER_TOKEN = 1;\nconst EMBEDDING_INDEX_CONCURRENCY = 4;\nconst EMBEDDING_RETRY_MAX_ATTEMPTS = 3;\nconst EMBEDDING_RETRY_BASE_DELAY_MS = 500;\nconst EMBEDDING_RETRY_MAX_DELAY_MS = 8000;\nconst VECTOR_LOAD_TIMEOUT_MS = 30_000;\nconst EMBEDDING_QUERY_TIMEOUT_REMOTE_MS = 60_000;\nconst EMBEDDING_QUERY_TIMEOUT_LOCAL_MS = 5 * 60_000;\n\nexport type MinimemConfig = {\n /** Directory containing memory files (MEMORY.md, memory/*.md) */\n memoryDir: string;\n /** Path to SQLite database. Defaults to memoryDir/.minimem/index.db */\n dbPath?: string;\n /** Embedding provider options */\n embedding: EmbeddingProviderOptions;\n /** Chunking configuration */\n chunking?: {\n /** Tokens per chunk (default: 256) */\n tokens?: number;\n /** Overlap tokens between chunks (default: 32) */\n overlap?: number;\n };\n /** Embedding cache configuration */\n cache?: {\n /** Enable embedding cache (default: true) */\n enabled?: boolean;\n /** Max cache entries before LRU pruning (default: 10000) */\n maxEntries?: number;\n };\n /** Hybrid search configuration */\n hybrid?: {\n /** Enable hybrid search (default: true) */\n enabled?: boolean;\n /** Weight for vector search (default: 0.7) */\n vectorWeight?: number;\n /** Weight for keyword search (default: 0.3) */\n textWeight?: number;\n /** Candidate multiplier for search (default: 2.0) */\n candidateMultiplier?: number;\n };\n /** Query configuration */\n query?: {\n /** Max results (default: 10) */\n maxResults?: number;\n /** Min score threshold (default: 0.3) */\n minScore?: number;\n };\n /** File watching configuration */\n watch?: {\n /** Enable file watching (default: true) */\n enabled?: boolean;\n /** Debounce delay in ms (default: 1000) */\n debounceMs?: number;\n };\n /** Batch embedding configuration */\n batch?: {\n /** Enable batch embedding API (default: false) */\n enabled?: boolean;\n /** Wait for batch completion (default: true) */\n wait?: boolean;\n /** Concurrent batch requests (default: 2) */\n concurrency?: number;\n /** Poll interval in ms (default: 2000) */\n pollIntervalMs?: number;\n /** Timeout in ms (default: 60 minutes) */\n timeoutMs?: number;\n };\n /** sqlite-vec extension path (optional) */\n vectorExtensionPath?: string;\n /** Debug logging function */\n debug?: (message: string, data?: Record<string, unknown>) => void;\n};\n\nexport type MinimemSearchResult = {\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n};\n\ntype MemoryIndexMeta = {\n model: string;\n provider: string;\n providerKey?: string;\n chunkTokens: number;\n chunkOverlap: number;\n vectorDims?: number;\n};\n\nexport class Minimem {\n private readonly memoryDir: string;\n private readonly dbPath: string;\n private readonly chunking: { tokens: number; overlap: number };\n private readonly cache: { enabled: boolean; maxEntries: number };\n private readonly hybrid: {\n enabled: boolean;\n vectorWeight: number;\n textWeight: number;\n candidateMultiplier: number;\n };\n private readonly queryConfig: { maxResults: number; minScore: number };\n private readonly watchConfig: { enabled: boolean; debounceMs: number };\n private readonly batchConfig: {\n enabled: boolean;\n wait: boolean;\n concurrency: number;\n pollIntervalMs: number;\n timeoutMs: number;\n };\n private readonly vectorExtensionPath?: string;\n private readonly debug?: (message: string, data?: Record<string, unknown>) => void;\n\n private provider!: EmbeddingProvider;\n private openAi?: OpenAiEmbeddingClient;\n private gemini?: GeminiEmbeddingClient;\n private providerKey: string = \"\";\n private providerFallbackReason?: string;\n private db!: DatabaseSync;\n\n private readonly vector: {\n enabled: boolean;\n available: boolean | null;\n extensionPath?: string;\n loadError?: string;\n dims?: number;\n };\n private readonly fts: {\n enabled: boolean;\n available: boolean;\n loadError?: string;\n };\n\n private vectorReady: Promise<boolean> | null = null;\n private watcher: FSWatcher | null = null;\n private watchTimer: NodeJS.Timeout | null = null;\n private closed = false;\n private dirty = true;\n private syncing: Promise<void> | null = null;\n private syncLock = false;\n private embeddingOptions: EmbeddingProviderOptions;\n\n private constructor(config: MinimemConfig) {\n this.memoryDir = path.resolve(config.memoryDir);\n this.dbPath = config.dbPath ?? path.join(this.memoryDir, \".minimem\", \"index.db\");\n this.chunking = {\n tokens: config.chunking?.tokens ?? 256,\n overlap: config.chunking?.overlap ?? 32,\n };\n this.cache = {\n enabled: config.cache?.enabled ?? true,\n maxEntries: config.cache?.maxEntries ?? 10000,\n };\n this.hybrid = {\n enabled: config.hybrid?.enabled ?? true,\n vectorWeight: config.hybrid?.vectorWeight ?? 0.7,\n textWeight: config.hybrid?.textWeight ?? 0.3,\n candidateMultiplier: config.hybrid?.candidateMultiplier ?? 2.0,\n };\n this.queryConfig = {\n maxResults: config.query?.maxResults ?? 10,\n minScore: config.query?.minScore ?? 0.3,\n };\n this.watchConfig = {\n enabled: config.watch?.enabled ?? true,\n debounceMs: config.watch?.debounceMs ?? 1000,\n };\n this.batchConfig = {\n enabled: config.batch?.enabled ?? false,\n wait: config.batch?.wait ?? true,\n concurrency: config.batch?.concurrency ?? 2,\n pollIntervalMs: config.batch?.pollIntervalMs ?? 2000,\n timeoutMs: config.batch?.timeoutMs ?? 60 * 60 * 1000,\n };\n this.vectorExtensionPath = config.vectorExtensionPath;\n this.debug = config.debug;\n this.embeddingOptions = config.embedding;\n\n this.vector = {\n enabled: true,\n available: null,\n extensionPath: this.vectorExtensionPath,\n };\n this.fts = { enabled: this.hybrid.enabled, available: false };\n }\n\n static async create(config: MinimemConfig): Promise<Minimem> {\n const instance = new Minimem(config);\n await instance.initialize();\n return instance;\n }\n\n private async initialize(): Promise<void> {\n // Create embedding provider\n const providerResult = await createEmbeddingProvider(this.embeddingOptions);\n this.provider = providerResult.provider;\n this.openAi = providerResult.openAi;\n this.gemini = providerResult.gemini;\n this.providerKey = this.computeProviderKey();\n this.providerFallbackReason = providerResult.fallbackReason;\n\n // Log warning if in BM25-only fallback mode\n if (this.provider.id === \"none\") {\n this.debug?.(\"Running in BM25-only mode (no embedding API available)\");\n }\n\n // Open database\n this.db = this.openDatabase();\n this.ensureSchema();\n\n // Check for existing vector dims\n const meta = this.readMeta();\n if (meta?.vectorDims) {\n this.vector.dims = meta.vectorDims;\n }\n\n // Start file watcher\n if (this.watchConfig.enabled) {\n this.ensureWatcher();\n }\n }\n\n private openDatabase(): DatabaseSync {\n const dbDir = path.dirname(this.dbPath);\n ensureDir(dbDir);\n return new DatabaseSync(this.dbPath);\n }\n\n private ensureSchema(): void {\n const result = ensureMemoryIndexSchema({\n db: this.db,\n embeddingCacheTable: EMBEDDING_CACHE_TABLE,\n ftsTable: FTS_TABLE,\n ftsEnabled: this.fts.enabled,\n });\n this.fts.available = result.ftsAvailable;\n if (result.ftsError) {\n this.fts.loadError = result.ftsError;\n }\n }\n\n private computeProviderKey(): string {\n const parts: string[] = [this.provider.id, this.provider.model];\n if (this.openAi) {\n parts.push(this.openAi.baseUrl);\n }\n if (this.gemini) {\n parts.push(this.gemini.baseUrl);\n }\n return hashText(parts.join(\":\"));\n }\n\n private readMeta(): MemoryIndexMeta | null {\n try {\n const row = this.db.prepare(`SELECT value FROM meta WHERE key = ?`).get(META_KEY) as\n | { value: string }\n | undefined;\n if (!row?.value) return null;\n return JSON.parse(row.value) as MemoryIndexMeta;\n } catch {\n return null;\n }\n }\n\n private writeMeta(meta: MemoryIndexMeta): void {\n this.db\n .prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)`)\n .run(META_KEY, JSON.stringify(meta));\n }\n\n private ensureWatcher(): void {\n if (this.watcher) return;\n const memorySubDir = path.join(this.memoryDir, \"memory\");\n const memoryFile = path.join(this.memoryDir, \"MEMORY.md\");\n\n this.watcher = chokidar.watch([memoryFile, memorySubDir], {\n ignoreInitial: true,\n persistent: true,\n awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },\n });\n\n const scheduleSync = () => {\n this.dirty = true;\n if (this.watchTimer) clearTimeout(this.watchTimer);\n this.watchTimer = setTimeout(() => {\n void this.sync({ reason: \"watch\" }).catch((err) => {\n this.debug?.(`memory sync failed (watch): ${String(err)}`);\n });\n }, this.watchConfig.debounceMs);\n };\n\n this.watcher.on(\"add\", scheduleSync);\n this.watcher.on(\"change\", scheduleSync);\n this.watcher.on(\"unlink\", scheduleSync);\n }\n\n /**\n * Check if the index is stale by comparing file mtimes against stored values.\n * This is a lightweight check (stat calls only, no file reads).\n */\n private async isStale(): Promise<boolean> {\n try {\n const files = await listMemoryFiles(this.memoryDir);\n\n // Get stored file records\n const stored = this.db\n .prepare(`SELECT path, mtime FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string; mtime: number }>;\n\n // Quick check: different file count means stale\n if (files.length !== stored.length) {\n this.debug?.(`Stale: file count changed (${stored.length} -> ${files.length})`);\n return true;\n }\n\n // Build lookup map of stored mtimes\n const storedMap = new Map(stored.map((f) => [f.path, f.mtime]));\n\n // Check each file's mtime against stored value\n for (const absPath of files) {\n const relPath = path.relative(this.memoryDir, absPath).replace(/\\\\/g, \"/\");\n const storedMtime = storedMap.get(relPath);\n\n // File not in index = stale\n if (storedMtime === undefined) {\n this.debug?.(`Stale: new file ${relPath}`);\n return true;\n }\n\n // Check mtime\n const stat = await fs.stat(absPath);\n const currentMtime = Math.floor(stat.mtimeMs);\n if (currentMtime !== storedMtime) {\n this.debug?.(`Stale: mtime changed for ${relPath}`);\n return true;\n }\n }\n\n return false;\n } catch (err) {\n // On error, assume stale to be safe\n this.debug?.(`Stale check failed: ${String(err)}`);\n return true;\n }\n }\n\n async search(\n query: string,\n opts?: { maxResults?: number; minScore?: number; type?: string },\n ): Promise<MinimemSearchResult[]> {\n // Check staleness: use dirty flag if watcher is on, otherwise check mtimes\n if (this.dirty || (!this.watchConfig.enabled && (await this.isStale()))) {\n await this.sync({ reason: \"search\" });\n }\n\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.queryConfig.minScore;\n const maxResults = opts?.maxResults ?? this.queryConfig.maxResults;\n const candidates = Math.min(\n 200,\n Math.max(1, Math.floor(maxResults * this.hybrid.candidateMultiplier)),\n );\n\n const sourceFilter = { sql: \"\", params: [] as string[] };\n\n const keywordResults = this.hybrid.enabled && this.fts.available\n ? await searchKeyword({\n db: this.db,\n ftsTable: FTS_TABLE,\n providerModel: this.provider.model,\n query: cleaned,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n sourceFilter,\n buildFtsQuery,\n bm25RankToScore,\n }).catch(() => [])\n : [];\n\n const queryVec = await this.embedQueryWithTimeout(cleaned);\n const hasVector = queryVec.some((v) => v !== 0);\n const vectorResults = hasVector\n ? await searchVector({\n db: this.db,\n vectorTable: VECTOR_TABLE,\n providerModel: this.provider.model,\n queryVec,\n limit: candidates,\n snippetMaxChars: SNIPPET_MAX_CHARS,\n ensureVectorReady: (dims) => this.ensureVectorReady(dims),\n sourceFilterVec: sourceFilter,\n sourceFilterChunks: sourceFilter,\n }).catch(() => [])\n : [];\n\n // Apply type filter if specified\n const typeFilterFn = opts?.type\n ? (id: string) => {\n const row = this.db\n .prepare(`SELECT type FROM chunks WHERE id = ?`)\n .get(id) as { type: string | null } | undefined;\n return row?.type === opts.type;\n }\n : undefined;\n\n if (!this.hybrid.enabled) {\n let results = vectorResults;\n if (typeFilterFn) results = results.filter((r) => typeFilterFn(r.id));\n return results\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n let filteredVector = vectorResults;\n let filteredKeyword = keywordResults;\n if (typeFilterFn) {\n filteredVector = vectorResults.filter((r) => typeFilterFn(r.id));\n filteredKeyword = keywordResults.filter((r) => typeFilterFn(r.id));\n }\n\n const merged = mergeHybridResults({\n vector: filteredVector.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.score,\n })),\n keyword: filteredKeyword.map((r) => ({\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n textScore: r.textScore,\n })),\n vectorWeight: this.hybrid.vectorWeight,\n textWeight: this.hybrid.textWeight,\n });\n\n return merged\n .filter((entry) => entry.score >= minScore)\n .slice(0, maxResults)\n .map((r) => ({\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n score: r.score,\n snippet: r.snippet,\n }));\n }\n\n async sync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n // If a sync is already running, wait for it instead of starting another\n if (this.syncing) {\n await this.syncing;\n return;\n }\n\n // Use a synchronous flag to prevent the race window between\n // checking this.syncing and assigning to it\n if (this.syncLock) {\n return;\n }\n this.syncLock = true;\n\n this.syncing = this.runSync(opts);\n try {\n await this.syncing;\n } finally {\n this.syncing = null;\n this.syncLock = false;\n }\n }\n\n private async runSync(opts?: { reason?: string; force?: boolean }): Promise<void> {\n this.debug?.(`memory sync starting`, { reason: opts?.reason });\n\n await this.ensureVectorReady();\n const meta = this.readMeta();\n const needsFullReindex =\n opts?.force ||\n !meta ||\n meta.model !== this.provider.model ||\n meta.provider !== this.provider.id ||\n meta.providerKey !== this.providerKey ||\n meta.chunkTokens !== this.chunking.tokens ||\n meta.chunkOverlap !== this.chunking.overlap ||\n (this.vector.available && !meta?.vectorDims);\n\n const files = await listMemoryFiles(this.memoryDir);\n const activePaths = new Set<string>();\n\n for (const absPath of files) {\n const entry = await buildFileEntry(absPath, this.memoryDir);\n activePaths.add(entry.path);\n\n const record = this.db\n .prepare(`SELECT hash FROM files WHERE path = ? AND source = ?`)\n .get(entry.path, \"memory\") as { hash: string } | undefined;\n\n if (!needsFullReindex && record?.hash === entry.hash) {\n continue;\n }\n\n await this.indexFile(entry);\n }\n\n // Delete stale entries\n const staleRows = this.db\n .prepare(`SELECT path FROM files WHERE source = ?`)\n .all(\"memory\") as Array<{ path: string }>;\n\n for (const stale of staleRows) {\n if (activePaths.has(stale.path)) continue;\n this.db.prepare(`DELETE FROM files WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(stale.path, \"memory\");\n } catch (err) {\n logError(\"deleteStaleVectorEntries\", err, this.debug);\n }\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(stale.path, \"memory\");\n this.db.prepare(`DELETE FROM knowledge_links WHERE source_path = ?`).run(stale.path);\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(stale.path, \"memory\", this.provider.model);\n } catch (err) {\n logError(\"deleteStaleFtsEntries\", err, this.debug);\n }\n }\n }\n\n // Write meta\n this.writeMeta({\n model: this.provider.model,\n provider: this.provider.id,\n providerKey: this.providerKey,\n chunkTokens: this.chunking.tokens,\n chunkOverlap: this.chunking.overlap,\n vectorDims: this.vector.dims,\n });\n\n // Prune embedding cache\n this.pruneEmbeddingCacheIfNeeded();\n\n this.dirty = false;\n this.debug?.(`memory sync complete`, { files: files.length });\n }\n\n private async indexFile(entry: MemoryFileEntry): Promise<void> {\n const content = await fs.readFile(entry.absPath, \"utf-8\");\n const chunks = chunkMarkdown(content, this.chunking);\n\n // Extract knowledge frontmatter\n const { frontmatter } = parseFrontmatter(content);\n const knowledgeType = frontmatter?.type ?? null;\n const knowledgeId = frontmatter?.id ?? null;\n const domains = frontmatter?.domain ?? null;\n const entities = frontmatter?.entities ?? null;\n const confidence = frontmatter?.confidence ?? null;\n const links = frontmatter?.links ?? null;\n\n // Get embeddings\n const embeddings = await this.embedChunks(chunks);\n\n // Update files table\n this.db\n .prepare(\n `INSERT OR REPLACE INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`,\n )\n .run(entry.path, \"memory\", entry.hash, Math.floor(entry.mtimeMs), entry.size);\n\n // Delete old chunks for this file\n try {\n this.db\n .prepare(\n `DELETE FROM ${VECTOR_TABLE} WHERE id IN (SELECT id FROM chunks WHERE path = ? AND source = ?)`,\n )\n .run(entry.path, \"memory\");\n } catch (err) {\n logError(\"deleteOldVectorChunks\", err, this.debug);\n }\n this.db.prepare(`DELETE FROM chunks WHERE path = ? AND source = ?`).run(entry.path, \"memory\");\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(`DELETE FROM ${FTS_TABLE} WHERE path = ? AND source = ? AND model = ?`)\n .run(entry.path, \"memory\", this.provider.model);\n } catch (err) {\n logError(\"deleteOldFtsChunks\", err, this.debug);\n }\n }\n\n // Delete old knowledge links for this file path on re-index\n this.db.prepare(`DELETE FROM knowledge_links WHERE source_path = ?`).run(entry.path);\n\n // Insert new chunks\n const now = Date.now();\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const embedding = embeddings[i] ?? [];\n const chunkId = randomUUID();\n const meta = extractChunkMetadata(chunk.text);\n\n this.db\n .prepare(\n `INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at, type, knowledge_type, knowledge_id, domains, entities, confidence)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunkId,\n entry.path,\n \"memory\",\n chunk.startLine,\n chunk.endLine,\n chunk.hash,\n this.provider.model,\n chunk.text,\n JSON.stringify(embedding),\n now,\n meta.type ?? null,\n knowledgeType,\n knowledgeId,\n domains ? JSON.stringify(domains) : null,\n entities ? JSON.stringify(entities) : null,\n confidence,\n );\n\n // Insert into vector table if available\n if (this.vector.available && embedding.length > 0) {\n if (!this.vector.dims) {\n this.vector.dims = embedding.length;\n this.ensureVectorTable(embedding.length);\n }\n try {\n this.db\n .prepare(`INSERT INTO ${VECTOR_TABLE} (id, embedding) VALUES (?, ?)`)\n .run(chunkId, vectorToBlob(embedding));\n } catch (err) {\n logError(\"insertVectorChunk\", err, this.debug);\n }\n }\n\n // Insert into FTS table if available\n if (this.fts.enabled && this.fts.available) {\n try {\n this.db\n .prepare(\n `INSERT INTO ${FTS_TABLE} (text, id, path, source, model, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n chunk.text,\n chunkId,\n entry.path,\n \"memory\",\n this.provider.model,\n chunk.startLine,\n chunk.endLine,\n );\n } catch (err) {\n logError(\"insertFtsChunk\", err, this.debug);\n }\n }\n }\n\n // Upsert knowledge links if present\n if (links && knowledgeId) {\n const upsertLink = this.db.prepare(\n `INSERT OR REPLACE INTO knowledge_links (from_id, to_id, relation, layer, weight, source_path, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n );\n for (const link of links) {\n upsertLink.run(\n knowledgeId,\n link.target,\n link.relation,\n link.layer ?? null,\n 0.5,\n entry.path,\n now,\n );\n }\n }\n }\n\n private async embedChunks(chunks: MemoryChunk[]): Promise<number[][]> {\n if (chunks.length === 0) return [];\n\n const hashes = chunks.map((c) => c.hash);\n const cached = this.loadEmbeddingCache(hashes);\n const missing: Array<{ index: number; chunk: MemoryChunk }> = [];\n\n for (let i = 0; i < chunks.length; i++) {\n if (!cached.has(hashes[i])) {\n missing.push({ index: i, chunk: chunks[i] });\n }\n }\n\n if (missing.length > 0) {\n const texts = missing.map((m) => m.chunk.text);\n const newEmbeddings = await this.embedBatchWithRetry(texts);\n\n for (let i = 0; i < missing.length; i++) {\n const hash = missing[i].chunk.hash;\n const embedding = newEmbeddings[i] ?? [];\n cached.set(hash, embedding);\n this.upsertEmbeddingCache(hash, embedding);\n }\n }\n\n return hashes.map((h) => cached.get(h) ?? []);\n }\n\n private async embedBatchWithRetry(texts: string[]): Promise<number[][]> {\n if (texts.length === 0) return [];\n\n // Try batch API first if enabled\n if (this.batchConfig.enabled) {\n try {\n return await this.embedWithBatchApi(texts);\n } catch (err) {\n this.debug?.(`batch embedding failed, falling back to direct: ${String(err)}`);\n }\n }\n\n // Fall back to direct embedding\n let lastError: Error | null = null;\n for (let attempt = 0; attempt < EMBEDDING_RETRY_MAX_ATTEMPTS; attempt++) {\n try {\n return await this.provider.embedBatch(texts);\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < EMBEDDING_RETRY_MAX_ATTEMPTS - 1) {\n const delay = Math.min(\n EMBEDDING_RETRY_MAX_DELAY_MS,\n EMBEDDING_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n }\n\n private async embedWithBatchApi(texts: string[]): Promise<number[][]> {\n if (this.openAi) {\n const requests: OpenAiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n method: \"POST\",\n url: OPENAI_BATCH_ENDPOINT,\n body: { model: this.openAi!.model, input: text },\n }));\n\n const results = await runOpenAiEmbeddingBatches({\n openAi: this.openAi,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n if (this.gemini) {\n const requests: GeminiBatchRequest[] = texts.map((text, i) => ({\n custom_id: `chunk-${i}`,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n\n const results = await runGeminiEmbeddingBatches({\n gemini: this.gemini,\n source: \"minimem\",\n requests,\n wait: this.batchConfig.wait,\n pollIntervalMs: this.batchConfig.pollIntervalMs,\n timeoutMs: this.batchConfig.timeoutMs,\n concurrency: this.batchConfig.concurrency,\n debug: this.debug,\n });\n\n return texts.map((_, i) => results.get(`chunk-${i}`) ?? []);\n }\n\n throw new Error(\"Batch API not available for local embeddings\");\n }\n\n private async embedQueryWithTimeout(text: string): Promise<number[]> {\n const timeout =\n this.provider.id === \"local\" ? EMBEDDING_QUERY_TIMEOUT_LOCAL_MS : EMBEDDING_QUERY_TIMEOUT_REMOTE_MS;\n\n const ac = new AbortController();\n const timer = setTimeout(() => ac.abort(), timeout);\n\n try {\n const result = await Promise.race([\n this.provider.embedQuery(text),\n new Promise<number[]>((_, reject) => {\n ac.signal.addEventListener(\"abort\", () =>\n reject(new Error(\"embedding query timeout\")),\n );\n }),\n ]);\n return result;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private loadEmbeddingCache(hashes: string[]): Map<string, number[]> {\n const result = new Map<string, number[]>();\n if (!this.cache.enabled || hashes.length === 0) return result;\n\n const placeholders = hashes.map(() => \"?\").join(\",\");\n const rows = this.db\n .prepare(\n `SELECT hash, embedding FROM ${EMBEDDING_CACHE_TABLE}\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash IN (${placeholders})`,\n )\n .all(this.provider.id, this.provider.model, this.providerKey, ...hashes) as Array<{\n hash: string;\n embedding: string;\n }>;\n\n const now = Date.now();\n for (const row of rows) {\n result.set(row.hash, parseEmbedding(row.embedding));\n // Touch for LRU\n this.db\n .prepare(\n `UPDATE ${EMBEDDING_CACHE_TABLE} SET updated_at = ?\n WHERE provider = ? AND model = ? AND provider_key = ? AND hash = ?`,\n )\n .run(now, this.provider.id, this.provider.model, this.providerKey, row.hash);\n }\n\n return result;\n }\n\n private upsertEmbeddingCache(hash: string, embedding: number[]): void {\n if (!this.cache.enabled) return;\n const now = Date.now();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO ${EMBEDDING_CACHE_TABLE}\n (provider, model, provider_key, hash, embedding, dims, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n this.provider.id,\n this.provider.model,\n this.providerKey,\n hash,\n JSON.stringify(embedding),\n embedding.length,\n now,\n );\n }\n\n private pruneEmbeddingCacheIfNeeded(): void {\n if (!this.cache.enabled) return;\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n if (row.count <= this.cache.maxEntries) return;\n\n const excess = row.count - this.cache.maxEntries;\n this.db\n .prepare(\n `DELETE FROM ${EMBEDDING_CACHE_TABLE}\n WHERE rowid IN (\n SELECT rowid FROM ${EMBEDDING_CACHE_TABLE}\n ORDER BY updated_at ASC\n LIMIT ?\n )`,\n )\n .run(excess);\n }\n\n private async ensureVectorReady(dimensions?: number): Promise<boolean> {\n if (this.vector.available === true) return true;\n if (this.vector.available === false) return false;\n\n if (!this.vectorReady) {\n this.vectorReady = this.loadVectorExtension();\n }\n\n const ready = await this.vectorReady;\n if (ready && dimensions && !this.vector.dims) {\n this.vector.dims = dimensions;\n this.ensureVectorTable(dimensions);\n }\n return ready;\n }\n\n private async loadVectorExtension(): Promise<boolean> {\n const result = await loadSqliteVecExtension({\n db: this.db,\n extensionPath: this.vectorExtensionPath,\n });\n\n this.vector.available = result.ok;\n if (result.error) {\n this.vector.loadError = result.error;\n this.debug?.(`sqlite-vec load failed: ${result.error}`);\n }\n if (result.extensionPath) {\n this.vector.extensionPath = result.extensionPath;\n }\n\n return result.ok;\n }\n\n private ensureVectorTable(dimensions: number): void {\n if (!this.vector.available) return;\n try {\n this.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${VECTOR_TABLE} USING vec0(\n id TEXT PRIMARY KEY,\n embedding FLOAT[${dimensions}]\n )`,\n );\n } catch (err) {\n this.debug?.(`vector table creation failed: ${String(err)}`);\n }\n }\n\n async readFile(relativePath: string): Promise<string | null> {\n const absPath = path.join(this.memoryDir, relativePath);\n try {\n return await fs.readFile(absPath, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n /**\n * Read specific lines from a memory file\n */\n async readLines(\n relativePath: string,\n opts?: { from?: number; lines?: number },\n ): Promise<{ content: string; startLine: number; endLine: number } | null> {\n const content = await this.readFile(relativePath);\n if (content === null) return null;\n\n const allLines = content.split(\"\\n\");\n const from = Math.max(1, opts?.from ?? 1);\n const lines = opts?.lines ?? allLines.length;\n\n const startIdx = from - 1;\n const endIdx = Math.min(startIdx + lines, allLines.length);\n const selectedLines = allLines.slice(startIdx, endIdx);\n\n return {\n content: selectedLines.join(\"\\n\"),\n startLine: from,\n endLine: startIdx + selectedLines.length,\n };\n }\n\n /**\n * Write content to a memory file (creates or overwrites)\n */\n async writeFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(absPath, content, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory write: ${relativePath}`);\n }\n\n /**\n * Append content to a memory file (creates if doesn't exist)\n */\n async appendFile(relativePath: string, content: string): Promise<void> {\n this.validateMemoryPath(relativePath);\n const absPath = path.join(this.memoryDir, relativePath);\n const dir = path.dirname(absPath);\n await fs.mkdir(dir, { recursive: true });\n\n // Ensure newline separation\n let toAppend = content;\n try {\n const existing = await fs.readFile(absPath, \"utf-8\");\n if (existing.length > 0 && !existing.endsWith(\"\\n\")) {\n toAppend = \"\\n\" + content;\n }\n } catch {\n // File doesn't exist, will be created\n }\n\n await fs.appendFile(absPath, toAppend, \"utf-8\");\n this.dirty = true;\n this.debug?.(`memory append: ${relativePath}`);\n }\n\n /**\n * Append content to today's daily log (memory/YYYY-MM-DD.md)\n */\n async appendToday(content: string): Promise<string> {\n const today = new Date().toISOString().split(\"T\")[0]; // YYYY-MM-DD\n const relativePath = `memory/${today}.md`;\n await this.appendFile(relativePath, content);\n return relativePath;\n }\n\n /**\n * List all memory files\n */\n async listFiles(): Promise<string[]> {\n const files = await listMemoryFiles(this.memoryDir);\n return files.map((f) => path.relative(this.memoryDir, f).replace(/\\\\/g, \"/\"));\n }\n\n /**\n * Validate that a path is within allowed memory locations\n */\n private validateMemoryPath(relativePath: string): void {\n const normalized = relativePath.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n\n // Allow MEMORY.md at root\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") {\n return;\n }\n\n // Allow anything under memory/\n if (normalized.startsWith(\"memory/\") && normalized.endsWith(\".md\")) {\n // Prevent path traversal\n if (normalized.includes(\"..\")) {\n throw new Error(`Invalid memory path: ${relativePath} (path traversal not allowed)`);\n }\n return;\n }\n\n throw new Error(\n `Invalid memory path: ${relativePath}. Must be MEMORY.md or memory/*.md`,\n );\n }\n\n async status(): Promise<{\n memoryDir: string;\n dbPath: string;\n provider: string;\n model: string;\n vectorAvailable: boolean;\n ftsAvailable: boolean;\n bm25Only: boolean;\n fallbackReason?: string;\n fileCount: number;\n chunkCount: number;\n cacheCount: number;\n }> {\n const fileRow = this.db.prepare(`SELECT COUNT(*) as count FROM files`).get() as { count: number };\n const chunkRow = this.db.prepare(`SELECT COUNT(*) as count FROM chunks`).get() as { count: number };\n const cacheRow = this.db\n .prepare(`SELECT COUNT(*) as count FROM ${EMBEDDING_CACHE_TABLE}`)\n .get() as { count: number };\n\n return {\n memoryDir: this.memoryDir,\n dbPath: this.dbPath,\n provider: this.provider.id,\n model: this.provider.model,\n vectorAvailable: this.vector.available === true,\n ftsAvailable: this.fts.available,\n bm25Only: this.provider.id === \"none\",\n fallbackReason: this.providerFallbackReason,\n fileCount: fileRow.count,\n chunkCount: chunkRow.count,\n cacheCount: cacheRow.count,\n };\n }\n\n /**\n * Search with knowledge metadata filters (domain, entities, confidence, type).\n * Runs a standard search then post-filters by knowledge columns.\n */\n async knowledgeSearch(\n query: string,\n opts?: {\n maxResults?: number;\n minScore?: number;\n domain?: string[];\n entities?: string[];\n minConfidence?: number;\n knowledgeType?: string;\n },\n ): Promise<MinimemSearchResult[]> {\n // Ensure index is up to date\n if (this.dirty || (!this.watchConfig.enabled && (await this.isStale()))) {\n await this.sync({ reason: \"knowledgeSearch\" });\n }\n\n const cleaned = query.trim();\n if (!cleaned) return [];\n\n const minScore = opts?.minScore ?? this.queryConfig.minScore;\n const maxResults = opts?.maxResults ?? this.queryConfig.maxResults;\n\n // Build knowledge filter SQL\n const { sql: knowledgeWhere, params: knowledgeParams } =\n buildKnowledgeFilterSql({\n domain: opts?.domain,\n entities: opts?.entities,\n minConfidence: opts?.minConfidence,\n knowledgeType: opts?.knowledgeType,\n });\n\n // If no knowledge filters, delegate to regular search\n if (!knowledgeWhere) {\n return this.search(query, { maxResults, minScore });\n }\n\n // Get all chunk IDs matching knowledge filters\n const matchingRows = this.db\n .prepare(\n `SELECT id FROM chunks c WHERE c.model = ? AND c.source = 'memory'${knowledgeWhere}`,\n )\n .all(this.provider.model, ...knowledgeParams) as Array<{ id: string }>;\n\n const matchingIds = new Set(matchingRows.map((r) => r.id));\n\n if (matchingIds.size === 0) return [];\n\n // Run standard search with extra candidates to compensate for filtering\n const overFetch = Math.max(maxResults * 3, 30);\n const results = await this.search(query, {\n maxResults: overFetch,\n minScore,\n });\n\n // Post-filter: look up chunk IDs for each result and keep only matching ones\n const filtered: MinimemSearchResult[] = [];\n for (const r of results) {\n const row = this.db\n .prepare(\n `SELECT id FROM chunks WHERE path = ? AND start_line = ? AND end_line = ? AND model = ?`,\n )\n .get(r.path, r.startLine, r.endLine, this.provider.model) as { id: string } | undefined;\n if (row && matchingIds.has(row.id)) {\n filtered.push(r);\n if (filtered.length >= maxResults) break;\n }\n }\n\n return filtered;\n }\n\n /**\n * Get knowledge graph links from or to a node.\n */\n getLinks(\n nodeId: string,\n direction: \"from\" | \"to\" = \"from\",\n opts?: { relation?: string; layer?: string },\n ): GraphLink[] {\n if (direction === \"from\") {\n return getLinksFrom(this.db, nodeId, opts);\n }\n return getLinksTo(this.db, nodeId, opts);\n }\n\n /**\n * Get neighbor nodes via BFS traversal.\n */\n getGraphNeighbors(\n nodeId: string,\n depth: number = 1,\n opts?: { relation?: string; layer?: string },\n ): GraphNeighbor[] {\n return getNeighbors(this.db, nodeId, depth, opts);\n }\n\n /**\n * Find shortest path between two knowledge nodes.\n */\n getGraphPath(fromId: string, toId: string, maxDepth: number = 3): GraphLink[] {\n return getPathBetween(this.db, fromId, toId, maxDepth);\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n if (this.watchTimer) {\n clearTimeout(this.watchTimer);\n this.watchTimer = null;\n }\n\n if (this.watcher) {\n void this.watcher.close();\n this.watcher = null;\n }\n\n try {\n this.db.close();\n } catch (err) {\n logError(\"dbClose\", err, this.debug);\n }\n }\n}\n","import crypto from \"node:crypto\";\nimport fsSync from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\n/**\n * Debug function type for optional logging\n */\nexport type DebugFn = (message: string, data?: Record<string, unknown>) => void;\n\n/**\n * Log an error with context (for debugging).\n * Only logs if a debug function is provided.\n *\n * @param context - A short identifier for where the error occurred\n * @param error - The error object or message\n * @param debug - Optional debug function to log to\n */\nexport function logError(\n context: string,\n error: unknown,\n debug?: DebugFn\n): void {\n if (!debug) return;\n\n const message = error instanceof Error ? error.message : String(error);\n debug(`[${context}] Error: ${message}`);\n}\n\nexport type MemoryFileEntry = {\n path: string;\n absPath: string;\n mtimeMs: number;\n size: number;\n hash: string;\n};\n\nexport type MemoryChunk = {\n startLine: number;\n endLine: number;\n text: string;\n hash: string;\n};\n\n/**\n * Ensure a directory exists, creating it if necessary.\n *\n * @param dir - The directory path to ensure exists\n * @param debug - Optional debug function for logging errors\n * @returns The directory path\n */\nexport function ensureDir(dir: string, debug?: DebugFn): string {\n try {\n fsSync.mkdirSync(dir, { recursive: true });\n } catch (error) {\n // Only swallow EEXIST errors (directory already exists)\n // Log other errors for debugging\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code !== \"EEXIST\") {\n logError(\"ensureDir\", error, debug);\n }\n }\n return dir;\n}\n\nexport function normalizeRelPath(value: string): string {\n const trimmed = value.trim().replace(/^[./]+/, \"\");\n return trimmed.replace(/\\\\/g, \"/\");\n}\n\nexport function isMemoryPath(relPath: string): boolean {\n const normalized = normalizeRelPath(relPath);\n if (!normalized) return false;\n if (normalized === \"MEMORY.md\" || normalized === \"memory.md\") return true;\n return normalized.startsWith(\"memory/\");\n}\n\nasync function exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function walkDir(dir: string, files: string[]) {\n const entries = await fs.readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await walkDir(full, files);\n continue;\n }\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith(\".md\")) continue;\n files.push(full);\n }\n}\n\nexport async function listMemoryFiles(memoryDir: string): Promise<string[]> {\n const result: string[] = [];\n const memoryFile = path.join(memoryDir, \"MEMORY.md\");\n const altMemoryFile = path.join(memoryDir, \"memory.md\");\n const hasUpper = await exists(memoryFile);\n const hasLower = await exists(altMemoryFile);\n\n // Prevent ambiguity: both MEMORY.md and memory.md cannot coexist\n // (unless they resolve to the same file on case-insensitive filesystems)\n if (hasUpper && hasLower) {\n let upperReal = memoryFile;\n let lowerReal = altMemoryFile;\n try { upperReal = await fs.realpath(memoryFile); } catch {}\n try { lowerReal = await fs.realpath(altMemoryFile); } catch {}\n if (upperReal !== lowerReal) {\n throw new Error(\n `Both MEMORY.md and memory.md exist in ${memoryDir}. ` +\n `Please remove one to avoid ambiguity.`\n );\n }\n // Same file (case-insensitive FS) — only include once\n result.push(memoryFile);\n } else if (hasUpper) {\n result.push(memoryFile);\n } else if (hasLower) {\n result.push(altMemoryFile);\n }\n\n const memorySubDir = path.join(memoryDir, \"memory\");\n if (await exists(memorySubDir)) {\n await walkDir(memorySubDir, result);\n }\n if (result.length <= 1) return result;\n const seen = new Set<string>();\n const deduped: string[] = [];\n for (const entry of result) {\n let key = entry;\n try {\n key = await fs.realpath(entry);\n } catch {}\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(entry);\n }\n return deduped;\n}\n\nexport function hashText(value: string): string {\n return crypto.createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nexport async function buildFileEntry(\n absPath: string,\n memoryDir: string,\n): Promise<MemoryFileEntry> {\n const stat = await fs.stat(absPath);\n const content = await fs.readFile(absPath, \"utf-8\");\n const hash = hashText(content);\n return {\n path: path.relative(memoryDir, absPath).replace(/\\\\/g, \"/\"),\n absPath,\n mtimeMs: stat.mtimeMs,\n size: stat.size,\n hash,\n };\n}\n\n/**\n * Strip content between <private>...</private> tags.\n * Replaces private blocks with the same number of empty lines to preserve line numbering.\n */\nexport function stripPrivateContent(content: string): string {\n return content.replace(/<private>[\\s\\S]*?<\\/private>/gi, (match) => {\n const lineCount = match.split(\"\\n\").length;\n return \"\\n\".repeat(lineCount - 1);\n });\n}\n\nexport function chunkMarkdown(\n content: string,\n chunking: { tokens: number; overlap: number },\n): MemoryChunk[] {\n const stripped = stripPrivateContent(content);\n const lines = stripped.split(\"\\n\");\n if (lines.length === 0) return [];\n const maxChars = Math.max(32, chunking.tokens * 4);\n const overlapChars = Math.max(0, chunking.overlap * 4);\n const chunks: MemoryChunk[] = [];\n\n let current: Array<{ line: string; lineNo: number }> = [];\n let currentChars = 0;\n\n const flush = () => {\n if (current.length === 0) return;\n const firstEntry = current[0];\n const lastEntry = current[current.length - 1];\n if (!firstEntry || !lastEntry) return;\n const text = current.map((entry) => entry.line).join(\"\\n\");\n const startLine = firstEntry.lineNo;\n const endLine = lastEntry.lineNo;\n chunks.push({\n startLine,\n endLine,\n text,\n hash: hashText(text),\n });\n };\n\n const carryOverlap = () => {\n if (overlapChars <= 0 || current.length === 0) {\n current = [];\n currentChars = 0;\n return;\n }\n let acc = 0;\n const kept: Array<{ line: string; lineNo: number }> = [];\n for (let i = current.length - 1; i >= 0; i -= 1) {\n const entry = current[i];\n if (!entry) continue;\n acc += entry.line.length + 1;\n kept.unshift(entry);\n if (acc >= overlapChars) break;\n }\n current = kept;\n currentChars = kept.reduce((sum, entry) => sum + entry.line.length + 1, 0);\n };\n\n for (let i = 0; i < lines.length; i += 1) {\n const line = lines[i] ?? \"\";\n const lineNo = i + 1;\n const segments: string[] = [];\n if (line.length === 0) {\n segments.push(\"\");\n } else {\n for (let start = 0; start < line.length; start += maxChars) {\n segments.push(line.slice(start, start + maxChars));\n }\n }\n for (const segment of segments) {\n const lineSize = segment.length + 1;\n if (currentChars + lineSize > maxChars && current.length > 0) {\n flush();\n carryOverlap();\n }\n current.push({ line: segment, lineNo });\n currentChars += lineSize;\n }\n }\n flush();\n return chunks;\n}\n\n/**\n * Extract metadata from a chunk's text content.\n * Looks for HTML comments like <!-- type: decision --> in the chunk.\n */\nexport function extractChunkMetadata(text: string): { type?: string } {\n const typeMatch = text.match(/<!--\\s*type:\\s*([\\w-]+)\\s*-->/i);\n return typeMatch ? { type: typeMatch[1].toLowerCase() } : {};\n}\n\nexport function parseEmbedding(raw: string): number[] {\n try {\n const parsed = JSON.parse(raw) as number[];\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length === 0 || b.length === 0) return 0;\n const len = Math.min(a.length, b.length);\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < len; i += 1) {\n const av = a[i] ?? 0;\n const bv = b[i] ?? 0;\n dot += av * bv;\n normA += av * av;\n normB += bv * bv;\n }\n if (normA === 0 || normB === 0) return 0;\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n\nexport function truncateUtf16Safe(text: string, maxChars: number): string {\n if (text.length <= maxChars) return text;\n return text.slice(0, maxChars);\n}\n\n/**\n * Convert a numeric embedding vector to a Buffer suitable for sqlite-vec storage.\n * Uses Float32 encoding, which is the format expected by sqlite-vec's vector functions.\n */\nexport function vectorToBlob(embedding: number[]): Buffer {\n return Buffer.from(new Float32Array(embedding).buffer);\n}\n","export type HybridSource = string;\n\nexport type HybridVectorResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n};\n\nexport type HybridKeywordResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n textScore: number;\n};\n\nexport function buildFtsQuery(raw: string): string | null {\n const tokens =\n raw\n .match(/[A-Za-z0-9_]+/g)\n ?.map((t) => t.trim())\n .filter(Boolean) ?? [];\n if (tokens.length === 0) return null;\n const quoted = tokens.map((t) => `\"${t.replaceAll('\"', \"\")}\"`);\n return quoted.join(\" AND \");\n}\n\n/**\n * Convert BM25 rank from SQLite FTS5 to a 0-1 score.\n *\n * FTS5 BM25 ranks are NEGATIVE numbers where more negative = better match.\n * A rank of 0 means no match, -10 is better than -1.\n *\n * We use absolute value to convert to positive, then normalize to 0-1\n * using the formula: score = 1 / (1 + absRank)\n *\n * Examples:\n * - rank 0 (no match) -> score 1.0\n * - rank -1 (weak match) -> score 0.5\n * - rank -10 (strong match) -> score ~0.09\n *\n * Note: Higher absolute rank magnitude = better match = higher score after conversion.\n */\nexport function bm25RankToScore(rank: number): number {\n // Handle non-finite values (NaN, Infinity)\n if (!Number.isFinite(rank)) {\n return 0;\n }\n\n // BM25 ranks from FTS5 are negative (more negative = better match)\n // Use absolute value to get the magnitude\n const absRank = Math.abs(rank);\n\n // Convert to 0-1 score where higher magnitude = higher score\n // Using 1/(1+x) gives us a nice 0-1 range that decreases smoothly\n return 1 / (1 + absRank);\n}\n\nexport function mergeHybridResults(params: {\n vector: HybridVectorResult[];\n keyword: HybridKeywordResult[];\n vectorWeight: number;\n textWeight: number;\n}): Array<{\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: HybridSource;\n}> {\n const byId = new Map<\n string,\n {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n source: HybridSource;\n snippet: string;\n vectorScore: number;\n textScore: number;\n }\n >();\n\n for (const r of params.vector) {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: r.vectorScore,\n textScore: 0,\n });\n }\n\n for (const r of params.keyword) {\n const existing = byId.get(r.id);\n if (existing) {\n existing.textScore = r.textScore;\n if (r.snippet && r.snippet.length > 0) existing.snippet = r.snippet;\n } else {\n byId.set(r.id, {\n id: r.id,\n path: r.path,\n startLine: r.startLine,\n endLine: r.endLine,\n source: r.source,\n snippet: r.snippet,\n vectorScore: 0,\n textScore: r.textScore,\n });\n }\n }\n\n // When one side of the hybrid search has no results, normalize weights\n // so the available side scores at full strength. Without this, BM25-only\n // results would be scaled to 0.3 * textScore which is too low to pass\n // the default minScore threshold.\n let vw = params.vectorWeight;\n let tw = params.textWeight;\n if (params.vector.length === 0 && params.keyword.length > 0) {\n vw = 0;\n tw = 1;\n } else if (params.keyword.length === 0 && params.vector.length > 0) {\n vw = 1;\n tw = 0;\n }\n\n const merged = Array.from(byId.values()).map((entry) => {\n const score = vw * entry.vectorScore + tw * entry.textScore;\n return {\n path: entry.path,\n startLine: entry.startLine,\n endLine: entry.endLine,\n score,\n snippet: entry.snippet,\n source: entry.source,\n };\n });\n\n return merged.sort((a, b) => b.score - a.score);\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nimport { cosineSimilarity, parseEmbedding, truncateUtf16Safe, vectorToBlob } from \"../internal.js\";\n\nexport type SearchSource = string;\n\nexport type SearchRowResult = {\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: SearchSource;\n};\n\n/**\n * Options for filtering search results by knowledge metadata\n */\nexport type KnowledgeSearchOptions = {\n /** Filter to chunks matching any of these domains */\n domain?: string[];\n /** Filter to chunks referencing any of these entities */\n entities?: string[];\n /** Minimum confidence threshold */\n minConfidence?: number;\n /** Filter to a specific knowledge type */\n knowledgeType?: string;\n};\n\n/**\n * Build SQL WHERE clause fragments for knowledge filters.\n * Uses json_each() for array column filtering.\n */\nexport function buildKnowledgeFilterSql(opts: KnowledgeSearchOptions): {\n sql: string;\n params: (string | number)[];\n} {\n const clauses: string[] = [];\n const params: (string | number)[] = [];\n\n if (opts.knowledgeType) {\n clauses.push(` AND c.knowledge_type = ?`);\n params.push(opts.knowledgeType);\n }\n\n if (opts.minConfidence !== undefined) {\n clauses.push(` AND c.confidence >= ?`);\n params.push(opts.minConfidence);\n }\n\n if (opts.domain && opts.domain.length > 0) {\n // At least one of the provided domains must appear in the JSON array\n const domainPlaceholders = opts.domain.map(() => \"?\").join(\", \");\n clauses.push(\n ` AND EXISTS (SELECT 1 FROM json_each(c.domains) AS d WHERE d.value IN (${domainPlaceholders}))`,\n );\n params.push(...opts.domain);\n }\n\n if (opts.entities && opts.entities.length > 0) {\n const entityPlaceholders = opts.entities.map(() => \"?\").join(\", \");\n clauses.push(\n ` AND EXISTS (SELECT 1 FROM json_each(c.entities) AS e WHERE e.value IN (${entityPlaceholders}))`,\n );\n params.push(...opts.entities);\n }\n\n return { sql: clauses.join(\"\"), params };\n}\n\n/**\n * Perform a vector similarity search against indexed memory chunks.\n *\n * First attempts to use sqlite-vec for fast approximate nearest neighbor search.\n * Falls back to brute-force cosine similarity over all chunks if the vector\n * extension is unavailable.\n *\n * @returns Matching chunks sorted by descending similarity score (0-1 range).\n */\nexport async function searchVector(params: {\n db: DatabaseSync;\n vectorTable: string;\n providerModel: string;\n queryVec: number[];\n limit: number;\n snippetMaxChars: number;\n ensureVectorReady: (dimensions: number) => Promise<boolean>;\n sourceFilterVec: { sql: string; params: SearchSource[] };\n sourceFilterChunks: { sql: string; params: SearchSource[] };\n}): Promise<SearchRowResult[]> {\n if (params.queryVec.length === 0 || params.limit <= 0) return [];\n if (await params.ensureVectorReady(params.queryVec.length)) {\n const rows = params.db\n .prepare(\n `SELECT c.id, c.path, c.start_line, c.end_line, c.text,\\n` +\n ` c.source,\\n` +\n ` vec_distance_cosine(v.embedding, ?) AS dist\\n` +\n ` FROM ${params.vectorTable} v\\n` +\n ` JOIN chunks c ON c.id = v.id\\n` +\n ` WHERE c.model = ?${params.sourceFilterVec.sql}\\n` +\n ` ORDER BY dist ASC\\n` +\n ` LIMIT ?`,\n )\n .all(\n vectorToBlob(params.queryVec),\n params.providerModel,\n ...params.sourceFilterVec.params,\n params.limit,\n ) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n source: SearchSource;\n dist: number;\n }>;\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: 1 - row.dist,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n }));\n }\n\n const candidates = listChunks({\n db: params.db,\n providerModel: params.providerModel,\n sourceFilter: params.sourceFilterChunks,\n });\n const scored = candidates\n .map((chunk) => ({\n chunk,\n score: cosineSimilarity(params.queryVec, chunk.embedding),\n }))\n .filter((entry) => Number.isFinite(entry.score));\n return scored\n .sort((a, b) => b.score - a.score)\n .slice(0, params.limit)\n .map((entry) => ({\n id: entry.chunk.id,\n path: entry.chunk.path,\n startLine: entry.chunk.startLine,\n endLine: entry.chunk.endLine,\n score: entry.score,\n snippet: truncateUtf16Safe(entry.chunk.text, params.snippetMaxChars),\n source: entry.chunk.source,\n }));\n}\n\n/**\n * List all indexed chunks for a given embedding model and source filter.\n * Used as a fallback when sqlite-vec is not available for vector search.\n *\n * @returns All matching chunks with their parsed embedding vectors.\n */\nexport function listChunks(params: {\n db: DatabaseSync;\n providerModel: string;\n sourceFilter: { sql: string; params: SearchSource[] };\n}): Array<{\n id: string;\n path: string;\n startLine: number;\n endLine: number;\n text: string;\n embedding: number[];\n source: SearchSource;\n}> {\n const rows = params.db\n .prepare(\n `SELECT id, path, start_line, end_line, text, embedding, source\\n` +\n ` FROM chunks\\n` +\n ` WHERE model = ?${params.sourceFilter.sql}`,\n )\n .all(params.providerModel, ...params.sourceFilter.params) as Array<{\n id: string;\n path: string;\n start_line: number;\n end_line: number;\n text: string;\n embedding: string;\n source: SearchSource;\n }>;\n\n return rows.map((row) => ({\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n text: row.text,\n embedding: parseEmbedding(row.embedding),\n source: row.source,\n }));\n}\n\n/**\n * Perform a full-text keyword search using SQLite FTS5 with BM25 ranking.\n *\n * Tokenizes the query into quoted AND terms and runs them against the FTS index.\n * Results are scored using BM25 rank converted to a 0-1 range.\n *\n * @returns Matching chunks sorted by BM25 relevance, with both score and textScore fields.\n */\nexport async function searchKeyword(params: {\n db: DatabaseSync;\n ftsTable: string;\n providerModel: string;\n query: string;\n limit: number;\n snippetMaxChars: number;\n sourceFilter: { sql: string; params: SearchSource[] };\n buildFtsQuery: (raw: string) => string | null;\n bm25RankToScore: (rank: number) => number;\n}): Promise<Array<SearchRowResult & { textScore: number }>> {\n if (params.limit <= 0) return [];\n const ftsQuery = params.buildFtsQuery(params.query);\n if (!ftsQuery) return [];\n\n const rows = params.db\n .prepare(\n `SELECT id, path, source, start_line, end_line, text,\\n` +\n ` bm25(${params.ftsTable}) AS rank\\n` +\n ` FROM ${params.ftsTable}\\n` +\n ` WHERE ${params.ftsTable} MATCH ? AND model = ?${params.sourceFilter.sql}\\n` +\n ` ORDER BY rank ASC\\n` +\n ` LIMIT ?`,\n )\n .all(ftsQuery, params.providerModel, ...params.sourceFilter.params, params.limit) as Array<{\n id: string;\n path: string;\n source: SearchSource;\n start_line: number;\n end_line: number;\n text: string;\n rank: number;\n }>;\n\n return rows.map((row) => {\n const textScore = params.bm25RankToScore(row.rank);\n return {\n id: row.id,\n path: row.path,\n startLine: row.start_line,\n endLine: row.end_line,\n score: textScore,\n textScore,\n snippet: truncateUtf16Safe(row.text, params.snippetMaxChars),\n source: row.source,\n };\n });\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\n/**\n * Current schema version. Increment this when making breaking schema changes.\n *\n * Version history:\n * - 1: Initial schema (meta, files, chunks, embedding_cache, FTS5)\n * - 2: Added source column to files and chunks tables\n * - 3: Added type column to chunks table for observation type metadata\n * - 4: Added knowledge columns to chunks + knowledge_links table\n */\nexport const SCHEMA_VERSION = 4;\n\nexport function ensureMemoryIndexSchema(params: {\n db: DatabaseSync;\n embeddingCacheTable: string;\n ftsTable: string;\n ftsEnabled: boolean;\n}): { ftsAvailable: boolean; ftsError?: string; migrated?: boolean } {\n // Create meta table first (needed for version tracking)\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n\n // Check schema version and handle migration\n const migrated = migrateIfNeeded(params.db, params.ftsTable);\n\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS files (\n path TEXT PRIMARY KEY,\n source TEXT NOT NULL DEFAULT 'memory',\n hash TEXT NOT NULL,\n mtime INTEGER NOT NULL,\n size INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS chunks (\n id TEXT PRIMARY KEY,\n path TEXT NOT NULL,\n source TEXT NOT NULL DEFAULT 'memory',\n start_line INTEGER NOT NULL,\n end_line INTEGER NOT NULL,\n hash TEXT NOT NULL,\n model TEXT NOT NULL,\n text TEXT NOT NULL,\n embedding TEXT NOT NULL,\n updated_at INTEGER NOT NULL\n );\n `);\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS ${params.embeddingCacheTable} (\n provider TEXT NOT NULL,\n model TEXT NOT NULL,\n provider_key TEXT NOT NULL,\n hash TEXT NOT NULL,\n embedding TEXT NOT NULL,\n dims INTEGER,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (provider, model, provider_key, hash)\n );\n `);\n params.db.exec(\n `CREATE INDEX IF NOT EXISTS idx_embedding_cache_updated_at ON ${params.embeddingCacheTable}(updated_at);`,\n );\n\n let ftsAvailable = false;\n let ftsError: string | undefined;\n if (params.ftsEnabled) {\n try {\n params.db.exec(\n `CREATE VIRTUAL TABLE IF NOT EXISTS ${params.ftsTable} USING fts5(\\n` +\n ` text,\\n` +\n ` id UNINDEXED,\\n` +\n ` path UNINDEXED,\\n` +\n ` source UNINDEXED,\\n` +\n ` model UNINDEXED,\\n` +\n ` start_line UNINDEXED,\\n` +\n ` end_line UNINDEXED\\n` +\n `);`,\n );\n ftsAvailable = true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n ftsAvailable = false;\n ftsError = message;\n }\n }\n\n ensureColumn(params.db, \"files\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n ensureColumn(params.db, \"chunks\", \"source\", \"TEXT NOT NULL DEFAULT 'memory'\");\n ensureColumn(params.db, \"chunks\", \"type\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"knowledge_type\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"knowledge_id\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"domains\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"entities\", \"TEXT\");\n ensureColumn(params.db, \"chunks\", \"confidence\", \"REAL\");\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_path ON chunks(path);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_source ON chunks(source);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_type ON chunks(type);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_knowledge_type ON chunks(knowledge_type);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_chunks_knowledge_id ON chunks(knowledge_id);`);\n\n // Knowledge links table for graph traversal\n params.db.exec(`\n CREATE TABLE IF NOT EXISTS knowledge_links (\n from_id TEXT NOT NULL,\n to_id TEXT NOT NULL,\n relation TEXT NOT NULL,\n layer TEXT,\n weight REAL DEFAULT 0.5,\n source_path TEXT,\n created_at INTEGER,\n PRIMARY KEY (from_id, to_id, relation)\n );\n `);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_kl_from ON knowledge_links(from_id);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_kl_to ON knowledge_links(to_id);`);\n params.db.exec(`CREATE INDEX IF NOT EXISTS idx_kl_layer ON knowledge_links(layer);`);\n\n // Store current schema version\n params.db.prepare(\n `INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', ?)`,\n ).run(String(SCHEMA_VERSION));\n\n return { ftsAvailable, ...(ftsError ? { ftsError } : {}), ...(migrated ? { migrated } : {}) };\n}\n\n/**\n * Check the stored schema version and migrate if needed.\n * For breaking changes, drops data tables so they get recreated fresh.\n * The embedding cache is preserved across migrations when possible.\n *\n * @returns true if a migration was performed, false otherwise.\n */\nfunction migrateIfNeeded(db: DatabaseSync, ftsTable: string): boolean {\n let storedVersion = 0;\n try {\n const row = db.prepare(\n `SELECT value FROM meta WHERE key = 'schema_version'`,\n ).get() as { value: string } | undefined;\n if (row) {\n storedVersion = parseInt(row.value, 10) || 0;\n }\n } catch {\n // meta table may not have the key yet (pre-versioning databases)\n storedVersion = 0;\n }\n\n if (storedVersion >= SCHEMA_VERSION) return false;\n\n if (storedVersion > 0 && storedVersion < SCHEMA_VERSION) {\n // Breaking schema change: drop and recreate data tables.\n // Embedding cache is preserved since embeddings are content-addressed\n // and will be reused on re-index.\n db.exec(`DROP TABLE IF EXISTS files`);\n db.exec(`DROP TABLE IF EXISTS chunks`);\n db.exec(`DROP TABLE IF EXISTS knowledge_links`);\n db.exec(`DROP TABLE IF EXISTS ${ftsTable}`);\n // Also drop the vector table if it exists\n try {\n db.exec(`DROP TABLE IF EXISTS chunks_vec`);\n } catch {\n // sqlite-vec table may not exist\n }\n }\n\n return storedVersion > 0;\n}\n\nfunction ensureColumn(\n db: DatabaseSync,\n table: \"files\" | \"chunks\",\n column: string,\n definition: string,\n): void {\n const rows = db.prepare(`PRAGMA table_info(${table})`).all() as Array<{ name: string }>;\n if (rows.some((row) => row.name === column)) return;\n db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);\n}\n","/**\n * Session tracking for memory entries\n *\n * Captures context about the originating session (Claude Code, VS Code, etc.)\n * and stores it as YAML frontmatter in memory files.\n */\n\nimport * as os from \"node:os\";\n\n/**\n * Session metadata for memory entries\n */\nexport type SessionContext = {\n /** Session identifier (e.g., Claude Code session ID) */\n id?: string;\n /** Source application (claude-code, vscode, cursor, etc.) */\n source?: string;\n /** Project directory path */\n project?: string;\n /** Path to session transcript/log file */\n transcript?: string;\n};\n\n/**\n * Source provenance for a knowledge entry\n */\nexport type KnowledgeSource = {\n origin?: string;\n trajectories?: string[];\n agentId?: string;\n};\n\n/**\n * A directional link from this entry to another knowledge node\n */\nexport type KnowledgeLink = {\n target: string;\n relation: string;\n layer?: string;\n};\n\n/**\n * Frontmatter structure for memory files\n */\nexport type MemoryFrontmatter = {\n session?: SessionContext;\n created?: string;\n updated?: string;\n tags?: string[];\n /** Knowledge node identifier */\n id?: string;\n /** Knowledge entry type */\n type?: \"observation\" | \"entity\" | \"domain-summary\" | string;\n /** Domain tags for this knowledge entry */\n domain?: string[];\n /** Entity references in this knowledge entry */\n entities?: string[];\n /** Confidence score 0-1 */\n confidence?: number;\n /** Source provenance */\n source?: KnowledgeSource;\n /** Links to other knowledge nodes */\n links?: KnowledgeLink[];\n /** ID of the entry this supersedes */\n supersedes?: string | null;\n};\n\n/**\n * Parse YAML frontmatter from content\n *\n * Frontmatter is delimited by --- at the start and end:\n * ```\n * ---\n * session:\n * id: abc123\n * source: claude-code\n * created: 2024-01-27T14:30:00Z\n * ---\n * Actual content here...\n * ```\n */\nexport function parseFrontmatter(content: string): {\n frontmatter: MemoryFrontmatter | undefined;\n body: string;\n} {\n const frontmatterRegex = /^---\\n([\\s\\S]*?)\\n---\\n/;\n const match = content.match(frontmatterRegex);\n\n if (!match) {\n return { frontmatter: undefined, body: content };\n }\n\n const yamlContent = match[1];\n const body = content.slice(match[0].length);\n\n try {\n const frontmatter = parseSimpleYaml(yamlContent);\n return { frontmatter, body };\n } catch {\n // If parsing fails, treat as no frontmatter\n return { frontmatter: undefined, body: content };\n }\n}\n\n/**\n * Simple YAML parser for frontmatter.\n *\n * **Limitations** (by design — keeps the dependency count at zero):\n * - Does not handle multi-line strings (block scalars `|` / `>`)\n * - Does not preserve comments\n * - Keys must be simple `\\w+` identifiers (no quoted or special-char keys)\n *\n * Supports:\n * - Multi-level nesting (objects within objects)\n * - Inline arrays `[a, b]`\n * - YAML list items with `- ` syntax (including `- {key: val}` objects)\n * - Null values via `~` or `null`\n */\nfunction parseSimpleYaml(yaml: string): MemoryFrontmatter {\n const lines = yaml.split(\"\\n\");\n return parseYamlBlock(lines, 0, 0, lines.length).value as MemoryFrontmatter;\n}\n\n/**\n * Parse a block of YAML lines at a given indentation level into an object.\n * Returns the parsed value and the line index where parsing stopped.\n */\nfunction parseYamlBlock(\n lines: string[],\n indent: number,\n startIdx: number,\n endIdx: number,\n): { value: Record<string, unknown>; nextIdx: number } {\n const result: Record<string, unknown> = {};\n let i = startIdx;\n\n while (i < endIdx) {\n const line = lines[i];\n if (!line || !line.trim()) {\n i++;\n continue;\n }\n\n const lineIndent = getIndent(line);\n // If we've dedented back beyond our level, stop\n if (lineIndent < indent) break;\n // Skip lines indented deeper than expected (shouldn't happen at top of block)\n if (lineIndent > indent) {\n i++;\n continue;\n }\n\n // Match a key: value line\n const keyMatch = line.match(/^(\\s*)([\\w-]+):\\s*(.*)?$/);\n if (!keyMatch) {\n i++;\n continue;\n }\n\n const [, , key, rawValue] = keyMatch;\n const value = rawValue?.trim() ?? \"\";\n\n if (value === \"\" || value === undefined) {\n // Could be an object or a list starting on next lines\n const nextNonEmpty = findNextNonEmptyLine(lines, i + 1, endIdx);\n if (nextNonEmpty < endIdx) {\n const nextLine = lines[nextNonEmpty]!;\n const nextIndent = getIndent(nextLine);\n if (nextIndent > indent) {\n // Check if it's a list (starts with \"- \")\n if (nextLine.trimStart().startsWith(\"- \")) {\n const listResult = parseYamlList(lines, nextIndent, i + 1, endIdx);\n result[key] = listResult.value;\n i = listResult.nextIdx;\n } else {\n // Nested object\n const blockResult = parseYamlBlock(lines, nextIndent, i + 1, endIdx);\n result[key] = blockResult.value;\n i = blockResult.nextIdx;\n }\n continue;\n }\n }\n // Empty value, no nested content\n result[key] = null;\n i++;\n } else {\n result[key] = parseYamlValue(value);\n i++;\n }\n }\n\n return { value: result, nextIdx: i };\n}\n\n/**\n * Parse a YAML list (lines starting with \"- \") at a given indentation level.\n */\nfunction parseYamlList(\n lines: string[],\n indent: number,\n startIdx: number,\n endIdx: number,\n): { value: unknown[]; nextIdx: number } {\n const result: unknown[] = [];\n let i = startIdx;\n\n while (i < endIdx) {\n const line = lines[i];\n if (!line || !line.trim()) {\n i++;\n continue;\n }\n\n const lineIndent = getIndent(line);\n if (lineIndent < indent) break;\n if (lineIndent > indent) {\n i++;\n continue;\n }\n\n const trimmed = line.trimStart();\n if (!trimmed.startsWith(\"- \")) break;\n\n // Get content after \"- \"\n const itemContent = trimmed.slice(2).trim();\n\n if (itemContent === \"\" || itemContent === undefined) {\n // Sub-block under this list item\n const nextNonEmpty = findNextNonEmptyLine(lines, i + 1, endIdx);\n if (nextNonEmpty < endIdx) {\n const nextIndent = getIndent(lines[nextNonEmpty]!);\n if (nextIndent > indent) {\n const blockResult = parseYamlBlock(lines, nextIndent, i + 1, endIdx);\n result.push(blockResult.value);\n i = blockResult.nextIdx;\n continue;\n }\n }\n result.push(null);\n i++;\n } else {\n // Check for inline key: value (object item like \"- target: foo\")\n const kvMatch = itemContent.match(/^([\\w-]+):\\s*(.*)$/);\n if (kvMatch) {\n // This list item is an object — collect all keys at this item's indent + 2\n const obj: Record<string, unknown> = {};\n const [, firstKey, firstVal] = kvMatch;\n obj[firstKey] = parseYamlValue(firstVal?.trim() ?? \"\");\n\n // Look for continuation keys indented further\n const itemKeyIndent = indent + 2;\n let j = i + 1;\n while (j < endIdx) {\n const nextLine = lines[j];\n if (!nextLine || !nextLine.trim()) {\n j++;\n continue;\n }\n const nextLineIndent = getIndent(nextLine);\n if (nextLineIndent < itemKeyIndent) break;\n if (nextLineIndent === itemKeyIndent) {\n const nextKv = nextLine.match(/^\\s*([\\w-]+):\\s*(.*)$/);\n if (nextKv) {\n const [, nk, nv] = nextKv;\n obj[nk] = parseYamlValue(nv?.trim() ?? \"\");\n j++;\n continue;\n }\n }\n break;\n }\n result.push(obj);\n i = j;\n } else {\n result.push(parseYamlValue(itemContent));\n i++;\n }\n }\n }\n\n return { value: result, nextIdx: i };\n}\n\nfunction getIndent(line: string): number {\n const match = line.match(/^(\\s*)/);\n return match ? match[1].length : 0;\n}\n\nfunction findNextNonEmptyLine(lines: string[], from: number, end: number): number {\n for (let i = from; i < end; i++) {\n if (lines[i]?.trim()) return i;\n }\n return end;\n}\n\n/**\n * Parse a YAML value (handles strings, numbers, booleans, null, arrays)\n */\nfunction parseYamlValue(value: string): unknown {\n // Empty string\n if (value === \"\") return null;\n\n // Remove quotes if present\n if ((value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n\n // Null\n if (value === \"null\" || value === \"~\") return null;\n\n // Boolean\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n\n // Number\n const num = Number(value);\n if (!isNaN(num) && value !== \"\") return num;\n\n // Array (simple inline format)\n if (value.startsWith(\"[\") && value.endsWith(\"]\")) {\n const inner = value.slice(1, -1);\n if (inner.trim() === \"\") return [];\n return inner.split(\",\").map((s) => parseYamlValue(s.trim()));\n }\n\n // String\n return value;\n}\n\n/**\n * Serialize frontmatter to YAML string\n */\nexport function serializeFrontmatter(frontmatter: MemoryFrontmatter): string {\n const lines: string[] = [\"---\"];\n\n if (frontmatter.id) {\n lines.push(`id: ${frontmatter.id}`);\n }\n\n if (frontmatter.type) {\n lines.push(`type: ${frontmatter.type}`);\n }\n\n if (frontmatter.session) {\n lines.push(\"session:\");\n const session = frontmatter.session;\n if (session.id) lines.push(` id: ${session.id}`);\n if (session.source) lines.push(` source: ${session.source}`);\n if (session.project) lines.push(` project: ${formatPath(session.project)}`);\n if (session.transcript) lines.push(` transcript: ${formatPath(session.transcript)}`);\n }\n\n if (frontmatter.created) {\n lines.push(`created: ${frontmatter.created}`);\n }\n\n if (frontmatter.updated) {\n lines.push(`updated: ${frontmatter.updated}`);\n }\n\n if (frontmatter.tags && frontmatter.tags.length > 0) {\n lines.push(`tags: [${frontmatter.tags.join(\", \")}]`);\n }\n\n if (frontmatter.domain && frontmatter.domain.length > 0) {\n lines.push(`domain: [${frontmatter.domain.join(\", \")}]`);\n }\n\n if (frontmatter.entities && frontmatter.entities.length > 0) {\n lines.push(`entities: [${frontmatter.entities.join(\", \")}]`);\n }\n\n if (frontmatter.confidence !== undefined) {\n lines.push(`confidence: ${frontmatter.confidence}`);\n }\n\n if (frontmatter.source) {\n lines.push(\"source:\");\n if (frontmatter.source.origin) lines.push(` origin: ${frontmatter.source.origin}`);\n if (frontmatter.source.trajectories && frontmatter.source.trajectories.length > 0) {\n lines.push(` trajectories: [${frontmatter.source.trajectories.join(\", \")}]`);\n }\n if (frontmatter.source.agentId) lines.push(` agentId: ${frontmatter.source.agentId}`);\n }\n\n if (frontmatter.links && frontmatter.links.length > 0) {\n lines.push(\"links:\");\n for (const link of frontmatter.links) {\n lines.push(` - target: ${link.target}`);\n lines.push(` relation: ${link.relation}`);\n if (link.layer) lines.push(` layer: ${link.layer}`);\n }\n }\n\n if (frontmatter.supersedes !== undefined) {\n lines.push(`supersedes: ${frontmatter.supersedes === null ? \"~\" : frontmatter.supersedes}`);\n }\n\n lines.push(\"---\");\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Add or update frontmatter in content\n */\nexport function addFrontmatter(\n content: string,\n frontmatter: MemoryFrontmatter,\n): string {\n const { frontmatter: existing, body } = parseFrontmatter(content);\n\n // Merge with existing frontmatter\n const merged: MemoryFrontmatter = {\n ...existing,\n ...frontmatter,\n session: {\n ...existing?.session,\n ...frontmatter.session,\n },\n };\n\n // Update timestamp\n if (!merged.created) {\n merged.created = new Date().toISOString();\n }\n merged.updated = new Date().toISOString();\n\n return serializeFrontmatter(merged) + body;\n}\n\n/**\n * Add session context as frontmatter to content\n */\nexport function addSessionToContent(\n content: string,\n session: SessionContext,\n): string {\n return addFrontmatter(content, { session });\n}\n\n/**\n * Format path for display (use ~ for home directory)\n */\nfunction formatPath(filePath: string): string {\n const home = os.homedir();\n if (filePath.startsWith(home)) {\n return \"~\" + filePath.slice(home.length);\n }\n return filePath;\n}\n\n/**\n * Extract session context from file content\n */\nexport function extractSession(content: string): SessionContext | undefined {\n const { frontmatter } = parseFrontmatter(content);\n return frontmatter?.session;\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\n/**\n * A knowledge graph link between two nodes\n */\nexport type GraphLink = {\n fromId: string;\n toId: string;\n relation: string;\n layer: string | null;\n weight: number;\n sourcePath: string | null;\n};\n\n/**\n * A neighbor node discovered during graph traversal\n */\nexport type GraphNeighbor = {\n id: string;\n depth: number;\n link: GraphLink;\n};\n\n/**\n * Get all outgoing links from a node.\n */\nexport function getLinksFrom(\n db: DatabaseSync,\n fromId: string,\n opts?: { relation?: string; layer?: string },\n): GraphLink[] {\n let sql = `SELECT from_id, to_id, relation, layer, weight, source_path FROM knowledge_links WHERE from_id = ?`;\n const params: (string | number)[] = [fromId];\n\n if (opts?.relation) {\n sql += ` AND relation = ?`;\n params.push(opts.relation);\n }\n if (opts?.layer) {\n sql += ` AND layer = ?`;\n params.push(opts.layer);\n }\n\n const rows = db.prepare(sql).all(...params) as Array<{\n from_id: string;\n to_id: string;\n relation: string;\n layer: string | null;\n weight: number;\n source_path: string | null;\n }>;\n\n return rows.map(toGraphLink);\n}\n\n/**\n * Get all incoming links to a node.\n */\nexport function getLinksTo(\n db: DatabaseSync,\n toId: string,\n opts?: { relation?: string; layer?: string },\n): GraphLink[] {\n let sql = `SELECT from_id, to_id, relation, layer, weight, source_path FROM knowledge_links WHERE to_id = ?`;\n const params: (string | number)[] = [toId];\n\n if (opts?.relation) {\n sql += ` AND relation = ?`;\n params.push(opts.relation);\n }\n if (opts?.layer) {\n sql += ` AND layer = ?`;\n params.push(opts.layer);\n }\n\n const rows = db.prepare(sql).all(...params) as Array<{\n from_id: string;\n to_id: string;\n relation: string;\n layer: string | null;\n weight: number;\n source_path: string | null;\n }>;\n\n return rows.map(toGraphLink);\n}\n\n/**\n * BFS traversal to find neighbors up to a given depth.\n *\n * @param db - Database handle\n * @param startId - The starting node ID\n * @param depth - Maximum traversal depth (default: 1)\n * @param opts - Optional filters for relation and layer\n * @returns Array of neighbor nodes with their depth and connecting link\n */\nexport function getNeighbors(\n db: DatabaseSync,\n startId: string,\n depth: number = 1,\n opts?: { relation?: string; layer?: string },\n): GraphNeighbor[] {\n const visited = new Set<string>([startId]);\n const result: GraphNeighbor[] = [];\n let frontier = [startId];\n\n for (let d = 1; d <= depth; d++) {\n const nextFrontier: string[] = [];\n\n for (const nodeId of frontier) {\n // Follow outgoing links\n const outgoing = getLinksFrom(db, nodeId, opts);\n for (const link of outgoing) {\n if (!visited.has(link.toId)) {\n visited.add(link.toId);\n nextFrontier.push(link.toId);\n result.push({ id: link.toId, depth: d, link });\n }\n }\n\n // Follow incoming links\n const incoming = getLinksTo(db, nodeId, opts);\n for (const link of incoming) {\n if (!visited.has(link.fromId)) {\n visited.add(link.fromId);\n nextFrontier.push(link.fromId);\n result.push({ id: link.fromId, depth: d, link });\n }\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return result;\n}\n\n/**\n * BFS shortest path between two nodes, max depth 3.\n *\n * @returns Array of links forming the path, or empty if no path found.\n */\nexport function getPathBetween(\n db: DatabaseSync,\n fromId: string,\n toId: string,\n maxDepth: number = 3,\n): GraphLink[] {\n if (fromId === toId) return [];\n\n // BFS with parent tracking\n const visited = new Set<string>([fromId]);\n // Maps each visited node to the link that discovered it\n const parentLink = new Map<string, GraphLink>();\n let frontier = [fromId];\n\n for (let d = 0; d < maxDepth; d++) {\n const nextFrontier: string[] = [];\n\n for (const nodeId of frontier) {\n // Follow outgoing links\n const outgoing = getLinksFrom(db, nodeId);\n for (const link of outgoing) {\n if (!visited.has(link.toId)) {\n visited.add(link.toId);\n parentLink.set(link.toId, link);\n if (link.toId === toId) {\n return reconstructPath(parentLink, fromId, toId);\n }\n nextFrontier.push(link.toId);\n }\n }\n\n // Follow incoming links\n const incoming = getLinksTo(db, nodeId);\n for (const link of incoming) {\n if (!visited.has(link.fromId)) {\n visited.add(link.fromId);\n parentLink.set(link.fromId, link);\n if (link.fromId === toId) {\n return reconstructPath(parentLink, fromId, toId);\n }\n nextFrontier.push(link.fromId);\n }\n }\n }\n\n frontier = nextFrontier;\n if (frontier.length === 0) break;\n }\n\n return []; // No path found\n}\n\n/**\n * Reconstruct the path from BFS parent map.\n */\nfunction reconstructPath(\n parentLink: Map<string, GraphLink>,\n fromId: string,\n toId: string,\n): GraphLink[] {\n const path: GraphLink[] = [];\n let current = toId;\n\n while (current !== fromId) {\n const link = parentLink.get(current);\n if (!link) break;\n path.unshift(link);\n // Determine which side led to `current`\n current = link.toId === current ? link.fromId : link.toId;\n }\n\n return path;\n}\n\nfunction toGraphLink(row: {\n from_id: string;\n to_id: string;\n relation: string;\n layer: string | null;\n weight: number;\n source_path: string | null;\n}): GraphLink {\n return {\n fromId: row.from_id,\n toId: row.to_id,\n relation: row.relation,\n layer: row.layer,\n weight: row.weight,\n sourcePath: row.source_path,\n };\n}\n","import type { DatabaseSync } from \"node:sqlite\";\n\nexport async function loadSqliteVecExtension(params: {\n db: DatabaseSync;\n extensionPath?: string;\n}): Promise<{ ok: boolean; extensionPath?: string; error?: string }> {\n try {\n const sqliteVec = await import(\"sqlite-vec\");\n const resolvedPath = params.extensionPath?.trim() ? params.extensionPath.trim() : undefined;\n const extensionPath = resolvedPath ?? sqliteVec.getLoadablePath();\n\n params.db.enableLoadExtension(true);\n if (resolvedPath) {\n params.db.loadExtension(extensionPath);\n } else {\n sqliteVec.load(params.db);\n }\n\n return { ok: true, extensionPath };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return { ok: false, error: message };\n }\n}\n","import fsSync from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nimport type { Llama, LlamaEmbeddingContext, LlamaModel } from \"node-llama-cpp\";\n\nexport type EmbeddingProvider = {\n id: string;\n model: string;\n embedQuery: (text: string) => Promise<number[]>;\n embedBatch: (texts: string[]) => Promise<number[][]>;\n};\n\nexport type EmbeddingProviderResult = {\n provider: EmbeddingProvider;\n requestedProvider: \"openai\" | \"local\" | \"gemini\" | \"auto\" | \"none\";\n fallbackFrom?: \"openai\" | \"local\" | \"gemini\" | \"auto\";\n fallbackReason?: string;\n openAi?: OpenAiEmbeddingClient;\n gemini?: GeminiEmbeddingClient;\n};\n\nexport type EmbeddingProviderOptions = {\n provider: \"openai\" | \"local\" | \"gemini\" | \"auto\" | \"none\";\n model?: string;\n fallback?: \"openai\" | \"gemini\" | \"local\" | \"none\";\n openai?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n gemini?: {\n apiKey?: string;\n baseUrl?: string;\n headers?: Record<string, string>;\n };\n local?: {\n modelPath?: string;\n modelCacheDir?: string;\n };\n};\n\nexport type OpenAiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n};\n\nexport type GeminiEmbeddingClient = {\n baseUrl: string;\n headers: Record<string, string>;\n model: string;\n modelPath: string;\n};\n\nconst DEFAULT_LOCAL_MODEL = \"hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf\";\nconst DEFAULT_OPENAI_EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst DEFAULT_OPENAI_BASE_URL = \"https://api.openai.com/v1\";\nconst DEFAULT_GEMINI_EMBEDDING_MODEL = \"gemini-embedding-001\";\nconst DEFAULT_GEMINI_BASE_URL = \"https://generativelanguage.googleapis.com/v1beta\";\n\n/**\n * Creates a no-op embedding provider that returns empty vectors.\n * Used for BM25-only mode when no embedding API is available.\n */\nfunction createNoOpEmbeddingProvider(): EmbeddingProvider {\n return {\n id: \"none\",\n model: \"bm25-only\",\n embedQuery: async () => [],\n embedBatch: async (texts) => texts.map(() => []),\n };\n}\n\nfunction resolveUserPath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.join(os.homedir(), filePath.slice(2));\n }\n return filePath;\n}\n\nfunction canAutoSelectLocal(options: EmbeddingProviderOptions): boolean {\n const modelPath = options.local?.modelPath?.trim();\n if (!modelPath) return false;\n if (/^(hf:|https?:)/i.test(modelPath)) return false;\n const resolved = resolveUserPath(modelPath);\n try {\n return fsSync.statSync(resolved).isFile();\n } catch {\n return false;\n }\n}\n\nfunction isMissingApiKeyError(err: unknown): boolean {\n const message = formatError(err);\n return message.includes(\"API key\") || message.includes(\"apiKey\");\n}\n\nasync function importNodeLlamaCpp() {\n const llama = await import(\"node-llama-cpp\");\n return llama;\n}\n\nasync function createLocalEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProvider> {\n const modelPath = options.local?.modelPath?.trim() || DEFAULT_LOCAL_MODEL;\n const modelCacheDir = options.local?.modelCacheDir?.trim();\n\n const { getLlama, resolveModelFile, LlamaLogLevel } = await importNodeLlamaCpp();\n\n let llama: Llama | null = null;\n let embeddingModel: LlamaModel | null = null;\n let embeddingContext: LlamaEmbeddingContext | null = null;\n\n const ensureContext = async () => {\n if (!llama) {\n llama = await getLlama({ logLevel: LlamaLogLevel.error });\n }\n if (!embeddingModel) {\n const resolved = await resolveModelFile(modelPath, modelCacheDir || undefined);\n embeddingModel = await llama.loadModel({ modelPath: resolved });\n }\n if (!embeddingContext) {\n embeddingContext = await embeddingModel.createEmbeddingContext();\n }\n return embeddingContext;\n };\n\n return {\n id: \"local\",\n model: modelPath,\n embedQuery: async (text) => {\n const ctx = await ensureContext();\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n },\n embedBatch: async (texts) => {\n const ctx = await ensureContext();\n const embeddings = await Promise.all(\n texts.map(async (text) => {\n const embedding = await ctx.getEmbeddingFor(text);\n return Array.from(embedding.vector) as number[];\n }),\n );\n return embeddings;\n },\n };\n}\n\nfunction normalizeOpenAiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_OPENAI_EMBEDDING_MODEL;\n if (trimmed.startsWith(\"openai/\")) return trimmed.slice(\"openai/\".length);\n return trimmed;\n}\n\nfunction resolveOpenAiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.openai?.apiKey?.trim();\n if (apiKey) return apiKey;\n const envKey = process.env.OPENAI_API_KEY?.trim();\n if (envKey) return envKey;\n throw new Error(\"OpenAI API key not found. Set OPENAI_API_KEY env var or pass openai.apiKey option.\");\n}\n\nexport async function createOpenAiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: OpenAiEmbeddingClient }> {\n const apiKey = resolveOpenAiApiKey(options);\n const baseUrl = options.openai?.baseUrl?.trim() || DEFAULT_OPENAI_BASE_URL;\n const headerOverrides = options.openai?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n ...headerOverrides,\n };\n const model = normalizeOpenAiModel(options.model || \"\");\n const client: OpenAiEmbeddingClient = { baseUrl, headers, model };\n const url = `${baseUrl.replace(/\\/$/, \"\")}/embeddings`;\n\n const embed = async (input: string[]): Promise<number[][]> => {\n if (input.length === 0) return [];\n const res = await fetch(url, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ model: client.model, input }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai embeddings failed: ${res.status} ${text}`);\n }\n const payload = (await res.json()) as {\n data?: Array<{ embedding?: number[] }>;\n };\n const data = payload.data ?? [];\n return data.map((entry) => entry.embedding ?? []);\n };\n\n return {\n provider: {\n id: \"openai\",\n model: client.model,\n embedQuery: async (text) => {\n const [vec] = await embed([text]);\n return vec ?? [];\n },\n embedBatch: embed,\n },\n client,\n };\n}\n\nfunction normalizeGeminiModel(model: string): string {\n const trimmed = model.trim();\n if (!trimmed) return DEFAULT_GEMINI_EMBEDDING_MODEL;\n const withoutPrefix = trimmed.replace(/^models\\//, \"\");\n if (withoutPrefix.startsWith(\"gemini/\")) return withoutPrefix.slice(\"gemini/\".length);\n if (withoutPrefix.startsWith(\"google/\")) return withoutPrefix.slice(\"google/\".length);\n return withoutPrefix;\n}\n\nfunction normalizeGeminiBaseUrl(raw: string): string {\n const trimmed = raw.replace(/\\/+$/, \"\");\n const openAiIndex = trimmed.indexOf(\"/openai\");\n if (openAiIndex > -1) return trimmed.slice(0, openAiIndex);\n return trimmed;\n}\n\nfunction buildGeminiModelPath(model: string): string {\n return model.startsWith(\"models/\") ? model : `models/${model}`;\n}\n\nfunction resolveGeminiApiKey(options: EmbeddingProviderOptions): string {\n const apiKey = options.gemini?.apiKey?.trim();\n if (apiKey) return apiKey;\n const googleKey = process.env.GOOGLE_API_KEY?.trim();\n if (googleKey) return googleKey;\n const geminiKey = process.env.GEMINI_API_KEY?.trim();\n if (geminiKey) return geminiKey;\n throw new Error(\"Gemini API key not found. Set GOOGLE_API_KEY or GEMINI_API_KEY env var or pass gemini.apiKey option.\");\n}\n\nexport async function createGeminiEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<{ provider: EmbeddingProvider; client: GeminiEmbeddingClient }> {\n const apiKey = resolveGeminiApiKey(options);\n const rawBaseUrl = options.gemini?.baseUrl?.trim() || DEFAULT_GEMINI_BASE_URL;\n const baseUrl = normalizeGeminiBaseUrl(rawBaseUrl);\n const headerOverrides = options.gemini?.headers ?? {};\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": apiKey,\n ...headerOverrides,\n };\n const model = normalizeGeminiModel(options.model || \"\");\n const modelPath = buildGeminiModelPath(model);\n const client: GeminiEmbeddingClient = { baseUrl, headers, model, modelPath };\n\n const embedUrl = `${baseUrl}/${modelPath}:embedContent`;\n const batchUrl = `${baseUrl}/${modelPath}:batchEmbedContents`;\n\n const embedQuery = async (text: string): Promise<number[]> => {\n if (!text.trim()) return [];\n const res = await fetch(embedUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_QUERY\",\n }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embedding?: { values?: number[] } };\n return payload.embedding?.values ?? [];\n };\n\n const embedBatch = async (texts: string[]): Promise<number[][]> => {\n if (texts.length === 0) return [];\n const requests = texts.map((text) => ({\n model: modelPath,\n content: { parts: [{ text }] },\n taskType: \"RETRIEVAL_DOCUMENT\",\n }));\n const res = await fetch(batchUrl, {\n method: \"POST\",\n headers: client.headers,\n body: JSON.stringify({ requests }),\n });\n if (!res.ok) {\n const payload = await res.text();\n throw new Error(`gemini embeddings failed: ${res.status} ${payload}`);\n }\n const payload = (await res.json()) as { embeddings?: Array<{ values?: number[] }> };\n const embeddings = Array.isArray(payload.embeddings) ? payload.embeddings : [];\n return texts.map((_, index) => embeddings[index]?.values ?? []);\n };\n\n return {\n provider: {\n id: \"gemini\",\n model: client.model,\n embedQuery,\n embedBatch,\n },\n client,\n };\n}\n\nexport async function createEmbeddingProvider(\n options: EmbeddingProviderOptions,\n): Promise<EmbeddingProviderResult> {\n const requestedProvider = options.provider;\n const fallback = options.fallback ?? \"none\";\n\n // Handle explicit \"none\" provider (BM25-only mode)\n if (requestedProvider === \"none\") {\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider: \"none\",\n };\n }\n\n const createProvider = async (id: \"openai\" | \"local\" | \"gemini\") => {\n if (id === \"local\") {\n const provider = await createLocalEmbeddingProvider(options);\n return { provider };\n }\n if (id === \"gemini\") {\n const { provider, client } = await createGeminiEmbeddingProvider(options);\n return { provider, gemini: client };\n }\n const { provider, client } = await createOpenAiEmbeddingProvider(options);\n return { provider, openAi: client };\n };\n\n const formatPrimaryError = (err: unknown, provider: \"openai\" | \"local\" | \"gemini\") =>\n provider === \"local\" ? formatLocalSetupError(err) : formatError(err);\n\n if (requestedProvider === \"auto\") {\n const missingKeyErrors: string[] = [];\n let localError: string | null = null;\n\n if (canAutoSelectLocal(options)) {\n try {\n const local = await createProvider(\"local\");\n return { ...local, requestedProvider };\n } catch (err) {\n localError = formatLocalSetupError(err);\n }\n }\n\n for (const provider of [\"openai\", \"gemini\"] as const) {\n try {\n const result = await createProvider(provider);\n return { ...result, requestedProvider };\n } catch (err) {\n const message = formatPrimaryError(err, provider);\n if (isMissingApiKeyError(err)) {\n missingKeyErrors.push(message);\n continue;\n }\n throw new Error(message);\n }\n }\n\n // Fall back to BM25-only mode instead of throwing\n // This allows the system to work without any API keys using full-text search only\n return {\n provider: createNoOpEmbeddingProvider(),\n requestedProvider,\n fallbackFrom: \"auto\",\n fallbackReason: \"No embedding API available. Using BM25 full-text search only.\",\n };\n }\n\n try {\n const primary = await createProvider(requestedProvider);\n return { ...primary, requestedProvider };\n } catch (primaryErr) {\n const reason = formatPrimaryError(primaryErr, requestedProvider);\n if (fallback && fallback !== \"none\" && fallback !== requestedProvider) {\n try {\n const fallbackResult = await createProvider(fallback);\n return {\n ...fallbackResult,\n requestedProvider,\n fallbackFrom: requestedProvider,\n fallbackReason: reason,\n };\n } catch (fallbackErr) {\n throw new Error(`${reason}\\n\\nFallback to ${fallback} failed: ${formatError(fallbackErr)}`);\n }\n }\n throw new Error(reason);\n }\n}\n\nfunction formatError(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nfunction isNodeLlamaCppMissing(err: unknown): boolean {\n if (!(err instanceof Error)) return false;\n const code = (err as Error & { code?: unknown }).code;\n if (code === \"ERR_MODULE_NOT_FOUND\") {\n return err.message.includes(\"node-llama-cpp\");\n }\n return false;\n}\n\nfunction formatLocalSetupError(err: unknown): string {\n const detail = formatError(err);\n const missing = isNodeLlamaCppMissing(err);\n return [\n \"Local embeddings unavailable.\",\n missing\n ? \"Reason: optional dependency node-llama-cpp is missing (or failed to install).\"\n : detail\n ? `Reason: ${detail}`\n : undefined,\n missing && detail ? `Detail: ${detail}` : null,\n \"To enable local embeddings:\",\n \"1) Use Node 22 LTS (recommended for installs/updates)\",\n missing ? \"2) Install node-llama-cpp: npm install node-llama-cpp\" : null,\n \"3) If you use pnpm: pnpm approve-builds (select node-llama-cpp), then pnpm rebuild node-llama-cpp\",\n 'Or set provider = \"openai\" or \"gemini\" (remote).',\n ]\n .filter(Boolean)\n .join(\"\\n\");\n}\n","import type { OpenAiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type OpenAiBatchRequest = {\n custom_id: string;\n method: \"POST\";\n url: \"/v1/embeddings\";\n body: {\n model: string;\n input: string;\n };\n};\n\nexport type OpenAiBatchStatus = {\n id?: string;\n status?: string;\n output_file_id?: string | null;\n error_file_id?: string | null;\n};\n\nexport type OpenAiBatchOutputLine = {\n custom_id?: string;\n response?: {\n status_code?: number;\n body?: {\n data?: Array<{ embedding?: number[]; index?: number }>;\n error?: { message?: string };\n };\n };\n error?: { message?: string };\n};\n\nexport const OPENAI_BATCH_ENDPOINT = \"/v1/embeddings\";\nconst OPENAI_BATCH_COMPLETION_WINDOW = \"24h\";\nconst OPENAI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getOpenAiBaseUrl(openAi: OpenAiEmbeddingClient): string {\n return openAi.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getOpenAiHeaders(\n openAi: OpenAiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = openAi.headers ? { ...openAi.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction splitOpenAiBatchRequests(requests: OpenAiBatchRequest[]): OpenAiBatchRequest[][] {\n if (requests.length <= OPENAI_BATCH_MAX_REQUESTS) return [requests];\n const groups: OpenAiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += OPENAI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + OPENAI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nasync function retryAsync<T>(\n fn: () => Promise<T>,\n opts: {\n attempts: number;\n minDelayMs: number;\n maxDelayMs: number;\n jitter: number;\n shouldRetry: (err: unknown) => boolean;\n },\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt < opts.attempts; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (!opts.shouldRetry(err) || attempt === opts.attempts - 1) {\n throw err;\n }\n const delay = Math.min(\n opts.maxDelayMs,\n opts.minDelayMs * Math.pow(2, attempt) * (1 + Math.random() * opts.jitter),\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n throw lastError;\n}\n\nasync function submitOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n requests: OpenAiBatchRequest[];\n source: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const jsonl = params.requests.map((request) => JSON.stringify(request)).join(\"\\n\");\n const form = new FormData();\n form.append(\"purpose\", \"batch\");\n form.append(\n \"file\",\n new Blob([jsonl], { type: \"application/jsonl\" }),\n `memory-embeddings.${hashText(String(Date.now()))}.jsonl`,\n );\n\n const fileRes = await fetch(`${baseUrl}/files`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: false }),\n body: form,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`openai batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { id?: string };\n if (!filePayload.id) {\n throw new Error(\"openai batch file upload failed: missing file id\");\n }\n\n const batchRes = await retryAsync(\n async () => {\n const res = await fetch(`${baseUrl}/batches`, {\n method: \"POST\",\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n body: JSON.stringify({\n input_file_id: filePayload.id,\n endpoint: OPENAI_BATCH_ENDPOINT,\n completion_window: OPENAI_BATCH_COMPLETION_WINDOW,\n metadata: {\n source: params.source,\n },\n }),\n });\n if (!res.ok) {\n const text = await res.text();\n const err = new Error(`openai batch create failed: ${res.status} ${text}`) as Error & {\n status?: number;\n };\n err.status = res.status;\n throw err;\n }\n return res;\n },\n {\n attempts: 3,\n minDelayMs: 300,\n maxDelayMs: 2000,\n jitter: 0.2,\n shouldRetry: (err) => {\n const status = (err as { status?: number }).status;\n return status === 429 || (typeof status === \"number\" && status >= 500);\n },\n },\n );\n return (await batchRes.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiBatchStatus(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n}): Promise<OpenAiBatchStatus> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/batches/${params.batchId}`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as OpenAiBatchStatus;\n}\n\nasync function fetchOpenAiFileContent(params: {\n openAi: OpenAiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getOpenAiBaseUrl(params.openAi);\n const res = await fetch(`${baseUrl}/files/${params.fileId}/content`, {\n headers: getOpenAiHeaders(params.openAi, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`openai batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseOpenAiBatchOutput(text: string): OpenAiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as OpenAiBatchOutputLine);\n}\n\nasync function readOpenAiBatchError(params: {\n openAi: OpenAiEmbeddingClient;\n errorFileId: string;\n}): Promise<string | undefined> {\n try {\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: params.errorFileId,\n });\n const lines = parseOpenAiBatchOutput(content);\n const first = lines.find((line) => line.error?.message || line.response?.body?.error);\n const message =\n first?.error?.message ??\n (typeof first?.response?.body?.error?.message === \"string\"\n ? first?.response?.body?.error?.message\n : undefined);\n return message;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return message ? `error file unavailable: ${message}` : undefined;\n }\n}\n\nasync function waitForOpenAiBatch(params: {\n openAi: OpenAiEmbeddingClient;\n batchId: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: OpenAiBatchStatus;\n}): Promise<{ outputFileId: string; errorFileId?: string }> {\n const start = Date.now();\n let current: OpenAiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchOpenAiBatchStatus({\n openAi: params.openAi,\n batchId: params.batchId,\n }));\n const state = status.status ?? \"unknown\";\n if (state === \"completed\") {\n if (!status.output_file_id) {\n throw new Error(`openai batch ${params.batchId} completed without output file`);\n }\n return {\n outputFileId: status.output_file_id,\n errorFileId: status.error_file_id ?? undefined,\n };\n }\n if ([\"failed\", \"expired\", \"cancelled\", \"canceled\"].includes(state)) {\n const detail = status.error_file_id\n ? await readOpenAiBatchError({ openAi: params.openAi, errorFileId: status.error_file_id })\n : undefined;\n const suffix = detail ? `: ${detail}` : \"\";\n throw new Error(`openai batch ${params.batchId} ${state}${suffix}`);\n }\n if (!params.wait) {\n throw new Error(`openai batch ${params.batchId} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`openai batch ${params.batchId} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`openai batch ${params.batchId} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runOpenAiEmbeddingBatches(params: {\n openAi: OpenAiEmbeddingClient;\n source: string;\n requests: OpenAiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitOpenAiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitOpenAiBatch({\n openAi: params.openAi,\n requests: group,\n source: params.source,\n });\n if (!batchInfo.id) {\n throw new Error(\"openai batch create failed: missing batch id\");\n }\n\n params.debug?.(\"memory embeddings: openai batch created\", {\n batchId: batchInfo.id,\n status: batchInfo.status,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (!params.wait && batchInfo.status !== \"completed\") {\n throw new Error(\n `openai batch ${batchInfo.id} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.status === \"completed\"\n ? {\n outputFileId: batchInfo.output_file_id ?? \"\",\n errorFileId: batchInfo.error_file_id ?? undefined,\n }\n : await waitForOpenAiBatch({\n openAi: params.openAi,\n batchId: batchInfo.id,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`openai batch ${batchInfo.id} completed without output file`);\n }\n\n const content = await fetchOpenAiFileContent({\n openAi: params.openAi,\n fileId: completed.outputFileId,\n });\n const outputLines = parseOpenAiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.custom_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n const response = line.response;\n const statusCode = response?.status_code ?? 0;\n if (statusCode >= 400) {\n const message =\n response?.body?.error?.message ??\n (typeof response?.body === \"string\" ? response.body : undefined) ??\n \"unknown error\";\n errors.push(`${customId}: ${message}`);\n continue;\n }\n const data = response?.body?.data ?? [];\n const embedding = data[0]?.embedding ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`openai batch ${batchInfo.id} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`openai batch ${batchInfo.id} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: openai batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","import type { GeminiEmbeddingClient } from \"./embeddings.js\";\nimport { hashText } from \"../internal.js\";\n\nexport type GeminiBatchRequest = {\n custom_id: string;\n content: { parts: Array<{ text: string }> };\n taskType: \"RETRIEVAL_DOCUMENT\" | \"RETRIEVAL_QUERY\";\n};\n\nexport type GeminiBatchStatus = {\n name?: string;\n state?: string;\n outputConfig?: { file?: string; fileId?: string };\n metadata?: {\n output?: {\n responsesFile?: string;\n };\n };\n error?: { message?: string };\n};\n\nexport type GeminiBatchOutputLine = {\n key?: string;\n custom_id?: string;\n request_id?: string;\n embedding?: { values?: number[] };\n response?: {\n embedding?: { values?: number[] };\n error?: { message?: string };\n };\n error?: { message?: string };\n};\n\nconst GEMINI_BATCH_MAX_REQUESTS = 50000;\n\nfunction getGeminiBaseUrl(gemini: GeminiEmbeddingClient): string {\n return gemini.baseUrl?.replace(/\\/$/, \"\") ?? \"\";\n}\n\nfunction getGeminiHeaders(\n gemini: GeminiEmbeddingClient,\n params: { json: boolean },\n): Record<string, string> {\n const headers = gemini.headers ? { ...gemini.headers } : {};\n if (params.json) {\n if (!headers[\"Content-Type\"] && !headers[\"content-type\"]) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n } else {\n delete headers[\"Content-Type\"];\n delete headers[\"content-type\"];\n }\n return headers;\n}\n\nfunction getGeminiUploadUrl(baseUrl: string): string {\n if (baseUrl.includes(\"/v1beta\")) {\n return baseUrl.replace(/\\/v1beta\\/?$/, \"/upload/v1beta\");\n }\n return `${baseUrl.replace(/\\/$/, \"\")}/upload`;\n}\n\nfunction splitGeminiBatchRequests(requests: GeminiBatchRequest[]): GeminiBatchRequest[][] {\n if (requests.length <= GEMINI_BATCH_MAX_REQUESTS) return [requests];\n const groups: GeminiBatchRequest[][] = [];\n for (let i = 0; i < requests.length; i += GEMINI_BATCH_MAX_REQUESTS) {\n groups.push(requests.slice(i, i + GEMINI_BATCH_MAX_REQUESTS));\n }\n return groups;\n}\n\nfunction buildGeminiUploadBody(params: { jsonl: string; displayName: string }): {\n body: Blob;\n contentType: string;\n} {\n const boundary = `minimem-${hashText(params.displayName)}`;\n const jsonPart = JSON.stringify({\n file: {\n displayName: params.displayName,\n mimeType: \"application/jsonl\",\n },\n });\n const delimiter = `--${boundary}\\r\\n`;\n const closeDelimiter = `--${boundary}--\\r\\n`;\n const parts = [\n `${delimiter}Content-Type: application/json; charset=UTF-8\\r\\n\\r\\n${jsonPart}\\r\\n`,\n `${delimiter}Content-Type: application/jsonl; charset=UTF-8\\r\\n\\r\\n${params.jsonl}\\r\\n`,\n closeDelimiter,\n ];\n const body = new Blob([parts.join(\"\")], { type: \"multipart/related\" });\n return {\n body,\n contentType: `multipart/related; boundary=${boundary}`,\n };\n}\n\nasync function submitGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n requests: GeminiBatchRequest[];\n source: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const jsonl = params.requests\n .map((request) =>\n JSON.stringify({\n key: request.custom_id,\n request: {\n content: request.content,\n task_type: request.taskType,\n },\n }),\n )\n .join(\"\\n\");\n const displayName = `memory-embeddings-${hashText(String(Date.now()))}`;\n const uploadPayload = buildGeminiUploadBody({ jsonl, displayName });\n\n const uploadUrl = `${getGeminiUploadUrl(baseUrl)}/files?uploadType=multipart`;\n const fileRes = await fetch(uploadUrl, {\n method: \"POST\",\n headers: {\n ...getGeminiHeaders(params.gemini, { json: false }),\n \"Content-Type\": uploadPayload.contentType,\n },\n body: uploadPayload.body,\n });\n if (!fileRes.ok) {\n const text = await fileRes.text();\n throw new Error(`gemini batch file upload failed: ${fileRes.status} ${text}`);\n }\n const filePayload = (await fileRes.json()) as { name?: string; file?: { name?: string } };\n const fileId = filePayload.name ?? filePayload.file?.name;\n if (!fileId) {\n throw new Error(\"gemini batch file upload failed: missing file id\");\n }\n\n const batchBody = {\n batch: {\n displayName: `memory-embeddings-${params.source}`,\n inputConfig: {\n file_name: fileId,\n },\n },\n };\n\n const batchEndpoint = `${baseUrl}/${params.gemini.modelPath}:asyncBatchEmbedContent`;\n const batchRes = await fetch(batchEndpoint, {\n method: \"POST\",\n headers: getGeminiHeaders(params.gemini, { json: true }),\n body: JSON.stringify(batchBody),\n });\n if (batchRes.ok) {\n return (await batchRes.json()) as GeminiBatchStatus;\n }\n const text = await batchRes.text();\n if (batchRes.status === 404) {\n throw new Error(\n \"gemini batch create failed: 404 (asyncBatchEmbedContent not available for this model/baseUrl). Disable batch.enabled or switch providers.\",\n );\n }\n throw new Error(`gemini batch create failed: ${batchRes.status} ${text}`);\n}\n\nasync function fetchGeminiBatchStatus(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n}): Promise<GeminiBatchStatus> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const name = params.batchName.startsWith(\"batches/\")\n ? params.batchName\n : `batches/${params.batchName}`;\n const statusUrl = `${baseUrl}/${name}`;\n const res = await fetch(statusUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch status failed: ${res.status} ${text}`);\n }\n return (await res.json()) as GeminiBatchStatus;\n}\n\nasync function fetchGeminiFileContent(params: {\n gemini: GeminiEmbeddingClient;\n fileId: string;\n}): Promise<string> {\n const baseUrl = getGeminiBaseUrl(params.gemini);\n const file = params.fileId.startsWith(\"files/\") ? params.fileId : `files/${params.fileId}`;\n const downloadUrl = `${baseUrl}/${file}:download`;\n const res = await fetch(downloadUrl, {\n headers: getGeminiHeaders(params.gemini, { json: true }),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`gemini batch file content failed: ${res.status} ${text}`);\n }\n return await res.text();\n}\n\nfunction parseGeminiBatchOutput(text: string): GeminiBatchOutputLine[] {\n if (!text.trim()) return [];\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => JSON.parse(line) as GeminiBatchOutputLine);\n}\n\nasync function waitForGeminiBatch(params: {\n gemini: GeminiEmbeddingClient;\n batchName: string;\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n initial?: GeminiBatchStatus;\n}): Promise<{ outputFileId: string }> {\n const start = Date.now();\n let current: GeminiBatchStatus | undefined = params.initial;\n while (true) {\n const status =\n current ??\n (await fetchGeminiBatchStatus({\n gemini: params.gemini,\n batchName: params.batchName,\n }));\n const state = status.state ?? \"UNKNOWN\";\n if ([\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(state)) {\n const outputFileId =\n status.outputConfig?.file ??\n status.outputConfig?.fileId ??\n status.metadata?.output?.responsesFile;\n if (!outputFileId) {\n throw new Error(`gemini batch ${params.batchName} completed without output file`);\n }\n return { outputFileId };\n }\n if ([\"FAILED\", \"CANCELLED\", \"CANCELED\", \"EXPIRED\"].includes(state)) {\n const message = status.error?.message ?? \"unknown error\";\n throw new Error(`gemini batch ${params.batchName} ${state}: ${message}`);\n }\n if (!params.wait) {\n throw new Error(`gemini batch ${params.batchName} still ${state}; wait disabled`);\n }\n if (Date.now() - start > params.timeoutMs) {\n throw new Error(`gemini batch ${params.batchName} timed out after ${params.timeoutMs}ms`);\n }\n params.debug?.(`gemini batch ${params.batchName} ${state}; waiting ${params.pollIntervalMs}ms`);\n await new Promise((resolve) => setTimeout(resolve, params.pollIntervalMs));\n current = undefined;\n }\n}\n\nasync function runWithConcurrency<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<T[]> {\n if (tasks.length === 0) return [];\n const resolvedLimit = Math.max(1, Math.min(limit, tasks.length));\n const results: T[] = Array.from({ length: tasks.length });\n let next = 0;\n let firstError: unknown = null;\n\n const workers = Array.from({ length: resolvedLimit }, async () => {\n while (true) {\n if (firstError) return;\n const index = next;\n next += 1;\n if (index >= tasks.length) return;\n try {\n results[index] = await tasks[index]();\n } catch (err) {\n firstError = err;\n return;\n }\n }\n });\n\n await Promise.allSettled(workers);\n if (firstError) throw firstError;\n return results;\n}\n\nexport async function runGeminiEmbeddingBatches(params: {\n gemini: GeminiEmbeddingClient;\n source: string;\n requests: GeminiBatchRequest[];\n wait: boolean;\n pollIntervalMs: number;\n timeoutMs: number;\n concurrency: number;\n debug?: (message: string, data?: Record<string, unknown>) => void;\n}): Promise<Map<string, number[]>> {\n if (params.requests.length === 0) return new Map();\n const groups = splitGeminiBatchRequests(params.requests);\n const byCustomId = new Map<string, number[]>();\n\n const tasks = groups.map((group, groupIndex) => async () => {\n const batchInfo = await submitGeminiBatch({\n gemini: params.gemini,\n requests: group,\n source: params.source,\n });\n const batchName = batchInfo.name ?? \"\";\n if (!batchName) {\n throw new Error(\"gemini batch create failed: missing batch name\");\n }\n\n params.debug?.(\"memory embeddings: gemini batch created\", {\n batchName,\n state: batchInfo.state,\n group: groupIndex + 1,\n groups: groups.length,\n requests: group.length,\n });\n\n if (\n !params.wait &&\n batchInfo.state &&\n ![\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ) {\n throw new Error(\n `gemini batch ${batchName} submitted; enable batch.wait to await completion`,\n );\n }\n\n const completed =\n batchInfo.state && [\"SUCCEEDED\", \"COMPLETED\", \"DONE\"].includes(batchInfo.state)\n ? {\n outputFileId:\n batchInfo.outputConfig?.file ??\n batchInfo.outputConfig?.fileId ??\n batchInfo.metadata?.output?.responsesFile ??\n \"\",\n }\n : await waitForGeminiBatch({\n gemini: params.gemini,\n batchName,\n wait: params.wait,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n debug: params.debug,\n initial: batchInfo,\n });\n if (!completed.outputFileId) {\n throw new Error(`gemini batch ${batchName} completed without output file`);\n }\n\n const content = await fetchGeminiFileContent({\n gemini: params.gemini,\n fileId: completed.outputFileId,\n });\n const outputLines = parseGeminiBatchOutput(content);\n const errors: string[] = [];\n const remaining = new Set(group.map((request) => request.custom_id));\n\n for (const line of outputLines) {\n const customId = line.key ?? line.custom_id ?? line.request_id;\n if (!customId) continue;\n remaining.delete(customId);\n if (line.error?.message) {\n errors.push(`${customId}: ${line.error.message}`);\n continue;\n }\n if (line.response?.error?.message) {\n errors.push(`${customId}: ${line.response.error.message}`);\n continue;\n }\n const embedding = line.embedding?.values ?? line.response?.embedding?.values ?? [];\n if (embedding.length === 0) {\n errors.push(`${customId}: empty embedding`);\n continue;\n }\n byCustomId.set(customId, embedding);\n }\n\n if (errors.length > 0) {\n throw new Error(`gemini batch ${batchName} failed: ${errors.join(\"; \")}`);\n }\n if (remaining.size > 0) {\n throw new Error(`gemini batch ${batchName} missing ${remaining.size} embedding responses`);\n }\n });\n\n params.debug?.(\"memory embeddings: gemini batch submit\", {\n requests: params.requests.length,\n groups: groups.length,\n wait: params.wait,\n concurrency: params.concurrency,\n pollIntervalMs: params.pollIntervalMs,\n timeoutMs: params.timeoutMs,\n });\n\n await runWithConcurrency(tasks, params.concurrency);\n return byCustomId;\n}\n","/**\n * minimem search - Semantic search through memory\n *\n * Supports searching across multiple memory directories in a single query.\n */\n\nimport { Minimem, type MinimemSearchResult } from \"../../minimem.js\";\nimport {\n resolveMemoryDirs,\n exitWithError,\n warn,\n note,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type SearchOptions = {\n dir?: string[];\n global?: boolean;\n max?: string;\n minScore?: string;\n provider?: string;\n json?: boolean;\n};\n\ntype SearchResultWithSource = MinimemSearchResult & {\n memoryDir: string;\n};\n\nexport async function search(\n query: string,\n options: SearchOptions,\n): Promise<void> {\n const directories = resolveMemoryDirs(options);\n\n if (directories.length === 0) {\n exitWithError(\n \"No memory directories specified.\",\n \"Use --dir <path> or --global to specify directories to search.\"\n );\n }\n\n // Validate all directories are initialized\n const validDirs: string[] = [];\n for (const dir of directories) {\n if (await isInitialized(dir)) {\n validDirs.push(dir);\n } else {\n warn(`${formatPath(dir)} is not initialized, skipping.`);\n }\n }\n\n if (validDirs.length === 0) {\n exitWithError(\"No valid initialized memory directories found.\");\n }\n\n const maxResults = options.max ? parseInt(options.max, 10) : 10;\n const minScore = options.minScore ? parseFloat(options.minScore) : undefined;\n\n // Search each directory and collect results\n const allResults: SearchResultWithSource[] = [];\n const instances: Minimem[] = [];\n\n let warnedBm25 = false;\n\n try {\n for (const memoryDir of validDirs) {\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n const minimem = await Minimem.create(config);\n instances.push(minimem);\n\n // Warn once if running in BM25-only mode\n if (!warnedBm25) {\n const status = await minimem.status();\n if (status.bm25Only) {\n note(\"Running in BM25-only mode (no embedding API configured).\");\n note(\"Results are based on keyword matching only.\\n\");\n warnedBm25 = true;\n }\n }\n\n // Get more results per directory, then merge and trim\n const perDirMax = Math.ceil(maxResults * 1.5);\n const results = await minimem.search(query, { maxResults: perDirMax, minScore });\n\n // Add source directory to each result\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir,\n });\n }\n }\n\n // Sort by score descending and limit to maxResults\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n console.log(\"No results found.\");\n return;\n }\n\n if (options.json) {\n console.log(JSON.stringify(topResults, null, 2));\n return;\n }\n\n // Format results for terminal\n const showSource = validDirs.length > 1;\n\n for (const result of topResults) {\n const score = (result.score * 100).toFixed(1);\n const location = `${result.path}:${result.startLine}-${result.endLine}`;\n\n if (showSource) {\n console.log(`[${score}%] ${formatPath(result.memoryDir)}`);\n console.log(` ${location}`);\n } else {\n console.log(`[${score}%] ${location}`);\n }\n console.log(formatSnippet(result.snippet));\n console.log();\n }\n\n const dirSummary = validDirs.length > 1\n ? ` across ${validDirs.length} directories`\n : \"\";\n console.log(`Found ${topResults.length} result${topResults.length === 1 ? \"\" : \"s\"}${dirSummary}`);\n } finally {\n // Clean up all instances\n for (const instance of instances) {\n instance.close();\n }\n }\n}\n\n/**\n * Format snippet for terminal display\n */\nfunction formatSnippet(snippet: string): string {\n const lines = snippet.split(\"\\n\");\n const formatted = lines.map((line) => ` ${line}`).join(\"\\n\");\n\n // Truncate if too long\n if (formatted.length > 500) {\n return formatted.slice(0, 497) + \"...\";\n }\n\n return formatted;\n}\n","/**\n * minimem sync - Force re-index memory files\n */\n\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n exitWithError,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type SyncOptions = {\n dir?: string;\n global?: boolean;\n force?: boolean;\n provider?: string;\n};\n\nexport async function sync(options: SyncOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n exitWithError(\n `${formatPath(memoryDir)} is not initialized.`,\n `Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`\n );\n }\n\n console.log(`Syncing ${formatPath(memoryDir)}...`);\n\n // Load config and create Minimem instance\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n // Add debug logging\n config.debug = (message, data) => {\n if (data) {\n console.log(` ${message}`, data);\n } else {\n console.log(` ${message}`);\n }\n };\n\n let minimem: Minimem | null = null;\n\n try {\n minimem = await Minimem.create(config);\n\n const startTime = Date.now();\n await minimem.sync({ force: options.force });\n const duration = Date.now() - startTime;\n\n const status = await minimem.status();\n\n console.log();\n console.log(`Sync complete in ${duration}ms`);\n console.log(` Files: ${status.fileCount}`);\n console.log(` Chunks: ${status.chunkCount}`);\n console.log(` Cache: ${status.cacheCount} embeddings`);\n } finally {\n minimem?.close();\n }\n}\n","/**\n * minimem status - Show index stats and provider info\n */\n\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n exitWithError,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type StatusOptions = {\n dir?: string;\n global?: boolean;\n json?: boolean;\n provider?: string;\n};\n\nexport async function status(options: StatusOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n exitWithError(\n `${formatPath(memoryDir)} is not initialized.`,\n `Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`\n );\n }\n\n // Load config and create Minimem instance\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n let minimem: Minimem | null = null;\n\n try {\n minimem = await Minimem.create(config);\n const info = await minimem.status();\n\n if (options.json) {\n console.log(JSON.stringify(info, null, 2));\n return;\n }\n\n console.log(\"Minimem Status\");\n console.log(\"==============\");\n console.log();\n console.log(`Memory Dir: ${formatPath(info.memoryDir)}`);\n console.log(`Database: ${formatPath(info.dbPath)}`);\n console.log();\n console.log(\"Embedding Provider\");\n if (info.bm25Only) {\n console.log(` Provider: none (BM25-only mode)`);\n console.log(` Model: ${info.model}`);\n if (info.fallbackReason) {\n console.log(` Reason: ${info.fallbackReason}`);\n }\n } else {\n console.log(` Provider: ${info.provider}`);\n console.log(` Model: ${info.model}`);\n }\n console.log();\n console.log(\"Search Capabilities\");\n if (info.bm25Only) {\n console.log(` Vector: disabled (no embedding provider)`);\n } else {\n console.log(` Vector: ${info.vectorAvailable ? \"available\" : \"not available\"}`);\n }\n console.log(` FTS: ${info.ftsAvailable ? \"available\" : \"not available\"}`);\n console.log();\n console.log(\"Index Stats\");\n console.log(` Files: ${info.fileCount}`);\n console.log(` Chunks: ${info.chunkCount}`);\n console.log(` Cache: ${info.cacheCount} embeddings`);\n } finally {\n minimem?.close();\n }\n}\n","/**\n * minimem append - Quick append to today's daily log\n */\n\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n exitWithError,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\n\nexport type AppendOptions = {\n dir?: string;\n global?: boolean;\n file?: string;\n provider?: string;\n session?: string;\n sessionSource?: string;\n};\n\nexport async function append(\n text: string,\n options: AppendOptions,\n): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n exitWithError(\n `${formatPath(memoryDir)} is not initialized.`,\n `Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`\n );\n }\n\n // Add session marker if explicit session provided\n let finalText = text;\n if (options.session) {\n const timestamp = new Date().toISOString();\n const sourceInfo = options.sessionSource ? ` source=${options.sessionSource}` : \"\";\n finalText = `<!-- ${timestamp} session=${options.session}${sourceInfo} -->\\n${text}`;\n }\n\n // Load config and create Minimem instance\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n let minimem: Minimem | null = null;\n\n try {\n minimem = await Minimem.create(config);\n\n let targetPath: string;\n\n if (options.file) {\n // Append to specific file\n targetPath = options.file;\n await minimem.appendFile(targetPath, finalText);\n } else {\n // Append to today's daily log\n targetPath = await minimem.appendToday(finalText);\n }\n\n console.log(`Appended to ${targetPath}`);\n if (options.session) {\n console.log(` Session: ${options.session}`);\n }\n } finally {\n minimem?.close();\n }\n}\n","/**\n * minimem upsert - Create or update a memory file\n *\n * File paths are relative to the memory directory:\n * minimem upsert MEMORY.md \"content\" → {memoryDir}/MEMORY.md\n * minimem upsert memory/notes.md \"content\" → {memoryDir}/memory/notes.md\n * minimem upsert /abs/path.md \"content\" → /abs/path.md\n */\n\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { Minimem } from \"../../minimem.js\";\nimport {\n resolveMemoryDir,\n exitWithError,\n note,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n} from \"../config.js\";\nimport {\n addFrontmatter,\n parseFrontmatter,\n type SessionContext,\n} from \"../../session.js\";\n\nexport type UpsertOptions = {\n dir?: string;\n global?: boolean;\n provider?: string;\n stdin?: boolean;\n session?: string;\n sessionSource?: string;\n};\n\nexport async function upsert(\n file: string,\n content: string | undefined,\n options: UpsertOptions,\n): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n exitWithError(\n `${formatPath(memoryDir)} is not initialized.`,\n `Run: minimem init${options.dir ? ` ${options.dir}` : \"\"}`\n );\n }\n\n // Get content from stdin if --stdin flag is set\n let finalContent = content;\n if (options.stdin) {\n finalContent = await readStdin();\n }\n\n if (!finalContent) {\n exitWithError(\n \"No content provided.\",\n \"Use --stdin or provide content as argument.\"\n );\n }\n\n // Build session context from explicit options\n const session: SessionContext | undefined = options.session\n ? {\n id: options.session,\n source: options.sessionSource,\n project: process.cwd(),\n }\n : undefined;\n\n // Resolve file path - all relative paths are relative to memoryDir\n const filePath = resolveFilePath(file, memoryDir);\n\n // Ensure the file is within the memory directory\n const resolvedPath = path.resolve(filePath);\n const resolvedMemoryDir = path.resolve(memoryDir);\n if (!resolvedPath.startsWith(resolvedMemoryDir + path.sep) && resolvedPath !== resolvedMemoryDir) {\n exitWithError(\n \"File path must be within the memory directory.\",\n `Memory dir: ${formatPath(memoryDir)}, File: ${formatPath(filePath)}`\n );\n }\n\n // Ensure parent directory exists\n const parentDir = path.dirname(filePath);\n await fs.mkdir(parentDir, { recursive: true });\n\n // Check if file exists (for reporting)\n let isUpdate = false;\n let existingContent: string | undefined;\n try {\n await fs.access(filePath);\n isUpdate = true;\n existingContent = await fs.readFile(filePath, \"utf-8\");\n } catch {\n // File doesn't exist, this is a create\n }\n\n // Add session frontmatter if session context exists and file is markdown\n let contentToWrite = finalContent;\n if (session && filePath.endsWith(\".md\")) {\n if (isUpdate && existingContent) {\n // For updates, preserve existing frontmatter but update session\n const { frontmatter: existing, body } = parseFrontmatter(existingContent);\n // Check if the new content already has frontmatter\n const { frontmatter: newFm, body: newBody } = parseFrontmatter(finalContent);\n if (newFm) {\n // New content has frontmatter, merge with existing\n contentToWrite = addFrontmatter(newBody, {\n ...existing,\n ...newFm,\n session: { ...existing?.session, ...newFm.session, ...session },\n });\n } else {\n // New content has no frontmatter, add session to new content\n contentToWrite = addFrontmatter(finalContent, {\n ...existing,\n session: { ...existing?.session, ...session },\n });\n }\n } else {\n // New file - add frontmatter with session\n const { frontmatter: existingFm, body } = parseFrontmatter(finalContent);\n contentToWrite = addFrontmatter(body, {\n ...existingFm,\n session,\n });\n }\n }\n\n // Write content to file\n await fs.writeFile(filePath, contentToWrite, \"utf-8\");\n\n const relativePath = path.relative(memoryDir, filePath);\n const action = isUpdate ? \"Updated\" : \"Created\";\n console.log(`${action}: ${relativePath}`);\n console.log(` in ${formatPath(memoryDir)}`);\n if (options.session) {\n console.log(` Session: ${options.session}`);\n }\n\n // Try to sync the index (requires embedding provider)\n let minimem: Minimem | null = null;\n\n try {\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: false,\n });\n\n minimem = await Minimem.create(config);\n await minimem.sync();\n console.log(\" Index synced.\");\n } catch {\n // Sync failed, but file was written successfully\n note(\"Index not synced (run 'minimem sync' with API key to index).\");\n } finally {\n minimem?.close();\n }\n}\n\n/**\n * Resolve file path to an absolute path.\n *\n * Simple rules:\n * - Absolute paths are used as-is\n * - Relative paths are relative to memoryDir\n *\n * Examples:\n * MEMORY.md → {memoryDir}/MEMORY.md\n * memory/notes.md → {memoryDir}/memory/notes.md\n * memory/2024/jan.md → {memoryDir}/memory/2024/jan.md\n * /abs/path.md → /abs/path.md\n */\nfunction resolveFilePath(file: string, memoryDir: string): string {\n if (path.isAbsolute(file)) {\n return file;\n }\n return path.join(memoryDir, file);\n}\n\n/**\n * Read content from stdin\n */\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n\n return new Promise((resolve, reject) => {\n process.stdin.on(\"data\", (chunk) => chunks.push(chunk));\n process.stdin.on(\"end\", () => resolve(Buffer.concat(chunks).toString(\"utf-8\")));\n process.stdin.on(\"error\", reject);\n });\n}\n","/**\n * minimem mcp - Run as MCP server (stdio)\n *\n * Supports multiple memory directories for cross-directory search.\n * Auto-initializes global ~/.minimem directory as a fallback.\n */\n\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { Minimem } from \"../../minimem.js\";\nimport { createMcpServer, runMcpServer } from \"../../server/mcp.js\";\nimport type { MemoryInstance } from \"../../server/tools.js\";\nimport {\n resolveMemoryDirs,\n getGlobalMemoryDir,\n getDirName,\n loadConfig,\n buildMinimemConfig,\n isInitialized,\n formatPath,\n getInitConfig,\n saveConfig,\n exitWithError,\n warn,\n note,\n} from \"../config.js\";\n\nexport type McpOptions = {\n dir?: string[];\n global?: boolean;\n provider?: string;\n};\n\nexport async function mcp(options: McpOptions): Promise<void> {\n // Collect all directories (now uses shared implementation)\n const directories = resolveMemoryDirs(options);\n const globalDir = getGlobalMemoryDir();\n\n if (directories.length === 0) {\n exitWithError(\n \"No memory directories specified.\",\n \"Use --dir <path> or --global to specify directories.\"\n );\n }\n\n // Auto-initialize global directory if it will be used\n const includesGlobal = directories.includes(globalDir);\n if (includesGlobal && !(await isInitialized(globalDir))) {\n await ensureGlobalInitialized(globalDir);\n }\n\n // Validate and create instances for each directory\n const instances: MemoryInstance[] = [];\n const minimemInstances: Minimem[] = [];\n\n for (const memoryDir of directories) {\n const isGlobal = memoryDir === globalDir;\n\n if (!(await isInitialized(memoryDir))) {\n // Write to stderr so it doesn't interfere with MCP JSON-RPC\n warn(`${formatPath(memoryDir)} is not initialized, skipping.`);\n\n // If current directory isn't initialized and global isn't already included,\n // add global as a fallback\n if (!isGlobal && !includesGlobal) {\n console.error(` Using global (~/.minimem) as fallback.`);\n if (!(await isInitialized(globalDir))) {\n await ensureGlobalInitialized(globalDir);\n }\n directories.push(globalDir);\n }\n continue;\n }\n\n try {\n const cliConfig = await loadConfig(memoryDir);\n const config = buildMinimemConfig(memoryDir, cliConfig, {\n provider: options.provider,\n watch: true, // Enable watching for MCP server\n });\n\n const minimem = await Minimem.create(config);\n minimemInstances.push(minimem);\n\n // Check if running in BM25-only mode\n const status = await minimem.status();\n if (status.bm25Only && instances.length === 0) {\n // Only warn once\n note(\"Running in BM25-only mode (no embedding API configured).\");\n note(\"Search results will be based on keyword matching only.\");\n }\n\n // Create a friendly name for the directory\n const name = getDirName(memoryDir);\n\n instances.push({\n minimem,\n memoryDir,\n name,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n warn(`Failed to load ${formatPath(memoryDir)}: ${message}`);\n }\n }\n\n if (instances.length === 0) {\n exitWithError(\"No valid memory directories found.\");\n }\n\n // Log which directories are being served (to stderr)\n if (instances.length === 1) {\n console.error(`Serving: ${instances[0].name} (${formatPath(instances[0].memoryDir)})`);\n } else {\n console.error(`Serving ${instances.length} directories:`);\n for (const inst of instances) {\n console.error(` - ${inst.name} (${formatPath(inst.memoryDir)})`);\n }\n }\n\n const server = createMcpServer(instances);\n\n // Handle shutdown gracefully\n const shutdown = () => {\n for (const minimem of minimemInstances) {\n minimem.close();\n }\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Run the MCP server (this blocks)\n await runMcpServer(server);\n}\n\n// resolveDirectories and getDirName are now imported from ../config.js (via shared.ts)\n\n/**\n * Auto-initialize the global memory directory silently\n */\nexport async function ensureGlobalInitialized(globalDir: string): Promise<void> {\n console.error(`Auto-initializing global memory directory (~/.minimem)...`);\n\n // Create directories\n await fs.mkdir(globalDir, { recursive: true });\n await fs.mkdir(path.join(globalDir, \"memory\"), { recursive: true });\n await fs.mkdir(path.join(globalDir, \".minimem\"), { recursive: true });\n\n // Create MEMORY.md\n const memoryFilePath = path.join(globalDir, \"MEMORY.md\");\n try {\n await fs.access(memoryFilePath);\n } catch {\n const template = `# Global Memory\n\nThis is your global memory file. Add notes, decisions, and context here.\n\nNotes stored here are available across all projects.\n\n## Notes\n\n`;\n await fs.writeFile(memoryFilePath, template, \"utf-8\");\n }\n\n // Create config\n const config = getInitConfig();\n await saveConfig(globalDir, config);\n\n // Create .gitignore\n const gitignorePath = path.join(globalDir, \".minimem\", \".gitignore\");\n await fs.writeFile(gitignorePath, \"index.db\\nindex.db-*\\n\", \"utf-8\");\n\n console.error(` Created ~/.minimem with default configuration.`);\n}\n","/**\n * MCP (Model Context Protocol) Server for Minimem\n *\n * Provides memory tools via JSON-RPC 2.0 over stdio.\n * Compatible with Claude Desktop, Cursor, and other MCP clients.\n *\n * Usage:\n * import { Minimem } from \"minimem\";\n * import { createMcpServer, runMcpServer } from \"minimem/mcp\";\n *\n * const minimem = await Minimem.create({ ... });\n * const server = createMcpServer(minimem);\n * await runMcpServer(server); // Runs over stdio\n */\n\nimport * as readline from \"node:readline\";\nimport type { Minimem } from \"../minimem.js\";\nimport {\n MEMORY_TOOLS,\n type ToolDefinition,\n type ToolResult,\n type MemoryInstance,\n MemoryToolExecutor,\n} from \"./tools.js\";\n\nconst PROTOCOL_VERSION = \"2024-11-05\";\nconst SERVER_NAME = \"minimem\";\nconst SERVER_VERSION = \"0.1.0\";\n\n/**\n * JSON-RPC 2.0 request\n */\ntype JsonRpcRequest = {\n jsonrpc: \"2.0\";\n id: string | number;\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * JSON-RPC 2.0 response\n */\ntype JsonRpcResponse = {\n jsonrpc: \"2.0\";\n id: string | number | null;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n};\n\n/**\n * JSON-RPC 2.0 notification (no id)\n */\ntype JsonRpcNotification = {\n jsonrpc: \"2.0\";\n method: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * MCP Server capabilities\n */\ntype ServerCapabilities = {\n tools?: {\n listChanged?: boolean;\n };\n};\n\n/**\n * MCP Server info\n */\ntype ServerInfo = {\n name: string;\n version: string;\n};\n\n/**\n * MCP Initialize result\n */\ntype InitializeResult = {\n protocolVersion: string;\n capabilities: ServerCapabilities;\n serverInfo: ServerInfo;\n};\n\n/**\n * MCP Tool in list format\n */\ntype McpTool = {\n name: string;\n description: string;\n inputSchema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n};\n\n/**\n * MCP Server implementation\n */\nexport class McpServer {\n private executor: MemoryToolExecutor;\n private initialized = false;\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n this.executor = new MemoryToolExecutor(instances);\n }\n\n /**\n * Handle a JSON-RPC request and return a response\n */\n async handleRequest(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n const result = await this.dispatch(request.method, request.params);\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n result,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const code = err instanceof McpError ? err.code : -32603;\n return {\n jsonrpc: \"2.0\",\n id: request.id,\n error: { code, message },\n };\n }\n }\n\n /**\n * Dispatch a method call\n */\n private async dispatch(\n method: string,\n params?: Record<string, unknown>,\n ): Promise<unknown> {\n switch (method) {\n case \"initialize\":\n return this.initialize(params);\n case \"initialized\":\n // Notification, no response needed\n return {};\n case \"tools/list\":\n return this.listTools();\n case \"tools/call\":\n return this.callTool(params);\n case \"ping\":\n return {};\n default:\n throw new McpError(-32601, `Method not found: ${method}`);\n }\n }\n\n /**\n * Handle initialize request\n */\n private initialize(\n params?: Record<string, unknown>,\n ): InitializeResult {\n this.initialized = true;\n return {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: {\n tools: {\n listChanged: false,\n },\n },\n serverInfo: {\n name: SERVER_NAME,\n version: SERVER_VERSION,\n },\n };\n }\n\n /**\n * List available tools\n */\n private listTools(): { tools: McpTool[] } {\n const tools: McpTool[] = MEMORY_TOOLS.map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n }));\n return { tools };\n }\n\n /**\n * Call a tool\n */\n private async callTool(\n params?: Record<string, unknown>,\n ): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> {\n if (!params?.name || typeof params.name !== \"string\") {\n throw new McpError(-32602, \"Missing tool name\");\n }\n\n const toolName = params.name;\n const toolParams = (params.arguments ?? {}) as Record<string, unknown>;\n\n const result = await this.executor.execute(toolName, toolParams);\n return result;\n }\n}\n\n/**\n * Custom error class for MCP errors\n */\nclass McpError extends Error {\n constructor(\n public code: number,\n message: string,\n ) {\n super(message);\n this.name = \"McpError\";\n }\n}\n\n/**\n * Create an MCP server for the given Minimem instance(s)\n */\nexport function createMcpServer(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): McpServer {\n return new McpServer(instances);\n}\n\n/**\n * Run the MCP server over stdio\n */\nexport async function runMcpServer(server: McpServer): Promise<void> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n terminal: false,\n });\n\n const send = (message: JsonRpcResponse | JsonRpcNotification) => {\n const json = JSON.stringify(message);\n process.stdout.write(json + \"\\n\");\n };\n\n rl.on(\"line\", async (line) => {\n if (!line.trim()) return;\n\n try {\n const request = JSON.parse(line) as JsonRpcRequest;\n\n if (request.jsonrpc !== \"2.0\") {\n send({\n jsonrpc: \"2.0\",\n id: request.id ?? null,\n error: { code: -32600, message: \"Invalid JSON-RPC version\" },\n });\n return;\n }\n\n // Handle notification (no id)\n if (request.id === undefined) {\n await server.handleRequest({ ...request, id: 0 });\n return;\n }\n\n const response = await server.handleRequest(request);\n send(response);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n send({\n jsonrpc: \"2.0\",\n id: null,\n error: { code: -32700, message: `Parse error: ${message}` },\n });\n }\n });\n\n rl.on(\"close\", () => {\n process.exit(0);\n });\n\n // Keep the process alive\n await new Promise(() => {});\n}\n\n/**\n * MCP server configuration for claude_desktop_config.json\n *\n * Example:\n * {\n * \"mcpServers\": {\n * \"minimem\": {\n * \"command\": \"node\",\n * \"args\": [\"path/to/your/mcp-server.js\"],\n * \"env\": {\n * \"MEMORY_DIR\": \"/path/to/memory\"\n * }\n * }\n * }\n * }\n */\nexport type McpServerConfig = {\n command: string;\n args: string[];\n env?: Record<string, string>;\n};\n\n/**\n * Generate MCP server config for Claude Desktop\n */\nexport function generateMcpConfig(opts: {\n serverPath: string;\n memoryDir: string;\n embeddingProvider?: \"openai\" | \"gemini\" | \"local\" | \"auto\";\n}): McpServerConfig {\n return {\n command: \"node\",\n args: [opts.serverPath],\n env: {\n MEMORY_DIR: opts.memoryDir,\n ...(opts.embeddingProvider ? { EMBEDDING_PROVIDER: opts.embeddingProvider } : {}),\n },\n };\n}\n","/**\n * Tool definitions for memory operations\n *\n * These tools are compatible with:\n * - MCP (Model Context Protocol)\n * - Anthropic Claude tool use\n * - OpenAI function calling\n *\n * Note: Only memory_search is provided since the memory system is file-based.\n * Agents can use filesystem tools directly for read/write operations.\n */\n\nimport type { Minimem, MinimemSearchResult } from \"../minimem.js\";\n\n/**\n * JSON Schema for tool parameters (MCP/OpenAI/Anthropic compatible)\n */\nexport type ToolInputSchema = {\n type: \"object\";\n properties: Record<\n string,\n {\n type: string;\n description?: string;\n enum?: string[];\n items?: { type: string };\n default?: unknown;\n }\n >;\n required?: string[];\n};\n\n/**\n * Tool definition compatible with MCP, Anthropic, and OpenAI\n */\nexport type ToolDefinition = {\n name: string;\n description: string;\n inputSchema: ToolInputSchema;\n};\n\n/**\n * Tool execution result\n */\nexport type ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n/**\n * Memory search tool parameters\n */\nexport type MemorySearchParams = {\n query: string;\n maxResults?: number;\n minScore?: number;\n directories?: string[];\n /** \"compact\" returns lightweight index; \"full\" returns complete snippets (default: \"compact\") */\n detail?: \"compact\" | \"full\";\n /** Filter by observation type (e.g., \"decision\", \"bugfix\", \"feature\", \"discovery\") */\n type?: string;\n};\n\n/**\n * Memory get details tool parameters\n */\nexport type MemoryGetDetailsParams = {\n results: Array<{ path: string; startLine: number; endLine: number }>;\n directories?: string[];\n};\n\n/**\n * Knowledge search tool parameters\n */\nexport type KnowledgeSearchParams = {\n query: string;\n domain?: string[];\n entities?: string[];\n minConfidence?: number;\n knowledgeType?: string;\n maxResults?: number;\n minScore?: number;\n directories?: string[];\n};\n\n/**\n * Knowledge graph traversal parameters\n */\nexport type KnowledgeGraphParams = {\n nodeId: string;\n depth?: number;\n relation?: string;\n layer?: string;\n directories?: string[];\n};\n\n/**\n * Knowledge path parameters\n */\nexport type KnowledgePathParams = {\n fromId: string;\n toId: string;\n maxDepth?: number;\n directories?: string[];\n};\n\n/**\n * Search result with source directory\n */\ntype SearchResultWithSource = MinimemSearchResult & {\n memoryDir: string;\n};\n\nexport const MEMORY_SEARCH_TOOL: ToolDefinition = {\n name: \"memory_search\",\n description:\n \"Semantically search through memory files (MEMORY.md and memory/*.md). \" +\n \"Use this to recall prior decisions, facts, preferences, people, dates, or context. \" +\n \"Returns ranked snippets with file paths and line numbers. \" +\n \"When multiple memory directories are configured, searches all by default.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Natural language search query\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return (default: 10)\",\n },\n minScore: {\n type: \"number\",\n description: \"Minimum relevance score threshold 0-1 (default: 0.3)\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Optional: filter to specific memory directories by name/path. \" +\n \"If omitted, searches all configured directories.\",\n },\n detail: {\n type: \"string\",\n enum: [\"compact\", \"full\"],\n description:\n \"Result detail level. 'compact' returns a lightweight index with short previews (~80 chars). \" +\n \"'full' returns complete snippets. Use 'compact' first, then memory_get_details for selected results. \" +\n \"(default: 'compact')\",\n },\n type: {\n type: \"string\",\n description:\n \"Filter by observation type. Matches <!-- type: X --> comments in memory entries. \" +\n \"Common types: decision, bugfix, feature, discovery, context, note.\",\n },\n },\n required: [\"query\"],\n },\n};\n\nexport const MEMORY_GET_DETAILS_TOOL: ToolDefinition = {\n name: \"memory_get_details\",\n description:\n \"Fetch full text for specific memory chunks identified by path and line range. \" +\n \"Use after memory_search with compact results to get details for selected items only. \" +\n \"This two-step approach significantly reduces token usage.\",\n inputSchema: {\n type: \"object\",\n properties: {\n results: {\n type: \"array\",\n items: { type: \"object\" },\n description:\n \"Array of { path, startLine, endLine } objects from compact search results.\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories.\",\n },\n },\n required: [\"results\"],\n },\n};\n\nexport const KNOWLEDGE_SEARCH_TOOL: ToolDefinition = {\n name: \"knowledge_search\",\n description:\n \"Search memory with knowledge metadata filters. \" +\n \"Filter by domain, entities, confidence level, or knowledge type (observation, entity, domain-summary). \" +\n \"Combines semantic search with structured knowledge filtering.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: {\n type: \"string\",\n description: \"Natural language search query\",\n },\n domain: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Filter to entries in these knowledge domains\",\n },\n entities: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Filter to entries referencing these entities\",\n },\n minConfidence: {\n type: \"number\",\n description: \"Minimum confidence threshold (0-1)\",\n },\n knowledgeType: {\n type: \"string\",\n description: \"Filter by knowledge type: observation, entity, domain-summary\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results (default: 10)\",\n },\n minScore: {\n type: \"number\",\n description: \"Minimum relevance score 0-1 (default: 0.3)\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories\",\n },\n },\n required: [\"query\"],\n },\n};\n\nexport const KNOWLEDGE_GRAPH_TOOL: ToolDefinition = {\n name: \"knowledge_graph\",\n description:\n \"Traverse knowledge graph links from a note. \" +\n \"Returns neighbor nodes connected by typed relationships (e.g., relates-to, supports, contradicts). \" +\n \"Use depth parameter for multi-hop traversal.\",\n inputSchema: {\n type: \"object\",\n properties: {\n nodeId: {\n type: \"string\",\n description: \"The knowledge node ID to start traversal from\",\n },\n depth: {\n type: \"number\",\n description: \"Maximum traversal depth (default: 1, max: 3)\",\n default: 1,\n },\n relation: {\n type: \"string\",\n description: \"Optional: filter to specific relation type\",\n },\n layer: {\n type: \"string\",\n description: \"Optional: filter to specific graph layer\",\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories\",\n },\n },\n required: [\"nodeId\"],\n },\n};\n\nexport const KNOWLEDGE_PATH_TOOL: ToolDefinition = {\n name: \"knowledge_path\",\n description:\n \"Find the shortest path between two knowledge nodes in the graph. \" +\n \"Uses BFS traversal up to a configurable max depth. \" +\n \"Returns the sequence of links connecting the two nodes.\",\n inputSchema: {\n type: \"object\",\n properties: {\n fromId: {\n type: \"string\",\n description: \"Starting knowledge node ID\",\n },\n toId: {\n type: \"string\",\n description: \"Target knowledge node ID\",\n },\n maxDepth: {\n type: \"number\",\n description: \"Maximum path length (default: 3)\",\n default: 3,\n },\n directories: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional: filter to specific memory directories\",\n },\n },\n required: [\"fromId\", \"toId\"],\n },\n};\n\n/**\n * All available memory tools\n */\nexport const MEMORY_TOOLS: ToolDefinition[] = [\n MEMORY_SEARCH_TOOL,\n MEMORY_GET_DETAILS_TOOL,\n KNOWLEDGE_SEARCH_TOOL,\n KNOWLEDGE_GRAPH_TOOL,\n KNOWLEDGE_PATH_TOOL,\n];\n\n/**\n * Get tool definitions for use with LLM APIs\n */\nexport function getToolDefinitions(): ToolDefinition[] {\n return MEMORY_TOOLS;\n}\n\n/**\n * Memory instance with its directory path\n */\nexport type MemoryInstance = {\n minimem: Minimem;\n memoryDir: string;\n name?: string;\n};\n\n/**\n * Tool executor that handles memory search across multiple directories\n */\nexport class MemoryToolExecutor {\n private instances: MemoryInstance[];\n\n constructor(instances: Minimem | MemoryInstance | MemoryInstance[]) {\n // Normalize to array of MemoryInstance\n if (Array.isArray(instances)) {\n this.instances = instances;\n } else if (\"minimem\" in instances) {\n this.instances = [instances];\n } else {\n // Legacy: single Minimem instance without directory info\n this.instances = [{ minimem: instances, memoryDir: \"default\" }];\n }\n }\n\n /**\n * Get list of configured directory names/paths\n */\n getDirectories(): string[] {\n return this.instances.map((i) => i.name ?? i.memoryDir);\n }\n\n /**\n * Execute a tool by name with given parameters\n */\n async execute(\n toolName: string,\n params: Record<string, unknown>,\n ): Promise<ToolResult> {\n try {\n switch (toolName) {\n case \"memory_search\":\n return await this.memorySearch(params as MemorySearchParams);\n case \"memory_get_details\":\n return await this.memoryGetDetails(params as MemoryGetDetailsParams);\n case \"knowledge_search\":\n return await this.knowledgeSearch(params as KnowledgeSearchParams);\n case \"knowledge_graph\":\n return await this.knowledgeGraph(params as KnowledgeGraphParams);\n case \"knowledge_path\":\n return await this.knowledgePath(params as KnowledgePathParams);\n default:\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${toolName}` }],\n isError: true,\n };\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: \"text\", text: `Error: ${message}` }],\n isError: true,\n };\n }\n }\n\n /**\n * Filter instances by directory names/paths\n */\n private filterInstances(directories?: string[]): MemoryInstance[] | null {\n if (!directories || directories.length === 0) return this.instances;\n\n const dirFilter = new Set(directories.map((d) => d.toLowerCase()));\n const filtered = this.instances.filter((i) => {\n const name = (i.name ?? i.memoryDir).toLowerCase();\n const dir = i.memoryDir.toLowerCase();\n return (\n dirFilter.has(name) ||\n dirFilter.has(dir) ||\n [...dirFilter].some((f) => dir.includes(f) || name.includes(f))\n );\n });\n\n return filtered.length > 0 ? filtered : null;\n }\n\n private async memorySearch(params: MemorySearchParams): Promise<ToolResult> {\n const maxResults = params.maxResults ?? 10;\n const minScore = params.minScore;\n const detail = params.detail ?? \"compact\";\n\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [\n {\n type: \"text\",\n text: `No matching directories found. Available: ${available}`,\n },\n ],\n isError: true,\n };\n }\n\n // Search all matching instances\n const allResults: SearchResultWithSource[] = [];\n\n for (const instance of instancesToSearch) {\n const perDirMax = Math.ceil(maxResults * 1.5);\n const results = await instance.minimem.search(params.query, {\n maxResults: perDirMax,\n minScore,\n type: params.type,\n });\n\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n // Sort by score and limit\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No results found.\" }],\n };\n }\n\n const showSource = instancesToSearch.length > 1;\n\n if (detail === \"compact\") {\n return this.formatCompactResults(topResults, showSource, instancesToSearch.length);\n }\n\n return this.formatFullResults(topResults, showSource, instancesToSearch.length);\n }\n\n private formatCompactResults(\n results: SearchResultWithSource[],\n showSource: boolean,\n dirCount: number,\n ): ToolResult {\n const formatted = results\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(0);\n const source = showSource ? ` [${r.memoryDir}]` : \"\";\n const preview = compactPreview(r.snippet);\n return `[${i}] ${location}${source} (${score}%) — ${preview}`;\n })\n .join(\"\\n\");\n\n const hint = \"\\n\\nUse memory_get_details to fetch full text for selected results.\";\n const dirSummary = dirCount > 1 ? `\\n(Searched ${dirCount} directories)` : \"\";\n\n return {\n content: [{ type: \"text\", text: formatted + dirSummary + hint }],\n };\n }\n\n private formatFullResults(\n results: SearchResultWithSource[],\n showSource: boolean,\n dirCount: number,\n ): ToolResult {\n const formatted = results\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(1);\n const source = showSource ? ` [${r.memoryDir}]` : \"\";\n return `[${i + 1}] ${location}${source} (${score}% match)\\n${r.snippet}`;\n })\n .join(\"\\n\\n\");\n\n const dirSummary =\n dirCount > 1 ? `\\n\\n(Searched ${dirCount} directories)` : \"\";\n\n return {\n content: [{ type: \"text\", text: formatted + dirSummary }],\n };\n }\n\n private async memoryGetDetails(params: MemoryGetDetailsParams): Promise<ToolResult> {\n if (!params.results || params.results.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No results specified.\" }],\n isError: true,\n };\n }\n\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [\n {\n type: \"text\",\n text: `No matching directories found. Available: ${available}`,\n },\n ],\n isError: true,\n };\n }\n\n const details: string[] = [];\n\n for (const ref of params.results) {\n let found = false;\n\n for (const instance of instancesToSearch) {\n const lineCount = ref.endLine - ref.startLine + 1;\n const result = await instance.minimem.readLines(ref.path, {\n from: ref.startLine,\n lines: lineCount,\n });\n\n if (result) {\n const location = `${ref.path}:${result.startLine}-${result.endLine}`;\n details.push(`--- ${location} ---\\n${result.content}`);\n found = true;\n break;\n }\n }\n\n if (!found) {\n details.push(`--- ${ref.path}:${ref.startLine}-${ref.endLine} ---\\n(not found)`);\n }\n }\n\n return {\n content: [{ type: \"text\", text: details.join(\"\\n\\n\") }],\n };\n }\n\n private async knowledgeSearch(params: KnowledgeSearchParams): Promise<ToolResult> {\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [{ type: \"text\", text: `No matching directories found. Available: ${available}` }],\n isError: true,\n };\n }\n\n const maxResults = params.maxResults ?? 10;\n const allResults: SearchResultWithSource[] = [];\n\n for (const instance of instancesToSearch) {\n const results = await instance.minimem.knowledgeSearch(params.query, {\n maxResults: Math.ceil(maxResults * 1.5),\n minScore: params.minScore,\n domain: params.domain,\n entities: params.entities,\n minConfidence: params.minConfidence,\n knowledgeType: params.knowledgeType,\n });\n\n for (const result of results) {\n allResults.push({\n ...result,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n allResults.sort((a, b) => b.score - a.score);\n const topResults = allResults.slice(0, maxResults);\n\n if (topResults.length === 0) {\n return { content: [{ type: \"text\", text: \"No knowledge results found.\" }] };\n }\n\n const formatted = topResults\n .map((r, i) => {\n const location = `${r.path}:${r.startLine}-${r.endLine}`;\n const score = (r.score * 100).toFixed(0);\n const preview = compactPreview(r.snippet);\n return `[${i}] ${location} (${score}%) — ${preview}`;\n })\n .join(\"\\n\");\n\n return { content: [{ type: \"text\", text: formatted }] };\n }\n\n private async knowledgeGraph(params: KnowledgeGraphParams): Promise<ToolResult> {\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [{ type: \"text\", text: `No matching directories found. Available: ${available}` }],\n isError: true,\n };\n }\n\n const depth = Math.min(params.depth ?? 1, 3);\n const allNeighbors: Array<{ id: string; depth: number; relation: string; layer: string | null; memoryDir: string }> = [];\n\n for (const instance of instancesToSearch) {\n const neighbors = instance.minimem.getGraphNeighbors(params.nodeId, depth, {\n relation: params.relation,\n layer: params.layer,\n });\n\n for (const n of neighbors) {\n allNeighbors.push({\n id: n.id,\n depth: n.depth,\n relation: n.link.relation,\n layer: n.link.layer,\n memoryDir: instance.name ?? instance.memoryDir,\n });\n }\n }\n\n if (allNeighbors.length === 0) {\n return { content: [{ type: \"text\", text: `No neighbors found for node \"${params.nodeId}\".` }] };\n }\n\n const formatted = allNeighbors\n .map((n) => ` [depth=${n.depth}] ${n.id} —(${n.relation})${n.layer ? ` [${n.layer}]` : \"\"}`)\n .join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: `Neighbors of \"${params.nodeId}\":\\n${formatted}` }],\n };\n }\n\n private async knowledgePath(params: KnowledgePathParams): Promise<ToolResult> {\n const instancesToSearch = this.filterInstances(params.directories);\n if (!instancesToSearch) {\n const available = this.getDirectories().join(\", \");\n return {\n content: [{ type: \"text\", text: `No matching directories found. Available: ${available}` }],\n isError: true,\n };\n }\n\n const maxDepth = Math.min(params.maxDepth ?? 3, 5);\n\n // Try each instance until a path is found\n for (const instance of instancesToSearch) {\n const path = instance.minimem.getGraphPath(params.fromId, params.toId, maxDepth);\n if (path.length > 0) {\n const steps = path\n .map((link) => ` ${link.fromId} —(${link.relation})→ ${link.toId}`)\n .join(\"\\n\");\n return {\n content: [{\n type: \"text\",\n text: `Path from \"${params.fromId}\" to \"${params.toId}\" (${path.length} steps):\\n${steps}`,\n }],\n };\n }\n }\n\n return {\n content: [{\n type: \"text\",\n text: `No path found from \"${params.fromId}\" to \"${params.toId}\" within depth ${maxDepth}.`,\n }],\n };\n }\n}\n\n/**\n * Generate a compact preview from a snippet (~80 chars).\n * Prefers the first heading or first non-empty line.\n */\nfunction compactPreview(snippet: string): string {\n const maxLen = 80;\n const lines = snippet.split(\"\\n\").filter((l) => l.trim());\n if (lines.length === 0) return \"(empty)\";\n\n // Prefer a heading line\n const heading = lines.find((l) => l.startsWith(\"#\"));\n const text = heading ?? lines[0];\n // Strip markdown heading markers for cleaner display\n const cleaned = text.replace(/^#+\\s*/, \"\").trim();\n\n if (cleaned.length <= maxLen) return `\"${cleaned}\"`;\n return `\"${cleaned.slice(0, maxLen - 3)}...\"`;\n}\n\n/**\n * Create a tool executor for the given Minimem instance(s)\n */\nexport function createToolExecutor(\n instances: Minimem | MemoryInstance | MemoryInstance[],\n): MemoryToolExecutor {\n return new MemoryToolExecutor(instances);\n}\n","/**\n * minimem config - View and manage configuration\n */\n\nimport {\n resolveMemoryDir,\n exitWithError,\n loadConfig,\n loadGlobalConfig,\n loadXdgConfig,\n saveConfig,\n saveXdgConfig,\n getConfigPath,\n getGlobalConfigPath,\n getXdgConfigPath,\n mergeConfig,\n getDefaultConfig,\n getSyncConfig,\n isInitialized,\n formatPath,\n type CliConfig,\n type GlobalConfig,\n} from \"../config.js\";\n\nexport type ConfigOptions = {\n dir?: string;\n global?: boolean;\n xdgGlobal?: boolean;\n json?: boolean;\n set?: string;\n unset?: string;\n};\n\nexport async function config(options: ConfigOptions): Promise<void> {\n // Handle --set and --unset\n if (options.set || options.unset) {\n await handleConfigEdit(options);\n return;\n }\n\n // Show config\n await showConfig(options);\n}\n\nasync function showConfig(options: ConfigOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n // Load configs\n const globalConfig = await loadGlobalConfig();\n const xdgConfig = await loadXdgConfig();\n const localConfig = await loadConfig(memoryDir);\n const mergedConfig = mergeConfig(localConfig);\n const syncConfig = await getSyncConfig(memoryDir);\n const defaults = getDefaultConfig();\n\n if (options.json) {\n console.log(JSON.stringify({\n effective: mergedConfig,\n local: localConfig,\n global: globalConfig,\n xdgGlobal: xdgConfig,\n syncConfig,\n defaults,\n }, null, 2));\n return;\n }\n\n console.log(\"Minimem Configuration\");\n console.log(\"=====================\");\n console.log();\n\n console.log(\"Config Files:\");\n console.log(` XDG Global: ${formatPath(getXdgConfigPath())}`);\n console.log(` Legacy Global: ${formatPath(getGlobalConfigPath())}`);\n console.log(` Local: ${formatPath(getConfigPath(memoryDir))}`);\n console.log();\n\n console.log(\"Effective Configuration:\");\n console.log(\"(merged from defaults → xdg global → legacy global → local)\");\n console.log();\n\n printConfigSection(\"Embedding\", {\n \"provider\": mergedConfig.embedding?.provider,\n \"model\": mergedConfig.embedding?.model || \"(provider default)\",\n \"fallback\": mergedConfig.embedding?.fallback || \"none\",\n });\n\n printConfigSection(\"Hybrid Search\", {\n \"enabled\": mergedConfig.hybrid?.enabled,\n \"vectorWeight\": mergedConfig.hybrid?.vectorWeight,\n \"textWeight\": mergedConfig.hybrid?.textWeight,\n });\n\n printConfigSection(\"Query Defaults\", {\n \"maxResults\": mergedConfig.query?.maxResults,\n \"minScore\": mergedConfig.query?.minScore,\n });\n\n printConfigSection(\"Chunking\", {\n \"tokens\": mergedConfig.chunking?.tokens,\n \"overlap\": mergedConfig.chunking?.overlap,\n });\n\n printConfigSection(\"Sync (Local)\", {\n \"enabled\": syncConfig.enabled,\n \"path\": syncConfig.path || \"(not configured)\",\n \"include\": syncConfig.include.join(\", \"),\n \"exclude\": syncConfig.exclude.length > 0 ? syncConfig.exclude.join(\", \") : \"(none)\",\n });\n\n printConfigSection(\"Sync (Global)\", {\n \"centralRepo\": syncConfig.centralRepo || \"(not configured)\",\n \"conflictStrategy\": syncConfig.conflictStrategy,\n \"autoSync\": syncConfig.autoSync,\n \"autoCommit\": syncConfig.autoCommit,\n \"mergeResolver\": syncConfig.mergeResolver || \"(default)\",\n });\n\n console.log();\n console.log(\"To modify configuration:\");\n console.log(\" minimem config --set embedding.provider=openai\");\n console.log(\" minimem config --set sync.enabled=true\");\n console.log(\" minimem config --set sync.path=myproject/\");\n console.log();\n console.log(\"Global sync settings (use --xdg-global flag):\");\n console.log(\" minimem config --xdg-global --set centralRepo=~/memories-repo\");\n console.log(\" minimem config --xdg-global --set sync.conflictStrategy=merge\");\n}\n\nfunction printConfigSection(title: string, values: Record<string, unknown>): void {\n console.log(` ${title}:`);\n for (const [key, value] of Object.entries(values)) {\n const displayValue = value === undefined ? \"(default)\" : String(value);\n console.log(` ${key}: ${displayValue}`);\n }\n}\n\nasync function handleConfigEdit(options: ConfigOptions): Promise<void> {\n // Handle XDG global config edits\n if (options.xdgGlobal) {\n await handleXdgConfigEdit(options);\n return;\n }\n\n const memoryDir = resolveMemoryDir({ dir: options.dir, global: options.global });\n const configPath = getConfigPath(memoryDir);\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n // Load current config (just the local file, not merged)\n const currentConfig = await loadConfigFile(configPath);\n\n if (options.set) {\n const [keyPath, value] = options.set.split(\"=\");\n if (!keyPath || value === undefined) {\n exitWithError(\n \"--set requires format: key.path=value\",\n \"Example: --set embedding.provider=openai\"\n );\n }\n\n const newConfig = setConfigValue(currentConfig, keyPath, parseValue(value));\n await saveConfig(memoryDir, newConfig);\n console.log(`Set ${keyPath}=${value} in ${formatPath(configPath)}`);\n }\n\n if (options.unset) {\n const keyPath = options.unset;\n const newConfig = unsetConfigValue(currentConfig, keyPath);\n await saveConfig(memoryDir, newConfig);\n console.log(`Unset ${keyPath} in ${formatPath(configPath)}`);\n }\n}\n\nasync function handleXdgConfigEdit(options: ConfigOptions): Promise<void> {\n const configPath = getXdgConfigPath();\n const currentConfig = await loadXdgConfig();\n\n if (options.set) {\n const [keyPath, value] = options.set.split(\"=\");\n if (!keyPath || value === undefined) {\n exitWithError(\n \"--set requires format: key.path=value\",\n \"Example: --set centralRepo=~/memories-repo\"\n );\n }\n\n const newConfig = setConfigValue(currentConfig as Record<string, unknown>, keyPath, parseValue(value)) as GlobalConfig;\n await saveXdgConfig(newConfig);\n console.log(`Set ${keyPath}=${value} in ${formatPath(configPath)}`);\n }\n\n if (options.unset) {\n const keyPath = options.unset;\n const newConfig = unsetConfigValue(currentConfig as Record<string, unknown>, keyPath) as GlobalConfig;\n await saveXdgConfig(newConfig);\n console.log(`Unset ${keyPath} in ${formatPath(configPath)}`);\n }\n}\n\nasync function loadConfigFile(configPath: string): Promise<CliConfig> {\n const fs = await import(\"node:fs/promises\");\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n return JSON.parse(content) as CliConfig;\n } catch {\n return {};\n }\n}\n\nfunction parseValue(value: string): unknown {\n // Try to parse as JSON (for booleans, numbers, etc.)\n try {\n return JSON.parse(value);\n } catch {\n // Return as string\n return value;\n }\n}\n\nfunction setConfigValue<T extends Record<string, unknown>>(config: T, keyPath: string, value: unknown): T {\n const parts = keyPath.split(\".\");\n const result = { ...config } as Record<string, unknown>;\n let current: Record<string, unknown> = result;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n if (!(key in current) || typeof current[key] !== \"object\") {\n current[key] = {};\n } else {\n current[key] = { ...(current[key] as Record<string, unknown>) };\n }\n current = current[key] as Record<string, unknown>;\n }\n\n current[parts[parts.length - 1]] = value;\n return result as T;\n}\n\nfunction unsetConfigValue<T extends Record<string, unknown>>(config: T, keyPath: string): T {\n const parts = keyPath.split(\".\");\n const result = { ...config } as Record<string, unknown>;\n let current: Record<string, unknown> = result;\n\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n if (!(key in current) || typeof current[key] !== \"object\") {\n return result as T; // Path doesn't exist\n }\n current[key] = { ...(current[key] as Record<string, unknown>) };\n current = current[key] as Record<string, unknown>;\n }\n\n delete current[parts[parts.length - 1]];\n return result as T;\n}\n","/**\n * minimem sync init - Initialize sync for a memory directory\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport {\n resolveMemoryDir,\n loadConfig,\n saveConfig,\n isInitialized,\n formatPath,\n getMachineId,\n expandPath,\n getDefaultSyncConfig,\n exitWithError,\n} from \"../config.js\";\nimport {\n getCentralRepoPath,\n initCentralRepo,\n validateCentralRepo,\n} from \"../sync/central.js\";\nimport {\n readRegistry,\n writeRegistry,\n checkCollision,\n addMapping,\n} from \"../sync/registry.js\";\nimport { detectDirectoryType } from \"../sync/detection.js\";\n\nexport type SyncInitOptions = {\n /** Memory directory to initialize sync for */\n local?: string;\n /** Path in central repo */\n path?: string;\n /** Use global ~/.minimem directory */\n global?: boolean;\n};\n\nexport type SyncInitCentralOptions = {\n /** Force creation even if directory exists */\n force?: boolean;\n};\n\n/**\n * Initialize a central repository\n */\nexport async function syncInitCentral(\n repoPath: string,\n options: SyncInitCentralOptions = {}\n): Promise<void> {\n console.log(`Initializing central repository at ${formatPath(repoPath)}...`);\n\n const result = await initCentralRepo(repoPath);\n\n if (!result.success) {\n exitWithError(result.message);\n }\n\n if (result.created) {\n console.log(\" Created new git repository\");\n console.log(\" Created .gitignore\");\n console.log(\" Created .minimem-registry.json\");\n console.log(\" Created README.md\");\n } else {\n console.log(\" Configured existing directory\");\n }\n\n console.log();\n console.log(\"Central repository is ready!\");\n console.log(`Set as centralRepo in ~/.config/minimem/config.json`);\n console.log();\n console.log(\"Next steps:\");\n console.log(\" 1. Initialize sync for a memory directory:\");\n console.log(\" minimem sync init --path myproject/\");\n console.log();\n console.log(\" 2. Or from a different directory:\");\n console.log(\" minimem sync init --local ~/my-memories --path mymemories/\");\n}\n\n/**\n * Initialize sync for a memory directory\n */\nexport async function syncInit(options: SyncInitOptions): Promise<void> {\n // Resolve the memory directory\n const memoryDir = resolveMemoryDir({\n dir: options.local,\n global: options.global,\n });\n\n // Check if initialized\n if (!(await isInitialized(memoryDir))) {\n exitWithError(\n `${formatPath(memoryDir)} is not initialized.`,\n \"Run 'minimem init' first.\"\n );\n }\n\n // Check if --path is provided\n if (!options.path) {\n exitWithError(\n \"--path is required.\",\n \"Example: minimem sync init --path myproject/\"\n );\n }\n\n const centralPath = options.path;\n\n // Get central repo\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n exitWithError(\n \"No central repository configured.\",\n \"First initialize a central repository: minimem sync init-central ~/memories-repo\"\n );\n }\n\n // Validate central repo\n const validation = await validateCentralRepo(centralRepo);\n if (!validation.valid) {\n exitWithError(\n `Central repository is invalid: ${validation.errors.join(\", \")}`\n );\n }\n\n if (validation.warnings.length > 0) {\n console.log(\"Warnings about central repository:\");\n for (const warning of validation.warnings) {\n console.log(` - ${warning}`);\n }\n console.log();\n }\n\n // Get machine ID\n const machineId = await getMachineId();\n\n // Check for collisions\n const registry = await readRegistry(centralRepo);\n const collisionResult = checkCollision(registry, centralPath, memoryDir, machineId);\n\n if (collisionResult === \"collision\") {\n const existingMapping = registry.mappings.find(\n (m) => m.path === centralPath || m.path === `${centralPath}/`\n );\n let details = `Path '${centralPath}' is already mapped by another machine.`;\n if (existingMapping) {\n details += ` Machine: ${existingMapping.machineId}, Local: ${existingMapping.localPath}`;\n }\n exitWithError(details, \"Choose a different path or remove the existing mapping.\");\n }\n\n // Detect directory type\n const dirType = await detectDirectoryType(memoryDir);\n\n console.log(`Initializing sync for ${formatPath(memoryDir)}...`);\n console.log(` Directory type: ${dirType}`);\n console.log(` Central path: ${centralPath}`);\n console.log(` Machine ID: ${machineId}`);\n console.log();\n\n // Update local config\n const localConfig = await loadConfig(memoryDir);\n const syncDefaults = getDefaultSyncConfig();\n\n localConfig.sync = {\n enabled: true,\n path: centralPath,\n include: localConfig.sync?.include ?? syncDefaults.include,\n exclude: localConfig.sync?.exclude ?? syncDefaults.exclude,\n };\n\n await saveConfig(memoryDir, localConfig);\n console.log(\" Updated .minimem/config.json with sync settings\");\n\n // Update registry\n const updatedRegistry = addMapping(registry, {\n path: centralPath,\n localPath: memoryDir,\n machineId,\n lastSync: new Date().toISOString(),\n });\n\n await writeRegistry(centralRepo, updatedRegistry);\n console.log(\" Registered mapping in central repository\");\n\n // Create central path directory if it doesn't exist\n const centralDir = path.join(centralRepo, centralPath);\n try {\n await fs.mkdir(centralDir, { recursive: true });\n } catch {\n // Directory might already exist\n }\n\n console.log();\n console.log(\"Sync initialized successfully!\");\n console.log();\n console.log(\"Next steps:\");\n console.log(\" Push local files to central:\");\n console.log(\" minimem push\");\n console.log();\n console.log(\" Or pull from central:\");\n console.log(\" minimem pull\");\n}\n\n/**\n * List all sync mappings\n */\nexport async function syncList(): Promise<void> {\n const centralRepo = await getCentralRepoPath();\n\n if (!centralRepo) {\n console.log(\"No central repository configured.\");\n console.log(\"Run: minimem sync init-central <path>\");\n return;\n }\n\n const machineId = await getMachineId();\n const registry = await readRegistry(centralRepo);\n\n console.log(`Central Repository: ${formatPath(centralRepo)}`);\n console.log(`Machine ID: ${machineId}`);\n console.log();\n\n if (registry.mappings.length === 0) {\n console.log(\"No sync mappings registered.\");\n console.log(\"Run: minimem sync init --path <name>/\");\n return;\n }\n\n console.log(\"Registered Mappings:\");\n console.log(\"-\".repeat(80));\n\n for (const mapping of registry.mappings) {\n const isCurrentMachine = mapping.machineId === machineId;\n const marker = isCurrentMachine ? \" *\" : \" \";\n const lastSync = new Date(mapping.lastSync).toLocaleString();\n\n console.log(`${marker}Path: ${mapping.path}`);\n console.log(` Local: ${mapping.localPath}`);\n console.log(` Machine: ${mapping.machineId}`);\n console.log(` Last Sync: ${lastSync}`);\n console.log();\n }\n\n console.log(\"* = this machine\");\n}\n\n/**\n * Remove sync mapping for a directory\n */\nexport async function syncRemove(options: { local?: string; global?: boolean }): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.local,\n global: options.global,\n });\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n exitWithError(\"No central repository configured.\");\n }\n\n const localConfig = await loadConfig(memoryDir);\n if (!localConfig.sync?.path) {\n exitWithError(`${formatPath(memoryDir)} is not configured for sync.`);\n }\n\n const centralPath = localConfig.sync.path;\n const machineId = await getMachineId();\n\n // Update local config\n delete localConfig.sync;\n await saveConfig(memoryDir, localConfig);\n console.log(`Removed sync config from ${formatPath(memoryDir)}`);\n\n // Update registry\n const registry = await readRegistry(centralRepo);\n const updatedRegistry = {\n ...registry,\n mappings: registry.mappings.filter(\n (m) => !(m.path === centralPath && m.machineId === machineId)\n ),\n };\n await writeRegistry(centralRepo, updatedRegistry);\n console.log(`Removed mapping from central registry`);\n\n console.log();\n console.log(\"Note: Files in the central repository were NOT deleted.\");\n console.log(`They remain at: ${formatPath(path.join(centralRepo, centralPath))}`);\n}\n","/**\n * Central repository initialization and management\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { execSync } from \"node:child_process\";\n\nimport { expandPath, saveXdgConfig, loadXdgConfig } from \"../config.js\";\nimport {\n createEmptyRegistry,\n writeRegistry,\n readRegistry,\n getRegistryPath,\n} from \"./registry.js\";\nimport { isInsideGitRepo } from \"./detection.js\";\n\nconst GITIGNORE_CONTENT = `# Minimem sync - ignore database files and temp directories\n*.db\n*.db-journal\n*.db-wal\n*.db-shm\nstaging/\nconflicts/\nshadows/\n.DS_Store\n`;\n\nconst README_CONTENT = `# Minimem Central Repository\n\nThis repository contains synchronized memory files from minimem.\n\n## Structure\n\nEach directory represents a mapped memory location:\n\n\\`\\`\\`\nmemories-repo/\n├── global/ # ~/.minimem/\n├── work/ # ~/work/memories/\n└── projects/\n └── myproject/ # ~/projects/myproject/\n\\`\\`\\`\n\n## Registry\n\nThe \\`.minimem-registry.json\\` file tracks which local directories are mapped to which paths.\nThis prevents path collisions when multiple machines sync to the same repository.\n\n## Usage\n\nTo sync a local memory directory to this repo:\n\n\\`\\`\\`bash\nminimem config --xdg-global --set centralRepo=<path-to-this-repo>\nminimem sync init --path <directory-name>/\n\\`\\`\\`\n\n## Files\n\n- \\`.minimem-registry.json\\` - Tracks sync mappings\n- \\`.gitignore\\` - Ignores database and temp files\n- \\`*/MEMORY.md\\` - Main memory files\n- \\`*/memory/*.md\\` - Additional memory files\n`;\n\nexport type InitCentralResult = {\n success: boolean;\n path: string;\n created: boolean;\n message: string;\n};\n\n/**\n * Check if a path is writable\n */\nasync function isWritable(dirPath: string): Promise<boolean> {\n try {\n const testFile = path.join(dirPath, `.minimem-write-test-${Date.now()}`);\n await fs.writeFile(testFile, \"test\");\n await fs.unlink(testFile);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if git is available\n */\nfunction isGitAvailable(): boolean {\n try {\n execSync(\"git --version\", { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Initialize a git repository\n */\nasync function initGitRepo(dirPath: string): Promise<void> {\n execSync(\"git init\", { cwd: dirPath, stdio: \"pipe\" });\n}\n\n/**\n * Initialize a new central repository or configure an existing one\n */\nexport async function initCentralRepo(\n repoPath: string\n): Promise<InitCentralResult> {\n const expandedPath = expandPath(repoPath);\n const resolvedPath = path.resolve(expandedPath);\n\n // Check if git is available\n if (!isGitAvailable()) {\n return {\n success: false,\n path: resolvedPath,\n created: false,\n message: \"Git is not installed or not available in PATH\",\n };\n }\n\n // Check if directory exists\n let dirExists = false;\n try {\n const stat = await fs.stat(resolvedPath);\n dirExists = stat.isDirectory();\n } catch {\n dirExists = false;\n }\n\n let created = false;\n\n if (!dirExists) {\n // Create new directory\n try {\n await fs.mkdir(resolvedPath, { recursive: true });\n created = true;\n } catch (error) {\n return {\n success: false,\n path: resolvedPath,\n created: false,\n message: `Failed to create directory: ${error}`,\n };\n }\n }\n\n // Check if writable\n if (!(await isWritable(resolvedPath))) {\n return {\n success: false,\n path: resolvedPath,\n created,\n message: \"Directory is not writable\",\n };\n }\n\n // Initialize git repo if not already\n const isGitRepo = await isInsideGitRepo(resolvedPath);\n if (!isGitRepo) {\n try {\n await initGitRepo(resolvedPath);\n } catch (error) {\n return {\n success: false,\n path: resolvedPath,\n created,\n message: `Failed to initialize git repository: ${error}`,\n };\n }\n }\n\n // Create .gitignore if not exists\n const gitignorePath = path.join(resolvedPath, \".gitignore\");\n try {\n await fs.access(gitignorePath);\n } catch {\n await fs.writeFile(gitignorePath, GITIGNORE_CONTENT, \"utf-8\");\n }\n\n // Create registry if not exists\n const registryPath = getRegistryPath(resolvedPath);\n try {\n await fs.access(registryPath);\n } catch {\n await writeRegistry(resolvedPath, createEmptyRegistry());\n }\n\n // Create README if not exists\n const readmePath = path.join(resolvedPath, \"README.md\");\n try {\n await fs.access(readmePath);\n } catch {\n await fs.writeFile(readmePath, README_CONTENT, \"utf-8\");\n }\n\n // Update global config with central repo path\n const globalConfig = await loadXdgConfig();\n globalConfig.centralRepo = repoPath; // Store original (possibly with ~)\n await saveXdgConfig(globalConfig);\n\n return {\n success: true,\n path: resolvedPath,\n created,\n message: created\n ? \"Created new central repository\"\n : \"Configured existing directory as central repository\",\n };\n}\n\n/**\n * Validate an existing central repository\n */\nexport async function validateCentralRepo(repoPath: string): Promise<{\n valid: boolean;\n warnings: string[];\n errors: string[];\n}> {\n const expandedPath = expandPath(repoPath);\n const resolvedPath = path.resolve(expandedPath);\n const warnings: string[] = [];\n const errors: string[] = [];\n\n // Check directory exists\n try {\n const stat = await fs.stat(resolvedPath);\n if (!stat.isDirectory()) {\n errors.push(\"Path is not a directory\");\n return { valid: false, warnings, errors };\n }\n } catch {\n errors.push(\"Directory does not exist\");\n return { valid: false, warnings, errors };\n }\n\n // Check if git repo\n const isGitRepo = await isInsideGitRepo(resolvedPath);\n if (!isGitRepo) {\n warnings.push(\"Not a git repository - sync features may be limited\");\n }\n\n // Check for registry\n const registryPath = getRegistryPath(resolvedPath);\n try {\n await fs.access(registryPath);\n // Validate registry content\n const registry = await readRegistry(resolvedPath);\n if (!registry.mappings) {\n warnings.push(\"Registry file is malformed\");\n }\n } catch {\n warnings.push(\"Registry file is missing - will be created on first sync\");\n }\n\n // Check for .gitignore\n const gitignorePath = path.join(resolvedPath, \".gitignore\");\n try {\n const gitignore = await fs.readFile(gitignorePath, \"utf-8\");\n if (!gitignore.includes(\"*.db\")) {\n warnings.push(\".gitignore does not exclude database files\");\n }\n } catch {\n warnings.push(\".gitignore is missing\");\n }\n\n // Check if writable\n if (!(await isWritable(resolvedPath))) {\n errors.push(\"Directory is not writable\");\n }\n\n return {\n valid: errors.length === 0,\n warnings,\n errors,\n };\n}\n\n/**\n * Get the configured central repo path\n */\nexport async function getCentralRepoPath(): Promise<string | undefined> {\n const globalConfig = await loadXdgConfig();\n if (globalConfig.centralRepo) {\n return path.resolve(expandPath(globalConfig.centralRepo));\n }\n return undefined;\n}\n","/**\n * Registry system for sync path collision prevention\n *\n * The registry is stored in the central repo as .minimem-registry.json\n * and tracks which local directories are mapped to which paths.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport crypto from \"node:crypto\";\n\nconst REGISTRY_FILENAME = \".minimem-registry.json\";\n\nexport type RegistryMapping = {\n /** Path in central repo (e.g., \"global/\", \"work/\") */\n path: string;\n /** Local directory path (with ~ for home) */\n localPath: string;\n /** Machine identifier */\n machineId: string;\n /** Last sync timestamp (ISO format) */\n lastSync: string;\n};\n\nexport type Registry = {\n version: number;\n mappings: RegistryMapping[];\n};\n\nexport type CollisionCheckResult = \"none\" | \"same-machine\" | \"collision\";\n\n/**\n * Get the registry file path for a central repo\n */\nexport function getRegistryPath(centralRepo: string): string {\n return path.join(centralRepo, REGISTRY_FILENAME);\n}\n\n/**\n * Create an empty registry\n */\nexport function createEmptyRegistry(): Registry {\n return {\n version: 1,\n mappings: [],\n };\n}\n\n/**\n * Read registry from central repo\n * Returns empty registry if file doesn't exist\n */\nexport async function readRegistry(centralRepo: string): Promise<Registry> {\n const registryPath = getRegistryPath(centralRepo);\n\n try {\n const content = await fs.readFile(registryPath, \"utf-8\");\n const registry = JSON.parse(content) as Registry;\n\n // Validate basic structure\n if (!registry.mappings || !Array.isArray(registry.mappings)) {\n return createEmptyRegistry();\n }\n\n return registry;\n } catch (error) {\n // File doesn't exist or is invalid\n return createEmptyRegistry();\n }\n}\n\n/**\n * Write registry to central repo atomically\n * Writes to temp file then renames to avoid corruption\n */\nexport async function writeRegistry(\n centralRepo: string,\n registry: Registry\n): Promise<void> {\n const registryPath = getRegistryPath(centralRepo);\n const tempPath = `${registryPath}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n\n // Ensure version is set\n registry.version = registry.version || 1;\n\n // Write to temp file\n await fs.writeFile(tempPath, JSON.stringify(registry, null, 2), \"utf-8\");\n\n // Atomic rename\n await fs.rename(tempPath, registryPath);\n}\n\n/**\n * Normalize a path for comparison\n * Expands ~ and resolves to absolute path\n */\nexport function normalizePath(filePath: string): string {\n if (filePath.startsWith(\"~/\")) {\n return path.resolve(os.homedir(), filePath.slice(2));\n }\n if (filePath === \"~\") {\n return os.homedir();\n }\n return path.resolve(filePath);\n}\n\n/**\n * Compress a path for storage\n * Replaces home directory with ~\n */\nexport function compressPath(filePath: string): string {\n const home = os.homedir();\n const resolved = path.resolve(filePath);\n if (resolved.startsWith(home)) {\n return \"~\" + resolved.slice(home.length);\n }\n return resolved;\n}\n\n/**\n * Normalize central repo path (remove trailing slash, etc.)\n */\nexport function normalizeRepoPath(repoPath: string): string {\n // Remove trailing slashes but keep at least one char\n let normalized = repoPath.replace(/\\/+$/, \"\");\n if (normalized === \"\") {\n normalized = \"/\";\n }\n // Ensure it ends with / for directory paths (except root)\n if (!normalized.endsWith(\"/\") && normalized !== \"/\") {\n normalized += \"/\";\n }\n return normalized;\n}\n\n/**\n * Check if a path mapping would collide with existing mappings\n *\n * Returns:\n * - \"none\": path is free, can be used\n * - \"same-machine\": same machine already has this path, can update\n * - \"collision\": different machine has this path, blocked\n */\nexport function checkCollision(\n registry: Registry,\n centralPath: string,\n localPath: string,\n machineId: string\n): CollisionCheckResult {\n const normalizedCentralPath = normalizeRepoPath(centralPath);\n const normalizedLocalPath = normalizePath(localPath);\n\n for (const mapping of registry.mappings) {\n const mappingCentralPath = normalizeRepoPath(mapping.path);\n const mappingLocalPath = normalizePath(mapping.localPath);\n\n // Check if central path matches\n if (mappingCentralPath === normalizedCentralPath) {\n // Same machine, same or different local path - can update\n if (mapping.machineId === machineId) {\n return \"same-machine\";\n }\n\n // Different machine - collision\n return \"collision\";\n }\n }\n\n return \"none\";\n}\n\n/**\n * Add or update a mapping in the registry\n */\nexport function addMapping(\n registry: Registry,\n mapping: RegistryMapping\n): Registry {\n const normalizedPath = normalizeRepoPath(mapping.path);\n const normalizedLocalPath = compressPath(mapping.localPath);\n\n // Remove existing mapping for this path+machine combination\n const filteredMappings = registry.mappings.filter(\n (m) =>\n !(\n normalizeRepoPath(m.path) === normalizedPath &&\n m.machineId === mapping.machineId\n )\n );\n\n // Add new mapping\n filteredMappings.push({\n ...mapping,\n path: normalizedPath,\n localPath: normalizedLocalPath,\n });\n\n return {\n ...registry,\n mappings: filteredMappings,\n };\n}\n\n/**\n * Remove a mapping from the registry\n */\nexport function removeMapping(\n registry: Registry,\n centralPath: string,\n machineId: string\n): Registry {\n const normalizedPath = normalizeRepoPath(centralPath);\n\n const filteredMappings = registry.mappings.filter(\n (m) =>\n !(normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId)\n );\n\n return {\n ...registry,\n mappings: filteredMappings,\n };\n}\n\n/**\n * Find a mapping by central path and machine ID\n */\nexport function findMapping(\n registry: Registry,\n centralPath: string,\n machineId: string\n): RegistryMapping | undefined {\n const normalizedPath = normalizeRepoPath(centralPath);\n\n return registry.mappings.find(\n (m) =>\n normalizeRepoPath(m.path) === normalizedPath && m.machineId === machineId\n );\n}\n\n/**\n * Get all mappings for a specific machine\n */\nexport function getMachineMappings(\n registry: Registry,\n machineId: string\n): RegistryMapping[] {\n return registry.mappings.filter((m) => m.machineId === machineId);\n}\n\n/**\n * Update the lastSync timestamp for a mapping\n */\nexport function updateLastSync(\n registry: Registry,\n centralPath: string,\n machineId: string\n): Registry {\n const normalizedPath = normalizeRepoPath(centralPath);\n\n const mappings = registry.mappings.map((m) => {\n if (\n normalizeRepoPath(m.path) === normalizedPath &&\n m.machineId === machineId\n ) {\n return {\n ...m,\n lastSync: new Date().toISOString(),\n };\n }\n return m;\n });\n\n return {\n ...registry,\n mappings,\n };\n}\n","/**\n * Directory type detection for sync system\n *\n * Detects whether a memory directory is:\n * - project-bound: inside git repo (synced via project's git)\n * - standalone: has minimem sync config (synced via central repo)\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getConfigPath } from \"../config.js\";\n\n/**\n * Directory type for sync purposes\n *\n * - project-bound: Memory is inside a git repo and synced via project's git\n * - standalone: Memory has minimem sync config and syncs via central repo\n */\nexport type DirectoryType = \"project-bound\" | \"standalone\";\n\n/**\n * Check if a directory is inside a git repository\n * Walks up the directory tree looking for .git\n */\nexport async function isInsideGitRepo(dir: string): Promise<boolean> {\n let current = path.resolve(dir);\n const root = path.parse(current).root;\n\n while (current !== root) {\n try {\n const gitPath = path.join(current, \".git\");\n const stat = await fs.stat(gitPath);\n if (stat.isDirectory() || stat.isFile()) {\n // .git can be a file in worktrees\n return true;\n }\n } catch {\n // .git doesn't exist at this level, continue up\n }\n current = path.dirname(current);\n }\n\n return false;\n}\n\n/**\n * Get the root of the git repository containing a directory\n * Returns undefined if not inside a git repo\n */\nexport async function getGitRoot(dir: string): Promise<string | undefined> {\n let current = path.resolve(dir);\n const root = path.parse(current).root;\n\n while (current !== root) {\n try {\n const gitPath = path.join(current, \".git\");\n const stat = await fs.stat(gitPath);\n if (stat.isDirectory() || stat.isFile()) {\n return current;\n }\n } catch {\n // Continue up\n }\n current = path.dirname(current);\n }\n\n return undefined;\n}\n\n/**\n * Check if a directory has sync configuration enabled\n */\nexport async function hasSyncConfig(dir: string): Promise<boolean> {\n const configPath = getConfigPath(dir);\n\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n const config = JSON.parse(content);\n // Check if sync is explicitly enabled or has a path configured\n return config.sync?.enabled === true || typeof config.sync?.path === \"string\";\n } catch {\n return false;\n }\n}\n\n/**\n * Detect the directory type based on git repo presence and sync config\n *\n * - If has sync config -> standalone (uses minimem central repo sync)\n * - If inside git repo -> project-bound (synced via project's git)\n * - Otherwise -> standalone (default, can set up sync later)\n */\nexport async function detectDirectoryType(dir: string): Promise<DirectoryType> {\n const hasSync = await hasSyncConfig(dir);\n\n // If has sync config, it's standalone (uses minimem sync)\n if (hasSync) {\n return \"standalone\";\n }\n\n // If inside git repo, it's project-bound (synced via git)\n const inGit = await isInsideGitRepo(dir);\n if (inGit) {\n return \"project-bound\";\n }\n\n // Default to standalone (can set up sync later)\n return \"standalone\";\n}\n\n/**\n * Get detailed directory info including type and git root\n */\nexport async function getDirectoryInfo(dir: string): Promise<{\n type: DirectoryType;\n gitRoot?: string;\n hasSyncConfig: boolean;\n}> {\n const [hasSync, gitRoot] = await Promise.all([\n hasSyncConfig(dir),\n getGitRoot(dir),\n ]);\n\n let type: DirectoryType;\n if (hasSync) {\n type = \"standalone\";\n } else if (gitRoot !== undefined) {\n type = \"project-bound\";\n } else {\n type = \"standalone\";\n }\n\n return {\n type,\n gitRoot,\n hasSyncConfig: hasSync,\n };\n}\n","/**\n * Sync operations - push and pull\n *\n * Uses last-write-wins conflict resolution:\n * - Push: local overwrites remote\n * - Pull: remote overwrites local\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\nimport { getSyncConfig } from \"../config.js\";\nimport { getCentralRepoPath } from \"./central.js\";\nimport {\n loadSyncState,\n saveSyncState,\n listSyncableFiles,\n computeFileHash,\n getFileSyncStatus,\n getFileHashInfo,\n} from \"./state.js\";\nimport { readRegistry, writeRegistry, updateLastSync } from \"./registry.js\";\nimport { getMachineId } from \"../config.js\";\nimport { appendSyncLog, type SyncLogEntry } from \"../commands/conflicts.js\";\n\nexport type SyncResult = {\n success: boolean;\n pushed: string[];\n pulled: string[];\n errors: string[];\n skipped: string[];\n};\n\n/**\n * Ensure a directory exists\n */\nasync function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\n/**\n * Copy a file atomically via temp file\n */\nasync function copyFileAtomic(src: string, dest: string): Promise<void> {\n const destDir = path.dirname(dest);\n await ensureDir(destDir);\n\n const tempDest = `${dest}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n\n try {\n await fs.copyFile(src, tempDest);\n await fs.rename(tempDest, dest);\n } catch (error) {\n // Clean up temp file on error\n try {\n await fs.unlink(tempDest);\n } catch {\n // Ignore cleanup errors\n }\n throw error;\n }\n}\n\n/**\n * Push local changes to central repository\n *\n * Last-write-wins: local files always overwrite remote files\n */\nexport async function push(\n memoryDir: string,\n options: {\n force?: boolean;\n dryRun?: boolean;\n } = {}\n): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n pushed: [],\n pulled: [],\n errors: [],\n skipped: [],\n };\n\n // Get config\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.enabled || !syncConfig.path) {\n result.success = false;\n result.errors.push(\"Sync not configured for this directory\");\n return result;\n }\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n result.success = false;\n result.errors.push(\"No central repository configured\");\n return result;\n }\n\n const remotePath = path.join(centralRepo, syncConfig.path);\n\n // Load state\n const state = await loadSyncState(memoryDir, syncConfig.path);\n\n // Get all local files\n const localFiles = await listSyncableFiles(\n memoryDir,\n syncConfig.include,\n syncConfig.exclude\n );\n\n // Get all remote files for comparison\n const remoteFiles = await listSyncableFiles(\n remotePath,\n syncConfig.include,\n syncConfig.exclude\n );\n\n const allFiles = new Set([...localFiles, ...remoteFiles]);\n\n // Process each file\n for (const file of allFiles) {\n const localPath = path.join(memoryDir, file);\n const remoteFilePath = path.join(remotePath, file);\n\n try {\n const [localInfo, remoteInfo] = await Promise.all([\n getFileHashInfo(localPath),\n getFileHashInfo(remoteFilePath),\n ]);\n\n const status = getFileSyncStatus(\n localInfo.hash ?? null,\n remoteInfo.hash ?? null\n );\n\n switch (status) {\n case \"unchanged\":\n // Already in sync\n break;\n\n case \"local-only\":\n case \"local-modified\":\n // Push local to remote (last-write-wins)\n if (!options.dryRun) {\n await copyFileAtomic(localPath, remoteFilePath);\n const hash = localInfo.hash!;\n state.files[file] = {\n localHash: hash,\n remoteHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pushed.push(file);\n break;\n\n case \"remote-only\":\n // File only exists on remote - skip on push (don't delete)\n result.skipped.push(file);\n break;\n\n default:\n result.skipped.push(file);\n break;\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n result.errors.push(`${file}: ${message}`);\n result.success = false;\n }\n }\n\n // Save state and update registry\n if (!options.dryRun && result.pushed.length > 0) {\n state.lastSync = new Date().toISOString();\n await saveSyncState(memoryDir, state);\n\n // Update registry lastSync\n const machineId = await getMachineId();\n const registry = await readRegistry(centralRepo);\n const updatedRegistry = updateLastSync(registry, syncConfig.path, machineId);\n await writeRegistry(centralRepo, updatedRegistry);\n }\n\n // Log the sync operation\n if (!options.dryRun) {\n const logEntry: SyncLogEntry = {\n timestamp: new Date().toISOString(),\n operation: \"push\",\n result: result.success ? \"success\" : \"failure\",\n pushed: result.pushed.length,\n errors: result.errors.length > 0 ? result.errors : undefined,\n };\n await appendSyncLog(memoryDir, logEntry);\n }\n\n return result;\n}\n\n/**\n * Pull changes from central repository\n *\n * Last-write-wins: remote files always overwrite local files\n */\nexport async function pull(\n memoryDir: string,\n options: {\n force?: boolean;\n dryRun?: boolean;\n } = {}\n): Promise<SyncResult> {\n const result: SyncResult = {\n success: true,\n pushed: [],\n pulled: [],\n errors: [],\n skipped: [],\n };\n\n // Get config\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.enabled || !syncConfig.path) {\n result.success = false;\n result.errors.push(\"Sync not configured for this directory\");\n return result;\n }\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n result.success = false;\n result.errors.push(\"No central repository configured\");\n return result;\n }\n\n const remotePath = path.join(centralRepo, syncConfig.path);\n\n // Load state\n const state = await loadSyncState(memoryDir, syncConfig.path);\n\n // Get all files from both sides\n const localFiles = await listSyncableFiles(\n memoryDir,\n syncConfig.include,\n syncConfig.exclude\n );\n\n const remoteFiles = await listSyncableFiles(\n remotePath,\n syncConfig.include,\n syncConfig.exclude\n );\n\n const allFiles = new Set([...localFiles, ...remoteFiles]);\n\n // Process each file\n for (const file of allFiles) {\n const localPath = path.join(memoryDir, file);\n const remoteFilePath = path.join(remotePath, file);\n\n try {\n const [localInfo, remoteInfo] = await Promise.all([\n getFileHashInfo(localPath),\n getFileHashInfo(remoteFilePath),\n ]);\n\n const status = getFileSyncStatus(\n localInfo.hash ?? null,\n remoteInfo.hash ?? null\n );\n\n switch (status) {\n case \"unchanged\":\n // Already in sync\n break;\n\n case \"remote-only\":\n // Pull new remote file to local\n if (!options.dryRun) {\n await copyFileAtomic(remoteFilePath, localPath);\n const hash = remoteInfo.hash!;\n state.files[file] = {\n localHash: hash,\n remoteHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pulled.push(file);\n break;\n\n case \"local-modified\":\n // Both have changes - with last-write-wins, pull overwrites local\n if (options.force || !localInfo.exists) {\n if (!options.dryRun) {\n await copyFileAtomic(remoteFilePath, localPath);\n const hash = remoteInfo.hash!;\n state.files[file] = {\n localHash: hash,\n remoteHash: hash,\n lastModified: new Date().toISOString(),\n };\n }\n result.pulled.push(file);\n } else {\n // Without --force, skip files that have local changes\n result.skipped.push(file);\n }\n break;\n\n case \"local-only\":\n // File only exists locally - skip on pull (don't delete)\n result.skipped.push(file);\n break;\n\n default:\n result.skipped.push(file);\n break;\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n result.errors.push(`${file}: ${message}`);\n result.success = false;\n }\n }\n\n // Save state and update registry\n if (!options.dryRun && result.pulled.length > 0) {\n state.lastSync = new Date().toISOString();\n await saveSyncState(memoryDir, state);\n\n // Update registry lastSync\n const machineId = await getMachineId();\n const registry = await readRegistry(centralRepo);\n const updatedRegistry = updateLastSync(registry, syncConfig.path, machineId);\n await writeRegistry(centralRepo, updatedRegistry);\n }\n\n // Log the sync operation\n if (!options.dryRun) {\n const logEntry: SyncLogEntry = {\n timestamp: new Date().toISOString(),\n operation: \"pull\",\n result: result.success ? \"success\" : \"failure\",\n pulled: result.pulled.length,\n errors: result.errors.length > 0 ? result.errors : undefined,\n };\n await appendSyncLog(memoryDir, logEntry);\n }\n\n return result;\n}\n\n/**\n * Bidirectional sync - push local changes, pull remote changes\n */\nexport async function bidirectionalSync(\n memoryDir: string,\n options: {\n force?: boolean;\n dryRun?: boolean;\n } = {}\n): Promise<SyncResult> {\n // First push, then pull\n const pushResult = await push(memoryDir, options);\n const pullResult = await pull(memoryDir, options);\n\n return {\n success: pushResult.success && pullResult.success,\n pushed: pushResult.pushed,\n pulled: pullResult.pulled,\n errors: [...pushResult.errors, ...pullResult.errors],\n skipped: [...new Set([...pushResult.skipped, ...pullResult.skipped])],\n };\n}\n","/**\n * Sync state tracking with content hashing\n *\n * Tracks file hashes to detect changes between local directories\n * and the central repository. Uses 2-way comparison (local vs remote).\n *\n * Conflict resolution: Last-write-wins\n * - Push: local overwrites remote\n * - Pull: remote overwrites local\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { minimatch } from \"minimatch\";\n\nconst STATE_FILENAME = \"sync-state.json\";\nconst STATE_DIR = \".minimem\";\n\nexport type FileHashInfo = {\n /** SHA-256 hash of local file content */\n localHash: string;\n /** SHA-256 hash of remote file content */\n remoteHash: string;\n /** Last modified timestamp (ISO) */\n lastModified: string;\n};\n\nexport type SyncState = {\n /** Version for future migrations */\n version: number;\n /** Last sync timestamp (ISO) */\n lastSync: string | null;\n /** Central repo path this directory syncs to */\n centralPath: string;\n /** File hashes keyed by relative path */\n files: Record<string, FileHashInfo>;\n};\n\n/**\n * Get the sync state file path for a directory\n */\nexport function getSyncStatePath(dir: string): string {\n return path.join(dir, STATE_DIR, STATE_FILENAME);\n}\n\n/**\n * Create an empty sync state\n */\nexport function createEmptySyncState(centralPath: string): SyncState {\n return {\n version: 2, // Bumped version for simplified state\n lastSync: null,\n centralPath,\n files: {},\n };\n}\n\n/**\n * Load sync state from a directory\n * Returns empty state if file doesn't exist\n */\nexport async function loadSyncState(\n dir: string,\n centralPath: string\n): Promise<SyncState> {\n const statePath = getSyncStatePath(dir);\n\n try {\n const content = await fs.readFile(statePath, \"utf-8\");\n const state = JSON.parse(content) as SyncState;\n\n // Validate basic structure\n if (!state.files || typeof state.files !== \"object\") {\n return createEmptySyncState(centralPath);\n }\n\n // Update centralPath if it changed\n state.centralPath = centralPath;\n\n // Migrate v1 state (remove lastSyncedHash if present)\n if (state.version === 1) {\n for (const file of Object.keys(state.files)) {\n const entry = state.files[file] as FileHashInfo & { lastSyncedHash?: string };\n delete entry.lastSyncedHash;\n }\n state.version = 2;\n }\n\n return state;\n } catch {\n return createEmptySyncState(centralPath);\n }\n}\n\n/**\n * Save sync state atomically\n */\nexport async function saveSyncState(\n dir: string,\n state: SyncState\n): Promise<void> {\n const statePath = getSyncStatePath(dir);\n const stateDir = path.dirname(statePath);\n const tempPath = `${statePath}.${crypto.randomBytes(4).toString(\"hex\")}.tmp`;\n\n // Ensure directory exists\n await fs.mkdir(stateDir, { recursive: true });\n\n // Ensure version is set\n state.version = state.version || 2;\n\n // Write to temp file\n await fs.writeFile(tempPath, JSON.stringify(state, null, 2), \"utf-8\");\n\n // Atomic rename\n await fs.rename(tempPath, statePath);\n}\n\n/**\n * Compute SHA-256 hash of a file's content\n */\nexport async function computeFileHash(filePath: string): Promise<string> {\n const content = await fs.readFile(filePath);\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/**\n * Compute hash of string content\n */\nexport function computeContentHash(content: string | Buffer): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\n/**\n * List files matching include/exclude patterns\n */\nexport async function listSyncableFiles(\n dir: string,\n include: string[],\n exclude: string[]\n): Promise<string[]> {\n const files: string[] = [];\n\n async function walkDir(currentDir: string, relativePath: string = \"\") {\n const entries = await fs.readdir(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = path.join(currentDir, entry.name);\n const relPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;\n\n // Skip .minimem directory\n if (entry.name === \".minimem\") continue;\n\n if (entry.isDirectory()) {\n await walkDir(entryPath, relPath);\n } else if (entry.isFile()) {\n // Check include patterns\n const matchesInclude = include.some((pattern) =>\n minimatch(relPath, pattern)\n );\n\n // Check exclude patterns\n const matchesExclude = exclude.some((pattern) =>\n minimatch(relPath, pattern)\n );\n\n if (matchesInclude && !matchesExclude) {\n files.push(relPath);\n }\n }\n }\n }\n\n try {\n await walkDir(dir);\n } catch (error) {\n // Directory might not exist yet\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n\n return files.sort();\n}\n\n/**\n * Get file hash info, computing hash if file exists\n */\nexport async function getFileHashInfo(\n filePath: string\n): Promise<{ exists: boolean; hash?: string; mtime?: string }> {\n try {\n const stat = await fs.stat(filePath);\n const hash = await computeFileHash(filePath);\n return {\n exists: true,\n hash,\n mtime: stat.mtime.toISOString(),\n };\n } catch {\n return { exists: false };\n }\n}\n\n/**\n * Sync status for a file (2-way comparison)\n *\n * With last-write-wins, there are no conflicts:\n * - Push operations: local changes overwrite remote\n * - Pull operations: remote changes overwrite local\n */\nexport type FileSyncStatus =\n | \"unchanged\" // Both same\n | \"local-modified\" // Local differs from remote (push will overwrite remote)\n | \"remote-modified\"// Remote differs from local (pull will overwrite local)\n | \"local-only\" // File exists only locally\n | \"remote-only\"; // File exists only on remote\n\n/**\n * Compare local and remote files to determine sync status\n * Simple 2-way comparison (no 3-way merge needed with last-write-wins)\n */\nexport function getFileSyncStatus(\n localHash: string | null,\n remoteHash: string | null\n): FileSyncStatus {\n // Both exist and are the same\n if (localHash && remoteHash && localHash === remoteHash) {\n return \"unchanged\";\n }\n\n // File exists in both but differs\n if (localHash && remoteHash && localHash !== remoteHash) {\n // With last-write-wins, caller decides direction\n // Return \"local-modified\" to indicate a difference\n return \"local-modified\";\n }\n\n // File only exists locally\n if (localHash && !remoteHash) {\n return \"local-only\";\n }\n\n // File only exists on remote\n if (!localHash && remoteHash) {\n return \"remote-only\";\n }\n\n return \"unchanged\";\n}\n\n/**\n * Update sync state after a successful sync\n */\nexport function updateSyncStateAfterSync(\n state: SyncState,\n filePath: string,\n hash: string\n): SyncState {\n return {\n ...state,\n lastSync: new Date().toISOString(),\n files: {\n ...state.files,\n [filePath]: {\n localHash: hash,\n remoteHash: hash,\n lastModified: new Date().toISOString(),\n },\n },\n };\n}\n\n/**\n * Remove a file from sync state\n */\nexport function removeFileFromSyncState(\n state: SyncState,\n filePath: string\n): SyncState {\n const { [filePath]: _, ...remainingFiles } = state.files;\n return {\n ...state,\n files: remainingFiles,\n };\n}\n\n/**\n * Build a complete sync state by scanning files\n */\nexport async function buildSyncState(\n localDir: string,\n remoteDir: string,\n centralPath: string,\n include: string[],\n exclude: string[]\n): Promise<{\n state: SyncState;\n changes: Array<{\n file: string;\n status: FileSyncStatus;\n localHash: string | null;\n remoteHash: string | null;\n }>;\n}> {\n const state = createEmptySyncState(centralPath);\n const changes: Array<{\n file: string;\n status: FileSyncStatus;\n localHash: string | null;\n remoteHash: string | null;\n }> = [];\n\n // Get all files from both sides\n const [localFiles, remoteFiles] = await Promise.all([\n listSyncableFiles(localDir, include, exclude),\n listSyncableFiles(remoteDir, include, exclude),\n ]);\n\n const allFiles = new Set([...localFiles, ...remoteFiles]);\n\n for (const file of allFiles) {\n const localPath = path.join(localDir, file);\n const remotePath = path.join(remoteDir, file);\n\n const [localInfo, remoteInfo] = await Promise.all([\n getFileHashInfo(localPath),\n getFileHashInfo(remotePath),\n ]);\n\n const status = getFileSyncStatus(\n localInfo.hash ?? null,\n remoteInfo.hash ?? null\n );\n\n if (status !== \"unchanged\") {\n changes.push({\n file,\n status,\n localHash: localInfo.hash ?? null,\n remoteHash: remoteInfo.hash ?? null,\n });\n }\n\n // Update state with current hashes\n state.files[file] = {\n localHash: localInfo.hash ?? \"\",\n remoteHash: remoteInfo.hash ?? \"\",\n lastModified: localInfo.mtime ?? remoteInfo.mtime ?? new Date().toISOString(),\n };\n }\n\n return { state, changes };\n}\n","/**\n * minimem sync:conflicts - Conflict management commands\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { spawn } from \"node:child_process\";\n\nimport {\n resolveMemoryDir,\n isInitialized,\n formatPath,\n getSyncConfig,\n exitWithError,\n warn,\n} from \"../config.js\";\nimport {\n listQuarantinedConflicts,\n getConflictsDir,\n getShadowsDir,\n} from \"../sync/conflicts.js\";\nimport { getSyncStatePath, loadSyncState } from \"../sync/state.js\";\n\nexport type ConflictsOptions = {\n dir?: string;\n global?: boolean;\n json?: boolean;\n};\n\n/**\n * List all quarantined conflicts\n */\nexport async function conflictsCommand(options: ConflictsOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n try {\n const conflicts = await listQuarantinedConflicts(memoryDir);\n\n if (options.json) {\n console.log(JSON.stringify(conflicts, null, 2));\n return;\n }\n\n if (conflicts.length === 0) {\n console.log(\"No quarantined conflicts.\");\n return;\n }\n\n console.log(`Quarantined conflicts in ${formatPath(memoryDir)}`);\n console.log(\"-\".repeat(50));\n\n for (const conflict of conflicts) {\n console.log(`\\n${conflict.timestamp}:`);\n for (const file of conflict.files) {\n console.log(` - ${file}`);\n }\n }\n\n console.log(`\\nTotal: ${conflicts.length} conflict set(s)`);\n console.log(\"\\nUse 'minimem sync:resolve <timestamp>' to resolve a conflict.\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n\nexport type ResolveOptions = {\n dir?: string;\n global?: boolean;\n tool?: string;\n};\n\n/**\n * Resolve a quarantined conflict\n */\nexport async function resolveCommand(\n timestamp: string,\n options: ResolveOptions\n): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n const conflictDir = path.join(getConflictsDir(memoryDir), timestamp);\n\n try {\n await fs.access(conflictDir);\n } catch {\n exitWithError(\n `Conflict '${timestamp}' not found.`,\n \"Use 'minimem sync:conflicts' to list available conflicts.\"\n );\n }\n\n try {\n const files = await fs.readdir(conflictDir);\n\n // Group files by base name\n const fileGroups = new Map<string, { local?: string; remote?: string; base?: string }>();\n for (const file of files) {\n const match = file.match(/^(.+)\\.(local|remote|base)$/);\n if (match) {\n const [, baseName, type] = match;\n if (!fileGroups.has(baseName)) {\n fileGroups.set(baseName, {});\n }\n const group = fileGroups.get(baseName)!;\n group[type as \"local\" | \"remote\" | \"base\"] = path.join(conflictDir, file);\n }\n }\n\n if (fileGroups.size === 0) {\n exitWithError(\"No conflict files found in this directory.\");\n }\n\n // Determine merge tool\n const mergeTool = options.tool || process.env.MERGE_TOOL || await detectMergeTool();\n\n if (!mergeTool) {\n console.log(\"No merge tool detected. Available conflict files:\");\n for (const [baseName, group] of fileGroups) {\n console.log(`\\n${baseName.replace(/_/g, \"/\")}:`);\n if (group.local) console.log(` Local: ${group.local}`);\n if (group.remote) console.log(` Remote: ${group.remote}`);\n if (group.base) console.log(` Base: ${group.base}`);\n }\n console.log(\"\\nManually edit the files or set MERGE_TOOL environment variable.\");\n return;\n }\n\n console.log(`Using merge tool: ${mergeTool}`);\n\n for (const [baseName, group] of fileGroups) {\n const fileName = baseName.replace(/_/g, \"/\");\n console.log(`\\nResolving: ${fileName}`);\n\n if (group.local && group.remote) {\n // Launch merge tool\n const args = group.base\n ? [group.local, group.base, group.remote]\n : [group.local, group.remote];\n\n const child = spawn(mergeTool, args, { stdio: \"inherit\" });\n\n await new Promise<void>((resolve, reject) => {\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Merge tool exited with code ${code}`));\n }\n });\n child.on(\"error\", reject);\n });\n }\n }\n\n console.log(\"\\nMerge complete. Remove conflict directory when satisfied:\");\n console.log(` rm -rf \"${conflictDir}\"`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n\n/**\n * Detect available merge tool\n */\nasync function detectMergeTool(): Promise<string | null> {\n const tools = [\"code\", \"meld\", \"kdiff3\", \"vimdiff\", \"opendiff\"];\n\n for (const tool of tools) {\n try {\n const { execSync } = await import(\"node:child_process\");\n execSync(`which ${tool}`, { stdio: \"ignore\" });\n return tool;\n } catch {\n continue;\n }\n }\n\n return null;\n}\n\nexport type CleanupOptions = {\n dir?: string;\n global?: boolean;\n days?: number;\n dryRun?: boolean;\n};\n\n/**\n * Clean up old quarantined conflicts\n */\nexport async function cleanupCommand(options: CleanupOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n const maxAgeDays = options.days ?? 30;\n const cutoffDate = new Date(Date.now() - maxAgeDays * 24 * 60 * 60 * 1000);\n\n try {\n const conflictsDir = getConflictsDir(memoryDir);\n let entries: string[] = [];\n\n try {\n entries = await fs.readdir(conflictsDir);\n } catch {\n console.log(\"No conflicts directory found.\");\n return;\n }\n\n let cleaned = 0;\n let kept = 0;\n\n for (const entry of entries) {\n // Timestamps are in ISO format with : and . replaced with -\n // e.g., 2026-02-03T07-20-56-704Z\n const timestamp = entry.replace(/-(\\d{2})-(\\d{2})-(\\d{3})Z$/, \":$1:$2.$3Z\");\n const entryDate = new Date(timestamp);\n\n if (isNaN(entryDate.getTime())) {\n console.log(` Skipping invalid timestamp: ${entry}`);\n continue;\n }\n\n const entryPath = path.join(conflictsDir, entry);\n\n if (entryDate < cutoffDate) {\n if (options.dryRun) {\n console.log(` Would remove: ${entry}`);\n } else {\n await fs.rm(entryPath, { recursive: true, force: true });\n console.log(` Removed: ${entry}`);\n }\n cleaned++;\n } else {\n kept++;\n }\n }\n\n if (options.dryRun) {\n console.log(`\\nWould remove ${cleaned} conflict(s), keep ${kept}`);\n } else {\n console.log(`\\nRemoved ${cleaned} conflict(s), kept ${kept}`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n\n/**\n * Sync logging\n */\nconst SYNC_LOG_FILE = \"sync.log\";\nconst MAX_LOG_ENTRIES = 1000;\n\nexport type SyncLogEntry = {\n timestamp: string;\n operation: \"push\" | \"pull\" | \"sync\";\n result: \"success\" | \"partial\" | \"failure\";\n pushed?: number;\n pulled?: number;\n conflicts?: number;\n errors?: string[];\n};\n\n/**\n * Get sync log path\n */\nexport function getSyncLogPath(memoryDir: string): string {\n return path.join(memoryDir, \".minimem\", SYNC_LOG_FILE);\n}\n\n/**\n * Append to sync log\n */\nexport async function appendSyncLog(\n memoryDir: string,\n entry: SyncLogEntry\n): Promise<void> {\n const logPath = getSyncLogPath(memoryDir);\n\n try {\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n\n // Read existing log\n let entries: SyncLogEntry[] = [];\n try {\n const content = await fs.readFile(logPath, \"utf-8\");\n entries = content\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line));\n } catch {\n // No existing log\n }\n\n // Add new entry and trim if needed\n entries.push(entry);\n if (entries.length > MAX_LOG_ENTRIES) {\n entries = entries.slice(-MAX_LOG_ENTRIES);\n }\n\n // Write back\n const content = entries.map((e) => JSON.stringify(e)).join(\"\\n\") + \"\\n\";\n await fs.writeFile(logPath, content);\n } catch (error) {\n // Log failures are non-fatal\n const message = error instanceof Error ? error.message : String(error);\n warn(`Failed to write sync log: ${message}`);\n }\n}\n\n/**\n * Read sync log\n */\nexport async function readSyncLog(memoryDir: string): Promise<SyncLogEntry[]> {\n const logPath = getSyncLogPath(memoryDir);\n\n try {\n const content = await fs.readFile(logPath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line));\n } catch {\n return [];\n }\n}\n\nexport type LogOptions = {\n dir?: string;\n global?: boolean;\n limit?: number;\n json?: boolean;\n};\n\n/**\n * Show sync log\n */\nexport async function logCommand(options: LogOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n try {\n let entries = await readSyncLog(memoryDir);\n\n const limit = options.limit ?? 20;\n entries = entries.slice(-limit);\n\n if (options.json) {\n console.log(JSON.stringify(entries, null, 2));\n return;\n }\n\n if (entries.length === 0) {\n console.log(\"No sync history.\");\n return;\n }\n\n console.log(`Sync history for ${formatPath(memoryDir)}`);\n console.log(\"-\".repeat(60));\n\n for (const entry of entries) {\n const time = new Date(entry.timestamp).toLocaleString();\n const status =\n entry.result === \"success\" ? \"OK\" :\n entry.result === \"partial\" ? \"PARTIAL\" : \"FAILED\";\n\n let details = \"\";\n if (entry.pushed) details += ` +${entry.pushed}`;\n if (entry.pulled) details += ` -${entry.pulled}`;\n if (entry.conflicts) details += ` !${entry.conflicts}`;\n\n console.log(`${time} ${entry.operation.padEnd(6)} ${status.padEnd(8)}${details}`);\n\n if (entry.errors && entry.errors.length > 0) {\n for (const error of entry.errors.slice(0, 3)) {\n console.log(` Error: ${error}`);\n }\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n","/**\n * Sync change detection\n *\n * Detects differences between local and remote files.\n * With last-write-wins, there are no conflicts - just differences.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { getSyncConfig } from \"../config.js\";\nimport {\n listSyncableFiles,\n getFileHashInfo,\n getFileSyncStatus,\n type FileSyncStatus,\n} from \"./state.js\";\nimport { getCentralRepoPath } from \"./central.js\";\n\nconst CONFLICTS_DIR = \"conflicts\";\n\nexport type FileChange = {\n /** Relative file path */\n file: string;\n /** Sync status */\n status: FileSyncStatus;\n /** Local file hash (null if missing) */\n localHash: string | null;\n /** Remote file hash (null if missing) */\n remoteHash: string | null;\n};\n\n// Keep FileConflict as an alias for backwards compatibility\nexport type FileConflict = FileChange;\n\nexport type ChangeDetectionResult = {\n /** Files that need action */\n changes: FileChange[];\n /** Files with no changes */\n unchanged: string[];\n /** Summary counts */\n summary: {\n unchanged: number;\n localOnly: number;\n remoteOnly: number;\n localModified: number;\n };\n};\n\n// Keep ConflictDetectionResult as an alias for backwards compatibility\nexport type ConflictDetectionResult = ChangeDetectionResult;\n\n/**\n * Get the conflicts directory path (for quarantined files)\n */\nexport function getConflictsDir(memoryDir: string): string {\n return path.join(memoryDir, \".minimem\", CONFLICTS_DIR);\n}\n\n/**\n * Quarantine file versions for manual review\n * Saves local and remote versions to conflicts directory\n */\nexport async function quarantineConflict(\n memoryDir: string,\n filePath: string,\n localContent: string | Buffer | null,\n remoteContent: string | Buffer | null\n): Promise<string> {\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const conflictDir = path.join(getConflictsDir(memoryDir), timestamp);\n const flatName = filePath.replace(/\\//g, \"_\");\n\n await fs.mkdir(conflictDir, { recursive: true });\n\n if (localContent !== null) {\n await fs.writeFile(path.join(conflictDir, `${flatName}.local`), localContent);\n }\n if (remoteContent !== null) {\n await fs.writeFile(path.join(conflictDir, `${flatName}.remote`), remoteContent);\n }\n\n return conflictDir;\n}\n\n/**\n * List all quarantined file versions\n */\nexport async function listQuarantinedConflicts(\n memoryDir: string\n): Promise<Array<{ timestamp: string; files: string[] }>> {\n const conflictsDir = getConflictsDir(memoryDir);\n const conflicts: Array<{ timestamp: string; files: string[] }> = [];\n\n try {\n const entries = await fs.readdir(conflictsDir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const dirPath = path.join(conflictsDir, entry.name);\n const files = await fs.readdir(dirPath);\n\n // Extract unique file names (remove .local, .remote suffixes)\n const uniqueFiles = new Set<string>();\n for (const file of files) {\n const baseName = file.replace(/\\.(local|remote|base)$/, \"\");\n uniqueFiles.add(baseName.replace(/_/g, \"/\"));\n }\n\n conflicts.push({\n timestamp: entry.name,\n files: Array.from(uniqueFiles),\n });\n }\n }\n } catch {\n // Directory might not exist\n }\n\n return conflicts.sort((a, b) => b.timestamp.localeCompare(a.timestamp));\n}\n\n/**\n * Detect changes between local and remote\n */\nexport async function detectChanges(\n memoryDir: string\n): Promise<ChangeDetectionResult> {\n // Get central repo path\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n throw new Error(\"No central repository configured\");\n }\n\n // Get sync config\n const syncConfig = await getSyncConfig(memoryDir);\n if (!syncConfig.path) {\n throw new Error(\"Directory is not configured for sync\");\n }\n\n const remotePath = path.join(centralRepo, syncConfig.path);\n\n // Get file lists\n const [localFiles, remoteFiles] = await Promise.all([\n listSyncableFiles(memoryDir, syncConfig.include, syncConfig.exclude),\n listSyncableFiles(remotePath, syncConfig.include, syncConfig.exclude),\n ]);\n\n const allFiles = new Set([...localFiles, ...remoteFiles]);\n\n const changes: FileChange[] = [];\n const unchanged: string[] = [];\n const summary = {\n unchanged: 0,\n localOnly: 0,\n remoteOnly: 0,\n localModified: 0,\n };\n\n for (const file of allFiles) {\n const localPath = path.join(memoryDir, file);\n const remoteFilePath = path.join(remotePath, file);\n\n const [localInfo, remoteInfo] = await Promise.all([\n getFileHashInfo(localPath),\n getFileHashInfo(remoteFilePath),\n ]);\n\n const status = getFileSyncStatus(\n localInfo.hash ?? null,\n remoteInfo.hash ?? null\n );\n\n if (status === \"unchanged\") {\n unchanged.push(file);\n summary.unchanged++;\n } else {\n changes.push({\n file,\n status,\n localHash: localInfo.hash ?? null,\n remoteHash: remoteInfo.hash ?? null,\n });\n\n // Update summary\n switch (status) {\n case \"local-only\":\n summary.localOnly++;\n break;\n case \"remote-only\":\n summary.remoteOnly++;\n break;\n case \"local-modified\":\n summary.localModified++;\n break;\n }\n }\n }\n\n return { changes, unchanged, summary };\n}\n\n// Keep detectConflicts as an alias for backwards compatibility\nexport const detectConflicts = detectChanges;\n","/**\n * minimem push/pull - Sync commands\n */\n\nimport {\n resolveMemoryDir,\n exitWithError,\n isInitialized,\n formatPath,\n} from \"../config.js\";\nimport { push, pull, bidirectionalSync } from \"../sync/operations.js\";\nimport { detectConflicts } from \"../sync/conflicts.js\";\n\nexport type PushPullOptions = {\n dir?: string;\n global?: boolean;\n force?: boolean;\n dryRun?: boolean;\n};\n\n/**\n * Push local changes to central repository\n */\nexport async function pushCommand(options: PushPullOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n console.log(`Pushing from ${formatPath(memoryDir)}...`);\n\n if (options.dryRun) {\n console.log(\"(dry run - no changes will be made)\");\n }\n\n try {\n const result = await push(memoryDir, {\n force: options.force,\n dryRun: options.dryRun,\n });\n\n if (result.pushed.length > 0) {\n console.log(`\\nPushed ${result.pushed.length} file(s):`);\n for (const file of result.pushed) {\n console.log(` + ${file}`);\n }\n }\n\n if (result.skipped.length > 0) {\n console.log(`\\nSkipped ${result.skipped.length} file(s) (no local changes)`);\n }\n\n if (result.conflicts.length > 0) {\n console.log(`\\nConflicts (${result.conflicts.length}):`);\n for (const file of result.conflicts) {\n console.log(` ! ${file}`);\n }\n console.log(\"\\nResolve conflicts or use --force to overwrite\");\n }\n\n if (result.errors.length > 0) {\n console.error(`\\nErrors:`);\n for (const error of result.errors) {\n console.error(` ${error}`);\n }\n }\n\n if (!result.success) {\n process.exit(1);\n }\n\n if (result.pushed.length === 0 && result.conflicts.length === 0) {\n console.log(\"Nothing to push - already in sync\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n\n/**\n * Pull changes from central repository\n */\nexport async function pullCommand(options: PushPullOptions): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n console.log(`Pulling to ${formatPath(memoryDir)}...`);\n\n if (options.dryRun) {\n console.log(\"(dry run - no changes will be made)\");\n }\n\n try {\n const result = await pull(memoryDir, {\n force: options.force,\n dryRun: options.dryRun,\n });\n\n if (result.pulled.length > 0) {\n console.log(`\\nPulled ${result.pulled.length} file(s):`);\n for (const file of result.pulled) {\n console.log(` + ${file}`);\n }\n }\n\n if (result.skipped.length > 0) {\n console.log(`\\nSkipped ${result.skipped.length} file(s) (no remote changes)`);\n }\n\n if (result.conflicts.length > 0) {\n console.log(`\\nConflicts (${result.conflicts.length}):`);\n for (const file of result.conflicts) {\n console.log(` ! ${file}`);\n }\n console.log(\"\\nResolve conflicts or use --force to overwrite\");\n }\n\n if (result.errors.length > 0) {\n console.error(`\\nErrors:`);\n for (const error of result.errors) {\n console.error(` ${error}`);\n }\n }\n\n if (!result.success) {\n process.exit(1);\n }\n\n if (result.pulled.length === 0 && result.conflicts.length === 0) {\n console.log(\"Nothing to pull - already in sync\");\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n\n/**\n * Show sync status\n */\nexport async function syncStatusCommand(options: { dir?: string; global?: boolean }): Promise<void> {\n const memoryDir = resolveMemoryDir({\n dir: options.dir,\n global: options.global,\n });\n\n if (!(await isInitialized(memoryDir))) {\n exitWithError(`${formatPath(memoryDir)} is not initialized.`);\n }\n\n try {\n const detection = await detectConflicts(memoryDir);\n const { summary } = detection;\n\n console.log(`Sync status for ${formatPath(memoryDir)}`);\n console.log(\"-\".repeat(50));\n\n if (summary.unchanged > 0) {\n console.log(` Unchanged: ${summary.unchanged}`);\n }\n if (summary.localOnly > 0) {\n console.log(` Local changes: ${summary.localOnly} (push to sync)`);\n }\n if (summary.remoteOnly > 0) {\n console.log(` Remote changes: ${summary.remoteOnly} (pull to sync)`);\n }\n if (summary.newLocal > 0) {\n console.log(` New local: ${summary.newLocal}`);\n }\n if (summary.newRemote > 0) {\n console.log(` New remote: ${summary.newRemote}`);\n }\n if (summary.deletedLocal > 0) {\n console.log(` Deleted local: ${summary.deletedLocal}`);\n }\n if (summary.deletedRemote > 0) {\n console.log(` Deleted remote: ${summary.deletedRemote}`);\n }\n if (summary.conflicts > 0) {\n console.log(` CONFLICTS: ${summary.conflicts}`);\n }\n\n const totalChanges =\n summary.localOnly +\n summary.remoteOnly +\n summary.newLocal +\n summary.newRemote +\n summary.conflicts;\n\n if (totalChanges === 0) {\n console.log(\"\\n All files in sync!\");\n } else {\n console.log(`\\n Total changes: ${totalChanges}`);\n if (summary.conflicts > 0) {\n console.log(\" Run 'minimem push --force' or 'minimem pull --force' to resolve\");\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(message);\n }\n}\n","/**\n * minimem daemon - Background sync daemon commands\n */\n\nimport fs from \"node:fs/promises\";\n\nimport {\n startDaemon,\n startDaemonBackground,\n stopDaemon,\n getDaemonStatus,\n isDaemonRunning,\n getDaemonLogPath,\n} from \"../sync/daemon.js\";\nimport { exitWithError } from \"../config.js\";\n\nexport type DaemonOptions = {\n background?: boolean;\n foreground?: boolean;\n};\n\n/**\n * Start the daemon\n */\nexport async function daemonCommand(options: DaemonOptions): Promise<void> {\n // If --foreground is specified, run in foreground (used by background spawn)\n if (options.foreground) {\n console.log(\"Starting daemon in foreground...\");\n try {\n await startDaemon();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(`Daemon: ${message}`);\n }\n return;\n }\n\n // Check if already running\n if (await isDaemonRunning()) {\n console.log(\"Daemon is already running.\");\n console.log(\"Use 'minimem daemon:stop' to stop it.\");\n return;\n }\n\n if (options.background) {\n console.log(\"Starting daemon in background...\");\n try {\n const pid = await startDaemonBackground();\n console.log(`Daemon started with PID ${pid}`);\n console.log(`Log file: ${getDaemonLogPath()}`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(`Failed to start daemon: ${message}`);\n }\n } else {\n console.log(\"Starting daemon in foreground...\");\n console.log(\"Press Ctrl+C to stop.\");\n console.log(\"\");\n try {\n await startDaemon();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(`Daemon: ${message}`);\n }\n }\n}\n\n/**\n * Stop the daemon\n */\nexport async function daemonStopCommand(): Promise<void> {\n const status = await getDaemonStatus();\n\n if (!status.running) {\n console.log(\"Daemon is not running.\");\n return;\n }\n\n console.log(`Stopping daemon (PID ${status.pid})...`);\n\n const stopped = await stopDaemon();\n\n if (stopped) {\n console.log(\"Daemon stopped.\");\n } else {\n exitWithError(\"Failed to stop daemon.\");\n }\n}\n\n/**\n * Show daemon status\n */\nexport async function daemonStatusCommand(): Promise<void> {\n const status = await getDaemonStatus();\n\n if (status.running) {\n console.log(\"Daemon status: running\");\n console.log(` PID: ${status.pid}`);\n console.log(` Log: ${getDaemonLogPath()}`);\n } else {\n console.log(\"Daemon status: stopped\");\n }\n}\n\nexport type LogOptions = {\n lines?: number;\n follow?: boolean;\n};\n\n/**\n * Show daemon logs\n */\nexport async function daemonLogsCommand(options: LogOptions): Promise<void> {\n const logPath = getDaemonLogPath();\n\n try {\n const content = await fs.readFile(logPath, \"utf-8\");\n const lines = content.split(\"\\n\").filter(Boolean);\n\n const numLines = options.lines ?? 50;\n const displayLines = lines.slice(-numLines);\n\n for (const line of displayLines) {\n console.log(line);\n }\n\n if (options.follow) {\n console.log(\"\\n--- Following log (Ctrl+C to stop) ---\\n\");\n\n // Simple follow implementation using polling\n let lastSize = (await fs.stat(logPath)).size;\n\n const poll = async () => {\n try {\n const stats = await fs.stat(logPath);\n if (stats.size > lastSize) {\n const fd = await fs.open(logPath, \"r\");\n const buffer = Buffer.alloc(stats.size - lastSize);\n await fd.read(buffer, 0, buffer.length, lastSize);\n await fd.close();\n\n process.stdout.write(buffer.toString());\n lastSize = stats.size;\n }\n } catch {\n // File may have been rotated\n lastSize = 0;\n }\n };\n\n const interval = setInterval(poll, 1000);\n\n process.on(\"SIGINT\", () => {\n clearInterval(interval);\n process.exit(0);\n });\n\n // Keep running\n await new Promise(() => {});\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n console.log(\"No daemon log found.\");\n } else {\n const message = error instanceof Error ? error.message : String(error);\n exitWithError(`Error reading log: ${message}`);\n }\n }\n}\n","/**\n * Sync daemon - watches directories and syncs automatically\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\n\nimport { createFileWatcher, type WatcherInstance, type FileChange } from \"./watcher.js\";\nimport { push, pull } from \"./operations.js\";\nimport { readRegistry, type Registry } from \"./registry.js\";\nimport { getCentralRepoPath } from \"./central.js\";\nimport { loadXdgConfig, getSyncConfig } from \"../config.js\";\nimport { validateRegistry, type ValidationResult } from \"./validation.js\";\n\nconst DAEMON_LOG_FILE = \"daemon.log\";\nconst PID_FILE = \"daemon.pid\";\nconst MAX_LOG_SIZE = 1024 * 1024; // 1MB\n\nexport type DaemonOptions = {\n /** Run in background (detach from terminal) */\n background?: boolean;\n /** Sync interval in milliseconds (for central repo polling) */\n pollInterval?: number;\n /** Validation interval in milliseconds (default: 5 minutes) */\n validationInterval?: number;\n /** Log level */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n};\n\nexport type DaemonStatus = {\n running: boolean;\n pid?: number;\n startTime?: string;\n watchedDirs?: string[];\n};\n\n/**\n * Get the daemon directory path\n */\nexport function getDaemonDir(): string {\n return path.join(os.homedir(), \".minimem\");\n}\n\n/**\n * Get PID file path\n */\nexport function getPidFilePath(): string {\n return path.join(getDaemonDir(), PID_FILE);\n}\n\n/**\n * Get daemon log path\n */\nexport function getDaemonLogPath(): string {\n return path.join(getDaemonDir(), DAEMON_LOG_FILE);\n}\n\n/**\n * Check if daemon is running\n */\nexport async function isDaemonRunning(): Promise<boolean> {\n const pidFile = getPidFilePath();\n\n try {\n const content = await fs.readFile(pidFile, \"utf-8\");\n const pid = parseInt(content.trim(), 10);\n\n if (isNaN(pid)) {\n return false;\n }\n\n // Check if process is running\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n // Process not running, clean up stale PID file\n await fs.unlink(pidFile).catch(() => {});\n return false;\n }\n } catch {\n return false;\n }\n}\n\n/**\n * Get daemon status\n */\nexport async function getDaemonStatus(): Promise<DaemonStatus> {\n const running = await isDaemonRunning();\n\n if (!running) {\n return { running: false };\n }\n\n const pidFile = getPidFilePath();\n const content = await fs.readFile(pidFile, \"utf-8\");\n const pid = parseInt(content.trim(), 10);\n\n return {\n running: true,\n pid,\n };\n}\n\n/**\n * Write to daemon log\n */\nasync function writeLog(\n message: string,\n level: \"debug\" | \"info\" | \"warn\" | \"error\" = \"info\"\n): Promise<void> {\n const logPath = getDaemonLogPath();\n const timestamp = new Date().toISOString();\n const line = `[${timestamp}] [${level.toUpperCase()}] ${message}\\n`;\n\n try {\n await fs.mkdir(path.dirname(logPath), { recursive: true });\n\n // Rotate log if too large\n try {\n const stats = await fs.stat(logPath);\n if (stats.size > MAX_LOG_SIZE) {\n await fs.rename(logPath, `${logPath}.old`);\n }\n } catch {\n // File doesn't exist\n }\n\n await fs.appendFile(logPath, line);\n } catch (error) {\n console.error(`Failed to write log: ${error}`);\n }\n}\n\n/**\n * Stop the daemon\n */\nexport async function stopDaemon(): Promise<boolean> {\n const status = await getDaemonStatus();\n\n if (!status.running || !status.pid) {\n return false;\n }\n\n try {\n process.kill(status.pid, \"SIGTERM\");\n\n // Wait for process to exit\n let attempts = 0;\n while (attempts < 10) {\n await new Promise((r) => setTimeout(r, 500));\n if (!(await isDaemonRunning())) {\n return true;\n }\n attempts++;\n }\n\n // Force kill if still running\n try {\n process.kill(status.pid, \"SIGKILL\");\n } catch {\n // Process may have already exited\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Start the daemon\n */\nexport async function startDaemon(options: DaemonOptions = {}): Promise<void> {\n const pollInterval = options.pollInterval ?? 30000; // 30 seconds\n\n // Check if already running\n if (await isDaemonRunning()) {\n throw new Error(\"Daemon is already running\");\n }\n\n // Write PID file\n const daemonDir = getDaemonDir();\n await fs.mkdir(daemonDir, { recursive: true });\n await fs.writeFile(getPidFilePath(), String(process.pid));\n\n await writeLog(\"Daemon starting\");\n\n // Get central repo path\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n await writeLog(\"No central repository configured\", \"warn\");\n }\n\n // Get all directories with sync enabled from registry\n const watchedDirs: Map<string, WatcherInstance> = new Map();\n let running = true;\n\n // Load directories from registry\n async function loadWatchedDirs(): Promise<void> {\n if (!centralRepo) return;\n\n try {\n const registry = await readRegistry(centralRepo);\n\n // Get local directories that should be watched\n const xdgConfig = await loadXdgConfig();\n const machineId = xdgConfig.machineId;\n\n for (const mapping of registry.mappings) {\n if (mapping.machineId !== machineId) continue;\n\n const localPath = mapping.localPath;\n\n // Skip if already watching\n if (watchedDirs.has(localPath)) continue;\n\n // Check if sync is enabled for this directory\n try {\n const syncConfig = await getSyncConfig(localPath);\n if (!syncConfig.enabled) continue;\n\n // Start watcher\n const watcher = createFileWatcher(localPath, {\n debounceMs: 2000,\n });\n\n watcher.on(\"changes\", async (changes: FileChange[]) => {\n await handleLocalChanges(localPath, changes);\n });\n\n watchedDirs.set(localPath, watcher);\n await writeLog(`Watching directory: ${localPath}`);\n } catch (error) {\n await writeLog(`Failed to watch ${localPath}: ${error}`, \"error\");\n }\n }\n } catch (error) {\n await writeLog(`Failed to load registry: ${error}`, \"error\");\n }\n }\n\n // Handle local file changes\n async function handleLocalChanges(\n memoryDir: string,\n changes: FileChange[]\n ): Promise<void> {\n await writeLog(`Local changes in ${memoryDir}: ${changes.map((c) => c.file).join(\", \")}`);\n\n try {\n const syncConfig = await getSyncConfig(memoryDir);\n\n if (syncConfig.autoSync) {\n await writeLog(`Auto-pushing changes from ${memoryDir}`);\n const result = await push(memoryDir, { dryRun: false });\n\n if (result.success) {\n await writeLog(`Pushed ${result.pushed.length} files from ${memoryDir}`);\n } else {\n await writeLog(\n `Push failed for ${memoryDir}: ${result.errors.join(\", \")}`,\n \"error\"\n );\n }\n }\n } catch (error) {\n await writeLog(`Failed to handle changes in ${memoryDir}: ${error}`, \"error\");\n }\n }\n\n // Poll central repo for changes\n async function pollCentralRepo(): Promise<void> {\n if (!centralRepo) return;\n\n try {\n // Check for changes in central repo that need to be pulled\n for (const [localPath] of watchedDirs) {\n try {\n const syncConfig = await getSyncConfig(localPath);\n\n if (syncConfig.autoSync) {\n const result = await pull(localPath, { dryRun: true });\n\n if (result.pulled.length > 0) {\n await writeLog(`Remote changes detected for ${localPath}, pulling...`);\n await pull(localPath, { dryRun: false });\n }\n }\n } catch (error) {\n await writeLog(`Failed to check/pull for ${localPath}: ${error}`, \"error\");\n }\n }\n } catch (error) {\n await writeLog(`Failed to poll central repo: ${error}`, \"error\");\n }\n }\n\n // Cleanup function\n async function cleanup(): Promise<void> {\n running = false;\n await writeLog(\"Daemon stopping\");\n\n // Close all watchers\n for (const [dir, watcher] of watchedDirs) {\n try {\n await watcher.close();\n await writeLog(`Stopped watching: ${dir}`);\n } catch (error) {\n await writeLog(`Error closing watcher for ${dir}: ${error}`, \"error\");\n }\n }\n watchedDirs.clear();\n\n // Remove PID file\n try {\n await fs.unlink(getPidFilePath());\n } catch {\n // Ignore\n }\n\n await writeLog(\"Daemon stopped\");\n }\n\n // Handle signals\n process.on(\"SIGTERM\", async () => {\n await cleanup();\n process.exit(0);\n });\n\n process.on(\"SIGINT\", async () => {\n await cleanup();\n process.exit(0);\n });\n\n // Validate registry on startup\n async function runValidation(): Promise<void> {\n try {\n const result = await validateRegistry();\n\n if (result.issues.length > 0) {\n for (const issue of result.issues) {\n const level = issue.severity === \"error\" ? \"error\" : \"warn\";\n await writeLog(`Validation: ${issue.message}`, level);\n }\n }\n } catch (error) {\n await writeLog(`Validation failed: ${error}`, \"error\");\n }\n }\n\n // Initial load and validation\n await runValidation();\n await loadWatchedDirs();\n\n // Validation interval tracking\n const validationInterval = options.validationInterval ?? 5 * 60 * 1000; // 5 minutes\n let lastValidation = Date.now();\n\n // Main loop\n while (running) {\n await new Promise((r) => setTimeout(r, pollInterval));\n\n if (!running) break;\n\n // Reload directories in case new ones were added\n await loadWatchedDirs();\n\n // Poll central repo for changes\n await pollCentralRepo();\n\n // Periodic validation\n if (Date.now() - lastValidation > validationInterval) {\n await runValidation();\n lastValidation = Date.now();\n }\n }\n}\n\n/**\n * Run daemon in background (fork process)\n */\nexport async function startDaemonBackground(): Promise<number> {\n const { spawn } = await import(\"node:child_process\");\n\n // Get the path to the CLI\n const cliPath = process.argv[1];\n\n const child = spawn(process.execPath, [cliPath, \"daemon\", \"--foreground\"], {\n detached: true,\n stdio: \"ignore\",\n });\n\n child.unref();\n\n if (child.pid) {\n // Wait a moment and verify it started\n await new Promise((r) => setTimeout(r, 1000));\n\n if (await isDaemonRunning()) {\n return child.pid;\n }\n }\n\n throw new Error(\"Failed to start daemon in background\");\n}\n","/**\n * File watcher with debouncing for memory directories\n */\n\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport path from \"node:path\";\nimport { EventEmitter } from \"node:events\";\n\nimport { listSyncableFiles } from \"./state.js\";\n\nexport type WatcherEvent = \"add\" | \"change\" | \"unlink\";\n\nexport type FileChange = {\n event: WatcherEvent;\n file: string; // Relative path\n};\n\nexport type WatcherOptions = {\n /** Debounce interval in milliseconds (default: 2000) */\n debounceMs?: number;\n /** Patterns to include (default: MEMORY.md, memory/*.md) */\n include?: string[];\n /** Patterns to exclude */\n exclude?: string[];\n /** Use polling instead of native events (for network drives) */\n usePolling?: boolean;\n /** Polling interval in milliseconds (default: 1000) */\n pollInterval?: number;\n};\n\nexport type WatcherInstance = {\n /** Stop watching and clean up */\n close: () => Promise<void>;\n /** Add event listener */\n on: (event: \"changes\", listener: (changes: FileChange[]) => void) => void;\n /** Remove event listener */\n off: (event: \"changes\", listener: (changes: FileChange[]) => void) => void;\n /** Whether the watcher is ready */\n ready: boolean;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 2000;\nconst DEFAULT_POLL_INTERVAL = 1000;\n\nconst DEFAULT_INCLUDE = [\"MEMORY.md\", \"memory/**/*.md\"];\nconst DEFAULT_EXCLUDE = [\".minimem/**\", \"node_modules/**\", \".git/**\"];\n\n/**\n * Create a file watcher for a memory directory\n */\nexport function createFileWatcher(\n memoryDir: string,\n options: WatcherOptions = {}\n): WatcherInstance {\n const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n const include = options.include ?? DEFAULT_INCLUDE;\n const exclude = options.exclude ?? DEFAULT_EXCLUDE;\n\n const emitter = new EventEmitter();\n let watcher: FSWatcher | null = null;\n let ready = false;\n\n // Pending changes for debouncing\n let pendingChanges: Map<string, FileChange> = new Map();\n let debounceTimer: NodeJS.Timeout | null = null;\n\n /**\n * Flush pending changes\n */\n const flushChanges = () => {\n if (pendingChanges.size > 0) {\n const changes = Array.from(pendingChanges.values());\n pendingChanges = new Map();\n emitter.emit(\"changes\", changes);\n }\n debounceTimer = null;\n };\n\n /**\n * Schedule a debounced flush\n */\n const scheduleFlush = () => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(flushChanges, debounceMs);\n };\n\n /**\n * Handle a file event\n */\n const handleEvent = (event: WatcherEvent, filePath: string) => {\n // Get relative path\n const relativePath = path.relative(memoryDir, filePath);\n\n // Skip files in .minimem\n if (relativePath.startsWith(\".minimem\")) {\n return;\n }\n\n // Check if file matches include patterns\n const isIncluded = include.some((pattern) => {\n if (pattern.includes(\"*\")) {\n // Simple glob matching\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*\\*/g, \".*\").replace(/\\*/g, \"[^/]*\") + \"$\"\n );\n return regex.test(relativePath);\n }\n return relativePath === pattern || relativePath.startsWith(pattern + \"/\");\n });\n\n if (!isIncluded) {\n return;\n }\n\n // Check if file matches exclude patterns\n const isExcluded = exclude.some((pattern) => {\n if (pattern.includes(\"*\")) {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*\\*/g, \".*\").replace(/\\*/g, \"[^/]*\") + \"$\"\n );\n return regex.test(relativePath);\n }\n return relativePath === pattern || relativePath.startsWith(pattern);\n });\n\n if (isExcluded) {\n return;\n }\n\n // Add to pending changes (later events override earlier for same file)\n pendingChanges.set(relativePath, { event, file: relativePath });\n scheduleFlush();\n };\n\n // Create watcher\n const watchPaths = include.map((pattern) => path.join(memoryDir, pattern));\n\n watcher = chokidar.watch(watchPaths, {\n ignored: exclude.map((pattern) => path.join(memoryDir, pattern)),\n persistent: true,\n ignoreInitial: true,\n usePolling: options.usePolling ?? false,\n interval: options.pollInterval ?? DEFAULT_POLL_INTERVAL,\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 100,\n },\n });\n\n watcher\n .on(\"add\", (filePath) => handleEvent(\"add\", filePath))\n .on(\"change\", (filePath) => handleEvent(\"change\", filePath))\n .on(\"unlink\", (filePath) => handleEvent(\"unlink\", filePath))\n .on(\"ready\", () => {\n ready = true;\n })\n .on(\"error\", (error) => {\n console.error(`Watcher error: ${error}`);\n });\n\n return {\n close: async () => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n debounceTimer = null;\n }\n if (watcher) {\n await watcher.close();\n watcher = null;\n }\n emitter.removeAllListeners();\n },\n\n on: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.on(event, listener);\n },\n\n off: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.off(event, listener);\n },\n\n get ready() {\n return ready;\n },\n };\n}\n\n/**\n * Watch multiple directories\n */\nexport function createMultiDirWatcher(\n memoryDirs: string[],\n options: WatcherOptions = {}\n): WatcherInstance {\n const watchers = memoryDirs.map((dir) => ({\n dir,\n watcher: createFileWatcher(dir, options),\n }));\n\n const emitter = new EventEmitter();\n\n // Forward events from all watchers\n for (const { dir, watcher } of watchers) {\n watcher.on(\"changes\", (changes) => {\n // Add directory info to changes\n const changesWithDir = changes.map((c) => ({\n ...c,\n file: path.join(dir, c.file),\n }));\n emitter.emit(\"changes\", changesWithDir);\n });\n }\n\n return {\n close: async () => {\n await Promise.all(watchers.map(({ watcher }) => watcher.close()));\n emitter.removeAllListeners();\n },\n\n on: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.on(event, listener);\n },\n\n off: (event: \"changes\", listener: (changes: FileChange[]) => void) => {\n emitter.off(event, listener);\n },\n\n get ready() {\n return watchers.every(({ watcher }) => watcher.ready);\n },\n };\n}\n","/**\n * Registry validation\n *\n * Validates registry for path collisions, stale mappings, and missing directories.\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { readRegistry, type Registry, type RegistryMapping } from \"./registry.js\";\nimport { getCentralRepoPath } from \"./central.js\";\nimport { loadXdgConfig } from \"../config.js\";\n\nexport type ValidationIssue = {\n type: \"collision\" | \"stale\" | \"missing\" | \"orphan\";\n severity: \"warning\" | \"error\";\n message: string;\n path?: string;\n machineId?: string;\n details?: Record<string, unknown>;\n};\n\nexport type ValidationResult = {\n valid: boolean;\n issues: ValidationIssue[];\n stats: {\n totalMappings: number;\n activeMappings: number;\n staleMappings: number;\n collisions: number;\n missingDirs: number;\n };\n};\n\nconst STALE_THRESHOLD_DAYS = 30;\n\n/**\n * Validate the registry\n */\nexport async function validateRegistry(): Promise<ValidationResult> {\n const result: ValidationResult = {\n valid: true,\n issues: [],\n stats: {\n totalMappings: 0,\n activeMappings: 0,\n staleMappings: 0,\n collisions: 0,\n missingDirs: 0,\n },\n };\n\n const centralRepo = await getCentralRepoPath();\n if (!centralRepo) {\n result.issues.push({\n type: \"missing\",\n severity: \"warning\",\n message: \"No central repository configured\",\n });\n return result;\n }\n\n let registry: Registry;\n try {\n registry = await readRegistry(centralRepo);\n } catch (error) {\n result.issues.push({\n type: \"missing\",\n severity: \"error\",\n message: `Failed to read registry: ${error}`,\n });\n result.valid = false;\n return result;\n }\n\n const xdgConfig = await loadXdgConfig();\n const currentMachineId = xdgConfig.machineId;\n const now = new Date();\n const staleThreshold = new Date(now.getTime() - STALE_THRESHOLD_DAYS * 24 * 60 * 60 * 1000);\n\n result.stats.totalMappings = registry.mappings.length;\n\n // Group mappings by central path to detect collisions\n const pathToMappings = new Map<string, RegistryMapping[]>();\n\n for (const mapping of registry.mappings) {\n const existing = pathToMappings.get(mapping.path) || [];\n existing.push(mapping);\n pathToMappings.set(mapping.path, existing);\n }\n\n // Check for collisions\n for (const [centralPath, mappings] of pathToMappings) {\n if (mappings.length > 1) {\n // Multiple machines mapping to same path\n const machineIds = mappings.map((m) => m.machineId);\n const uniqueMachines = new Set(machineIds);\n\n if (uniqueMachines.size > 1) {\n result.issues.push({\n type: \"collision\",\n severity: \"error\",\n message: `Path '${centralPath}' is mapped by multiple machines: ${Array.from(uniqueMachines).join(\", \")}`,\n path: centralPath,\n details: { machines: Array.from(uniqueMachines) },\n });\n result.stats.collisions++;\n result.valid = false;\n }\n }\n }\n\n // Check each mapping\n for (const mapping of registry.mappings) {\n // Check for stale mappings\n const lastSyncDate = new Date(mapping.lastSync);\n if (lastSyncDate < staleThreshold) {\n const daysSinceSync = Math.floor(\n (now.getTime() - lastSyncDate.getTime()) / (24 * 60 * 60 * 1000)\n );\n\n result.issues.push({\n type: \"stale\",\n severity: \"warning\",\n message: `Mapping '${mapping.path}' by '${mapping.machineId}' is stale (last sync: ${daysSinceSync} days ago)`,\n path: mapping.path,\n machineId: mapping.machineId,\n details: { lastSync: mapping.lastSync, daysSinceSync },\n });\n result.stats.staleMappings++;\n } else {\n result.stats.activeMappings++;\n }\n\n // Check if local directory exists (only for current machine)\n if (mapping.machineId === currentMachineId) {\n const localPath = expandPath(mapping.localPath);\n try {\n await fs.access(localPath);\n } catch {\n result.issues.push({\n type: \"missing\",\n severity: \"warning\",\n message: `Local directory no longer exists: ${mapping.localPath}`,\n path: mapping.path,\n machineId: mapping.machineId,\n details: { localPath: mapping.localPath },\n });\n result.stats.missingDirs++;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Expand path (handle ~ for home directory)\n */\nfunction expandPath(p: string): string {\n if (p.startsWith(\"~/\")) {\n return path.join(process.env.HOME || \"\", p.slice(2));\n }\n return p;\n}\n\n/**\n * Format validation result for display\n */\nexport function formatValidationResult(result: ValidationResult): string {\n const lines: string[] = [];\n\n lines.push(\"Registry Validation Results\");\n lines.push(\"-\".repeat(40));\n\n lines.push(`Total mappings: ${result.stats.totalMappings}`);\n lines.push(`Active mappings: ${result.stats.activeMappings}`);\n\n if (result.stats.staleMappings > 0) {\n lines.push(`Stale mappings: ${result.stats.staleMappings}`);\n }\n if (result.stats.collisions > 0) {\n lines.push(`Collisions: ${result.stats.collisions}`);\n }\n if (result.stats.missingDirs > 0) {\n lines.push(`Missing directories: ${result.stats.missingDirs}`);\n }\n\n if (result.issues.length > 0) {\n lines.push(\"\");\n lines.push(\"Issues:\");\n\n for (const issue of result.issues) {\n const prefix = issue.severity === \"error\" ? \"ERROR\" : \"WARN\";\n lines.push(` [${prefix}] ${issue.message}`);\n }\n } else {\n lines.push(\"\");\n lines.push(\"No issues found.\");\n }\n\n lines.push(\"\");\n lines.push(result.valid ? \"Registry is valid.\" : \"Registry has errors that need attention.\");\n\n return lines.join(\"\\n\");\n}\n","/**\n * Version management for the CLI\n *\n * Reads the version from package.json at runtime for consistency.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * Get the package version from package.json\n *\n * This reads from the package.json at runtime to ensure the CLI\n * version always matches the published package version.\n */\nfunction getPackageVersion(): string {\n try {\n // In ESM, we need to get __dirname equivalent\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n\n // Navigate from src/cli/ to package root\n const packagePath = join(__dirname, \"../../package.json\");\n const packageJson = JSON.parse(readFileSync(packagePath, \"utf-8\"));\n return packageJson.version || \"0.0.0\";\n } catch {\n // Fallback if we can't read package.json\n // This might happen in bundled builds where path resolution differs\n return \"0.0.0\";\n }\n}\n\nexport const VERSION = getPackageVersion();\n"],"mappings":"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","names":["fs","path","path","os","path","os","config","path","config","os","fs","path","config","fs","path","crypto","fs","path","logError","fs","path","crypto","os","formatPath","formatPath","path","fsSync","path","os","payload","provider","client","resolve","status","text","status","resolve","runWithConcurrency","config","path","fs","logError","resolve","config","status","config","status","config","config","fs","path","config","resolve","fs","path","path","config","status","loadConfigFile","fs","config","fs","path","fs","path","fs","path","os","crypto","fs","path","path","fs","fs","config","path","fs","path","fs","fs","path","crypto","fs","path","crypto","walkDir","fs","path","fs","path","fs","path","path","fs","path","status","path","fs","resolve","execSync","content","status","ensureDir","fs","path","crypto","status","fs","fs","path","os","chokidar","path","fs","path","expandPath","fs","path","path","os","fs","status","spawn","status","fs","dirname","join"]}
|