@vheins/local-memory-mcp 0.7.4 → 0.8.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.
|
@@ -172,40 +172,28 @@ function addLogSink(sink) {
|
|
|
172
172
|
var LOG_LEVEL_VALUES = Object.keys(LEVELS);
|
|
173
173
|
|
|
174
174
|
// src/mcp/storage/sqlite.ts
|
|
175
|
-
import
|
|
175
|
+
import Database from "better-sqlite3";
|
|
176
176
|
import path2 from "path";
|
|
177
177
|
import fs2 from "fs";
|
|
178
178
|
import os from "os";
|
|
179
179
|
|
|
180
180
|
// src/mcp/storage/migrations.ts
|
|
181
181
|
var MigrationManager = class {
|
|
182
|
-
constructor(db
|
|
182
|
+
constructor(db) {
|
|
183
183
|
this.db = db;
|
|
184
|
-
this.saveDb = saveDb;
|
|
185
184
|
}
|
|
186
185
|
db;
|
|
187
|
-
saveDb;
|
|
188
186
|
run(sql) {
|
|
189
|
-
this.db.
|
|
187
|
+
this.db.prepare(sql).run();
|
|
190
188
|
}
|
|
191
189
|
exec(sql) {
|
|
192
190
|
this.db.exec(sql);
|
|
193
191
|
}
|
|
194
192
|
all(sql) {
|
|
195
|
-
|
|
196
|
-
if (result.length === 0) return [];
|
|
197
|
-
const { columns, values } = result[0];
|
|
198
|
-
return values.map((row) => {
|
|
199
|
-
const obj = {};
|
|
200
|
-
columns.forEach((col, i) => {
|
|
201
|
-
obj[col] = row[i];
|
|
202
|
-
});
|
|
203
|
-
return obj;
|
|
204
|
-
});
|
|
193
|
+
return this.db.prepare(sql).all();
|
|
205
194
|
}
|
|
206
195
|
get(sql) {
|
|
207
|
-
|
|
208
|
-
return rows[0];
|
|
196
|
+
return this.db.prepare(sql).get();
|
|
209
197
|
}
|
|
210
198
|
migrate() {
|
|
211
199
|
this.exec(`
|
|
@@ -427,7 +415,6 @@ var MigrationManager = class {
|
|
|
427
415
|
this.run("UPDATE tasks SET task_code = substr(id, 1, 8) WHERE task_code IS NULL");
|
|
428
416
|
} catch {
|
|
429
417
|
}
|
|
430
|
-
if (this.saveDb) this.saveDb();
|
|
431
418
|
}
|
|
432
419
|
ensureMemoryTypeConstraint() {
|
|
433
420
|
const tableSql = this.get("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memories'");
|
|
@@ -531,7 +518,7 @@ var MigrationManager = class {
|
|
|
531
518
|
}
|
|
532
519
|
ensureMemoryStatusConstraintRemoved() {
|
|
533
520
|
const tableSql = this.get("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memories'");
|
|
534
|
-
if (tableSql?.sql
|
|
521
|
+
if (typeof tableSql?.sql === "string" && tableSql.sql.includes("status TEXT NOT NULL DEFAULT 'active' CHECK")) {
|
|
535
522
|
this.ensureMemoryTypeConstraint();
|
|
536
523
|
}
|
|
537
524
|
}
|
|
@@ -792,36 +779,25 @@ function tokenize(text) {
|
|
|
792
779
|
|
|
793
780
|
// src/mcp/storage/base.ts
|
|
794
781
|
var BaseEntity = class {
|
|
795
|
-
constructor(db
|
|
782
|
+
constructor(db) {
|
|
796
783
|
this.db = db;
|
|
797
|
-
this.saveDb = saveDb;
|
|
798
784
|
}
|
|
799
785
|
db;
|
|
800
|
-
saveDb;
|
|
801
786
|
run(sql, params = []) {
|
|
802
|
-
this.db.
|
|
803
|
-
|
|
804
|
-
return { changes:
|
|
787
|
+
const stmt = this.db.prepare(sql);
|
|
788
|
+
const result = stmt.run(...params);
|
|
789
|
+
return { changes: result.changes };
|
|
805
790
|
}
|
|
806
791
|
exec(sql) {
|
|
807
792
|
this.db.exec(sql);
|
|
808
|
-
if (this.saveDb) this.saveDb();
|
|
809
793
|
}
|
|
810
794
|
all(sql, params = []) {
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
const { columns, values } = result[0];
|
|
814
|
-
return values.map((row) => {
|
|
815
|
-
const obj = {};
|
|
816
|
-
columns.forEach((col, i) => {
|
|
817
|
-
obj[col] = row[i];
|
|
818
|
-
});
|
|
819
|
-
return obj;
|
|
820
|
-
});
|
|
795
|
+
const stmt = this.db.prepare(sql);
|
|
796
|
+
return stmt.all(...params);
|
|
821
797
|
}
|
|
822
798
|
get(sql, params = []) {
|
|
823
|
-
const
|
|
824
|
-
return
|
|
799
|
+
const stmt = this.db.prepare(sql);
|
|
800
|
+
return stmt.get(...params);
|
|
825
801
|
}
|
|
826
802
|
safeJSONParse(json, defaultValue) {
|
|
827
803
|
if (!json) return defaultValue;
|
|
@@ -1135,7 +1111,7 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
1135
1111
|
}
|
|
1136
1112
|
return count;
|
|
1137
1113
|
}
|
|
1138
|
-
getRecentMemories(repo, limit, offset = 0, includeArchived = false, excludeTypes = []) {
|
|
1114
|
+
getRecentMemories(repo, limit, offset = 0, includeArchived = false, excludeTypes = [], sortOrder = "DESC") {
|
|
1139
1115
|
let query = "SELECT * FROM memories WHERE repo = ?";
|
|
1140
1116
|
const params = [repo];
|
|
1141
1117
|
if (!includeArchived) {
|
|
@@ -1145,7 +1121,7 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
1145
1121
|
query += ` AND type NOT IN (${excludeTypes.map(() => "?").join(",")})`;
|
|
1146
1122
|
params.push(...excludeTypes);
|
|
1147
1123
|
}
|
|
1148
|
-
query +=
|
|
1124
|
+
query += ` ORDER BY importance DESC, created_at ${sortOrder} LIMIT ? OFFSET ?`;
|
|
1149
1125
|
params.push(limit, offset);
|
|
1150
1126
|
const rows = this.all(query, params);
|
|
1151
1127
|
return rows.map((row) => this.rowToMemoryEntry(row));
|
|
@@ -1380,8 +1356,28 @@ var TaskEntity = class extends BaseEntity {
|
|
|
1380
1356
|
const fields = [];
|
|
1381
1357
|
const values = [];
|
|
1382
1358
|
const anyUpdates = updates;
|
|
1359
|
+
const VALID_COLUMNS = /* @__PURE__ */ new Set([
|
|
1360
|
+
"repo",
|
|
1361
|
+
"task_code",
|
|
1362
|
+
"phase",
|
|
1363
|
+
"title",
|
|
1364
|
+
"description",
|
|
1365
|
+
"status",
|
|
1366
|
+
"priority",
|
|
1367
|
+
"agent",
|
|
1368
|
+
"role",
|
|
1369
|
+
"doc_path",
|
|
1370
|
+
"finished_at",
|
|
1371
|
+
"canceled_at",
|
|
1372
|
+
"tags",
|
|
1373
|
+
"metadata",
|
|
1374
|
+
"parent_id",
|
|
1375
|
+
"depends_on",
|
|
1376
|
+
"est_tokens",
|
|
1377
|
+
"in_progress_at"
|
|
1378
|
+
]);
|
|
1383
1379
|
Object.keys(updates).forEach((key) => {
|
|
1384
|
-
if (key
|
|
1380
|
+
if (VALID_COLUMNS.has(key) && anyUpdates[key] !== void 0) {
|
|
1385
1381
|
if (key === "tags" || key === "metadata") {
|
|
1386
1382
|
fields.push(`${key} = ?`);
|
|
1387
1383
|
values.push(JSON.stringify(anyUpdates[key]));
|
|
@@ -1899,32 +1895,6 @@ function resolveDbPath() {
|
|
|
1899
1895
|
return standardPath;
|
|
1900
1896
|
}
|
|
1901
1897
|
var DB_PATH = resolveDbPath();
|
|
1902
|
-
var sqlJsReady = null;
|
|
1903
|
-
var sqlJsModule = null;
|
|
1904
|
-
async function getSqlJs() {
|
|
1905
|
-
if (!sqlJsModule) {
|
|
1906
|
-
sqlJsModule = await initSqlJs();
|
|
1907
|
-
}
|
|
1908
|
-
await sqlJsReady;
|
|
1909
|
-
return sqlJsModule;
|
|
1910
|
-
}
|
|
1911
|
-
function createSaveFunction(db, dbPath) {
|
|
1912
|
-
return () => {
|
|
1913
|
-
if (dbPath && dbPath !== ":memory:") {
|
|
1914
|
-
const data = db.export();
|
|
1915
|
-
const buffer = Buffer.from(data);
|
|
1916
|
-
fs2.writeFileSync(dbPath, buffer);
|
|
1917
|
-
}
|
|
1918
|
-
};
|
|
1919
|
-
}
|
|
1920
|
-
function warmUpSqlJs() {
|
|
1921
|
-
if (!sqlJsReady) {
|
|
1922
|
-
sqlJsReady = (async () => {
|
|
1923
|
-
sqlJsModule = await initSqlJs();
|
|
1924
|
-
})();
|
|
1925
|
-
}
|
|
1926
|
-
return sqlJsReady;
|
|
1927
|
-
}
|
|
1928
1898
|
var SQLiteStore = class _SQLiteStore {
|
|
1929
1899
|
db;
|
|
1930
1900
|
memories;
|
|
@@ -1932,106 +1902,42 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
1932
1902
|
actions;
|
|
1933
1903
|
system;
|
|
1934
1904
|
summaries;
|
|
1935
|
-
_ready;
|
|
1936
|
-
lastLoadedAt = 0;
|
|
1937
|
-
saveDbPtr;
|
|
1938
1905
|
dbPathInstance;
|
|
1939
1906
|
constructor(dbPath) {
|
|
1940
1907
|
const finalPath = dbPath ?? DB_PATH;
|
|
1941
1908
|
this.dbPathInstance = finalPath;
|
|
1942
|
-
|
|
1943
|
-
this.db = {};
|
|
1944
|
-
this.memories = {};
|
|
1945
|
-
this.tasks = {};
|
|
1946
|
-
this.actions = {};
|
|
1947
|
-
this.system = {};
|
|
1948
|
-
this.summaries = {};
|
|
1949
|
-
this._ready = this._init(finalPath);
|
|
1950
|
-
}
|
|
1951
|
-
async _init(finalPath) {
|
|
1952
|
-
const SQL = await getSqlJs();
|
|
1953
|
-
let db;
|
|
1954
|
-
if (finalPath === ":memory:") {
|
|
1955
|
-
db = new SQL.Database();
|
|
1956
|
-
} else {
|
|
1909
|
+
if (finalPath !== ":memory:") {
|
|
1957
1910
|
const dbDir = path2.dirname(finalPath);
|
|
1958
1911
|
if (!fs2.existsSync(dbDir)) {
|
|
1959
1912
|
fs2.mkdirSync(dbDir, { recursive: true });
|
|
1960
1913
|
}
|
|
1961
|
-
if (fs2.existsSync(finalPath)) {
|
|
1962
|
-
const fileBuffer = fs2.readFileSync(finalPath);
|
|
1963
|
-
db = new SQL.Database(fileBuffer);
|
|
1964
|
-
} else {
|
|
1965
|
-
db = new SQL.Database();
|
|
1966
|
-
}
|
|
1967
1914
|
}
|
|
1968
|
-
this.
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
};
|
|
1975
|
-
db.run("PRAGMA journal_mode = WAL");
|
|
1976
|
-
db.run("PRAGMA synchronous = NORMAL");
|
|
1977
|
-
db.run("PRAGMA busy_timeout = 5000");
|
|
1978
|
-
const migrator = new MigrationManager(db, wrappedSaveDb);
|
|
1915
|
+
this.db = new Database(finalPath);
|
|
1916
|
+
this.db.pragma("journal_mode = WAL");
|
|
1917
|
+
this.db.pragma("synchronous = NORMAL");
|
|
1918
|
+
this.db.pragma("busy_timeout = 5000");
|
|
1919
|
+
this.db.pragma("foreign_keys = ON");
|
|
1920
|
+
const migrator = new MigrationManager(this.db);
|
|
1979
1921
|
migrator.migrate();
|
|
1980
1922
|
migrator.addMemoryCodeColumn();
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
system: new SystemEntity(db, wrappedSaveDb),
|
|
1987
|
-
summaries: new SummaryEntity(db, wrappedSaveDb)
|
|
1988
|
-
});
|
|
1989
|
-
this.lastLoadedAt = Date.now();
|
|
1990
|
-
if (finalPath !== ":memory:") {
|
|
1991
|
-
wrappedSaveDb();
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
async refresh(force = false) {
|
|
1995
|
-
const path5 = this.getDbPath();
|
|
1996
|
-
if (path5 === ":memory:") return;
|
|
1997
|
-
try {
|
|
1998
|
-
const stats = fs2.statSync(path5);
|
|
1999
|
-
const mtime = stats.mtimeMs;
|
|
2000
|
-
if (force || mtime > this.lastLoadedAt) {
|
|
2001
|
-
const SQL = await getSqlJs();
|
|
2002
|
-
const fileBuffer = fs2.readFileSync(path5);
|
|
2003
|
-
const newDb = new SQL.Database(fileBuffer);
|
|
2004
|
-
const wrappedSaveDb = () => {
|
|
2005
|
-
if (this.saveDbPtr) {
|
|
2006
|
-
this.saveDbPtr();
|
|
2007
|
-
this.lastLoadedAt = Date.now();
|
|
2008
|
-
}
|
|
2009
|
-
};
|
|
2010
|
-
this.db = newDb;
|
|
2011
|
-
this.memories = new MemoryEntity(newDb, wrappedSaveDb);
|
|
2012
|
-
this.tasks = new TaskEntity(newDb, wrappedSaveDb);
|
|
2013
|
-
this.actions = new ActionEntity(newDb, wrappedSaveDb);
|
|
2014
|
-
this.system = new SystemEntity(newDb, wrappedSaveDb);
|
|
2015
|
-
this.summaries = new SummaryEntity(newDb, wrappedSaveDb);
|
|
2016
|
-
this.lastLoadedAt = Date.now();
|
|
2017
|
-
}
|
|
2018
|
-
} catch (e) {
|
|
2019
|
-
console.error("Failed to refresh database from disk:", e);
|
|
2020
|
-
}
|
|
1923
|
+
this.memories = new MemoryEntity(this.db);
|
|
1924
|
+
this.tasks = new TaskEntity(this.db);
|
|
1925
|
+
this.actions = new ActionEntity(this.db);
|
|
1926
|
+
this.system = new SystemEntity(this.db);
|
|
1927
|
+
this.summaries = new SummaryEntity(this.db);
|
|
2021
1928
|
}
|
|
2022
1929
|
async ready() {
|
|
2023
|
-
|
|
1930
|
+
}
|
|
1931
|
+
async refresh() {
|
|
2024
1932
|
}
|
|
2025
1933
|
static async create(dbPath) {
|
|
2026
|
-
|
|
2027
|
-
await store.ready();
|
|
2028
|
-
return store;
|
|
1934
|
+
return new _SQLiteStore(dbPath);
|
|
2029
1935
|
}
|
|
2030
1936
|
getDbPath() {
|
|
2031
1937
|
return this.dbPathInstance;
|
|
2032
1938
|
}
|
|
2033
1939
|
close() {
|
|
2034
|
-
if (this.db && this.db.
|
|
1940
|
+
if (this.db && this.db.open) {
|
|
2035
1941
|
this.db.close();
|
|
2036
1942
|
}
|
|
2037
1943
|
}
|
|
@@ -2057,7 +1963,8 @@ function updateSessionFromInitialize(session, params) {
|
|
|
2057
1963
|
session.clientCapabilities = capabilities;
|
|
2058
1964
|
session.supportsRoots = Boolean(capabilities.roots);
|
|
2059
1965
|
session.supportsSampling = Boolean(capabilities.sampling);
|
|
2060
|
-
|
|
1966
|
+
const sampling = capabilities.sampling;
|
|
1967
|
+
session.supportsSamplingTools = Boolean(sampling?.tools);
|
|
2061
1968
|
session.supportsElicitation = Boolean(capabilities.elicitation);
|
|
2062
1969
|
session.supportsElicitationForm = supportsElicitationMode(capabilities.elicitation, "form");
|
|
2063
1970
|
session.supportsElicitationUrl = supportsElicitationMode(capabilities.elicitation, "url");
|