@vheins/local-memory-mcp 0.6.2 → 0.7.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.
|
@@ -535,6 +535,15 @@ var MigrationManager = class {
|
|
|
535
535
|
this.ensureMemoryTypeConstraint();
|
|
536
536
|
}
|
|
537
537
|
}
|
|
538
|
+
addMemoryCodeColumn() {
|
|
539
|
+
const tableInfo = this.all("PRAGMA table_info(memories)");
|
|
540
|
+
const hasCode = tableInfo.some((col) => col.name === "code");
|
|
541
|
+
if (!hasCode) {
|
|
542
|
+
this.run("ALTER TABLE memories ADD COLUMN code TEXT");
|
|
543
|
+
this.run("CREATE INDEX IF NOT EXISTS idx_memories_code ON memories(code)");
|
|
544
|
+
this.run("CREATE INDEX IF NOT EXISTS idx_memories_repo_code ON memories(repo, code)");
|
|
545
|
+
}
|
|
546
|
+
}
|
|
538
547
|
};
|
|
539
548
|
|
|
540
549
|
// src/mcp/utils/normalize.ts
|
|
@@ -826,6 +835,7 @@ var BaseEntity = class {
|
|
|
826
835
|
const r = row;
|
|
827
836
|
return {
|
|
828
837
|
id: r.id,
|
|
838
|
+
code: r.code || void 0,
|
|
829
839
|
type: r.type,
|
|
830
840
|
title: r.title || "Untitled",
|
|
831
841
|
content: r.content,
|
|
@@ -909,12 +919,13 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
909
919
|
insert(entry) {
|
|
910
920
|
this.run(
|
|
911
921
|
`INSERT INTO memories (
|
|
912
|
-
id, repo, type, title, content, importance, folder, language,
|
|
922
|
+
id, code, repo, type, title, content, importance, folder, language,
|
|
913
923
|
created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
|
|
914
924
|
supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
|
|
915
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
925
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
916
926
|
[
|
|
917
927
|
entry.id,
|
|
928
|
+
entry.code || null,
|
|
918
929
|
entry.scope.repo,
|
|
919
930
|
entry.type,
|
|
920
931
|
entry.title || null,
|
|
@@ -983,6 +994,10 @@ var MemoryEntity = class extends BaseEntity {
|
|
|
983
994
|
const row = this.get("SELECT * FROM memories WHERE id = ?", [id]);
|
|
984
995
|
return row ? this.rowToMemoryEntry(row) : null;
|
|
985
996
|
}
|
|
997
|
+
getByCode(code) {
|
|
998
|
+
const row = this.get("SELECT * FROM memories WHERE code = ?", [code]);
|
|
999
|
+
return row ? this.rowToMemoryEntry(row) : null;
|
|
1000
|
+
}
|
|
986
1001
|
getByIdWithStats(id) {
|
|
987
1002
|
const row = this.get(
|
|
988
1003
|
`SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate FROM memories WHERE id = ?`,
|
|
@@ -1885,7 +1900,15 @@ function resolveDbPath() {
|
|
|
1885
1900
|
}
|
|
1886
1901
|
var DB_PATH = resolveDbPath();
|
|
1887
1902
|
var dbPathInstance = "";
|
|
1888
|
-
var
|
|
1903
|
+
var sqlJsReady = null;
|
|
1904
|
+
var sqlJsModule = null;
|
|
1905
|
+
async function getSqlJs() {
|
|
1906
|
+
if (!sqlJsModule) {
|
|
1907
|
+
sqlJsModule = await initSqlJs();
|
|
1908
|
+
}
|
|
1909
|
+
await sqlJsReady;
|
|
1910
|
+
return sqlJsModule;
|
|
1911
|
+
}
|
|
1889
1912
|
function createSaveFunction(db, dbPath) {
|
|
1890
1913
|
return () => {
|
|
1891
1914
|
if (dbPath && dbPath !== ":memory:") {
|
|
@@ -1895,6 +1918,14 @@ function createSaveFunction(db, dbPath) {
|
|
|
1895
1918
|
}
|
|
1896
1919
|
};
|
|
1897
1920
|
}
|
|
1921
|
+
function warmUpSqlJs() {
|
|
1922
|
+
if (!sqlJsReady) {
|
|
1923
|
+
sqlJsReady = (async () => {
|
|
1924
|
+
sqlJsModule = await initSqlJs();
|
|
1925
|
+
})();
|
|
1926
|
+
}
|
|
1927
|
+
return sqlJsReady;
|
|
1928
|
+
}
|
|
1898
1929
|
var SQLiteStore = class _SQLiteStore {
|
|
1899
1930
|
db;
|
|
1900
1931
|
memories;
|
|
@@ -1902,18 +1933,21 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
1902
1933
|
actions;
|
|
1903
1934
|
system;
|
|
1904
1935
|
summaries;
|
|
1905
|
-
|
|
1936
|
+
_ready;
|
|
1937
|
+
constructor(dbPath) {
|
|
1938
|
+
const finalPath = dbPath ?? DB_PATH;
|
|
1939
|
+
dbPathInstance = finalPath;
|
|
1940
|
+
warmUpSqlJs();
|
|
1906
1941
|
this.db = {};
|
|
1907
1942
|
this.memories = {};
|
|
1908
1943
|
this.tasks = {};
|
|
1909
1944
|
this.actions = {};
|
|
1910
1945
|
this.system = {};
|
|
1911
1946
|
this.summaries = {};
|
|
1947
|
+
this._ready = this._init(finalPath);
|
|
1912
1948
|
}
|
|
1913
|
-
|
|
1914
|
-
const
|
|
1915
|
-
dbPathInstance = finalPath;
|
|
1916
|
-
const SQL = await initSqlJs();
|
|
1949
|
+
async _init(finalPath) {
|
|
1950
|
+
const SQL = await getSqlJs();
|
|
1917
1951
|
let db;
|
|
1918
1952
|
if (finalPath === ":memory:") {
|
|
1919
1953
|
db = new SQL.Database();
|
|
@@ -1935,30 +1969,34 @@ var SQLiteStore = class _SQLiteStore {
|
|
|
1935
1969
|
db.run("PRAGMA busy_timeout = 5000");
|
|
1936
1970
|
const migrator = new MigrationManager(db, saveDb);
|
|
1937
1971
|
migrator.migrate();
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1972
|
+
migrator.addMemoryCodeColumn();
|
|
1973
|
+
Object.assign(this, {
|
|
1974
|
+
db,
|
|
1975
|
+
memories: new MemoryEntity(db, saveDb),
|
|
1976
|
+
tasks: new TaskEntity(db, saveDb),
|
|
1977
|
+
actions: new ActionEntity(db, saveDb),
|
|
1978
|
+
system: new SystemEntity(db, saveDb),
|
|
1979
|
+
summaries: new SummaryEntity(db, saveDb)
|
|
1980
|
+
});
|
|
1945
1981
|
if (finalPath !== ":memory:") {
|
|
1946
1982
|
saveDb();
|
|
1947
1983
|
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1984
|
+
}
|
|
1985
|
+
async ready() {
|
|
1986
|
+
await this._ready;
|
|
1987
|
+
}
|
|
1988
|
+
static async create(dbPath) {
|
|
1989
|
+
const store = new _SQLiteStore(dbPath);
|
|
1990
|
+
await store.ready();
|
|
1952
1991
|
return store;
|
|
1953
1992
|
}
|
|
1954
1993
|
getDbPath() {
|
|
1955
1994
|
return dbPathInstance;
|
|
1956
1995
|
}
|
|
1957
1996
|
close() {
|
|
1958
|
-
if (
|
|
1959
|
-
|
|
1997
|
+
if (this.db && this.db.close) {
|
|
1998
|
+
this.db.close();
|
|
1960
1999
|
}
|
|
1961
|
-
this.db.close();
|
|
1962
2000
|
}
|
|
1963
2001
|
};
|
|
1964
2002
|
|
|
@@ -2082,8 +2120,9 @@ var MemoryTypeSchema = z.enum([
|
|
|
2082
2120
|
"task_archive"
|
|
2083
2121
|
]);
|
|
2084
2122
|
var MemoryStoreSchema = z.object({
|
|
2123
|
+
code: z.string().max(20).optional(),
|
|
2085
2124
|
type: MemoryTypeSchema,
|
|
2086
|
-
title: z.string().min(3).max(
|
|
2125
|
+
title: z.string().min(3).max(255),
|
|
2087
2126
|
content: z.string().min(10),
|
|
2088
2127
|
importance: z.number().min(1).max(5),
|
|
2089
2128
|
agent: z.string().min(1),
|
|
@@ -2099,7 +2138,7 @@ var MemoryStoreSchema = z.object({
|
|
|
2099
2138
|
var MemoryUpdateSchema = z.object({
|
|
2100
2139
|
id: z.string().uuid(),
|
|
2101
2140
|
type: MemoryTypeSchema.optional(),
|
|
2102
|
-
title: z.string().min(3).max(
|
|
2141
|
+
title: z.string().min(3).max(255).optional(),
|
|
2103
2142
|
content: z.string().min(10).optional(),
|
|
2104
2143
|
importance: z.number().min(1).max(5).optional(),
|
|
2105
2144
|
agent: z.string().optional(),
|
|
@@ -2126,7 +2165,8 @@ var MemorySearchSchema = z.object({
|
|
|
2126
2165
|
current_file_path: z.string().optional(),
|
|
2127
2166
|
include_archived: z.boolean().default(false),
|
|
2128
2167
|
current_tags: z.array(z.string()).optional(),
|
|
2129
|
-
scope: MemoryScopeSchema.partial().optional()
|
|
2168
|
+
scope: MemoryScopeSchema.partial().optional(),
|
|
2169
|
+
structured: z.boolean().default(false)
|
|
2130
2170
|
});
|
|
2131
2171
|
var MemoryAcknowledgeSchema = z.object({
|
|
2132
2172
|
memory_id: z.string().uuid(),
|
|
@@ -2136,7 +2176,8 @@ var MemoryAcknowledgeSchema = z.object({
|
|
|
2136
2176
|
var MemoryRecapSchema = z.object({
|
|
2137
2177
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
2138
2178
|
limit: z.number().min(1).max(50).default(20),
|
|
2139
|
-
offset: z.number().min(0).default(0)
|
|
2179
|
+
offset: z.number().min(0).default(0),
|
|
2180
|
+
structured: z.boolean().default(false)
|
|
2140
2181
|
});
|
|
2141
2182
|
var MemoryDeleteSchema = z.object({
|
|
2142
2183
|
repo: z.string().min(1).transform(normalizeRepo).optional(),
|
|
@@ -2196,10 +2237,13 @@ var TaskCreateSchema = z.object({
|
|
|
2196
2237
|
est_tokens: z.number().int().min(0).optional(),
|
|
2197
2238
|
// Allow bulk tasks
|
|
2198
2239
|
tasks: z.array(SingleTaskCreateSchema).min(1).optional()
|
|
2199
|
-
}).refine(
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2240
|
+
}).refine(
|
|
2241
|
+
(data) => {
|
|
2242
|
+
if (data.tasks) return true;
|
|
2243
|
+
return !!(data.task_code && data.phase && data.title && data.description);
|
|
2244
|
+
},
|
|
2245
|
+
{ message: "Either 'tasks' array or single task fields (task_code, phase, title, description) must be provided" }
|
|
2246
|
+
);
|
|
2203
2247
|
var TaskCreateInteractiveSchema = SingleTaskCreateSchema.partial().extend({
|
|
2204
2248
|
repo: z.string().min(1).transform(normalizeRepo).optional()
|
|
2205
2249
|
});
|
|
@@ -2235,14 +2279,16 @@ var TaskListSchema = z.object({
|
|
|
2235
2279
|
phase: z.string().optional(),
|
|
2236
2280
|
query: z.string().optional(),
|
|
2237
2281
|
limit: z.number().min(1).max(100).default(15),
|
|
2238
|
-
offset: z.number().min(0).default(0)
|
|
2282
|
+
offset: z.number().min(0).default(0),
|
|
2283
|
+
structured: z.boolean().default(false)
|
|
2239
2284
|
});
|
|
2240
2285
|
var TaskSearchSchema = z.object({
|
|
2241
2286
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
2242
2287
|
query: z.string().min(1),
|
|
2243
2288
|
status: z.string().optional(),
|
|
2244
2289
|
limit: z.number().min(1).max(100).default(10),
|
|
2245
|
-
offset: z.number().min(0).default(0)
|
|
2290
|
+
offset: z.number().min(0).default(0),
|
|
2291
|
+
structured: z.boolean().default(false)
|
|
2246
2292
|
});
|
|
2247
2293
|
var TaskDeleteSchema = z.object({
|
|
2248
2294
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
@@ -2252,12 +2298,16 @@ var TaskDeleteSchema = z.object({
|
|
|
2252
2298
|
message: "Either 'id' or 'ids' must be provided for deletion"
|
|
2253
2299
|
});
|
|
2254
2300
|
var MemoryDetailSchema = z.object({
|
|
2255
|
-
id: z.string().uuid()
|
|
2301
|
+
id: z.string().uuid().optional(),
|
|
2302
|
+
code: z.string().max(20).optional()
|
|
2303
|
+
}).refine((data) => data.id !== void 0 || data.code !== void 0, {
|
|
2304
|
+
message: "Either id or code must be provided"
|
|
2256
2305
|
});
|
|
2257
2306
|
var TaskGetSchema = z.object({
|
|
2258
2307
|
repo: z.string().min(1).transform(normalizeRepo),
|
|
2259
2308
|
id: z.string().uuid().optional(),
|
|
2260
|
-
task_code: z.string().optional()
|
|
2309
|
+
task_code: z.string().optional(),
|
|
2310
|
+
structured: z.boolean().default(false)
|
|
2261
2311
|
}).refine((data) => data.id !== void 0 || data.task_code !== void 0, {
|
|
2262
2312
|
message: "Either id or task_code must be provided"
|
|
2263
2313
|
});
|
|
@@ -2371,7 +2421,12 @@ var TOOL_DEFINITIONS = [
|
|
|
2371
2421
|
properties: {
|
|
2372
2422
|
repo: { type: "string", description: "Repository name" },
|
|
2373
2423
|
id: { type: "string", format: "uuid", description: "Task ID (optional if task_code is provided)" },
|
|
2374
|
-
task_code: { type: "string", description: "Task code (e.g. TASK-001) (optional if id is provided)" }
|
|
2424
|
+
task_code: { type: "string", description: "Task code (e.g. TASK-001) (optional if id is provided)" },
|
|
2425
|
+
structured: {
|
|
2426
|
+
type: "boolean",
|
|
2427
|
+
default: false,
|
|
2428
|
+
description: "If true, returns structured JSON without the text content details."
|
|
2429
|
+
}
|
|
2375
2430
|
},
|
|
2376
2431
|
required: ["repo"]
|
|
2377
2432
|
}
|
|
@@ -2465,6 +2520,7 @@ var TOOL_DEFINITIONS = [
|
|
|
2465
2520
|
properties: {
|
|
2466
2521
|
success: { type: "boolean" },
|
|
2467
2522
|
id: { type: "string" },
|
|
2523
|
+
code: { type: "string" },
|
|
2468
2524
|
repo: { type: "string" },
|
|
2469
2525
|
type: { type: "string" },
|
|
2470
2526
|
title: { type: "string" },
|
|
@@ -2607,6 +2663,11 @@ var TOOL_DEFINITIONS = [
|
|
|
2607
2663
|
folder: { type: "string" },
|
|
2608
2664
|
language: { type: "string" }
|
|
2609
2665
|
}
|
|
2666
|
+
},
|
|
2667
|
+
structured: {
|
|
2668
|
+
type: "boolean",
|
|
2669
|
+
default: false,
|
|
2670
|
+
description: "If true, returns structured JSON without the text content summary."
|
|
2610
2671
|
}
|
|
2611
2672
|
},
|
|
2612
2673
|
required: ["query", "repo"]
|
|
@@ -2733,6 +2794,11 @@ var TOOL_DEFINITIONS = [
|
|
|
2733
2794
|
minimum: 0,
|
|
2734
2795
|
default: 0,
|
|
2735
2796
|
description: "Number of memories to skip for pagination (optional, default 0)"
|
|
2797
|
+
},
|
|
2798
|
+
structured: {
|
|
2799
|
+
type: "boolean",
|
|
2800
|
+
default: false,
|
|
2801
|
+
description: "If true, returns structured JSON without the text content summary."
|
|
2736
2802
|
}
|
|
2737
2803
|
},
|
|
2738
2804
|
required: ["repo"]
|
|
@@ -2791,7 +2857,12 @@ var TOOL_DEFINITIONS = [
|
|
|
2791
2857
|
repo: { type: "string", description: "Repository name" },
|
|
2792
2858
|
task_code: { type: "string", description: "Unique task code (e.g. TASK-001) (Required for single task)" },
|
|
2793
2859
|
phase: { type: "string", description: "Project phase (Required for single task)" },
|
|
2794
|
-
title: {
|
|
2860
|
+
title: {
|
|
2861
|
+
type: "string",
|
|
2862
|
+
minLength: 3,
|
|
2863
|
+
maxLength: 100,
|
|
2864
|
+
description: "Task objective (Required for single task)"
|
|
2865
|
+
},
|
|
2795
2866
|
description: { type: "string", description: "Detailed description (Required for single task)" },
|
|
2796
2867
|
status: {
|
|
2797
2868
|
type: "string",
|
|
@@ -2840,8 +2911,8 @@ var TOOL_DEFINITIONS = [
|
|
|
2840
2911
|
properties: {
|
|
2841
2912
|
success: { type: "boolean" },
|
|
2842
2913
|
id: { type: "string" },
|
|
2843
|
-
repo: { type: "string" },
|
|
2844
2914
|
task_code: { type: "string" },
|
|
2915
|
+
repo: { type: "string" },
|
|
2845
2916
|
phase: { type: "string" },
|
|
2846
2917
|
title: { type: "string" },
|
|
2847
2918
|
status: { type: "string" },
|
|
@@ -2894,7 +2965,10 @@ var TOOL_DEFINITIONS = [
|
|
|
2894
2965
|
minimum: 0,
|
|
2895
2966
|
description: "Estimated total tokens actually used for this task. Required when status changes to 'completed'."
|
|
2896
2967
|
},
|
|
2897
|
-
force: {
|
|
2968
|
+
force: {
|
|
2969
|
+
type: "boolean",
|
|
2970
|
+
description: "If true, bypasses status transition validation (e.g. pending -> completed)."
|
|
2971
|
+
}
|
|
2898
2972
|
},
|
|
2899
2973
|
required: ["repo"]
|
|
2900
2974
|
},
|
|
@@ -2988,6 +3062,11 @@ var TOOL_DEFINITIONS = [
|
|
|
2988
3062
|
minimum: 0,
|
|
2989
3063
|
default: 0,
|
|
2990
3064
|
description: "Offset for pagination"
|
|
3065
|
+
},
|
|
3066
|
+
structured: {
|
|
3067
|
+
type: "boolean",
|
|
3068
|
+
default: false,
|
|
3069
|
+
description: "If true, returns structured JSON without the text content summary."
|
|
2991
3070
|
}
|
|
2992
3071
|
},
|
|
2993
3072
|
required: ["repo"]
|
|
@@ -3466,7 +3545,29 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
3466
3545
|
import matter from "gray-matter";
|
|
3467
3546
|
var __filename = fileURLToPath3(import.meta.url);
|
|
3468
3547
|
var __dirname2 = path4.dirname(__filename);
|
|
3469
|
-
|
|
3548
|
+
function findPromptDir() {
|
|
3549
|
+
const candidates = [
|
|
3550
|
+
// Production: /dist/prompts (sibling of dist/mcp/)
|
|
3551
|
+
["../../prompts", "../../prompts"],
|
|
3552
|
+
// Dev: /src/mcp/prompts/definitions (next to loader.ts)
|
|
3553
|
+
["./definitions", "./definitions"]
|
|
3554
|
+
].map(([prod, dev]) => {
|
|
3555
|
+
const prodPath = path4.resolve(__dirname2, prod);
|
|
3556
|
+
if (fs3.existsSync(prodPath) && fs3.readdirSync(prodPath).some((f) => f.endsWith(".md"))) {
|
|
3557
|
+
return prodPath;
|
|
3558
|
+
}
|
|
3559
|
+
const devPath = path4.resolve(__dirname2, dev);
|
|
3560
|
+
if (fs3.existsSync(devPath) && fs3.readdirSync(devPath).some((f) => f.endsWith(".md"))) {
|
|
3561
|
+
return devPath;
|
|
3562
|
+
}
|
|
3563
|
+
return null;
|
|
3564
|
+
}).filter(Boolean);
|
|
3565
|
+
if (candidates[0]) {
|
|
3566
|
+
return candidates[0];
|
|
3567
|
+
}
|
|
3568
|
+
return path4.resolve(__dirname2, "./definitions");
|
|
3569
|
+
}
|
|
3570
|
+
var PROMPT_DIR = findPromptDir();
|
|
3470
3571
|
function listPromptFiles() {
|
|
3471
3572
|
if (!fs3.existsSync(PROMPT_DIR)) return [];
|
|
3472
3573
|
return fs3.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
|