import Database from 'better-sqlite3'; import path from 'path'; import fs from 'fs'; const SCHEMA = ` CREATE TABLE IF NOT EXISTS nodes ( id TEXT PRIMARY KEY, kind TEXT NOT NULL, title TEXT NOT NULL, content TEXT NOT NULL DEFAULT '', status TEXT, tags TEXT DEFAULT '[]', metadata TEXT DEFAULT '{}', embedding BLOB, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, is_stale INTEGER DEFAULT 0 ); CREATE TABLE IF NOT EXISTS edges ( id TEXT PRIMARY KEY, from_id TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, to_id TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, type TEXT NOT NULL, metadata TEXT DEFAULT '{}', created_at INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS node_tags ( node_id TEXT NOT NULL REFERENCES nodes(id) ON DELETE CASCADE, tag TEXT NOT NULL, PRIMARY KEY (node_id, tag) ); CREATE INDEX IF NOT EXISTS idx_nodes_kind ON nodes(kind); CREATE INDEX IF NOT EXISTS idx_nodes_status ON nodes(status); CREATE INDEX IF NOT EXISTS idx_nodes_created ON nodes(created_at DESC); CREATE INDEX IF NOT EXISTS idx_nodes_stale ON nodes(is_stale); CREATE INDEX IF NOT EXISTS idx_edges_from ON edges(from_id); CREATE INDEX IF NOT EXISTS idx_edges_to ON edges(to_id); CREATE INDEX IF NOT EXISTS idx_edges_type ON edges(type); CREATE INDEX IF NOT EXISTS idx_tags_tag ON node_tags(tag); `; let _db: Database.Database | null = null; export function getMemoryDir(): string { return path.join(process.cwd(), '.memory'); } export function getDb(): Database.Database { if (_db) return _db; const dir = getMemoryDir(); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } _db = new Database(path.join(dir, 'cortex.db')); _db.pragma('journal_mode = WAL'); _db.pragma('foreign_keys = ON'); _db.exec(SCHEMA); // Migration: add last_accessed_at column const cols = _db.prepare("PRAGMA table_info(nodes)").all() as any[]; if (!cols.some((c: any) => c.name === 'last_accessed_at')) { _db.exec('ALTER TABLE nodes ADD COLUMN last_accessed_at INTEGER'); _db.exec('UPDATE nodes SET last_accessed_at = updated_at WHERE last_accessed_at IS NULL'); } return _db; } export function closeDb(): void { if (_db) { _db.close(); _db = null; } }