kiro-memory 1.5.0 → 1.6.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.
@@ -1,386 +1,10 @@
1
1
  import { createRequire } from 'module';const require = createRequire(import.meta.url);
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
2
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
3
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
4
  }) : x)(function(x) {
7
5
  if (typeof require !== "undefined") return require.apply(this, arguments);
8
6
  throw Error('Dynamic require of "' + x + '" is not supported');
9
7
  });
10
- var __esm = (fn, res) => function __init() {
11
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
- };
13
- var __export = (target, all) => {
14
- for (var name in all)
15
- __defProp(target, name, { get: all[name], enumerable: true });
16
- };
17
-
18
- // src/services/sqlite/Sessions.ts
19
- var Sessions_exports = {};
20
- __export(Sessions_exports, {
21
- completeSession: () => completeSession,
22
- createSession: () => createSession,
23
- failSession: () => failSession,
24
- getActiveSessions: () => getActiveSessions,
25
- getSessionByContentId: () => getSessionByContentId,
26
- getSessionById: () => getSessionById,
27
- getSessionsByProject: () => getSessionsByProject,
28
- updateSessionMemoryId: () => updateSessionMemoryId
29
- });
30
- function createSession(db, contentSessionId, project, userPrompt) {
31
- const now = /* @__PURE__ */ new Date();
32
- const result = db.run(
33
- `INSERT INTO sessions (content_session_id, project, user_prompt, status, started_at, started_at_epoch)
34
- VALUES (?, ?, ?, 'active', ?, ?)`,
35
- [contentSessionId, project, userPrompt, now.toISOString(), now.getTime()]
36
- );
37
- return Number(result.lastInsertRowid);
38
- }
39
- function getSessionByContentId(db, contentSessionId) {
40
- const query = db.query("SELECT * FROM sessions WHERE content_session_id = ?");
41
- return query.get(contentSessionId);
42
- }
43
- function getSessionById(db, id) {
44
- const query = db.query("SELECT * FROM sessions WHERE id = ?");
45
- return query.get(id);
46
- }
47
- function updateSessionMemoryId(db, id, memorySessionId) {
48
- db.run(
49
- "UPDATE sessions SET memory_session_id = ? WHERE id = ?",
50
- [memorySessionId, id]
51
- );
52
- }
53
- function completeSession(db, id) {
54
- const now = /* @__PURE__ */ new Date();
55
- db.run(
56
- `UPDATE sessions
57
- SET status = 'completed', completed_at = ?, completed_at_epoch = ?
58
- WHERE id = ?`,
59
- [now.toISOString(), now.getTime(), id]
60
- );
61
- }
62
- function failSession(db, id) {
63
- const now = /* @__PURE__ */ new Date();
64
- db.run(
65
- `UPDATE sessions
66
- SET status = 'failed', completed_at = ?, completed_at_epoch = ?
67
- WHERE id = ?`,
68
- [now.toISOString(), now.getTime(), id]
69
- );
70
- }
71
- function getActiveSessions(db) {
72
- const query = db.query("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at_epoch DESC");
73
- return query.all();
74
- }
75
- function getSessionsByProject(db, project, limit = 100) {
76
- const query = db.query("SELECT * FROM sessions WHERE project = ? ORDER BY started_at_epoch DESC LIMIT ?");
77
- return query.all(project, limit);
78
- }
79
- var init_Sessions = __esm({
80
- "src/services/sqlite/Sessions.ts"() {
81
- "use strict";
82
- }
83
- });
84
-
85
- // src/services/sqlite/Observations.ts
86
- var Observations_exports = {};
87
- __export(Observations_exports, {
88
- createObservation: () => createObservation,
89
- deleteObservation: () => deleteObservation,
90
- getObservationsByProject: () => getObservationsByProject,
91
- getObservationsBySession: () => getObservationsBySession,
92
- searchObservations: () => searchObservations
93
- });
94
- function createObservation(db, memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber) {
95
- const now = /* @__PURE__ */ new Date();
96
- const result = db.run(
97
- `INSERT INTO observations
98
- (memory_session_id, project, type, title, subtitle, text, narrative, facts, concepts, files_read, files_modified, prompt_number, created_at, created_at_epoch)
99
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
100
- [memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber, now.toISOString(), now.getTime()]
101
- );
102
- return Number(result.lastInsertRowid);
103
- }
104
- function getObservationsBySession(db, memorySessionId) {
105
- const query = db.query(
106
- "SELECT * FROM observations WHERE memory_session_id = ? ORDER BY prompt_number ASC"
107
- );
108
- return query.all(memorySessionId);
109
- }
110
- function getObservationsByProject(db, project, limit = 100) {
111
- const query = db.query(
112
- "SELECT * FROM observations WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
113
- );
114
- return query.all(project, limit);
115
- }
116
- function searchObservations(db, searchTerm, project) {
117
- const sql = project ? `SELECT * FROM observations
118
- WHERE project = ? AND (title LIKE ? OR text LIKE ? OR narrative LIKE ?)
119
- ORDER BY created_at_epoch DESC` : `SELECT * FROM observations
120
- WHERE title LIKE ? OR text LIKE ? OR narrative LIKE ?
121
- ORDER BY created_at_epoch DESC`;
122
- const pattern = `%${searchTerm}%`;
123
- const query = db.query(sql);
124
- if (project) {
125
- return query.all(project, pattern, pattern, pattern);
126
- }
127
- return query.all(pattern, pattern, pattern);
128
- }
129
- function deleteObservation(db, id) {
130
- db.run("DELETE FROM observations WHERE id = ?", [id]);
131
- }
132
- var init_Observations = __esm({
133
- "src/services/sqlite/Observations.ts"() {
134
- "use strict";
135
- }
136
- });
137
-
138
- // src/services/sqlite/Summaries.ts
139
- var Summaries_exports = {};
140
- __export(Summaries_exports, {
141
- createSummary: () => createSummary,
142
- deleteSummary: () => deleteSummary,
143
- getSummariesByProject: () => getSummariesByProject,
144
- getSummaryBySession: () => getSummaryBySession,
145
- searchSummaries: () => searchSummaries
146
- });
147
- function createSummary(db, sessionId, project, request, investigated, learned, completed, nextSteps, notes) {
148
- const now = /* @__PURE__ */ new Date();
149
- const result = db.run(
150
- `INSERT INTO summaries
151
- (session_id, project, request, investigated, learned, completed, next_steps, notes, created_at, created_at_epoch)
152
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
153
- [sessionId, project, request, investigated, learned, completed, nextSteps, notes, now.toISOString(), now.getTime()]
154
- );
155
- return Number(result.lastInsertRowid);
156
- }
157
- function getSummaryBySession(db, sessionId) {
158
- const query = db.query("SELECT * FROM summaries WHERE session_id = ? ORDER BY created_at_epoch DESC LIMIT 1");
159
- return query.get(sessionId);
160
- }
161
- function getSummariesByProject(db, project, limit = 50) {
162
- const query = db.query(
163
- "SELECT * FROM summaries WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
164
- );
165
- return query.all(project, limit);
166
- }
167
- function searchSummaries(db, searchTerm, project) {
168
- const sql = project ? `SELECT * FROM summaries
169
- WHERE project = ? AND (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?)
170
- ORDER BY created_at_epoch DESC` : `SELECT * FROM summaries
171
- WHERE request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?
172
- ORDER BY created_at_epoch DESC`;
173
- const pattern = `%${searchTerm}%`;
174
- const query = db.query(sql);
175
- if (project) {
176
- return query.all(project, pattern, pattern, pattern, pattern);
177
- }
178
- return query.all(pattern, pattern, pattern, pattern);
179
- }
180
- function deleteSummary(db, id) {
181
- db.run("DELETE FROM summaries WHERE id = ?", [id]);
182
- }
183
- var init_Summaries = __esm({
184
- "src/services/sqlite/Summaries.ts"() {
185
- "use strict";
186
- }
187
- });
188
-
189
- // src/services/sqlite/Prompts.ts
190
- var Prompts_exports = {};
191
- __export(Prompts_exports, {
192
- createPrompt: () => createPrompt,
193
- deletePrompt: () => deletePrompt,
194
- getLatestPrompt: () => getLatestPrompt,
195
- getPromptsByProject: () => getPromptsByProject,
196
- getPromptsBySession: () => getPromptsBySession
197
- });
198
- function createPrompt(db, contentSessionId, project, promptNumber, promptText) {
199
- const now = /* @__PURE__ */ new Date();
200
- const result = db.run(
201
- `INSERT INTO prompts
202
- (content_session_id, project, prompt_number, prompt_text, created_at, created_at_epoch)
203
- VALUES (?, ?, ?, ?, ?, ?)`,
204
- [contentSessionId, project, promptNumber, promptText, now.toISOString(), now.getTime()]
205
- );
206
- return Number(result.lastInsertRowid);
207
- }
208
- function getPromptsBySession(db, contentSessionId) {
209
- const query = db.query(
210
- "SELECT * FROM prompts WHERE content_session_id = ? ORDER BY prompt_number ASC"
211
- );
212
- return query.all(contentSessionId);
213
- }
214
- function getPromptsByProject(db, project, limit = 100) {
215
- const query = db.query(
216
- "SELECT * FROM prompts WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
217
- );
218
- return query.all(project, limit);
219
- }
220
- function getLatestPrompt(db, contentSessionId) {
221
- const query = db.query(
222
- "SELECT * FROM prompts WHERE content_session_id = ? ORDER BY prompt_number DESC LIMIT 1"
223
- );
224
- return query.get(contentSessionId);
225
- }
226
- function deletePrompt(db, id) {
227
- db.run("DELETE FROM prompts WHERE id = ?", [id]);
228
- }
229
- var init_Prompts = __esm({
230
- "src/services/sqlite/Prompts.ts"() {
231
- "use strict";
232
- }
233
- });
234
-
235
- // src/services/sqlite/Search.ts
236
- var Search_exports = {};
237
- __export(Search_exports, {
238
- getObservationsByIds: () => getObservationsByIds,
239
- getProjectStats: () => getProjectStats,
240
- getTimeline: () => getTimeline,
241
- searchObservationsFTS: () => searchObservationsFTS,
242
- searchObservationsLIKE: () => searchObservationsLIKE,
243
- searchSummariesFiltered: () => searchSummariesFiltered
244
- });
245
- function searchObservationsFTS(db, query, filters = {}) {
246
- const limit = filters.limit || 50;
247
- try {
248
- let sql = `
249
- SELECT o.* FROM observations o
250
- JOIN observations_fts fts ON o.id = fts.rowid
251
- WHERE observations_fts MATCH ?
252
- `;
253
- const params = [query];
254
- if (filters.project) {
255
- sql += " AND o.project = ?";
256
- params.push(filters.project);
257
- }
258
- if (filters.type) {
259
- sql += " AND o.type = ?";
260
- params.push(filters.type);
261
- }
262
- if (filters.dateStart) {
263
- sql += " AND o.created_at_epoch >= ?";
264
- params.push(filters.dateStart);
265
- }
266
- if (filters.dateEnd) {
267
- sql += " AND o.created_at_epoch <= ?";
268
- params.push(filters.dateEnd);
269
- }
270
- sql += " ORDER BY rank LIMIT ?";
271
- params.push(limit);
272
- const stmt = db.query(sql);
273
- return stmt.all(...params);
274
- } catch {
275
- return searchObservationsLIKE(db, query, filters);
276
- }
277
- }
278
- function searchObservationsLIKE(db, query, filters = {}) {
279
- const limit = filters.limit || 50;
280
- const pattern = `%${query}%`;
281
- let sql = `
282
- SELECT * FROM observations
283
- WHERE (title LIKE ? OR text LIKE ? OR narrative LIKE ? OR concepts LIKE ?)
284
- `;
285
- const params = [pattern, pattern, pattern, pattern];
286
- if (filters.project) {
287
- sql += " AND project = ?";
288
- params.push(filters.project);
289
- }
290
- if (filters.type) {
291
- sql += " AND type = ?";
292
- params.push(filters.type);
293
- }
294
- if (filters.dateStart) {
295
- sql += " AND created_at_epoch >= ?";
296
- params.push(filters.dateStart);
297
- }
298
- if (filters.dateEnd) {
299
- sql += " AND created_at_epoch <= ?";
300
- params.push(filters.dateEnd);
301
- }
302
- sql += " ORDER BY created_at_epoch DESC LIMIT ?";
303
- params.push(limit);
304
- const stmt = db.query(sql);
305
- return stmt.all(...params);
306
- }
307
- function searchSummariesFiltered(db, query, filters = {}) {
308
- const limit = filters.limit || 20;
309
- const pattern = `%${query}%`;
310
- let sql = `
311
- SELECT * FROM summaries
312
- WHERE (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ? OR next_steps LIKE ?)
313
- `;
314
- const params = [pattern, pattern, pattern, pattern, pattern];
315
- if (filters.project) {
316
- sql += " AND project = ?";
317
- params.push(filters.project);
318
- }
319
- if (filters.dateStart) {
320
- sql += " AND created_at_epoch >= ?";
321
- params.push(filters.dateStart);
322
- }
323
- if (filters.dateEnd) {
324
- sql += " AND created_at_epoch <= ?";
325
- params.push(filters.dateEnd);
326
- }
327
- sql += " ORDER BY created_at_epoch DESC LIMIT ?";
328
- params.push(limit);
329
- const stmt = db.query(sql);
330
- return stmt.all(...params);
331
- }
332
- function getObservationsByIds(db, ids) {
333
- if (ids.length === 0) return [];
334
- const placeholders = ids.map(() => "?").join(",");
335
- const sql = `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`;
336
- const stmt = db.query(sql);
337
- return stmt.all(...ids);
338
- }
339
- function getTimeline(db, anchorId, depthBefore = 5, depthAfter = 5) {
340
- const anchorStmt = db.query("SELECT created_at_epoch FROM observations WHERE id = ?");
341
- const anchor = anchorStmt.get(anchorId);
342
- if (!anchor) return [];
343
- const anchorEpoch = anchor.created_at_epoch;
344
- const beforeStmt = db.query(`
345
- SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
346
- FROM observations
347
- WHERE created_at_epoch < ?
348
- ORDER BY created_at_epoch DESC
349
- LIMIT ?
350
- `);
351
- const before = beforeStmt.all(anchorEpoch, depthBefore).reverse();
352
- const selfStmt = db.query(`
353
- SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
354
- FROM observations WHERE id = ?
355
- `);
356
- const self = selfStmt.all(anchorId);
357
- const afterStmt = db.query(`
358
- SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
359
- FROM observations
360
- WHERE created_at_epoch > ?
361
- ORDER BY created_at_epoch ASC
362
- LIMIT ?
363
- `);
364
- const after = afterStmt.all(anchorEpoch, depthAfter);
365
- return [...before, ...self, ...after];
366
- }
367
- function getProjectStats(db, project) {
368
- const obsStmt = db.query("SELECT COUNT(*) as count FROM observations WHERE project = ?");
369
- const sumStmt = db.query("SELECT COUNT(*) as count FROM summaries WHERE project = ?");
370
- const sesStmt = db.query("SELECT COUNT(*) as count FROM sessions WHERE project = ?");
371
- const prmStmt = db.query("SELECT COUNT(*) as count FROM prompts WHERE project = ?");
372
- return {
373
- observations: obsStmt.get(project)?.count || 0,
374
- summaries: sumStmt.get(project)?.count || 0,
375
- sessions: sesStmt.get(project)?.count || 0,
376
- prompts: prmStmt.get(project)?.count || 0
377
- };
378
- }
379
- var init_Search = __esm({
380
- "src/services/sqlite/Search.ts"() {
381
- "use strict";
382
- }
383
- });
384
8
 
