kiro-memory 1.9.0 → 3.0.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.
- package/README.md +5 -1
- package/package.json +5 -5
- package/plugin/dist/cli/contextkit.js +2611 -345
- package/plugin/dist/hooks/agentSpawn.js +853 -223
- package/plugin/dist/hooks/kiro-hooks.js +841 -211
- package/plugin/dist/hooks/postToolUse.js +853 -222
- package/plugin/dist/hooks/stop.js +850 -220
- package/plugin/dist/hooks/userPromptSubmit.js +848 -216
- package/plugin/dist/index.js +843 -340
- package/plugin/dist/plugins/github/github-client.js +152 -0
- package/plugin/dist/plugins/github/index.js +412 -0
- package/plugin/dist/plugins/github/issue-parser.js +54 -0
- package/plugin/dist/plugins/slack/formatter.js +90 -0
- package/plugin/dist/plugins/slack/index.js +215 -0
- package/plugin/dist/sdk/index.js +841 -215
- package/plugin/dist/servers/mcp-server.js +4461 -397
- package/plugin/dist/services/search/EmbeddingService.js +146 -37
- package/plugin/dist/services/search/HybridSearch.js +564 -116
- package/plugin/dist/services/search/VectorSearch.js +187 -60
- package/plugin/dist/services/search/index.js +565 -254
- package/plugin/dist/services/sqlite/Backup.js +416 -0
- package/plugin/dist/services/sqlite/Database.js +126 -153
- package/plugin/dist/services/sqlite/ImportExport.js +452 -0
- package/plugin/dist/services/sqlite/Observations.js +314 -19
- package/plugin/dist/services/sqlite/Prompts.js +1 -1
- package/plugin/dist/services/sqlite/Search.js +41 -29
- package/plugin/dist/services/sqlite/Summaries.js +4 -4
- package/plugin/dist/services/sqlite/index.js +1428 -208
- package/plugin/dist/viewer.css +1 -0
- package/plugin/dist/viewer.html +2 -179
- package/plugin/dist/viewer.js +23 -24942
- package/plugin/dist/viewer.js.map +7 -0
- package/plugin/dist/worker-service.js +427 -5569
- package/plugin/dist/worker-service.js.map +7 -0
|
@@ -4,14 +4,15 @@ import { createRequire } from 'module';const require = createRequire(import.meta
|
|
|
4
4
|
import BetterSqlite3 from "better-sqlite3";
|
|
5
5
|
var Database = class {
|
|
6
6
|
_db;
|
|
7
|
+
_stmtCache = /* @__PURE__ */ new Map();
|
|
7
8
|
constructor(path, options) {
|
|
8
9
|
this._db = new BetterSqlite3(path, {
|
|
9
|
-
// better-sqlite3
|
|
10
|
+
// better-sqlite3 creates the file by default ('create' not needed)
|
|
10
11
|
readonly: options?.readwrite === false ? true : false
|
|
11
12
|
});
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
+
* Execute a SQL query without results
|
|
15
16
|
*/
|
|
16
17
|
run(sql, params) {
|
|
17
18
|
const stmt = this._db.prepare(sql);
|
|
@@ -19,51 +20,53 @@ var Database = class {
|
|
|
19
20
|
return result;
|
|
20
21
|
}
|
|
21
22
|
/**
|
|
22
|
-
*
|
|
23
|
+
* Prepare a query with bun:sqlite-compatible interface.
|
|
24
|
+
* Returns a cached prepared statement for repeated queries.
|
|
23
25
|
*/
|
|
24
26
|
query(sql) {
|
|
25
|
-
|
|
27
|
+
let cached = this._stmtCache.get(sql);
|
|
28
|
+
if (!cached) {
|
|
29
|
+
cached = new BunQueryCompat(this._db, sql);
|
|
30
|
+
this._stmtCache.set(sql, cached);
|
|
31
|
+
}
|
|
32
|
+
return cached;
|
|
26
33
|
}
|
|
27
34
|
/**
|
|
28
|
-
*
|
|
35
|
+
* Create a transaction
|
|
29
36
|
*/
|
|
30
37
|
transaction(fn) {
|
|
31
38
|
return this._db.transaction(fn);
|
|
32
39
|
}
|
|
33
40
|
/**
|
|
34
|
-
*
|
|
41
|
+
* Close the connection
|
|
35
42
|
*/
|
|
36
43
|
close() {
|
|
44
|
+
this._stmtCache.clear();
|
|
37
45
|
this._db.close();
|
|
38
46
|
}
|
|
39
47
|
};
|
|
40
48
|
var BunQueryCompat = class {
|
|
41
|
-
|
|
42
|
-
_sql;
|
|
49
|
+
_stmt;
|
|
43
50
|
constructor(db, sql) {
|
|
44
|
-
this.
|
|
45
|
-
this._sql = sql;
|
|
51
|
+
this._stmt = db.prepare(sql);
|
|
46
52
|
}
|
|
47
53
|
/**
|
|
48
|
-
*
|
|
54
|
+
* Returns all rows
|
|
49
55
|
*/
|
|
50
56
|
all(...params) {
|
|
51
|
-
|
|
52
|
-
return params.length > 0 ? stmt.all(...params) : stmt.all();
|
|
57
|
+
return params.length > 0 ? this._stmt.all(...params) : this._stmt.all();
|
|
53
58
|
}
|
|
54
59
|
/**
|
|
55
|
-
*
|
|
60
|
+
* Returns the first row or null
|
|
56
61
|
*/
|
|
57
62
|
get(...params) {
|
|
58
|
-
|
|
59
|
-
return params.length > 0 ? stmt.get(...params) : stmt.get();
|
|
63
|
+
return params.length > 0 ? this._stmt.get(...params) : this._stmt.get();
|
|
60
64
|
}
|
|
61
65
|
/**
|
|
62
|
-
*
|
|
66
|
+
* Execute without results
|
|
63
67
|
*/
|
|
64
68
|
run(...params) {
|
|
65
|
-
|
|
66
|
-
return params.length > 0 ? stmt.run(...params) : stmt.run();
|
|
69
|
+
return params.length > 0 ? this._stmt.run(...params) : this._stmt.run();
|
|
67
70
|
}
|
|
68
71
|
};
|
|
69
72
|
|
|
@@ -324,150 +327,63 @@ function ensureDir(dirPath) {
|
|
|
324
327
|
// src/services/sqlite/Database.ts
|
|
325
328
|
var SQLITE_MMAP_SIZE_BYTES = 256 * 1024 * 1024;
|
|
326
329
|
var SQLITE_CACHE_SIZE_PAGES = 1e4;
|
|
327
|
-
var dbInstance = null;
|
|
328
330
|
var KiroMemoryDatabase = class {
|
|
329
|
-
|
|
331
|
+
_db;
|
|
330
332
|
/**
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
+
* Readonly accessor for the underlying Database instance.
|
|
334
|
+
* Prefer using query() and run() proxy methods directly.
|
|
335
|
+
*/
|
|
336
|
+
get db() {
|
|
337
|
+
return this._db;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* @param dbPath - Path to the SQLite file (default: DB_PATH)
|
|
341
|
+
* @param skipMigrations - If true, skip the migration runner (for high-frequency hooks)
|
|
333
342
|
*/
|
|
334
343
|
constructor(dbPath = DB_PATH, skipMigrations = false) {
|
|
335
344
|
if (dbPath !== ":memory:") {
|
|
336
345
|
ensureDir(DATA_DIR);
|
|
337
346
|
}
|
|
338
|
-
this.
|
|
339
|
-
this.
|
|
340
|
-
this.
|
|
341
|
-
this.
|
|
342
|
-
this.
|
|
343
|
-
this.
|
|
344
|
-
this.
|
|
347
|
+
this._db = new Database(dbPath, { create: true, readwrite: true });
|
|
348
|
+
this._db.run("PRAGMA journal_mode = WAL");
|
|
349
|
+
this._db.run("PRAGMA busy_timeout = 5000");
|
|
350
|
+
this._db.run("PRAGMA synchronous = NORMAL");
|
|
351
|
+
this._db.run("PRAGMA foreign_keys = ON");
|
|
352
|
+
this._db.run("PRAGMA temp_store = memory");
|
|
353
|
+
this._db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
|
|
354
|
+
this._db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
|
|
345
355
|
if (!skipMigrations) {
|
|
346
|
-
const migrationRunner = new MigrationRunner(this.
|
|
356
|
+
const migrationRunner = new MigrationRunner(this._db);
|
|
347
357
|
migrationRunner.runAllMigrations();
|
|
348
358
|
}
|
|
349
359
|
}
|
|
350
360
|
/**
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*/
|
|
354
|
-
withTransaction(fn) {
|
|
355
|
-
const transaction = this.db.transaction(fn);
|
|
356
|
-
return transaction(this.db);
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Close the database connection
|
|
360
|
-
*/
|
|
361
|
-
close() {
|
|
362
|
-
this.db.close();
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
var DatabaseManager = class _DatabaseManager {
|
|
366
|
-
static instance;
|
|
367
|
-
db = null;
|
|
368
|
-
migrations = [];
|
|
369
|
-
static getInstance() {
|
|
370
|
-
if (!_DatabaseManager.instance) {
|
|
371
|
-
_DatabaseManager.instance = new _DatabaseManager();
|
|
372
|
-
}
|
|
373
|
-
return _DatabaseManager.instance;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Register a migration to be run during initialization
|
|
377
|
-
*/
|
|
378
|
-
registerMigration(migration) {
|
|
379
|
-
this.migrations.push(migration);
|
|
380
|
-
this.migrations.sort((a, b) => a.version - b.version);
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Initialize database connection with optimized settings
|
|
361
|
+
* Prepare a query (delegates to underlying Database).
|
|
362
|
+
* Proxy method to avoid ctx.db.db.query() double access.
|
|
384
363
|
*/
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
return this.db;
|
|
388
|
-
}
|
|
389
|
-
ensureDir(DATA_DIR);
|
|
390
|
-
this.db = new Database(DB_PATH, { create: true, readwrite: true });
|
|
391
|
-
this.db.run("PRAGMA journal_mode = WAL");
|
|
392
|
-
this.db.run("PRAGMA synchronous = NORMAL");
|
|
393
|
-
this.db.run("PRAGMA foreign_keys = ON");
|
|
394
|
-
this.db.run("PRAGMA temp_store = memory");
|
|
395
|
-
this.db.run(`PRAGMA mmap_size = ${SQLITE_MMAP_SIZE_BYTES}`);
|
|
396
|
-
this.db.run(`PRAGMA cache_size = ${SQLITE_CACHE_SIZE_PAGES}`);
|
|
397
|
-
this.initializeSchemaVersions();
|
|
398
|
-
await this.runMigrations();
|
|
399
|
-
dbInstance = this.db;
|
|
400
|
-
return this.db;
|
|
364
|
+
query(sql) {
|
|
365
|
+
return this._db.query(sql);
|
|
401
366
|
}
|
|
402
367
|
/**
|
|
403
|
-
*
|
|
368
|
+
* Execute a SQL statement without results (delegates to underlying Database).
|
|
369
|
+
* Proxy method to avoid ctx.db.db.run() double access.
|
|
404
370
|
*/
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
throw new Error("Database not initialized. Call initialize() first.");
|
|
408
|
-
}
|
|
409
|
-
return this.db;
|
|
371
|
+
run(sql, params) {
|
|
372
|
+
return this._db.run(sql, params);
|
|
410
373
|
}
|
|
411
374
|
/**
|
|
412
|
-
*
|
|
375
|
+
* Executes a function within an atomic transaction.
|
|
376
|
+
* If fn() throws an error, the transaction is automatically rolled back.
|
|
413
377
|
*/
|
|
414
378
|
withTransaction(fn) {
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
return transaction(db);
|
|
379
|
+
const transaction = this._db.transaction(fn);
|
|
380
|
+
return transaction(this._db);
|
|
418
381
|
}
|
|
419
382
|
/**
|
|
420
383
|
* Close the database connection
|
|
421
384
|
*/
|
|
422
385
|
close() {
|
|
423
|
-
|
|
424
|
-
this.db.close();
|
|
425
|
-
this.db = null;
|
|
426
|
-
dbInstance = null;
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* Initialize the schema_versions table
|
|
431
|
-
*/
|
|
432
|
-
initializeSchemaVersions() {
|
|
433
|
-
if (!this.db) return;
|
|
434
|
-
this.db.run(`
|
|
435
|
-
CREATE TABLE IF NOT EXISTS schema_versions (
|
|
436
|
-
id INTEGER PRIMARY KEY,
|
|
437
|
-
version INTEGER UNIQUE NOT NULL,
|
|
438
|
-
applied_at TEXT NOT NULL
|
|
439
|
-
)
|
|
440
|
-
`);
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Run all pending migrations
|
|
444
|
-
*/
|
|
445
|
-
async runMigrations() {
|
|
446
|
-
if (!this.db) return;
|
|
447
|
-
const query = this.db.query("SELECT version FROM schema_versions ORDER BY version");
|
|
448
|
-
const appliedVersions = query.all().map((row) => row.version);
|
|
449
|
-
const maxApplied = appliedVersions.length > 0 ? Math.max(...appliedVersions) : 0;
|
|
450
|
-
for (const migration of this.migrations) {
|
|
451
|
-
if (migration.version > maxApplied) {
|
|
452
|
-
logger.info("DB", `Applying migration ${migration.version}`);
|
|
453
|
-
const transaction = this.db.transaction(() => {
|
|
454
|
-
migration.up(this.db);
|
|
455
|
-
const insertQuery = this.db.query("INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)");
|
|
456
|
-
insertQuery.run(migration.version, (/* @__PURE__ */ new Date()).toISOString());
|
|
457
|
-
});
|
|
458
|
-
transaction();
|
|
459
|
-
logger.info("DB", `Migration ${migration.version} applied successfully`);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Get current schema version
|
|
465
|
-
*/
|
|
466
|
-
getCurrentVersion() {
|
|
467
|
-
if (!this.db) return 0;
|
|
468
|
-
const query = this.db.query("SELECT MAX(version) as version FROM schema_versions");
|
|
469
|
-
const result = query.get();
|
|
470
|
-
return result?.version || 0;
|
|
386
|
+
this._db.close();
|
|
471
387
|
}
|
|
472
388
|
};
|
|
473
389
|
var MigrationRunner = class {
|
|
@@ -708,25 +624,82 @@ var MigrationRunner = class {
|
|
|
708
624
|
db.run("CREATE INDEX IF NOT EXISTS idx_summaries_project_epoch ON summaries(project, created_at_epoch DESC)");
|
|
709
625
|
db.run("CREATE INDEX IF NOT EXISTS idx_prompts_project_epoch ON prompts(project, created_at_epoch DESC)");
|
|
710
626
|
}
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
version: 10,
|
|
630
|
+
up: (db) => {
|
|
631
|
+
db.run(`
|
|
632
|
+
CREATE TABLE IF NOT EXISTS job_queue (
|
|
633
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
634
|
+
type TEXT NOT NULL,
|
|
635
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
636
|
+
payload TEXT,
|
|
637
|
+
result TEXT,
|
|
638
|
+
error TEXT,
|
|
639
|
+
retry_count INTEGER DEFAULT 0,
|
|
640
|
+
max_retries INTEGER DEFAULT 3,
|
|
641
|
+
priority INTEGER DEFAULT 0,
|
|
642
|
+
created_at TEXT NOT NULL,
|
|
643
|
+
created_at_epoch INTEGER NOT NULL,
|
|
644
|
+
started_at_epoch INTEGER,
|
|
645
|
+
completed_at_epoch INTEGER
|
|
646
|
+
)
|
|
647
|
+
`);
|
|
648
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_jobs_status ON job_queue(status)");
|
|
649
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_jobs_type ON job_queue(type)");
|
|
650
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_jobs_priority ON job_queue(status, priority DESC, created_at_epoch ASC)");
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
version: 11,
|
|
655
|
+
up: (db) => {
|
|
656
|
+
db.run("ALTER TABLE observations ADD COLUMN auto_category TEXT");
|
|
657
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_observations_category ON observations(auto_category)");
|
|
658
|
+
}
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
version: 12,
|
|
662
|
+
up: (db) => {
|
|
663
|
+
db.run(`
|
|
664
|
+
CREATE TABLE IF NOT EXISTS github_links (
|
|
665
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
666
|
+
observation_id INTEGER,
|
|
667
|
+
session_id TEXT,
|
|
668
|
+
repo TEXT NOT NULL,
|
|
669
|
+
issue_number INTEGER,
|
|
670
|
+
pr_number INTEGER,
|
|
671
|
+
event_type TEXT NOT NULL,
|
|
672
|
+
action TEXT,
|
|
673
|
+
title TEXT,
|
|
674
|
+
url TEXT,
|
|
675
|
+
author TEXT,
|
|
676
|
+
created_at TEXT NOT NULL,
|
|
677
|
+
created_at_epoch INTEGER NOT NULL,
|
|
678
|
+
FOREIGN KEY (observation_id) REFERENCES observations(id)
|
|
679
|
+
)
|
|
680
|
+
`);
|
|
681
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_github_links_repo ON github_links(repo)");
|
|
682
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_github_links_obs ON github_links(observation_id)");
|
|
683
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_github_links_event ON github_links(event_type)");
|
|
684
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_github_links_repo_issue ON github_links(repo, issue_number)");
|
|
685
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_github_links_repo_pr ON github_links(repo, pr_number)");
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
version: 13,
|
|
690
|
+
up: (db) => {
|
|
691
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_observations_keyset ON observations(created_at_epoch DESC, id DESC)");
|
|
692
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_observations_project_keyset ON observations(project, created_at_epoch DESC, id DESC)");
|
|
693
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_summaries_keyset ON summaries(created_at_epoch DESC, id DESC)");
|
|
694
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_summaries_project_keyset ON summaries(project, created_at_epoch DESC, id DESC)");
|
|
695
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_prompts_keyset ON prompts(created_at_epoch DESC, id DESC)");
|
|
696
|
+
db.run("CREATE INDEX IF NOT EXISTS idx_prompts_project_keyset ON prompts(project, created_at_epoch DESC, id DESC)");
|
|
697
|
+
}
|
|
711
698
|
}
|
|
712
699
|
];
|
|
713
700
|
}
|
|
714
701
|
};
|
|
715
|
-
function getDatabase() {
|
|
716
|
-
if (!dbInstance) {
|
|
717
|
-
throw new Error("Database not initialized. Call DatabaseManager.getInstance().initialize() first.");
|
|
718
|
-
}
|
|
719
|
-
return dbInstance;
|
|
720
|
-
}
|
|
721
|
-
async function initializeDatabase() {
|
|
722
|
-
const manager = DatabaseManager.getInstance();
|
|
723
|
-
return await manager.initialize();
|
|
724
|
-
}
|
|
725
702
|
export {
|
|
726
|
-
KiroMemoryDatabase as ContextKitDatabase,
|
|
727
703
|
Database,
|
|
728
|
-
|
|
729
|
-
KiroMemoryDatabase,
|
|
730
|
-
getDatabase,
|
|
731
|
-
initializeDatabase
|
|
704
|
+
KiroMemoryDatabase
|
|
732
705
|
};
|