@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 saveDbFn = null;
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
- constructor() {
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
- static async create(dbPath) {
1914
- const finalPath = dbPath ?? DB_PATH;
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
- const store = Object.create(_SQLiteStore.prototype);
1939
- store.db = db;
1940
- store.memories = new MemoryEntity(db, saveDb);
1941
- store.tasks = new TaskEntity(db, saveDb);
1942
- store.actions = new ActionEntity(db, saveDb);
1943
- store.system = new SystemEntity(db, saveDb);
1944
- store.summaries = new SummaryEntity(db, saveDb);
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
- if (process.env.MCP_SERVER !== "true") {
1949
- process.stderr.write(`${(/* @__PURE__ */ new Date()).toISOString()} [INFO ] SQLiteStore initialized at ${finalPath}
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 (saveDbFn) {
1959
- saveDbFn();
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(100),
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(100).optional(),
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((data) => {
2200
- if (data.tasks) return true;
2201
- return !!(data.task_code && data.phase && data.title && data.description);
2202
- }, { message: "Either 'tasks' array or single task fields (task_code, phase, title, description) must be provided" });
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: { type: "string", minLength: 3, maxLength: 100, description: "Task objective (Required for single task)" },
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: { type: "boolean", description: "If true, bypasses status transition validation (e.g. pending -> completed)." }
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
- var PROMPT_DIR = path4.join(__dirname2, "definitions");
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();