@vheins/local-memory-mcp 0.8.3 → 0.8.5

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.
@@ -35,6 +35,7 @@ var CAPABILITIES = {
35
35
  };
36
36
 
37
37
  // src/mcp/utils/logger.ts
38
+ import fs2 from "fs";
38
39
  var LEVELS = {
39
40
  debug: 0,
40
41
  info: 1,
@@ -170,11 +171,31 @@ function addLogSink(sink) {
170
171
  return () => sinks.delete(sink);
171
172
  }
172
173
  var LOG_LEVEL_VALUES = Object.keys(LEVELS);
174
+ function createFileSink(logDir, maxFiles = 5) {
175
+ fs2.mkdirSync(logDir, { recursive: true });
176
+ const existing = fs2.readdirSync(logDir).filter((f) => f.startsWith("mcp-") && f.endsWith(".log")).sort();
177
+ while (existing.length >= maxFiles) {
178
+ try {
179
+ fs2.unlinkSync(`${logDir}/${existing.shift()}`);
180
+ } catch {
181
+ }
182
+ }
183
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
184
+ const logFile = `${logDir}/mcp-${timestamp}.log`;
185
+ return (payload) => {
186
+ const line = `${(/* @__PURE__ */ new Date()).toISOString()} [${payload.level.toUpperCase()}] ${JSON.stringify(payload.data)}
187
+ `;
188
+ try {
189
+ fs2.appendFileSync(logFile, line);
190
+ } catch {
191
+ }
192
+ };
193
+ }
173
194
 
174
195
  // src/mcp/storage/sqlite.ts
175
196
  import Database from "better-sqlite3";
176
197
  import path3 from "path";
177
- import fs3 from "fs";
198
+ import fs4 from "fs";
178
199
  import os from "os";
179
200
 
180
201
  // src/mcp/storage/migrations.ts
@@ -1896,7 +1917,7 @@ var SummaryEntity = class extends BaseEntity {
1896
1917
  // src/mcp/storage/write-lock.ts
1897
1918
  import lockfile from "proper-lockfile";
1898
1919
  import path2 from "path";
1899
- import fs2 from "fs";
1920
+ import fs3 from "fs";
1900
1921
  var LOCK_STALE_MS = 15e3;
1901
1922
  var LOCK_RETRY_DELAY_MS = 100;
1902
1923
  var LOCK_RETRY_COUNT = 150;
@@ -1905,9 +1926,9 @@ var WriteLock = class {
1905
1926
  locked = false;
1906
1927
  constructor(dbPath) {
1907
1928
  this.lockTarget = dbPath;
1908
- if (!fs2.existsSync(dbPath)) {
1909
- fs2.mkdirSync(path2.dirname(dbPath), { recursive: true });
1910
- fs2.writeFileSync(dbPath, "");
1929
+ if (!fs3.existsSync(dbPath)) {
1930
+ fs3.mkdirSync(path2.dirname(dbPath), { recursive: true });
1931
+ fs3.writeFileSync(dbPath, "");
1911
1932
  }
1912
1933
  }
1913
1934
  /**
@@ -1961,11 +1982,11 @@ function resolveDbPath() {
1961
1982
  if (process.env.MEMORY_DB_PATH) return process.env.MEMORY_DB_PATH;
1962
1983
  const standardConfigDir = process.platform === "win32" ? path3.join(os.homedir(), ".local-memory-mcp") : process.platform === "darwin" ? path3.join(os.homedir(), "Library", "Application Support", "local-memory-mcp") : path3.join(os.homedir(), ".config", "local-memory-mcp");
1963
1984
  const standardPath = path3.join(standardConfigDir, "memory.db");
1964
- if (fs3.existsSync(standardPath)) return standardPath;
1985
+ if (fs4.existsSync(standardPath)) return standardPath;
1965
1986
  const legacyPath = path3.join(os.homedir(), ".config", "local-memory-mcp", "memory.db");
1966
- if (fs3.existsSync(legacyPath)) return legacyPath;
1987
+ if (fs4.existsSync(legacyPath)) return legacyPath;
1967
1988
  const localCwdFile = path3.join(process.cwd(), "storage", "memory.db");
1968
- if (fs3.existsSync(localCwdFile)) return localCwdFile;
1989
+ if (fs4.existsSync(localCwdFile)) return localCwdFile;
1969
1990
  return standardPath;
1970
1991
  }
1971
1992
  var DB_PATH = resolveDbPath();
@@ -1983,8 +2004,8 @@ var SQLiteStore = class _SQLiteStore {
1983
2004
  this.dbPathInstance = finalPath;
1984
2005
  if (finalPath !== ":memory:") {
1985
2006
  const dbDir = path3.dirname(finalPath);
1986
- if (!fs3.existsSync(dbDir)) {
1987
- fs3.mkdirSync(dbDir, { recursive: true });
2007
+ if (!fs4.existsSync(dbDir)) {
2008
+ fs4.mkdirSync(dbDir, { recursive: true });
1988
2009
  }
1989
2010
  }
1990
2011
  this.db = new Database(finalPath);
@@ -2036,12 +2057,12 @@ var SQLiteStore = class _SQLiteStore {
2036
2057
  */
2037
2058
  _attemptRecovery(dbPath) {
2038
2059
  const backupPath = dbPath + ".backup";
2039
- if (fs3.existsSync(backupPath)) {
2060
+ if (fs4.existsSync(backupPath)) {
2040
2061
  logger.warn("[SQLiteStore] Attempting recovery from backup", { backupPath });
2041
2062
  try {
2042
2063
  const corruptPath = `${dbPath}.corrupt_${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").slice(0, 15)}`;
2043
- fs3.copyFileSync(dbPath, corruptPath);
2044
- fs3.copyFileSync(backupPath, dbPath);
2064
+ fs4.copyFileSync(dbPath, corruptPath);
2065
+ fs4.copyFileSync(backupPath, dbPath);
2045
2066
  logger.warn("[SQLiteStore] Recovery successful. Corrupt file saved to", { corruptPath });
2046
2067
  } catch (err) {
2047
2068
  logger.error("[SQLiteStore] Recovery failed", { error: String(err) });
@@ -2059,7 +2080,7 @@ var SQLiteStore = class _SQLiteStore {
2059
2080
  try {
2060
2081
  this.db.pragma("wal_checkpoint(PASSIVE)");
2061
2082
  const backupPath = this.dbPathInstance + ".backup";
2062
- fs3.copyFileSync(this.dbPathInstance, backupPath);
2083
+ fs4.copyFileSync(this.dbPathInstance, backupPath);
2063
2084
  } catch (err) {
2064
2085
  logger.warn("[SQLiteStore] Backup failed", { error: String(err) });
2065
2086
  }
@@ -3666,7 +3687,7 @@ function invalidCompletionParams(message) {
3666
3687
  }
3667
3688
 
3668
3689
  // src/mcp/prompts/loader.ts
3669
- import fs4 from "fs";
3690
+ import fs5 from "fs";
3670
3691
  import path5 from "path";
3671
3692
  import { fileURLToPath as fileURLToPath3 } from "url";
3672
3693
  import matter from "gray-matter";
@@ -3682,8 +3703,8 @@ function findPromptDir() {
3682
3703
  "./definitions"
3683
3704
  ].map((relPath) => path5.resolve(__dirname2, relPath));
3684
3705
  for (const dir of candidates) {
3685
- if (fs4.existsSync(dir)) {
3686
- const files = fs4.readdirSync(dir);
3706
+ if (fs5.existsSync(dir)) {
3707
+ const files = fs5.readdirSync(dir);
3687
3708
  if (files.some((f) => f.endsWith(".md"))) {
3688
3709
  return dir;
3689
3710
  }
@@ -3693,15 +3714,15 @@ function findPromptDir() {
3693
3714
  }
3694
3715
  var PROMPT_DIR = findPromptDir();
3695
3716
  function listPromptFiles() {
3696
- if (!fs4.existsSync(PROMPT_DIR)) return [];
3697
- return fs4.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
3717
+ if (!fs5.existsSync(PROMPT_DIR)) return [];
3718
+ return fs5.readdirSync(PROMPT_DIR).filter((file) => file.endsWith(".md")).map((file) => file.replace(/\.md$/, "")).sort();
3698
3719
  }
3699
3720
  function loadPromptFromMarkdown(name) {
3700
3721
  const filePath = path5.join(PROMPT_DIR, `${name}.md`);
3701
- if (!fs4.existsSync(filePath)) {
3722
+ if (!fs5.existsSync(filePath)) {
3702
3723
  throw new Error(`Prompt file not found: ${filePath}`);
3703
3724
  }
3704
- const fileContent = fs4.readFileSync(filePath, "utf-8");
3725
+ const fileContent = fs5.readFileSync(filePath, "utf-8");
3705
3726
  const { data, content } = matter(fileContent);
3706
3727
  return {
3707
3728
  name: data.name || name,
@@ -3800,6 +3821,7 @@ export {
3800
3821
  getLogLevel,
3801
3822
  addLogSink,
3802
3823
  LOG_LEVEL_VALUES,
3824
+ createFileSink,
3803
3825
  normalizeRepo,
3804
3826
  SQLiteStore,
3805
3827
  MemoryStoreSchema,
@@ -6,7 +6,7 @@ import {
6
6
  TOOL_DEFINITIONS,
7
7
  listResources,
8
8
  logger
9
- } from "../chunk-MC6NSQJ6.js";
9
+ } from "../chunk-NQHH7CDG.js";
10
10
 
11
11
  // src/dashboard/server.ts
12
12
  import express from "express";
@@ -899,7 +899,7 @@ function getStaticRoot() {
899
899
  }
900
900
  var staticRoot = getStaticRoot();
901
901
  logger.debug("Dashboard serving assets from", { staticRoot });
902
- app.use(express.static(staticRoot));
902
+ app.use(express.static(staticRoot, { fallthrough: true }));
903
903
  app.use((req, res, next) => {
904
904
  if (req.path.startsWith("/api")) return next();
905
905
  const indexPath = path3.join(staticRoot, "index.html");
@@ -936,6 +936,11 @@ app.use((req, res, next) => {
936
936
  `);
937
937
  }
938
938
  });
939
+ app.use((err, req, res, _next) => {
940
+ if (err.status === 404) return res.status(404).end();
941
+ logger.error("Unhandled error", { error: err.message });
942
+ res.status(500).end();
943
+ });
939
944
  if (process.env.DASHBOARD_ENABLE_MCP === "true") {
940
945
  mcpClient.start().catch((e) => logger.error("MCP Client failed", { error: e.message }));
941
946
  }
@@ -23,6 +23,7 @@ import {
23
23
  addLogSink,
24
24
  completePromptArgument,
25
25
  completeResourceArgument,
26
+ createFileSink,
26
27
  createSessionContext,
27
28
  decodeCursor,
28
29
  encodeCursor,
@@ -42,7 +43,7 @@ import {
42
43
  setLogLevel,
43
44
  updateSessionFromInitialize,
44
45
  updateSessionRoots
45
- } from "../chunk-MC6NSQJ6.js";
46
+ } from "../chunk-NQHH7CDG.js";
46
47
 
47
48
  // src/mcp/server.ts
48
49
  import readline from "readline";
@@ -2137,6 +2138,7 @@ var RealVectorStore = class {
2137
2138
 
2138
2139
  // src/mcp/server.ts
2139
2140
  import fs2 from "fs";
2141
+ import path3 from "path";
2140
2142
  process.env.MCP_SERVER = "true";
2141
2143
  if (process.argv.includes("doctor")) {
2142
2144
  process.stderr.write("\n\u{1F3E5} MCP Local Memory - System Diagnosis\n\n");
@@ -2168,6 +2170,7 @@ if (process.argv.includes("doctor")) {
2168
2170
  }
2169
2171
  var db = await SQLiteStore.create();
2170
2172
  var vectors = new RealVectorStore(db);
2173
+ addLogSink(createFileSink(path3.dirname(db.getDbPath())));
2171
2174
  vectors.initialize().catch((err) => {
2172
2175
  logger.warn("[Server] Initial vector model loading failed. Will retry on first use.", { error: String(err) });
2173
2176
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vheins/local-memory-mcp",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "MCP Local Memory Service for coding copilot agents",
5
5
  "mcpName": "io.github.vheins/local-memory-mcp",
6
6
  "type": "module",