kiro-memory 1.4.2 → 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,391 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module';const require = createRequire(import.meta.url);
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
3
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
6
4
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
7
5
  }) : x)(function(x) {
8
6
  if (typeof require !== "undefined") return require.apply(this, arguments);
9
7
  throw Error('Dynamic require of "' + x + '" is not supported');
10
8
  });
11
- var __esm = (fn, res) => function __init() {
12
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
13
- };
14
- var __export = (target, all) => {
15
- for (var name in all)
16
- __defProp(target, name, { get: all[name], enumerable: true });
17
- };
18
-
19
- // src/services/sqlite/Sessions.ts
20
- var Sessions_exports = {};
21
- __export(Sessions_exports, {
22
- completeSession: () => completeSession,
23
- createSession: () => createSession,
24
- failSession: () => failSession,
25
- getActiveSessions: () => getActiveSessions,
26
- getSessionByContentId: () => getSessionByContentId,
27
- getSessionById: () => getSessionById,
28
- getSessionsByProject: () => getSessionsByProject,
29
- updateSessionMemoryId: () => updateSessionMemoryId
30
- });
31
- function createSession(db, contentSessionId, project, userPrompt) {
32
- const now = /* @__PURE__ */ new Date();
33
- const result = db.run(
34
- `INSERT INTO sessions (content_session_id, project, user_prompt, status, started_at, started_at_epoch)
35
- VALUES (?, ?, ?, 'active', ?, ?)`,
36
- [contentSessionId, project, userPrompt, now.toISOString(), now.getTime()]
37
- );
38
- return Number(result.lastInsertRowid);
39
- }
40
- function getSessionByContentId(db, contentSessionId) {
41
- const query = db.query("SELECT * FROM sessions WHERE content_session_id = ?");
42
- return query.get(contentSessionId);
43
- }
44
- function getSessionById(db, id) {
45
- const query = db.query("SELECT * FROM sessions WHERE id = ?");
46
- return query.get(id);
47
- }
48
- function updateSessionMemoryId(db, id, memorySessionId) {
49
- db.run(
50
- "UPDATE sessions SET memory_session_id = ? WHERE id = ?",
51
- [memorySessionId, id]
52
- );
53
- }
54
- function completeSession(db, id) {
55
- const now = /* @__PURE__ */ new Date();
56
- db.run(
57
- `UPDATE sessions
58
- SET status = 'completed', completed_at = ?, completed_at_epoch = ?
59
- WHERE id = ?`,
60
- [now.toISOString(), now.getTime(), id]
61
- );
62
- }
63
- function failSession(db, id) {
64
- const now = /* @__PURE__ */ new Date();
65
- db.run(
66
- `UPDATE sessions
67
- SET status = 'failed', completed_at = ?, completed_at_epoch = ?
68
- WHERE id = ?`,
69
- [now.toISOString(), now.getTime(), id]
70
- );
71
- }
72
- function getActiveSessions(db) {
73
- const query = db.query("SELECT * FROM sessions WHERE status = 'active' ORDER BY started_at_epoch DESC");
74
- return query.all();
75
- }
76
- function getSessionsByProject(db, project, limit = 100) {
77
- const query = db.query("SELECT * FROM sessions WHERE project = ? ORDER BY started_at_epoch DESC LIMIT ?");
78
- return query.all(project, limit);
79
- }
80
- var init_Sessions = __esm({
81
- "src/services/sqlite/Sessions.ts"() {
82
- "use strict";
83
- }
84
- });
85
-
86
- // src/services/sqlite/Observations.ts
87
- var Observations_exports = {};
88
- __export(Observations_exports, {
89
- createObservation: () => createObservation,
90
- deleteObservation: () => deleteObservation,
91
- getObservationsByProject: () => getObservationsByProject,
92
- getObservationsBySession: () => getObservationsBySession,
93
- searchObservations: () => searchObservations
94
- });
95
- function createObservation(db, memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber) {
96
- const now = /* @__PURE__ */ new Date();
97
- const result = db.run(
98
- `INSERT INTO observations
99
- (memory_session_id, project, type, title, subtitle, text, narrative, facts, concepts, files_read, files_modified, prompt_number, created_at, created_at_epoch)
100
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
101
- [memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber, now.toISOString(), now.getTime()]
102
- );
103
- return Number(result.lastInsertRowid);
104
- }
105
- function getObservationsBySession(db, memorySessionId) {
106
- const query = db.query(
107
- "SELECT * FROM observations WHERE memory_session_id = ? ORDER BY prompt_number ASC"
108
- );
109
- return query.all(memorySessionId);
110
- }
111
- function getObservationsByProject(db, project, limit = 100) {
112
- const query = db.query(
113
- "SELECT * FROM observations WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
114
- );
115
- return query.all(project, limit);
116
- }
117
- function searchObservations(db, searchTerm, project) {
118
- const sql = project ? `SELECT * FROM observations
119
- WHERE project = ? AND (title LIKE ? OR text LIKE ? OR narrative LIKE ?)
120
- ORDER BY created_at_epoch DESC` : `SELECT * FROM observations
121
- WHERE title LIKE ? OR text LIKE ? OR narrative LIKE ?
122
- ORDER BY created_at_epoch DESC`;
123
- const pattern = `%${searchTerm}%`;
124
- const query = db.query(sql);
125
- if (project) {
126
- return query.all(project, pattern, pattern, pattern);
127
- }
128
- return query.all(pattern, pattern, pattern);
129
- }
130
- function deleteObservation(db, id) {
131
- db.run("DELETE FROM observations WHERE id = ?", [id]);
132
- }
133
- var init_Observations = __esm({
134
- "src/services/sqlite/Observations.ts"() {
135
- "use strict";
136
- }
137
- });
138
-
139
- // src/services/sqlite/Summaries.ts
140
- var Summaries_exports = {};
141
- __export(Summaries_exports, {
142
- createSummary: () => createSummary,
143
- deleteSummary: () => deleteSummary,
144
- getSummariesByProject: () => getSummariesByProject,
145
- getSummaryBySession: () => getSummaryBySession,
146
- searchSummaries: () => searchSummaries
147
- });
148
- function createSummary(db, sessionId, project, request, investigated, learned, completed, nextSteps, notes) {
149
- const now = /* @__PURE__ */ new Date();
150
- const result = db.run(
151
- `INSERT INTO summaries
152
- (session_id, project, request, investigated, learned, completed, next_steps, notes, created_at, created_at_epoch)
153
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
154
- [sessionId, project, request, investigated, learned, completed, nextSteps, notes, now.toISOString(), now.getTime()]
155
- );
156
- return Number(result.lastInsertRowid);
157
- }
158
- function getSummaryBySession(db, sessionId) {
159
- const query = db.query("SELECT * FROM summaries WHERE session_id = ? ORDER BY created_at_epoch DESC LIMIT 1");
160
- return query.get(sessionId);
161
- }
162
- function getSummariesByProject(db, project, limit = 50) {
163
- const query = db.query(
164
- "SELECT * FROM summaries WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
165
- );
166
- return query.all(project, limit);
167
- }
168
- function searchSummaries(db, searchTerm, project) {
169
- const sql = project ? `SELECT * FROM summaries
170
- WHERE project = ? AND (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?)
171
- ORDER BY created_at_epoch DESC` : `SELECT * FROM summaries
172
- WHERE request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?
173
- ORDER BY created_at_epoch DESC`;
174
- const pattern = `%${searchTerm}%`;
175
- const query = db.query(sql);
176
- if (project) {
177
- return query.all(project, pattern, pattern, pattern, pattern);
178
- }
179
- return query.all(pattern, pattern, pattern, pattern);
180
- }
181
- function deleteSummary(db, id) {
182
- db.run("DELETE FROM summaries WHERE id = ?", [id]);
183
- }
184
- var init_Summaries = __esm({
185
- "src/services/sqlite/Summaries.ts"() {
186
- "use strict";
187
- }
188
- });
189
-
190
- // src/services/sqlite/Prompts.ts
191
- var Prompts_exports = {};
192
- __export(Prompts_exports, {
193
- createPrompt: () => createPrompt,
194
- deletePrompt: () => deletePrompt,
195
- getLatestPrompt: () => getLatestPrompt,
196
- getPromptsByProject: () => getPromptsByProject,
197
- getPromptsBySession: () => getPromptsBySession
198
- });
199
- function createPrompt(db, contentSessionId, project, promptNumber, promptText) {
200
- const now = /* @__PURE__ */ new Date();
201
- const result = db.run(
202
- `INSERT INTO prompts
203
- (content_session_id, project, prompt_number, prompt_text, created_at, created_at_epoch)
204
- VALUES (?, ?, ?, ?, ?, ?)`,
205
- [contentSessionId, project, promptNumber, promptText, now.toISOString(), now.getTime()]
206
- );
207
- return Number(result.lastInsertRowid);
208
- }
209
- function getPromptsBySession(db, contentSessionId) {
210
- const query = db.query(
211
- "SELECT * FROM prompts WHERE content_session_id = ? ORDER BY prompt_number ASC"
212
- );
213
- return query.all(contentSessionId);
214
- }
215
- function getPromptsByProject(db, project, limit = 100) {
216
- const query = db.query(
217
- "SELECT * FROM prompts WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
218
- );
219
- return query.all(project, limit);
220
- }
221
- function getLatestPrompt(db, contentSessionId) {
222
- const query = db.query(
223
- "SELECT * FROM prompts WHERE content_session_id = ? ORDER BY prompt_number DESC LIMIT 1"
224
- );
225
- return query.get(contentSessionId);
226
- }
227
- function deletePrompt(db, id) {
228
- db.run("DELETE FROM prompts WHERE id = ?", [id]);
229
- }
230
- var init_Prompts = __esm({
231
- "src/services/sqlite/Prompts.ts"() {
232
- "use strict";
233
- }
234
- });
235
-
236
- // src/services/sqlite/Search.ts
237
- var Search_exports = {};
238
- __export(Search_exports, {
239
- getObservationsByIds: () => getObservationsByIds,
240
- getProjectStats: () => getProjectStats,
241
- getTimeline: () => getTimeline,
242
- searchObservationsFTS: () => searchObservationsFTS,
243
- searchObservationsLIKE: () => searchObservationsLIKE,
244
- searchSummariesFiltered: () => searchSummariesFiltered
245
- });
246
- function searchObservationsFTS(db, query, filters = {}) {
247
- const limit = filters.limit || 50;
248
- try {
249
- let sql = `
250
- SELECT o.* FROM observations o
251
- JOIN observations_fts fts ON o.id = fts.rowid
252
- WHERE observations_fts MATCH ?
253
- `;
254
- const params = [query];
255
- if (filters.project) {
256
- sql += " AND o.project = ?";
257
- params.push(filters.project);
258
- }
259
- if (filters.type) {
260
- sql += " AND o.type = ?";
261
- params.push(filters.type);
262
- }
263
- if (filters.dateStart) {
264
- sql += " AND o.created_at_epoch >= ?";
265
- params.push(filters.dateStart);
266
- }
267
- if (filters.dateEnd) {
268
- sql += " AND o.created_at_epoch <= ?";
269
- params.push(filters.dateEnd);
270
- }
271
- sql += " ORDER BY rank LIMIT ?";
272
- params.push(limit);
273
- const stmt = db.query(sql);
274
- return stmt.all(...params);
275
- } catch {
276
- return searchObservationsLIKE(db, query, filters);
277
- }
278
- }
279
- function searchObservationsLIKE(db, query, filters = {}) {
280
- const limit = filters.limit || 50;
281
- const pattern = `%${query}%`;
282
- let sql = `
283
- SELECT * FROM observations
284
- WHERE (title LIKE ? OR text LIKE ? OR narrative LIKE ? OR concepts LIKE ?)
285
- `;
286
- const params = [pattern, pattern, pattern, pattern];
287
- if (filters.project) {
288
- sql += " AND project = ?";
289
- params.push(filters.project);
290
- }
291
- if (filters.type) {
292
- sql += " AND type = ?";
293
- params.push(filters.type);
294
- }
295
- if (filters.dateStart) {
296
- sql += " AND created_at_epoch >= ?";
297
- params.push(filters.dateStart);
298
- }
299
- if (filters.dateEnd) {
300
- sql += " AND created_at_epoch <= ?";
301
- params.push(filters.dateEnd);
302
- }
303
- sql += " ORDER BY created_at_epoch DESC LIMIT ?";
304
- params.push(limit);
305
- const stmt = db.query(sql);
306
- return stmt.all(...params);
307
- }
308
- function searchSummariesFiltered(db, query, filters = {}) {
309
- const limit = filters.limit || 20;
310
- const pattern = `%${query}%`;
311
- let sql = `
312
- SELECT * FROM summaries
313
- WHERE (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ? OR next_steps LIKE ?)
314
- `;
315
- const params = [pattern, pattern, pattern, pattern, pattern];
316
- if (filters.project) {
317
- sql += " AND project = ?";
318
- params.push(filters.project);
319
- }
320
- if (filters.dateStart) {
321
- sql += " AND created_at_epoch >= ?";
322
- params.push(filters.dateStart);
323
- }
324
- if (filters.dateEnd) {
325
- sql += " AND created_at_epoch <= ?";
326
- params.push(filters.dateEnd);
327
- }
328
- sql += " ORDER BY created_at_epoch DESC LIMIT ?";
329
- params.push(limit);
330
- const stmt = db.query(sql);
331
- return stmt.all(...params);
332
- }
333
- function getObservationsByIds(db, ids) {
334
- if (ids.length === 0) return [];
335
- const placeholders = ids.map(() => "?").join(",");
336
- const sql = `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`;
337
- const stmt = db.query(sql);
338
- return stmt.all(...ids);
339
- }
340
- function getTimeline(db, anchorId, depthBefore = 5, depthAfter = 5) {
341
- const anchorStmt = db.query("SELECT created_at_epoch FROM observations WHERE id = ?");
342
- const anchor = anchorStmt.get(anchorId);
343
- if (!anchor) return [];
344
- const anchorEpoch = anchor.created_at_epoch;
345
- const beforeStmt = db.query(`
346
- SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
347
- FROM observations
348
- WHERE created_at_epoch < ?
349
- ORDER BY created_at_epoch DESC
350
- LIMIT ?
351
- `);
352
- const before = beforeStmt.all(anchorEpoch, depthBefore).reverse();
353
- const selfStmt = db.query(`
354
- SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
355
- FROM observations WHERE id = ?
356
- `);
357
- const self = selfStmt.all(anchorId);
358
- const afterStmt = db.query(`
359
- SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
360
- FROM observations
361
- WHERE created_at_epoch > ?
362
- ORDER BY created_at_epoch ASC
363
- LIMIT ?
364
- `);
365
- const after = afterStmt.all(anchorEpoch, depthAfter);
366
- return [...before, ...self, ...after];
367
- }
368
- function getProjectStats(db, project) {
369
- const obsStmt = db.query("SELECT COUNT(*) as count FROM observations WHERE project = ?");
370
- const sumStmt = db.query("SELECT COUNT(*) as count FROM summaries WHERE project = ?");
371
- const sesStmt = db.query("SELECT COUNT(*) as count FROM sessions WHERE project = ?");
372
- const prmStmt = db.query("SELECT COUNT(*) as count FROM prompts WHERE project = ?");
373
- return {
374
- observations: obsStmt.get(project)?.count || 0,
375
- summaries: sumStmt.get(project)?.count || 0,
376
- sessions: sesStmt.get(project)?.count || 0,
377
- prompts: prmStmt.get(project)?.count || 0
378
- };
379
- }
380
- var init_Search = __esm({
381
- "src/services/sqlite/Search.ts"() {
382
- "use strict";
383
- }
384
- });
385
9
 