385
9
  // src/shims/bun-sqlite.ts
386
10
  import BetterSqlite3 from "better-sqlite3";
@@ -452,7 +76,7 @@ var BunQueryCompat = class {
452
76
  // src/shared/paths.ts
453
77
  import { join as join2, dirname, basename } from "path";
454
78
  import { homedir as homedir2 } from "os";
455
- import { mkdirSync as mkdirSync2 } from "fs";
79
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
456
80
  import { fileURLToPath } from "url";
457
81
 
458
82
  // src/utils/logger.ts
@@ -682,7 +306,9 @@ function getDirname() {
682
306
  return dirname(fileURLToPath(import.meta.url));
683
307
  }
684
308
  var _dirname = getDirname();
685
- var DATA_DIR = process.env.KIRO_MEMORY_DATA_DIR || process.env.CONTEXTKIT_DATA_DIR || join2(homedir2(), ".contextkit");
309
+ var _legacyDir = join2(homedir2(), ".contextkit");
310
+ var _defaultDir = existsSync2(_legacyDir) ? _legacyDir : join2(homedir2(), ".kiro-memory");
311
+ var DATA_DIR = process.env.KIRO_MEMORY_DATA_DIR || process.env.CONTEXTKIT_DATA_DIR || _defaultDir;
686
312
  var KIRO_CONFIG_DIR = process.env.KIRO_CONFIG_DIR || join2(homedir2(), ".kiro");
687
313
  var PLUGIN_ROOT = join2(KIRO_CONFIG_DIR, "plugins", "kiro-memory");
688
314
  var ARCHIVES_DIR = join2(DATA_DIR, "archives");
@@ -691,7 +317,8 @@ var TRASH_DIR = join2(DATA_DIR, "trash");
691
317
  var BACKUPS_DIR = join2(DATA_DIR, "backups");
692
318
  var MODES_DIR = join2(DATA_DIR, "modes");
693
319
  var USER_SETTINGS_PATH = join2(DATA_DIR, "settings.json");
694
- var DB_PATH = join2(DATA_DIR, "contextkit.db");
320
+ var _legacyDb = join2(DATA_DIR, "contextkit.db");
321
+ var DB_PATH = existsSync2(_legacyDb) ? _legacyDb : join2(DATA_DIR, "kiro-memory.db");
695
322
  var VECTOR_DB_DIR = join2(DATA_DIR, "vector-db");
696
323
  var OBSERVER_SESSIONS_DIR = join2(DATA_DIR, "observer-sessions");
697
324
  var KIRO_SETTINGS_PATH = join2(KIRO_CONFIG_DIR, "settings.json");
@@ -706,7 +333,11 @@ var SQLITE_CACHE_SIZE_PAGES = 1e4;
706
333
  var dbInstance = null;
707
334
  var KiroMemoryDatabase = class {
708
335
  db;
709
- constructor(dbPath = DB_PATH) {
336
+ /**
337
+ * @param dbPath - Percorso al file SQLite (default: DB_PATH)
338
+ * @param skipMigrations - Se true, salta il migration runner (per hook ad alta frequenza)
339
+ */
340
+ constructor(dbPath = DB_PATH, skipMigrations = false) {
710
341
  if (dbPath !== ":memory:") {
711
342
  ensureDir(DATA_DIR);
712
343
  }
@@ -717,8 +348,18 @@ var KiroMemoryDatabase = class {
717
348
  this.db.run("PRAGMA temp_store = memory");
718
349
  this.db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
719
350
  this.db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
720
- const migrationRunner = new MigrationRunner(this.db);
721
- migrationRunner.runAllMigrations();
351
+ if (!skipMigrations) {
352
+ const migrationRunner = new MigrationRunner(this.db);
353
+ migrationRunner.runAllMigrations();
354
+ }
355
+ }
356
+ /**
357
+ * Esegue una funzione all'interno di una transazione atomica.
358
+ * Se fn() lancia un errore, la transazione viene annullata automaticamente.
359
+ */
360
+ withTransaction(fn) {
361
+ const transaction = this.db.transaction(fn);
362
+ return transaction(this.db);
722
363
  }
723
364
  /**
724
365
  * Close the database connection
@@ -1016,19 +657,258 @@ async function initializeDatabase() {
1016
657
  return await manager.initialize();
1017
658
  }
1018
659
 
1019
- // src/services/sqlite/index.ts
1020
- init_Sessions();
1021
- init_Observations();
1022
- init_Summaries();
1023
- init_Prompts();
1024
- init_Search();
660
+ // src/services/sqlite/Sessions.ts
661
+ function createSession(db, contentSessionId, project, userPrompt) {
662
+ const now = /* @__PURE__ */ new Date();
663
+ const result = db.run(
664
+ `INSERT INTO sessions (content_session_id, project, user_prompt, status, started_at, started_at_epoch)
665
+ VALUES (?, ?, ?, 'active', ?, ?)`,
666
+ [contentSessionId, project, userPrompt, now.toISOString(), now.getTime()]
667
+ );
668
+ return Number(result.lastInsertRowid);
669
+ }
670
+ function getSessionByContentId(db, contentSessionId) {
671
+ const query = db.query("SELECT * FROM sessions WHERE content_session_id = ?");
672
+ return query.get(contentSessionId);
673
+ }
674
+ function completeSession(db, id) {
675
+ const now = /* @__PURE__ */ new Date();
676
+ db.run(
677
+ `UPDATE sessions
678
+ SET status = 'completed', completed_at = ?, completed_at_epoch = ?
679
+ WHERE id = ?`,
680
+ [now.toISOString(), now.getTime(), id]
681
+ );
682
+ }
683
+
684
+ // src/services/sqlite/Observations.ts
685
+ function createObservation(db, memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber) {
686
+ const now = /* @__PURE__ */ new Date();
687
+ const result = db.run(
688
+ `INSERT INTO observations
689
+ (memory_session_id, project, type, title, subtitle, text, narrative, facts, concepts, files_read, files_modified, prompt_number, created_at, created_at_epoch)
690
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
691
+ [memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber, now.toISOString(), now.getTime()]
692
+ );
693
+ return Number(result.lastInsertRowid);
694
+ }
695
+ function getObservationsByProject(db, project, limit = 100) {
696
+ const query = db.query(
697
+ "SELECT * FROM observations WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
698
+ );
699
+ return query.all(project, limit);
700
+ }
701
+ function searchObservations(db, searchTerm, project) {
702
+ const sql = project ? `SELECT * FROM observations
703
+ WHERE project = ? AND (title LIKE ? OR text LIKE ? OR narrative LIKE ?)
704
+ ORDER BY created_at_epoch DESC` : `SELECT * FROM observations
705
+ WHERE title LIKE ? OR text LIKE ? OR narrative LIKE ?
706
+ ORDER BY created_at_epoch DESC`;
707
+ const pattern = `%${searchTerm}%`;
708
+ const query = db.query(sql);
709
+ if (project) {
710
+ return query.all(project, pattern, pattern, pattern);
711
+ }
712
+ return query.all(pattern, pattern, pattern);
713
+ }
714
+
715
+ // src/services/sqlite/Summaries.ts
716
+ function createSummary(db, sessionId, project, request, investigated, learned, completed, nextSteps, notes) {
717
+ const now = /* @__PURE__ */ new Date();
718
+ const result = db.run(
719
+ `INSERT INTO summaries
720
+ (session_id, project, request, investigated, learned, completed, next_steps, notes, created_at, created_at_epoch)
721
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
722
+ [sessionId, project, request, investigated, learned, completed, nextSteps, notes, now.toISOString(), now.getTime()]
723
+ );
724
+ return Number(result.lastInsertRowid);
725
+ }
726
+ function getSummariesByProject(db, project, limit = 50) {
727
+ const query = db.query(
728
+ "SELECT * FROM summaries WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
729
+ );
730
+ return query.all(project, limit);
731
+ }
732
+ function searchSummaries(db, searchTerm, project) {
733
+ const sql = project ? `SELECT * FROM summaries
734
+ WHERE project = ? AND (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?)
735
+ ORDER BY created_at_epoch DESC` : `SELECT * FROM summaries
736
+ WHERE request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?
737
+ ORDER BY created_at_epoch DESC`;
738
+ const pattern = `%${searchTerm}%`;
739
+ const query = db.query(sql);
740
+ if (project) {
741
+ return query.all(project, pattern, pattern, pattern, pattern);
742
+ }
743
+ return query.all(pattern, pattern, pattern, pattern);
744
+ }
745
+
746
+ // src/services/sqlite/Prompts.ts
747
+ function createPrompt(db, contentSessionId, project, promptNumber, promptText) {
748
+ const now = /* @__PURE__ */ new Date();
749
+ const result = db.run(
750
+ `INSERT INTO prompts
751
+ (content_session_id, project, prompt_number, prompt_text, created_at, created_at_epoch)
752
+ VALUES (?, ?, ?, ?, ?, ?)`,
753
+ [contentSessionId, project, promptNumber, promptText, now.toISOString(), now.getTime()]
754
+ );
755
+ return Number(result.lastInsertRowid);
756
+ }
757
+ function getPromptsByProject(db, project, limit = 100) {
758
+ const query = db.query(
759
+ "SELECT * FROM prompts WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
760
+ );
761
+ return query.all(project, limit);
762
+ }
763
+
764
+ // src/services/sqlite/Search.ts
765
+ function sanitizeFTS5Query(query) {
766
+ const terms = query.replace(/[""]/g, "").split(/\s+/).filter((t) => t.length > 0).map((t) => `"${t}"`);
767
+ return terms.join(" ");
768
+ }
769
+ function searchObservationsFTS(db, query, filters = {}) {
770
+ const limit = filters.limit || 50;
771
+ try {
772
+ const safeQuery = sanitizeFTS5Query(query);
773
+ if (!safeQuery) return searchObservationsLIKE(db, query, filters);
774
+ let sql = `
775
+ SELECT o.* FROM observations o
776
+ JOIN observations_fts fts ON o.id = fts.rowid
777
+ WHERE observations_fts MATCH ?
778
+ `;
779
+ const params = [safeQuery];
780
+ if (filters.project) {
781
+ sql += " AND o.project = ?";
782
+ params.push(filters.project);
783
+ }
784
+ if (filters.type) {
785
+ sql += " AND o.type = ?";
786
+ params.push(filters.type);
787
+ }
788
+ if (filters.dateStart) {
789
+ sql += " AND o.created_at_epoch >= ?";
790
+ params.push(filters.dateStart);
791
+ }
792
+ if (filters.dateEnd) {
793
+ sql += " AND o.created_at_epoch <= ?";
794
+ params.push(filters.dateEnd);
795
+ }
796
+ sql += " ORDER BY rank LIMIT ?";
797
+ params.push(limit);
798
+ const stmt = db.query(sql);
799
+ return stmt.all(...params);
800
+ } catch {
801
+ return searchObservationsLIKE(db, query, filters);
802
+ }
803
+ }
804
+ function searchObservationsLIKE(db, query, filters = {}) {
805
+ const limit = filters.limit || 50;
806
+ const pattern = `%${query}%`;
807
+ let sql = `
808
+ SELECT * FROM observations
809
+ WHERE (title LIKE ? OR text LIKE ? OR narrative LIKE ? OR concepts LIKE ?)
810
+ `;
811
+ const params = [pattern, pattern, pattern, pattern];
812
+ if (filters.project) {
813
+ sql += " AND project = ?";
814
+ params.push(filters.project);
815
+ }
816
+ if (filters.type) {
817
+ sql += " AND type = ?";
818
+ params.push(filters.type);
819
+ }
820
+ if (filters.dateStart) {
821
+ sql += " AND created_at_epoch >= ?";
822
+ params.push(filters.dateStart);
823
+ }
824
+ if (filters.dateEnd) {
825
+ sql += " AND created_at_epoch <= ?";
826
+ params.push(filters.dateEnd);
827
+ }
828
+ sql += " ORDER BY created_at_epoch DESC LIMIT ?";
829
+ params.push(limit);
830
+ const stmt = db.query(sql);
831
+ return stmt.all(...params);
832
+ }
833
+ function searchSummariesFiltered(db, query, filters = {}) {
834
+ const limit = filters.limit || 20;
835
+ const pattern = `%${query}%`;
836
+ let sql = `
837
+ SELECT * FROM summaries
838
+ WHERE (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ? OR next_steps LIKE ?)
839
+ `;
840
+ const params = [pattern, pattern, pattern, pattern, pattern];
841
+ if (filters.project) {
842
+ sql += " AND project = ?";
843
+ params.push(filters.project);
844
+ }
845
+ if (filters.dateStart) {
846
+ sql += " AND created_at_epoch >= ?";
847
+ params.push(filters.dateStart);
848
+ }
849
+ if (filters.dateEnd) {
850
+ sql += " AND created_at_epoch <= ?";
851
+ params.push(filters.dateEnd);
852
+ }
853
+ sql += " ORDER BY created_at_epoch DESC LIMIT ?";
854
+ params.push(limit);
855
+ const stmt = db.query(sql);
856
+ return stmt.all(...params);
857
+ }
858
+ function getObservationsByIds(db, ids) {
859
+ if (ids.length === 0) return [];
860
+ const placeholders = ids.map(() => "?").join(",");
861
+ const sql = `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`;
862
+ const stmt = db.query(sql);
863
+ return stmt.all(...ids);
864
+ }
865
+ function getTimeline(db, anchorId, depthBefore = 5, depthAfter = 5) {
866
+ const anchorStmt = db.query("SELECT created_at_epoch FROM observations WHERE id = ?");
867
+ const anchor = anchorStmt.get(anchorId);
868
+ if (!anchor) return [];
869
+ const anchorEpoch = anchor.created_at_epoch;
870
+ const beforeStmt = db.query(`
871
+ SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
872
+ FROM observations
873
+ WHERE created_at_epoch < ?
874
+ ORDER BY created_at_epoch DESC
875
+ LIMIT ?
876
+ `);
877
+ const before = beforeStmt.all(anchorEpoch, depthBefore).reverse();
878
+ const selfStmt = db.query(`
879
+ SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
880
+ FROM observations WHERE id = ?
881
+ `);
882
+ const self = selfStmt.all(anchorId);
883
+ const afterStmt = db.query(`
884
+ SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
885
+ FROM observations
886
+ WHERE created_at_epoch > ?
887
+ ORDER BY created_at_epoch ASC
888
+ LIMIT ?
889
+ `);
890
+ const after = afterStmt.all(anchorEpoch, depthAfter);
891
+ return [...before, ...self, ...after];
892
+ }
893
+ function getProjectStats(db, project) {
894
+ const obsStmt = db.query("SELECT COUNT(*) as count FROM observations WHERE project = ?");
895
+ const sumStmt = db.query("SELECT COUNT(*) as count FROM summaries WHERE project = ?");
896
+ const sesStmt = db.query("SELECT COUNT(*) as count FROM sessions WHERE project = ?");
897
+ const prmStmt = db.query("SELECT COUNT(*) as count FROM prompts WHERE project = ?");
898
+ return {
899
+ observations: obsStmt.get(project)?.count || 0,
900
+ summaries: sumStmt.get(project)?.count || 0,
901
+ sessions: sesStmt.get(project)?.count || 0,
902
+ prompts: prmStmt.get(project)?.count || 0
903
+ };
904
+ }
1025
905
 
1026
906
  // src/sdk/index.ts
1027
907
  var KiroMemorySDK = class {
1028
908
  db;
1029
909
  project;
1030
910
  constructor(config = {}) {
1031
- this.db = new KiroMemoryDatabase(config.dataDir);
911
+ this.db = new KiroMemoryDatabase(config.dataDir, config.skipMigrations || false);
1032
912
  this.project = config.project || this.detectProject();
1033
913
  }
1034
914
  detectProject() {
@@ -1048,22 +928,18 @@ var KiroMemorySDK = class {
1048
928
  * Get context for the current project
1049
929
  */
1050
930
  async getContext() {
1051
- const { getObservationsByProject: getObservationsByProject2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1052
- const { getSummariesByProject: getSummariesByProject2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1053
- const { getPromptsByProject: getPromptsByProject2 } = await Promise.resolve().then(() => (init_Prompts(), Prompts_exports));
1054
931
  return {
1055
932
  project: this.project,
1056
- relevantObservations: getObservationsByProject2(this.db.db, this.project, 20),
1057
- relevantSummaries: getSummariesByProject2(this.db.db, this.project, 5),
1058
- recentPrompts: getPromptsByProject2(this.db.db, this.project, 10)
933
+ relevantObservations: getObservationsByProject(this.db.db, this.project, 20),
934
+ relevantSummaries: getSummariesByProject(this.db.db, this.project, 5),
935
+ recentPrompts: getPromptsByProject(this.db.db, this.project, 10)
1059
936
  };
1060
937
  }
1061
938
  /**
1062
939
  * Store a new observation
1063
940
  */
1064
941
  async storeObservation(data) {
1065
- const { createObservation: createObservation2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1066
- return createObservation2(
942
+ return createObservation(
1067
943
  this.db.db,
1068
944
  "sdk-" + Date.now(),
1069
945
  this.project,
@@ -1089,8 +965,7 @@ var KiroMemorySDK = class {
1089
965
  * Store a session summary
1090
966
  */
1091
967
  async storeSummary(data) {
1092
- const { createSummary: createSummary2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1093
- return createSummary2(
968
+ return createSummary(
1094
969
  this.db.db,
1095
970
  "sdk-" + Date.now(),
1096
971
  this.project,
@@ -1106,61 +981,52 @@ var KiroMemorySDK = class {
1106
981
  * Search across all stored context
1107
982
  */
1108
983
  async search(query) {
1109
- const { searchObservations: searchObservations2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1110
- const { searchSummaries: searchSummaries2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1111
984
  return {
1112
- observations: searchObservations2(this.db.db, query, this.project),
1113
- summaries: searchSummaries2(this.db.db, query, this.project)
985
+ observations: searchObservations(this.db.db, query, this.project),
986
+ summaries: searchSummaries(this.db.db, query, this.project)
1114
987
  };
1115
988
  }
1116
989
  /**
1117
990
  * Get recent observations
1118
991
  */
1119
992
  async getRecentObservations(limit = 10) {
1120
- const { getObservationsByProject: getObservationsByProject2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1121
- return getObservationsByProject2(this.db.db, this.project, limit);
993
+ return getObservationsByProject(this.db.db, this.project, limit);
1122
994
  }
1123
995
  /**
1124
996
  * Get recent summaries
1125
997
  */
1126
998
  async getRecentSummaries(limit = 5) {
1127
- const { getSummariesByProject: getSummariesByProject2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1128
- return getSummariesByProject2(this.db.db, this.project, limit);
999
+ return getSummariesByProject(this.db.db, this.project, limit);
1129
1000
  }
1130
1001
  /**
1131
1002
  * Advanced search with FTS5 and filters
1132
1003
  */
1133
1004
  async searchAdvanced(query, filters = {}) {
1134
- const { searchObservationsFTS: searchObservationsFTS2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1135
- const { searchSummariesFiltered: searchSummariesFiltered2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1136
1005
  const projectFilters = { ...filters, project: filters.project || this.project };
1137
1006
  return {
1138
- observations: searchObservationsFTS2(this.db.db, query, projectFilters),
1139
- summaries: searchSummariesFiltered2(this.db.db, query, projectFilters)
1007
+ observations: searchObservationsFTS(this.db.db, query, projectFilters),
1008
+ summaries: searchSummariesFiltered(this.db.db, query, projectFilters)
1140
1009
  };
1141
1010
  }
1142
1011
  /**
1143
1012
  * Retrieve observations by ID (batch)
1144
1013
  */
1145
1014
  async getObservationsByIds(ids) {
1146
- const { getObservationsByIds: getObservationsByIds2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1147
- return getObservationsByIds2(this.db.db, ids);
1015
+ return getObservationsByIds(this.db.db, ids);
1148
1016
  }
1149
1017
  /**
1150
1018
  * Timeline: chronological context around an observation
1151
1019
  */
1152
1020
  async getTimeline(anchorId, depthBefore = 5, depthAfter = 5) {
1153
- const { getTimeline: getTimeline2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1154
- return getTimeline2(this.db.db, anchorId, depthBefore, depthAfter);
1021
+ return getTimeline(this.db.db, anchorId, depthBefore, depthAfter);
1155
1022
  }
1156
1023
  /**
1157
1024
  * Create or retrieve a session for the current project
1158
1025
  */
1159
1026
  async getOrCreateSession(contentSessionId) {
1160
- const { getSessionByContentId: getSessionByContentId2, createSession: createSession2 } = await Promise.resolve().then(() => (init_Sessions(), Sessions_exports));
1161
- let session = getSessionByContentId2(this.db.db, contentSessionId);
1027
+ let session = getSessionByContentId(this.db.db, contentSessionId);
1162
1028
  if (!session) {
1163
- const id = createSession2(this.db.db, contentSessionId, this.project, "");
1029
+ const id = createSession(this.db.db, contentSessionId, this.project, "");
1164
1030
  session = {
1165
1031
  id,
1166
1032
  content_session_id: contentSessionId,
@@ -1180,15 +1046,13 @@ var KiroMemorySDK = class {
1180
1046
  * Store a user prompt
1181
1047
  */
1182
1048
  async storePrompt(contentSessionId, promptNumber, text) {
1183
- const { createPrompt: createPrompt2 } = await Promise.resolve().then(() => (init_Prompts(), Prompts_exports));
1184
- return createPrompt2(this.db.db, contentSessionId, this.project, promptNumber, text);
1049
+ return createPrompt(this.db.db, contentSessionId, this.project, promptNumber, text);
1185
1050
  }
1186
1051
  /**
1187
1052
  * Complete a session
1188
1053
  */
1189
1054
  async completeSession(sessionId) {
1190
- const { completeSession: completeSession2 } = await Promise.resolve().then(() => (init_Sessions(), Sessions_exports));
1191
- completeSession2(this.db.db, sessionId);
1055
+ completeSession(this.db.db, sessionId);
1192
1056
  }
1193
1057
  /**
1194
1058
  * Getter for current project name
@@ -1215,12 +1079,11 @@ function createKiroMemory(config) {
1215
1079
  var ContextKitSDK = KiroMemorySDK;
1216
1080
  var createContextKit = createKiroMemory;
1217
1081
 
1218
- // src/index.ts
1219
- init_Search();
1220
-
1221
1082
  // src/hooks/utils.ts
1222
- import { writeFileSync, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
1083
+ import { writeFileSync, mkdirSync as mkdirSync3, existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
1223
1084
  import { join as join3 } from "path";
1085
+ var DATA_DIR2 = process.env.KIRO_MEMORY_DATA_DIR || process.env.CONTEXTKIT_DATA_DIR || join3(process.env.HOME || "/tmp", ".kiro-memory");
1086
+ var TOKEN_FILE = join3(DATA_DIR2, "worker.token");
1224
1087
  function debugLog(hookName, label, data) {
1225
1088
  if ((process.env.KIRO_MEMORY_LOG_LEVEL || "").toUpperCase() !== "DEBUG") return;
1226
1089
  try {
@@ -1321,7 +1184,7 @@ async function runHook(name, handler) {
1321
1184
  }
1322
1185
 
1323
1186
  // src/index.ts
1324
- var VERSION = "1.0.0";
1187
+ var VERSION = "1.5.0";
1325
1188
  export {
1326
1189
  KiroMemoryDatabase as ContextKitDatabase,
1327
1190
  ContextKitSDK,