@patravishek/memex 0.2.0

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.
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getMemexDir = getMemexDir;
37
+ exports.memoryExists = memoryExists;
38
+ exports.loadMemory = loadMemory;
39
+ exports.saveMemory = saveMemory;
40
+ exports.initMemory = initMemory;
41
+ exports.clearMemory = clearMemory;
42
+ exports.formatMemoryForPrompt = formatMemoryForPrompt;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
45
+ const db_js_1 = require("../storage/db.js");
46
+ const queries_js_1 = require("../storage/queries.js");
47
+ const LEGACY_MEMORY_FILE = "memory.json";
48
+ function getMemexDir(projectPath) {
49
+ return path.join(projectPath, ".memex");
50
+ }
51
+ function memoryExists(projectPath) {
52
+ const memexDir = getMemexDir(projectPath);
53
+ const db = (0, db_js_1.getDb)(memexDir);
54
+ return (0, queries_js_1.projectExists)(db, projectPath);
55
+ }
56
+ function loadMemory(projectPath) {
57
+ const memexDir = getMemexDir(projectPath);
58
+ const db = (0, db_js_1.getDb)(memexDir);
59
+ // Auto-migrate legacy memory.json on first access
60
+ const legacyPath = path.join(memexDir, LEGACY_MEMORY_FILE);
61
+ if (!(0, queries_js_1.projectExists)(db, projectPath) && fs.existsSync(legacyPath)) {
62
+ try {
63
+ const legacy = JSON.parse(fs.readFileSync(legacyPath, "utf-8"));
64
+ (0, queries_js_1.migrateFromJson)(db, legacy);
65
+ fs.renameSync(legacyPath, legacyPath + ".bak");
66
+ }
67
+ catch {
68
+ // If migration fails, continue — worst case is a fresh start
69
+ }
70
+ }
71
+ return (0, queries_js_1.getProject)(db, projectPath);
72
+ }
73
+ function saveMemory(projectPath, memory) {
74
+ const memexDir = getMemexDir(projectPath);
75
+ fs.mkdirSync(memexDir, { recursive: true });
76
+ memory.lastUpdated = new Date().toISOString();
77
+ const db = (0, db_js_1.getDb)(memexDir);
78
+ (0, queries_js_1.upsertProject)(db, memory);
79
+ }
80
+ function initMemory(projectPath) {
81
+ const memory = {
82
+ projectName: path.basename(projectPath),
83
+ projectPath,
84
+ stack: [],
85
+ description: "",
86
+ keyDecisions: [],
87
+ currentFocus: "",
88
+ pendingTasks: [],
89
+ importantFiles: [],
90
+ gotchas: [],
91
+ recentSessions: [],
92
+ lastConversation: [],
93
+ lastUpdated: new Date().toISOString(),
94
+ };
95
+ saveMemory(projectPath, memory);
96
+ return memory;
97
+ }
98
+ function clearMemory(projectPath, keepSessions = false) {
99
+ const memexDir = getMemexDir(projectPath);
100
+ const db = (0, db_js_1.getDb)(memexDir);
101
+ if (keepSessions) {
102
+ // Only wipe project metadata, leave session history intact
103
+ const blank = initMemory(projectPath);
104
+ (0, queries_js_1.upsertProject)(db, blank);
105
+ }
106
+ else {
107
+ (0, queries_js_1.deleteProject)(db, projectPath);
108
+ }
109
+ }
110
+ function formatMemoryForPrompt(memory) {
111
+ const lines = [];
112
+ lines.push(`Project: ${memory.projectName}`);
113
+ lines.push(`Path: ${memory.projectPath}`);
114
+ if (memory.description) {
115
+ lines.push(`\nWhat this project does:\n${memory.description}`);
116
+ }
117
+ if (memory.stack.length > 0) {
118
+ lines.push(`\nTech stack: ${memory.stack.join(", ")}`);
119
+ }
120
+ if (memory.currentFocus) {
121
+ lines.push(`\nCurrent focus: ${memory.currentFocus}`);
122
+ }
123
+ if (memory.pendingTasks.length > 0) {
124
+ lines.push("\nPending tasks:");
125
+ memory.pendingTasks.forEach((t) => lines.push(` - ${t}`));
126
+ }
127
+ if (memory.keyDecisions.length > 0) {
128
+ lines.push("\nKey decisions made:");
129
+ memory.keyDecisions.forEach((d) => lines.push(` - ${d.decision} (reason: ${d.reason})`));
130
+ }
131
+ if (memory.importantFiles.length > 0) {
132
+ lines.push("\nImportant files:");
133
+ memory.importantFiles.forEach((f) => lines.push(` - ${f.filePath}: ${f.purpose}`));
134
+ }
135
+ if (memory.gotchas.length > 0) {
136
+ lines.push("\nGotchas (things that tripped us up before):");
137
+ memory.gotchas.forEach((g) => lines.push(` - ${g}`));
138
+ }
139
+ if (memory.recentSessions.length > 0) {
140
+ const last = memory.recentSessions[memory.recentSessions.length - 1];
141
+ lines.push(`\nLast session (${last.date}):\n${last.summary}`);
142
+ }
143
+ return lines.join("\n");
144
+ }
145
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,kCAEC;AAED,oCAIC;AAED,gCAmBC;AAED,gCASC;AAED,gCAkBC;AAED,kCAcC;AAED,sDAgDC;AAlLD,uCAAyB;AACzB,2CAA6B;AAE7B,4CAAyC;AACzC,sDAM+B;AAwC/B,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEzC,SAAgB,WAAW,CAAC,WAAmB;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC1C,CAAC;AAED,SAAgB,YAAY,CAAC,WAAmB;IAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAA,aAAK,EAAC,QAAQ,CAAC,CAAC;IAC3B,OAAO,IAAA,0BAAa,EAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED,SAAgB,UAAU,CAAC,WAAmB;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAA,aAAK,EAAC,QAAQ,CAAC,CAAC;IAE3B,kDAAkD;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAA,0BAAa,EAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACjE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CACvB,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CACpB,CAAC;YACnB,IAAA,4BAAe,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAC5B,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAC,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACP,6DAA6D;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,IAAA,uBAAU,EAAC,EAAE,EAAE,WAAW,CAAC,CAAC;AACrC,CAAC;AAED,SAAgB,UAAU,CACxB,WAAmB,EACnB,MAAqB;IAErB,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAC1C,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,EAAE,GAAG,IAAA,aAAK,EAAC,QAAQ,CAAC,CAAC;IAC3B,IAAA,0BAAa,EAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,SAAgB,UAAU,CAAC,WAAmB;IAC5C,MAAM,MAAM,GAAkB;QAC5B,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QACvC,WAAW;QACX,KAAK,EAAE,EAAE;QACT,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,EAAE;QAChB,YAAY,EAAE,EAAE;QAChB,YAAY,EAAE,EAAE;QAChB,cAAc,EAAE,EAAE;QAClB,OAAO,EAAE,EAAE;QACX,cAAc,EAAE,EAAE;QAClB,gBAAgB,EAAE,EAAE;QACpB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtC,CAAC;IAEF,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,WAAW,CACzB,WAAmB,EACnB,YAAY,GAAG,KAAK;IAEpB,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAA,aAAK,EAAC,QAAQ,CAAC,CAAC;IAE3B,IAAI,YAAY,EAAE,CAAC;QACjB,2DAA2D;QAC3D,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;QACtC,IAAA,0BAAa,EAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,IAAA,0BAAa,EAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAgB,qBAAqB,CAAC,MAAqB;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC/B,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACpC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAChC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,CACtD,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACjC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAC9C,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrE,KAAK,CAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import Database from "better-sqlite3";
2
+ /**
3
+ * Returns a singleton DB connection for the given memex directory.
4
+ * Switches to a new connection if the project path changes.
5
+ */
6
+ export declare function getDb(memexDir: string): Database.Database;
7
+ export declare function closeDb(): void;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.getDb = getDb;
40
+ exports.closeDb = closeDb;
41
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
42
+ const path = __importStar(require("path"));
43
+ const fs = __importStar(require("fs"));
44
+ let _db = null;
45
+ let _dbPath = null;
46
+ /**
47
+ * Returns a singleton DB connection for the given memex directory.
48
+ * Switches to a new connection if the project path changes.
49
+ */
50
+ function getDb(memexDir) {
51
+ const dbPath = path.join(memexDir, "memex.db");
52
+ if (_db && _dbPath === dbPath)
53
+ return _db;
54
+ if (_db)
55
+ _db.close();
56
+ fs.mkdirSync(memexDir, { recursive: true });
57
+ _db = new better_sqlite3_1.default(dbPath);
58
+ _dbPath = dbPath;
59
+ _db.pragma("journal_mode = WAL");
60
+ _db.pragma("foreign_keys = ON");
61
+ runMigrations(_db);
62
+ return _db;
63
+ }
64
+ function closeDb() {
65
+ if (_db) {
66
+ _db.close();
67
+ _db = null;
68
+ _dbPath = null;
69
+ }
70
+ }
71
+ function runMigrations(db) {
72
+ db.exec(`
73
+ CREATE TABLE IF NOT EXISTS schema_version (
74
+ version INTEGER PRIMARY KEY
75
+ );
76
+ `);
77
+ const row = db
78
+ .prepare("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1")
79
+ .get();
80
+ const currentVersion = row?.version ?? 0;
81
+ if (currentVersion < 1) {
82
+ db.exec(`
83
+ -- Core project metadata (one row per tracked project)
84
+ CREATE TABLE IF NOT EXISTS project (
85
+ path TEXT PRIMARY KEY,
86
+ name TEXT NOT NULL DEFAULT '',
87
+ description TEXT NOT NULL DEFAULT '',
88
+ stack TEXT NOT NULL DEFAULT '[]',
89
+ current_focus TEXT NOT NULL DEFAULT '',
90
+ pending_tasks TEXT NOT NULL DEFAULT '[]',
91
+ gotchas TEXT NOT NULL DEFAULT '[]',
92
+ important_files TEXT NOT NULL DEFAULT '[]',
93
+ key_decisions TEXT NOT NULL DEFAULT '[]',
94
+ -- Cached last N turns for fast CLAUDE.md injection (JSON blob)
95
+ last_conversation TEXT NOT NULL DEFAULT '[]',
96
+ created_at TEXT NOT NULL,
97
+ updated_at TEXT NOT NULL
98
+ );
99
+
100
+ -- One row per agent session (started/ended)
101
+ CREATE TABLE IF NOT EXISTS sessions (
102
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
103
+ project_path TEXT NOT NULL,
104
+ agent TEXT NOT NULL DEFAULT 'claude',
105
+ started_at TEXT NOT NULL,
106
+ ended_at TEXT,
107
+ summary TEXT NOT NULL DEFAULT '',
108
+ log_file TEXT,
109
+ FOREIGN KEY (project_path) REFERENCES project(path)
110
+ );
111
+
112
+ -- Individual conversation turns per session (for memex show / search)
113
+ CREATE TABLE IF NOT EXISTS conversation_turns (
114
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
115
+ session_id INTEGER NOT NULL,
116
+ role TEXT NOT NULL,
117
+ content TEXT NOT NULL,
118
+ ts INTEGER NOT NULL,
119
+ FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
120
+ );
121
+
122
+ -- FTS5 index over session summaries for memex search
123
+ CREATE VIRTUAL TABLE IF NOT EXISTS sessions_fts USING fts5(
124
+ summary,
125
+ content='sessions',
126
+ content_rowid='id'
127
+ );
128
+
129
+ CREATE TRIGGER IF NOT EXISTS sessions_ai AFTER INSERT ON sessions BEGIN
130
+ INSERT INTO sessions_fts(rowid, summary) VALUES (new.id, new.summary);
131
+ END;
132
+
133
+ CREATE TRIGGER IF NOT EXISTS sessions_ad AFTER DELETE ON sessions BEGIN
134
+ INSERT INTO sessions_fts(sessions_fts, rowid, summary)
135
+ VALUES('delete', old.id, old.summary);
136
+ END;
137
+
138
+ CREATE TRIGGER IF NOT EXISTS sessions_au AFTER UPDATE OF summary ON sessions BEGIN
139
+ INSERT INTO sessions_fts(sessions_fts, rowid, summary)
140
+ VALUES('delete', old.id, old.summary);
141
+ INSERT INTO sessions_fts(rowid, summary) VALUES (new.id, new.summary);
142
+ END;
143
+
144
+ INSERT INTO schema_version VALUES (1);
145
+ `);
146
+ }
147
+ }
148
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/storage/db.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,sBAgBC;AAED,0BAMC;AAnCD,oEAAsC;AACtC,2CAA6B;AAC7B,uCAAyB;AAEzB,IAAI,GAAG,GAA6B,IAAI,CAAC;AACzC,IAAI,OAAO,GAAkB,IAAI,CAAC;AAElC;;;GAGG;AACH,SAAgB,KAAK,CAAC,QAAgB;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAE/C,IAAI,GAAG,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,GAAG,CAAC;IAE1C,IAAI,GAAG;QAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IAErB,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,GAAG,GAAG,IAAI,wBAAQ,CAAC,MAAM,CAAC,CAAC;IAC3B,OAAO,GAAG,MAAM,CAAC;IAEjB,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACjC,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAEhC,aAAa,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAgB,OAAO;IACrB,IAAI,GAAG,EAAE,CAAC;QACR,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,GAAG,GAAG,IAAI,CAAC;QACX,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,EAAqB;IAC1C,EAAE,CAAC,IAAI,CAAC;;;;GAIP,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CACN,kEAAkE,CACnE;SACA,GAAG,EAAqC,CAAC;IAC5C,MAAM,cAAc,GAAG,GAAG,EAAE,OAAO,IAAI,CAAC,CAAC;IAEzC,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+DP,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,38 @@
1
+ import Database from "better-sqlite3";
2
+ import { ProjectMemory } from "../memory/store.js";
3
+ import { ConversationTurn } from "../core/session-logger.js";
4
+ export interface SessionRow {
5
+ id: number;
6
+ project_path: string;
7
+ agent: string;
8
+ started_at: string;
9
+ ended_at: string | null;
10
+ summary: string;
11
+ log_file: string | null;
12
+ }
13
+ export interface SessionDetail extends SessionRow {
14
+ turns: ConversationTurn[];
15
+ }
16
+ export interface SearchResult extends SessionRow {
17
+ snippet: string;
18
+ }
19
+ export declare function getProject(db: Database.Database, projectPath: string): ProjectMemory | null;
20
+ export declare function upsertProject(db: Database.Database, memory: ProjectMemory): void;
21
+ export declare function deleteProject(db: Database.Database, projectPath: string): void;
22
+ export declare function projectExists(db: Database.Database, projectPath: string): boolean;
23
+ export declare function createSession(db: Database.Database, projectPath: string, agent: string): number;
24
+ export declare function finalizeSession(db: Database.Database, sessionId: number, summary: string, logFile: string, turns: ConversationTurn[]): void;
25
+ export declare function listSessions(db: Database.Database, projectPath?: string, limit?: number): SessionRow[];
26
+ export declare function getSession(db: Database.Database, sessionId: number): SessionDetail | null;
27
+ export declare function getTurns(db: Database.Database, sessionId: number): ConversationTurn[];
28
+ export declare function searchSessions(db: Database.Database, query: string, projectPath?: string): SearchResult[];
29
+ /**
30
+ * Import an existing memory.json into the DB.
31
+ * Called once on first open when a legacy file is found.
32
+ */
33
+ export declare function migrateFromJson(db: Database.Database, memory: ProjectMemory): void;
34
+ /**
35
+ * Delete sessions (and their turns) older than `days` days.
36
+ * Raw JSONL log files are NOT deleted — callers handle that separately.
37
+ */
38
+ export declare function pruneOldSessions(db: Database.Database, projectPath: string, keepDays: number): number;
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getProject = getProject;
37
+ exports.upsertProject = upsertProject;
38
+ exports.deleteProject = deleteProject;
39
+ exports.projectExists = projectExists;
40
+ exports.createSession = createSession;
41
+ exports.finalizeSession = finalizeSession;
42
+ exports.listSessions = listSessions;
43
+ exports.getSession = getSession;
44
+ exports.getTurns = getTurns;
45
+ exports.searchSessions = searchSessions;
46
+ exports.migrateFromJson = migrateFromJson;
47
+ exports.pruneOldSessions = pruneOldSessions;
48
+ const path = __importStar(require("path"));
49
+ // ─── Project ─────────────────────────────────────────────────────────────────
50
+ function getProject(db, projectPath) {
51
+ const row = db
52
+ .prepare("SELECT * FROM project WHERE path = ?")
53
+ .get(projectPath);
54
+ if (!row)
55
+ return null;
56
+ const recentSessions = listSessions(db, projectPath, 5).map((s) => ({
57
+ date: s.ended_at ?? s.started_at,
58
+ summary: s.summary,
59
+ logFile: s.log_file ?? "",
60
+ }));
61
+ const lastSession = recentSessions.at(-1);
62
+ let lastConversation = [];
63
+ const latestSession = listSessions(db, projectPath, 1)[0];
64
+ if (latestSession) {
65
+ lastConversation = getTurns(db, latestSession.id);
66
+ }
67
+ return {
68
+ projectName: row.name,
69
+ projectPath: row.path,
70
+ description: row.description,
71
+ stack: parseJson(row.stack, []),
72
+ currentFocus: row.current_focus,
73
+ pendingTasks: parseJson(row.pending_tasks, []),
74
+ gotchas: parseJson(row.gotchas, []),
75
+ importantFiles: parseJson(row.important_files, []),
76
+ keyDecisions: parseJson(row.key_decisions, []),
77
+ recentSessions,
78
+ lastConversation,
79
+ lastUpdated: row.updated_at,
80
+ };
81
+ }
82
+ function upsertProject(db, memory) {
83
+ const now = new Date().toISOString();
84
+ db.prepare(`
85
+ INSERT INTO project
86
+ (path, name, description, stack, current_focus, pending_tasks,
87
+ gotchas, important_files, key_decisions, last_conversation,
88
+ created_at, updated_at)
89
+ VALUES
90
+ (@path, @name, @description, @stack, @current_focus, @pending_tasks,
91
+ @gotchas, @important_files, @key_decisions, @last_conversation,
92
+ @created_at, @updated_at)
93
+ ON CONFLICT(path) DO UPDATE SET
94
+ name = excluded.name,
95
+ description = excluded.description,
96
+ stack = excluded.stack,
97
+ current_focus = excluded.current_focus,
98
+ pending_tasks = excluded.pending_tasks,
99
+ gotchas = excluded.gotchas,
100
+ important_files = excluded.important_files,
101
+ key_decisions = excluded.key_decisions,
102
+ last_conversation = excluded.last_conversation,
103
+ updated_at = excluded.updated_at
104
+ `).run({
105
+ path: memory.projectPath,
106
+ name: memory.projectName,
107
+ description: memory.description,
108
+ stack: JSON.stringify(memory.stack),
109
+ current_focus: memory.currentFocus,
110
+ pending_tasks: JSON.stringify(memory.pendingTasks),
111
+ gotchas: JSON.stringify(memory.gotchas),
112
+ important_files: JSON.stringify(memory.importantFiles),
113
+ key_decisions: JSON.stringify(memory.keyDecisions),
114
+ last_conversation: JSON.stringify(memory.lastConversation ?? []),
115
+ created_at: now,
116
+ updated_at: now,
117
+ });
118
+ }
119
+ function deleteProject(db, projectPath) {
120
+ // Cascade via FK: sessions → conversation_turns
121
+ const sessionIds = db
122
+ .prepare("SELECT id FROM sessions WHERE project_path = ?")
123
+ .all(projectPath);
124
+ for (const { id } of sessionIds) {
125
+ db.prepare("DELETE FROM conversation_turns WHERE session_id = ?").run(id);
126
+ }
127
+ db.prepare("DELETE FROM sessions WHERE project_path = ?").run(projectPath);
128
+ db.prepare("DELETE FROM project WHERE path = ?").run(projectPath);
129
+ }
130
+ function projectExists(db, projectPath) {
131
+ const row = db
132
+ .prepare("SELECT 1 FROM project WHERE path = ?")
133
+ .get(projectPath);
134
+ return row !== undefined;
135
+ }
136
+ // ─── Sessions ─────────────────────────────────────────────────────────────────
137
+ function createSession(db, projectPath, agent) {
138
+ // Ensure a project row exists (may not exist on very first run)
139
+ const exists = projectExists(db, projectPath);
140
+ if (!exists) {
141
+ const now = new Date().toISOString();
142
+ db.prepare(`
143
+ INSERT OR IGNORE INTO project
144
+ (path, name, created_at, updated_at)
145
+ VALUES (?, ?, ?, ?)
146
+ `).run(projectPath, path.basename(projectPath), now, now);
147
+ }
148
+ const result = db.prepare(`
149
+ INSERT INTO sessions (project_path, agent, started_at)
150
+ VALUES (?, ?, ?)
151
+ `).run(projectPath, agent, new Date().toISOString());
152
+ return result.lastInsertRowid;
153
+ }
154
+ function finalizeSession(db, sessionId, summary, logFile, turns) {
155
+ db.prepare(`
156
+ UPDATE sessions
157
+ SET ended_at = ?, summary = ?, log_file = ?
158
+ WHERE id = ?
159
+ `).run(new Date().toISOString(), summary, logFile, sessionId);
160
+ if (turns.length > 0) {
161
+ const insert = db.prepare(`
162
+ INSERT INTO conversation_turns (session_id, role, content, ts)
163
+ VALUES (?, ?, ?, ?)
164
+ `);
165
+ const insertMany = db.transaction((rows) => {
166
+ for (const t of rows) {
167
+ insert.run(sessionId, t.role, t.content, t.ts);
168
+ }
169
+ });
170
+ insertMany(turns);
171
+ }
172
+ }
173
+ function listSessions(db, projectPath, limit = 20) {
174
+ if (projectPath) {
175
+ return db
176
+ .prepare("SELECT * FROM sessions WHERE project_path = ? ORDER BY started_at DESC LIMIT ?")
177
+ .all(projectPath, limit);
178
+ }
179
+ return db
180
+ .prepare("SELECT * FROM sessions ORDER BY started_at DESC LIMIT ?")
181
+ .all(limit);
182
+ }
183
+ function getSession(db, sessionId) {
184
+ const row = db
185
+ .prepare("SELECT * FROM sessions WHERE id = ?")
186
+ .get(sessionId);
187
+ if (!row)
188
+ return null;
189
+ return { ...row, turns: getTurns(db, sessionId) };
190
+ }
191
+ function getTurns(db, sessionId) {
192
+ return db
193
+ .prepare("SELECT role, content, ts FROM conversation_turns WHERE session_id = ? ORDER BY ts ASC")
194
+ .all(sessionId);
195
+ }
196
+ // ─── Search ───────────────────────────────────────────────────────────────────
197
+ function searchSessions(db, query, projectPath) {
198
+ // FTS5 snippet() for highlighted excerpts
199
+ const ftsQuery = query
200
+ .trim()
201
+ .split(/\s+/)
202
+ .map((w) => `"${w.replace(/"/g, '""')}"`)
203
+ .join(" OR ");
204
+ if (projectPath) {
205
+ return db.prepare(`
206
+ SELECT s.*, snippet(sessions_fts, 0, '[', ']', '...', 12) AS snippet
207
+ FROM sessions_fts
208
+ JOIN sessions s ON s.id = sessions_fts.rowid
209
+ WHERE sessions_fts MATCH ?
210
+ AND s.project_path = ?
211
+ ORDER BY rank
212
+ LIMIT 20
213
+ `).all(ftsQuery, projectPath);
214
+ }
215
+ return db.prepare(`
216
+ SELECT s.*, snippet(sessions_fts, 0, '[', ']', '...', 12) AS snippet
217
+ FROM sessions_fts
218
+ JOIN sessions s ON s.id = sessions_fts.rowid
219
+ WHERE sessions_fts MATCH ?
220
+ ORDER BY rank
221
+ LIMIT 20
222
+ `).all(ftsQuery);
223
+ }
224
+ // ─── Migration ────────────────────────────────────────────────────────────────
225
+ /**
226
+ * Import an existing memory.json into the DB.
227
+ * Called once on first open when a legacy file is found.
228
+ */
229
+ function migrateFromJson(db, memory) {
230
+ upsertProject(db, memory);
231
+ // Seed recentSessions as session rows so history is preserved
232
+ for (const s of memory.recentSessions ?? []) {
233
+ const res = db.prepare(`
234
+ INSERT INTO sessions (project_path, agent, started_at, ended_at, summary, log_file)
235
+ VALUES (?, 'unknown', ?, ?, ?, ?)
236
+ `).run(memory.projectPath, s.date, s.date, s.summary, s.logFile ?? null);
237
+ // Seed last conversation into most recent migrated session
238
+ const isLast = s === memory.recentSessions[memory.recentSessions.length - 1];
239
+ if (isLast && memory.lastConversation?.length) {
240
+ finalizeSession(db, res.lastInsertRowid, s.summary, s.logFile ?? "", memory.lastConversation);
241
+ }
242
+ }
243
+ }
244
+ // ─── Retention ────────────────────────────────────────────────────────────────
245
+ /**
246
+ * Delete sessions (and their turns) older than `days` days.
247
+ * Raw JSONL log files are NOT deleted — callers handle that separately.
248
+ */
249
+ function pruneOldSessions(db, projectPath, keepDays) {
250
+ const cutoff = new Date(Date.now() - keepDays * 24 * 60 * 60 * 1000).toISOString();
251
+ const old = db
252
+ .prepare("SELECT id FROM sessions WHERE project_path = ? AND started_at < ?")
253
+ .all(projectPath, cutoff);
254
+ for (const { id } of old) {
255
+ db.prepare("DELETE FROM conversation_turns WHERE session_id = ?").run(id);
256
+ }
257
+ const result = db
258
+ .prepare("DELETE FROM sessions WHERE project_path = ? AND started_at < ?")
259
+ .run(projectPath, cutoff);
260
+ return result.changes;
261
+ }
262
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
263
+ function parseJson(raw, fallback) {
264
+ try {
265
+ return JSON.parse(raw);
266
+ }
267
+ catch {
268
+ return fallback;
269
+ }
270
+ }
271
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/storage/queries.ts"],"names":[],"mappings":"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"}