386
10
  // src/hooks/utils.ts
387
- import { writeFileSync, mkdirSync, existsSync } from "fs";
11
+ import { writeFileSync, mkdirSync, existsSync, readFileSync } from "fs";
388
12
  import { join } from "path";
13
+ var DATA_DIR = process.env.KIRO_MEMORY_DATA_DIR || process.env.CONTEXTKIT_DATA_DIR || join(process.env.HOME || "/tmp", ".kiro-memory");
14
+ var TOKEN_FILE = join(DATA_DIR, "worker.token");
389
15
  function debugLog(hookName, label, data) {
390
16
  if ((process.env.KIRO_MEMORY_LOG_LEVEL || "").toUpperCase() !== "DEBUG") return;
391
17
  try {
@@ -555,11 +181,11 @@ var BunQueryCompat = class {
555
181
  // src/shared/paths.ts
556
182
  import { join as join3, dirname, basename } from "path";
557
183
  import { homedir as homedir2 } from "os";
558
- import { mkdirSync as mkdirSync3 } from "fs";
184
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3 } from "fs";
559
185
  import { fileURLToPath } from "url";
560
186
 
561
187
  // src/utils/logger.ts
562
- import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync } from "fs";
188
+ import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2 } from "fs";
563
189
  import { join as join2 } from "path";
564
190
  import { homedir } from "os";
565
191
  var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
@@ -591,7 +217,7 @@ var Logger = class {
591
217
  mkdirSync2(logsDir, { recursive: true });
592
218
  }
593
219
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
594
- this.logFilePath = join2(logsDir, `contextkit-${date}.log`);
220
+ this.logFilePath = join2(logsDir, `kiro-memory-${date}.log`);
595
221
  } catch (error) {
596
222
  console.error("[LOGGER] Failed to initialize log file:", error);
597
223
  this.logFilePath = null;
@@ -605,9 +231,9 @@ var Logger = class {
605
231
  try {
606
232
  const settingsPath = join2(DEFAULT_DATA_DIR, "settings.json");
607
233
  if (existsSync2(settingsPath)) {
608
- const settingsData = readFileSync(settingsPath, "utf-8");
234
+ const settingsData = readFileSync2(settingsPath, "utf-8");
609
235
  const settings = JSON.parse(settingsData);
610
- const envLevel = (settings.CONTEXTKIT_LOG_LEVEL || "INFO").toUpperCase();
236
+ const envLevel = (settings.KIRO_MEMORY_LOG_LEVEL || settings.CONTEXTKIT_LOG_LEVEL || "INFO").toUpperCase();
611
237
  this.level = LogLevel[envLevel] ?? 1 /* INFO */;
612
238
  } else {
613
239
  this.level = 1 /* INFO */;
@@ -785,18 +411,21 @@ function getDirname() {
785
411
  return dirname(fileURLToPath(import.meta.url));
786
412
  }
787
413
  var _dirname = getDirname();
788
- var DATA_DIR = process.env.CONTEXTKIT_DATA_DIR || join3(homedir2(), ".contextkit");
414
+ var _legacyDir = join3(homedir2(), ".contextkit");
415
+ var _defaultDir = existsSync3(_legacyDir) ? _legacyDir : join3(homedir2(), ".kiro-memory");
416
+ var DATA_DIR2 = process.env.KIRO_MEMORY_DATA_DIR || process.env.CONTEXTKIT_DATA_DIR || _defaultDir;
789
417
  var KIRO_CONFIG_DIR = process.env.KIRO_CONFIG_DIR || join3(homedir2(), ".kiro");
790
- var PLUGIN_ROOT = join3(KIRO_CONFIG_DIR, "plugins", "contextkit");
791
- var ARCHIVES_DIR = join3(DATA_DIR, "archives");
792
- var LOGS_DIR = join3(DATA_DIR, "logs");
793
- var TRASH_DIR = join3(DATA_DIR, "trash");
794
- var BACKUPS_DIR = join3(DATA_DIR, "backups");
795
- var MODES_DIR = join3(DATA_DIR, "modes");
796
- var USER_SETTINGS_PATH = join3(DATA_DIR, "settings.json");
797
- var DB_PATH = join3(DATA_DIR, "contextkit.db");
798
- var VECTOR_DB_DIR = join3(DATA_DIR, "vector-db");
799
- var OBSERVER_SESSIONS_DIR = join3(DATA_DIR, "observer-sessions");
418
+ var PLUGIN_ROOT = join3(KIRO_CONFIG_DIR, "plugins", "kiro-memory");
419
+ var ARCHIVES_DIR = join3(DATA_DIR2, "archives");
420
+ var LOGS_DIR = join3(DATA_DIR2, "logs");
421
+ var TRASH_DIR = join3(DATA_DIR2, "trash");
422
+ var BACKUPS_DIR = join3(DATA_DIR2, "backups");
423
+ var MODES_DIR = join3(DATA_DIR2, "modes");
424
+ var USER_SETTINGS_PATH = join3(DATA_DIR2, "settings.json");
425
+ var _legacyDb = join3(DATA_DIR2, "contextkit.db");
426
+ var DB_PATH = existsSync3(_legacyDb) ? _legacyDb : join3(DATA_DIR2, "kiro-memory.db");
427
+ var VECTOR_DB_DIR = join3(DATA_DIR2, "vector-db");
428
+ var OBSERVER_SESSIONS_DIR = join3(DATA_DIR2, "observer-sessions");
800
429
  var KIRO_SETTINGS_PATH = join3(KIRO_CONFIG_DIR, "settings.json");
801
430
  var KIRO_CONTEXT_PATH = join3(KIRO_CONFIG_DIR, "context.md");
802
431
  function ensureDir(dirPath) {
@@ -806,11 +435,15 @@ function ensureDir(dirPath) {
806
435
  // src/services/sqlite/Database.ts
807
436
  var SQLITE_MMAP_SIZE_BYTES = 256 * 1024 * 1024;
808
437
  var SQLITE_CACHE_SIZE_PAGES = 1e4;
809
- var ContextKitDatabase = class {
438
+ var KiroMemoryDatabase = class {
810
439
  db;
811
- constructor(dbPath = DB_PATH) {
440
+ /**
441
+ * @param dbPath - Percorso al file SQLite (default: DB_PATH)
442
+ * @param skipMigrations - Se true, salta il migration runner (per hook ad alta frequenza)
443
+ */
444
+ constructor(dbPath = DB_PATH, skipMigrations = false) {
812
445
  if (dbPath !== ":memory:") {
813
- ensureDir(DATA_DIR);
446
+ ensureDir(DATA_DIR2);
814
447
  }
815
448
  this.db = new Database(dbPath, { create: true, readwrite: true });
816
449
  this.db.run("PRAGMA journal_mode = WAL");
@@ -819,8 +452,18 @@ var ContextKitDatabase = class {
819
452
  this.db.run("PRAGMA temp_store = memory");
820
453
  this.db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
821
454
  this.db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
822
- const migrationRunner = new MigrationRunner(this.db);
823
- migrationRunner.runAllMigrations();
455
+ if (!skipMigrations) {
456
+ const migrationRunner = new MigrationRunner(this.db);
457
+ migrationRunner.runAllMigrations();
458
+ }
459
+ }
460
+ /**
461
+ * Esegue una funzione all'interno di una transazione atomica.
462
+ * Se fn() lancia un errore, la transazione viene annullata automaticamente.
463
+ */
464
+ withTransaction(fn) {
465
+ const transaction = this.db.transaction(fn);
466
+ return transaction(this.db);
824
467
  }
825
468
  /**
826
469
  * Close the database connection
@@ -1000,19 +643,246 @@ var MigrationRunner = class {
1000
643
  }
1001
644
  };
1002
645
 
1003
- // src/services/sqlite/index.ts
1004
- init_Sessions();
1005
- init_Observations();
1006
- init_Summaries();
1007
- init_Prompts();
1008
- init_Search();
646
+ // src/services/sqlite/Sessions.ts
647
+ function createSession(db, contentSessionId, project, userPrompt) {
648
+ const now = /* @__PURE__ */ new Date();
649
+ const result = db.run(
650
+ `INSERT INTO sessions (content_session_id, project, user_prompt, status, started_at, started_at_epoch)
651
+ VALUES (?, ?, ?, 'active', ?, ?)`,
652
+ [contentSessionId, project, userPrompt, now.toISOString(), now.getTime()]
653
+ );
654
+ return Number(result.lastInsertRowid);
655
+ }
656
+ function getSessionByContentId(db, contentSessionId) {
657
+ const query = db.query("SELECT * FROM sessions WHERE content_session_id = ?");
658
+ return query.get(contentSessionId);
659
+ }
660
+ function completeSession(db, id) {
661
+ const now = /* @__PURE__ */ new Date();
662
+ db.run(
663
+ `UPDATE sessions
664
+ SET status = 'completed', completed_at = ?, completed_at_epoch = ?
665
+ WHERE id = ?`,
666
+ [now.toISOString(), now.getTime(), id]
667
+ );
668
+ }
669
+
670
+ // src/services/sqlite/Observations.ts
671
+ function createObservation(db, memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber) {
672
+ const now = /* @__PURE__ */ new Date();
673
+ const result = db.run(
674
+ `INSERT INTO observations
675
+ (memory_session_id, project, type, title, subtitle, text, narrative, facts, concepts, files_read, files_modified, prompt_number, created_at, created_at_epoch)
676
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
677
+ [memorySessionId, project, type, title, subtitle, text, narrative, facts, concepts, filesRead, filesModified, promptNumber, now.toISOString(), now.getTime()]
678
+ );
679
+ return Number(result.lastInsertRowid);
680
+ }
681
+ function getObservationsByProject(db, project, limit = 100) {
682
+ const query = db.query(
683
+ "SELECT * FROM observations WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
684
+ );
685
+ return query.all(project, limit);
686
+ }
687
+ function searchObservations(db, searchTerm, project) {
688
+ const sql = project ? `SELECT * FROM observations
689
+ WHERE project = ? AND (title LIKE ? OR text LIKE ? OR narrative LIKE ?)
690
+ ORDER BY created_at_epoch DESC` : `SELECT * FROM observations
691
+ WHERE title LIKE ? OR text LIKE ? OR narrative LIKE ?
692
+ ORDER BY created_at_epoch DESC`;
693
+ const pattern = `%${searchTerm}%`;
694
+ const query = db.query(sql);
695
+ if (project) {
696
+ return query.all(project, pattern, pattern, pattern);
697
+ }
698
+ return query.all(pattern, pattern, pattern);
699
+ }
700
+
701
+ // src/services/sqlite/Summaries.ts
702
+ function createSummary(db, sessionId, project, request, investigated, learned, completed, nextSteps, notes) {
703
+ const now = /* @__PURE__ */ new Date();
704
+ const result = db.run(
705
+ `INSERT INTO summaries
706
+ (session_id, project, request, investigated, learned, completed, next_steps, notes, created_at, created_at_epoch)
707
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
708
+ [sessionId, project, request, investigated, learned, completed, nextSteps, notes, now.toISOString(), now.getTime()]
709
+ );
710
+ return Number(result.lastInsertRowid);
711
+ }
712
+ function getSummariesByProject(db, project, limit = 50) {
713
+ const query = db.query(
714
+ "SELECT * FROM summaries WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
715
+ );
716
+ return query.all(project, limit);
717
+ }
718
+ function searchSummaries(db, searchTerm, project) {
719
+ const sql = project ? `SELECT * FROM summaries
720
+ WHERE project = ? AND (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?)
721
+ ORDER BY created_at_epoch DESC` : `SELECT * FROM summaries
722
+ WHERE request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ?
723
+ ORDER BY created_at_epoch DESC`;
724
+ const pattern = `%${searchTerm}%`;
725
+ const query = db.query(sql);
726
+ if (project) {
727
+ return query.all(project, pattern, pattern, pattern, pattern);
728
+ }
729
+ return query.all(pattern, pattern, pattern, pattern);
730
+ }
731
+
732
+ // src/services/sqlite/Prompts.ts
733
+ function createPrompt(db, contentSessionId, project, promptNumber, promptText) {
734
+ const now = /* @__PURE__ */ new Date();
735
+ const result = db.run(
736
+ `INSERT INTO prompts
737
+ (content_session_id, project, prompt_number, prompt_text, created_at, created_at_epoch)
738
+ VALUES (?, ?, ?, ?, ?, ?)`,
739
+ [contentSessionId, project, promptNumber, promptText, now.toISOString(), now.getTime()]
740
+ );
741
+ return Number(result.lastInsertRowid);
742
+ }
743
+ function getPromptsByProject(db, project, limit = 100) {
744
+ const query = db.query(
745
+ "SELECT * FROM prompts WHERE project = ? ORDER BY created_at_epoch DESC LIMIT ?"
746
+ );
747
+ return query.all(project, limit);
748
+ }
749
+
750
+ // src/services/sqlite/Search.ts
751
+ function sanitizeFTS5Query(query) {
752
+ const terms = query.replace(/[""]/g, "").split(/\s+/).filter((t) => t.length > 0).map((t) => `"${t}"`);
753
+ return terms.join(" ");
754
+ }
755
+ function searchObservationsFTS(db, query, filters = {}) {
756
+ const limit = filters.limit || 50;
757
+ try {
758
+ const safeQuery = sanitizeFTS5Query(query);
759
+ if (!safeQuery) return searchObservationsLIKE(db, query, filters);
760
+ let sql = `
761
+ SELECT o.* FROM observations o
762
+ JOIN observations_fts fts ON o.id = fts.rowid
763
+ WHERE observations_fts MATCH ?
764
+ `;
765
+ const params = [safeQuery];
766
+ if (filters.project) {
767
+ sql += " AND o.project = ?";
768
+ params.push(filters.project);
769
+ }
770
+ if (filters.type) {
771
+ sql += " AND o.type = ?";
772
+ params.push(filters.type);
773
+ }
774
+ if (filters.dateStart) {
775
+ sql += " AND o.created_at_epoch >= ?";
776
+ params.push(filters.dateStart);
777
+ }
778
+ if (filters.dateEnd) {
779
+ sql += " AND o.created_at_epoch <= ?";
780
+ params.push(filters.dateEnd);
781
+ }
782
+ sql += " ORDER BY rank LIMIT ?";
783
+ params.push(limit);
784
+ const stmt = db.query(sql);
785
+ return stmt.all(...params);
786
+ } catch {
787
+ return searchObservationsLIKE(db, query, filters);
788
+ }
789
+ }
790
+ function searchObservationsLIKE(db, query, filters = {}) {
791
+ const limit = filters.limit || 50;
792
+ const pattern = `%${query}%`;
793
+ let sql = `
794
+ SELECT * FROM observations
795
+ WHERE (title LIKE ? OR text LIKE ? OR narrative LIKE ? OR concepts LIKE ?)
796
+ `;
797
+ const params = [pattern, pattern, pattern, pattern];
798
+ if (filters.project) {
799
+ sql += " AND project = ?";
800
+ params.push(filters.project);
801
+ }
802
+ if (filters.type) {
803
+ sql += " AND type = ?";
804
+ params.push(filters.type);
805
+ }
806
+ if (filters.dateStart) {
807
+ sql += " AND created_at_epoch >= ?";
808
+ params.push(filters.dateStart);
809
+ }
810
+ if (filters.dateEnd) {
811
+ sql += " AND created_at_epoch <= ?";
812
+ params.push(filters.dateEnd);
813
+ }
814
+ sql += " ORDER BY created_at_epoch DESC LIMIT ?";
815
+ params.push(limit);
816
+ const stmt = db.query(sql);
817
+ return stmt.all(...params);
818
+ }
819
+ function searchSummariesFiltered(db, query, filters = {}) {
820
+ const limit = filters.limit || 20;
821
+ const pattern = `%${query}%`;
822
+ let sql = `
823
+ SELECT * FROM summaries
824
+ WHERE (request LIKE ? OR learned LIKE ? OR completed LIKE ? OR notes LIKE ? OR next_steps LIKE ?)
825
+ `;
826
+ const params = [pattern, pattern, pattern, pattern, pattern];
827
+ if (filters.project) {
828
+ sql += " AND project = ?";
829
+ params.push(filters.project);
830
+ }
831
+ if (filters.dateStart) {
832
+ sql += " AND created_at_epoch >= ?";
833
+ params.push(filters.dateStart);
834
+ }
835
+ if (filters.dateEnd) {
836
+ sql += " AND created_at_epoch <= ?";
837
+ params.push(filters.dateEnd);
838
+ }
839
+ sql += " ORDER BY created_at_epoch DESC LIMIT ?";
840
+ params.push(limit);
841
+ const stmt = db.query(sql);
842
+ return stmt.all(...params);
843
+ }
844
+ function getObservationsByIds(db, ids) {
845
+ if (ids.length === 0) return [];
846
+ const placeholders = ids.map(() => "?").join(",");
847
+ const sql = `SELECT * FROM observations WHERE id IN (${placeholders}) ORDER BY created_at_epoch DESC`;
848
+ const stmt = db.query(sql);
849
+ return stmt.all(...ids);
850
+ }
851
+ function getTimeline(db, anchorId, depthBefore = 5, depthAfter = 5) {
852
+ const anchorStmt = db.query("SELECT created_at_epoch FROM observations WHERE id = ?");
853
+ const anchor = anchorStmt.get(anchorId);
854
+ if (!anchor) return [];
855
+ const anchorEpoch = anchor.created_at_epoch;
856
+ const beforeStmt = db.query(`
857
+ SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
858
+ FROM observations
859
+ WHERE created_at_epoch < ?
860
+ ORDER BY created_at_epoch DESC
861
+ LIMIT ?
862
+ `);
863
+ const before = beforeStmt.all(anchorEpoch, depthBefore).reverse();
864
+ const selfStmt = db.query(`
865
+ SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
866
+ FROM observations WHERE id = ?
867
+ `);
868
+ const self = selfStmt.all(anchorId);
869
+ const afterStmt = db.query(`
870
+ SELECT id, 'observation' as type, title, text as content, project, created_at, created_at_epoch
871
+ FROM observations
872
+ WHERE created_at_epoch > ?
873
+ ORDER BY created_at_epoch ASC
874
+ LIMIT ?
875
+ `);
876
+ const after = afterStmt.all(anchorEpoch, depthAfter);
877
+ return [...before, ...self, ...after];
878
+ }
1009
879
 
1010
880
  // src/sdk/index.ts
1011
- var ContextKitSDK = class {
881
+ var KiroMemorySDK = class {
1012
882
  db;
1013
883
  project;
1014
884
  constructor(config = {}) {
1015
- this.db = new ContextKitDatabase(config.dataDir);
885
+ this.db = new KiroMemoryDatabase(config.dataDir, config.skipMigrations || false);
1016
886
  this.project = config.project || this.detectProject();
1017
887
  }
1018
888
  detectProject() {
@@ -1032,22 +902,18 @@ var ContextKitSDK = class {
1032
902
  * Get context for the current project
1033
903
  */
1034
904
  async getContext() {
1035
- const { getObservationsByProject: getObservationsByProject2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1036
- const { getSummariesByProject: getSummariesByProject2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1037
- const { getPromptsByProject: getPromptsByProject2 } = await Promise.resolve().then(() => (init_Prompts(), Prompts_exports));
1038
905
  return {
1039
906
  project: this.project,
1040
- relevantObservations: getObservationsByProject2(this.db.db, this.project, 20),
1041
- relevantSummaries: getSummariesByProject2(this.db.db, this.project, 5),
1042
- recentPrompts: getPromptsByProject2(this.db.db, this.project, 10)
907
+ relevantObservations: getObservationsByProject(this.db.db, this.project, 20),
908
+ relevantSummaries: getSummariesByProject(this.db.db, this.project, 5),
909
+ recentPrompts: getPromptsByProject(this.db.db, this.project, 10)
1043
910
  };
1044
911
  }
1045
912
  /**
1046
913
  * Store a new observation
1047
914
  */
1048
915
  async storeObservation(data) {
1049
- const { createObservation: createObservation2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1050
- return createObservation2(
916
+ return createObservation(
1051
917
  this.db.db,
1052
918
  "sdk-" + Date.now(),
1053
919
  this.project,
@@ -1073,8 +939,7 @@ var ContextKitSDK = class {
1073
939
  * Store a session summary
1074
940
  */
1075
941
  async storeSummary(data) {
1076
- const { createSummary: createSummary2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1077
- return createSummary2(
942
+ return createSummary(
1078
943
  this.db.db,
1079
944
  "sdk-" + Date.now(),
1080
945
  this.project,
@@ -1090,61 +955,52 @@ var ContextKitSDK = class {
1090
955
  * Search across all stored context
1091
956
  */
1092
957
  async search(query) {
1093
- const { searchObservations: searchObservations2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1094
- const { searchSummaries: searchSummaries2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1095
958
  return {
1096
- observations: searchObservations2(this.db.db, query, this.project),
1097
- summaries: searchSummaries2(this.db.db, query, this.project)
959
+ observations: searchObservations(this.db.db, query, this.project),
960
+ summaries: searchSummaries(this.db.db, query, this.project)
1098
961
  };
1099
962
  }
1100
963
  /**
1101
964
  * Get recent observations
1102
965
  */
1103
966
  async getRecentObservations(limit = 10) {
1104
- const { getObservationsByProject: getObservationsByProject2 } = await Promise.resolve().then(() => (init_Observations(), Observations_exports));
1105
- return getObservationsByProject2(this.db.db, this.project, limit);
967
+ return getObservationsByProject(this.db.db, this.project, limit);
1106
968
  }
1107
969
  /**
1108
970
  * Get recent summaries
1109
971
  */
1110
972
  async getRecentSummaries(limit = 5) {
1111
- const { getSummariesByProject: getSummariesByProject2 } = await Promise.resolve().then(() => (init_Summaries(), Summaries_exports));
1112
- return getSummariesByProject2(this.db.db, this.project, limit);
973
+ return getSummariesByProject(this.db.db, this.project, limit);
1113
974
  }
1114
975
  /**
1115
- * Ricerca avanzata con FTS5 e filtri
976
+ * Advanced search with FTS5 and filters
1116
977
  */
1117
978
  async searchAdvanced(query, filters = {}) {
1118
- const { searchObservationsFTS: searchObservationsFTS2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1119
- const { searchSummariesFiltered: searchSummariesFiltered2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1120
979
  const projectFilters = { ...filters, project: filters.project || this.project };
1121
980
  return {
1122
- observations: searchObservationsFTS2(this.db.db, query, projectFilters),
1123
- summaries: searchSummariesFiltered2(this.db.db, query, projectFilters)
981
+ observations: searchObservationsFTS(this.db.db, query, projectFilters),
982
+ summaries: searchSummariesFiltered(this.db.db, query, projectFilters)
1124
983
  };
1125
984
  }
1126
985
  /**
1127
- * Recupera osservazioni per ID (batch)
986
+ * Retrieve observations by ID (batch)
1128
987
  */
1129
988
  async getObservationsByIds(ids) {
1130
- const { getObservationsByIds: getObservationsByIds2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1131
- return getObservationsByIds2(this.db.db, ids);
989
+ return getObservationsByIds(this.db.db, ids);
1132
990
  }
1133
991
  /**
1134
- * Timeline: contesto cronologico attorno a un'osservazione
992
+ * Timeline: chronological context around an observation
1135
993
  */
1136
994
  async getTimeline(anchorId, depthBefore = 5, depthAfter = 5) {
1137
- const { getTimeline: getTimeline2 } = await Promise.resolve().then(() => (init_Search(), Search_exports));
1138
- return getTimeline2(this.db.db, anchorId, depthBefore, depthAfter);
995
+ return getTimeline(this.db.db, anchorId, depthBefore, depthAfter);
1139
996
  }
1140
997
  /**
1141
- * Crea o recupera una sessione per il progetto corrente
998
+ * Create or retrieve a session for the current project
1142
999
  */
1143
1000
  async getOrCreateSession(contentSessionId) {
1144
- const { getSessionByContentId: getSessionByContentId2, createSession: createSession2 } = await Promise.resolve().then(() => (init_Sessions(), Sessions_exports));
1145
- let session = getSessionByContentId2(this.db.db, contentSessionId);
1001
+ let session = getSessionByContentId(this.db.db, contentSessionId);
1146
1002
  if (!session) {
1147
- const id = createSession2(this.db.db, contentSessionId, this.project, "");
1003
+ const id = createSession(this.db.db, contentSessionId, this.project, "");
1148
1004
  session = {
1149
1005
  id,
1150
1006
  content_session_id: contentSessionId,
@@ -1161,27 +1017,25 @@ var ContextKitSDK = class {
1161
1017
  return session;
1162
1018
  }
1163
1019
  /**
1164
- * Salva un prompt utente
1020
+ * Store a user prompt
1165
1021
  */
1166
1022
  async storePrompt(contentSessionId, promptNumber, text) {
1167
- const { createPrompt: createPrompt2 } = await Promise.resolve().then(() => (init_Prompts(), Prompts_exports));
1168
- return createPrompt2(this.db.db, contentSessionId, this.project, promptNumber, text);
1023
+ return createPrompt(this.db.db, contentSessionId, this.project, promptNumber, text);
1169
1024
  }
1170
1025
  /**
1171
- * Completa una sessione
1026
+ * Complete a session
1172
1027
  */
1173
1028
  async completeSession(sessionId) {
1174
- const { completeSession: completeSession2 } = await Promise.resolve().then(() => (init_Sessions(), Sessions_exports));
1175
- completeSession2(this.db.db, sessionId);
1029
+ completeSession(this.db.db, sessionId);
1176
1030
  }
1177
1031
  /**
1178
- * Getter per il nome progetto corrente
1032
+ * Getter for current project name
1179
1033
  */
1180
1034
  getProject() {
1181
1035
  return this.project;
1182
1036
  }
1183
1037
  /**
1184
- * Getter per accesso diretto al database (per route API)
1038
+ * Getter for direct database access (for API routes)
1185
1039
  */
1186
1040
  getDb() {
1187
1041
  return this.db.db;
@@ -1193,8 +1047,8 @@ var ContextKitSDK = class {
1193
1047
  this.db.close();
1194
1048
  }
1195
1049
  };
1196
- function createContextKit(config) {
1197
- return new ContextKitSDK(config);
1050
+ function createKiroMemory(config) {
1051
+ return new KiroMemorySDK(config);
1198
1052
  }
1199
1053
 
1200
1054
  // src/hooks/agentSpawn.ts
@@ -1238,7 +1092,7 @@ runHook("agentSpawn", async (input) => {
1238
1092
  await ensureWorkerRunning().catch(() => {
1239
1093
  });
1240
1094
  const project = detectProject(input.cwd);
1241
- const sdk = createContextKit({ project });
1095
+ const sdk = createKiroMemory({ project });
1242
1096
  try {
1243
1097
  const ctx = await sdk.getContext();
1244
1098
  if (ctx.relevantObservations.length === 0 && ctx.relevantSummaries.length === 0) {