mnemosyne-core 2.0.2 → 2.1.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.
Files changed (47) hide show
  1. package/README.md +42 -25
  2. package/dist/{Store-BtdYuiUx.d.mts → Store-BJ8b6xbs.d.mts} +2 -0
  3. package/dist/{Store-BtdYuiUx.d.ts → Store-BJ8b6xbs.d.ts} +2 -0
  4. package/dist/cli/index.js +475 -5708
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/index.mjs +475 -5709
  7. package/dist/cli/index.mjs.map +1 -1
  8. package/dist/{index-yTOihMUk.d.mts → index-2AoCh09i.d.mts} +1 -1
  9. package/dist/{index-B2oTMNlL.d.ts → index-BZrUZX8Z.d.ts} +1 -1
  10. package/dist/{index-B8PTQKy9.d.mts → index-CHbW0NJZ.d.mts} +1 -1
  11. package/dist/{index-DWk78ifo.d.ts → index-CfqixdlW.d.ts} +1 -1
  12. package/dist/index.d.mts +4 -4
  13. package/dist/index.d.ts +4 -4
  14. package/dist/index.js +328 -5739
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +327 -5739
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/mcp/index.d.mts +2 -2
  19. package/dist/mcp/index.d.ts +2 -2
  20. package/dist/mcp/index.js +19 -2
  21. package/dist/mcp/index.js.map +1 -1
  22. package/dist/mcp/index.mjs +26 -2
  23. package/dist/mcp/index.mjs.map +1 -1
  24. package/dist/sdk/index.d.mts +202 -50
  25. package/dist/sdk/index.d.ts +202 -50
  26. package/dist/sdk/index.js +76 -34
  27. package/dist/sdk/index.js.map +1 -1
  28. package/dist/sdk/index.mjs +76 -34
  29. package/dist/sdk/index.mjs.map +1 -1
  30. package/dist/server/api.d.mts +1 -1
  31. package/dist/server/api.d.ts +1 -1
  32. package/dist/server/api.js +231 -154
  33. package/dist/server/api.js.map +1 -1
  34. package/dist/server/api.mjs +231 -154
  35. package/dist/server/api.mjs.map +1 -1
  36. package/dist/server/index.d.mts +2 -2
  37. package/dist/server/index.d.ts +2 -2
  38. package/dist/server/index.js +296 -5711
  39. package/dist/server/index.js.map +1 -1
  40. package/dist/server/index.mjs +295 -5711
  41. package/dist/server/index.mjs.map +1 -1
  42. package/dist/server/websocket.d.mts +1 -1
  43. package/dist/server/websocket.d.ts +1 -1
  44. package/dist/ws/index.d.mts +1 -1
  45. package/dist/ws/index.d.ts +1 -1
  46. package/package.json +1 -1
  47. package/dist/sharp-win32-x64-CXV3GA3G.node +0 -0
@@ -14,130 +14,6 @@ var __export = (target, all) => {
14
14
  __defProp(target, name, { get: all[name], enumerable: true });
15
15
  };
16
16
 
17
- // src/config.ts
18
- import { readFileSync, existsSync } from "fs";
19
- import { resolve } from "path";
20
- function parseValue(v) {
21
- const trimmed = v.trim();
22
- if (trimmed === "true") return true;
23
- if (trimmed === "false") return false;
24
- if (trimmed === "null" || trimmed === "~") return null;
25
- if (/^-?\d+$/.test(trimmed)) return parseInt(trimmed, 10);
26
- if (/^-?\d+\.\d+$/.test(trimmed)) return parseFloat(trimmed);
27
- if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
28
- return trimmed.slice(1, -1);
29
- }
30
- return trimmed;
31
- }
32
- function parseYaml(text) {
33
- const lines = text.split("\n");
34
- const root = {};
35
- const stack = [{ obj: root, indent: -1, isArray: false }];
36
- for (const rawLine of lines) {
37
- const commentIdx = rawLine.indexOf("#");
38
- const line = commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine;
39
- if (!line.trim()) continue;
40
- const indent = line.length - line.trimStart().length;
41
- const trimmed = line.trim();
42
- while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
43
- stack.pop();
44
- }
45
- const parent = stack[stack.length - 1];
46
- if (trimmed.startsWith("- ")) {
47
- const valueStr2 = trimmed.slice(2).trim();
48
- if (!parent.isArray) {
49
- }
50
- let target = parent.obj;
51
- if (!Array.isArray(target)) {
52
- target = [];
53
- }
54
- if (valueStr2.includes(":")) {
55
- const item = {};
56
- const colonIdx2 = valueStr2.indexOf(":");
57
- const k = valueStr2.slice(0, colonIdx2).trim();
58
- const v = valueStr2.slice(colonIdx2 + 1).trim();
59
- item[k] = parseValue(v);
60
- target.push(item);
61
- } else {
62
- target.push(parseValue(valueStr2));
63
- }
64
- continue;
65
- }
66
- const colonIdx = trimmed.indexOf(":");
67
- if (colonIdx === -1) continue;
68
- const key = trimmed.slice(0, colonIdx).trim();
69
- const valueStr = trimmed.slice(colonIdx + 1).trim();
70
- if (!valueStr) {
71
- const newObj = {};
72
- parent.obj[key] = newObj;
73
- stack.push({ obj: newObj, indent, isArray: false });
74
- } else {
75
- parent.obj[key] = parseValue(valueStr);
76
- }
77
- }
78
- return root;
79
- }
80
- function loadConfig() {
81
- const configPath = resolve(process.cwd(), "config.yaml");
82
- if (!existsSync(configPath)) {
83
- console.warn("[Config] config.yaml not found, using defaults");
84
- return defaultConfig();
85
- }
86
- try {
87
- const raw = readFileSync(configPath, "utf-8");
88
- const parsed = parseYaml(raw);
89
- return mergeDeep(defaultConfig(), parsed);
90
- } catch (err) {
91
- console.error("[Config] Failed to parse config.yaml:", err.message);
92
- return defaultConfig();
93
- }
94
- }
95
- function getVersion() {
96
- try {
97
- const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf-8"));
98
- return pkg.version;
99
- } catch {
100
- try {
101
- const pkg = JSON.parse(readFileSync(resolve(process.cwd(), "package.json"), "utf-8"));
102
- return pkg.version;
103
- } catch {
104
- return "2.0.1";
105
- }
106
- }
107
- }
108
- function defaultConfig() {
109
- return {
110
- server: { port: 7321, host: "localhost", version: getVersion() },
111
- database: { path: "data/nexus.db", wal_mode: true, vec_extension_path: "data/vec0" },
112
- storage: { files_dir: "data/files", max_file_size_mb: 50, backups_dir: "data/backups", backup_interval_hours: 24, max_backups: 7 },
113
- limits: { max_atoms_per_project: 1e4, rate_limit_requests: 100, rate_limit_window_ms: 6e4 },
114
- embeddings: { model: "Xenova/all-MiniLM-L6-v2", dimension: 384, max_text_length: 1e4 },
115
- features: { mcp_enabled: true, auto_index_enabled: true, file_processing_enabled: true },
116
- index: { debounce_ms: 3e4 },
117
- search: { semantic_weight: 0.6, fts_weight: 0.4 },
118
- bonds: { default_type: "relates" }
119
- };
120
- }
121
- function mergeDeep(target, source) {
122
- if (!source || typeof source !== "object") return target;
123
- const output = { ...target };
124
- for (const key of Object.keys(source)) {
125
- if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
126
- output[key] = mergeDeep(target[key] || {}, source[key]);
127
- } else {
128
- output[key] = source[key];
129
- }
130
- }
131
- return output;
132
- }
133
- var CONFIG;
134
- var init_config = __esm({
135
- "src/config.ts"() {
136
- "use strict";
137
- CONFIG = loadConfig();
138
- }
139
- });
140
-
141
17
  // src/server/embedder.ts
142
18
  var embedder_exports = {};
143
19
  __export(embedder_exports, {
@@ -146,20 +22,18 @@ __export(embedder_exports, {
146
22
  isReady: () => isReady
147
23
  });
148
24
  import { pipeline } from "@xenova/transformers";
149
- async function getExtractor() {
150
- if (extractor) return extractor;
151
- if (loadError) return null;
25
+ async function getExtractor(model) {
26
+ if (extractor && loadedModel === model) return extractor;
27
+ if (loadError && loadedModel === model) return null;
152
28
  if (loading) {
153
29
  while (loading) await new Promise((r) => setTimeout(r, 100));
154
- return extractor;
30
+ return extractor && loadedModel === model ? extractor : null;
155
31
  }
156
32
  loading = true;
157
33
  try {
158
- extractor = await pipeline("feature-extraction", CONFIG.embeddings.model, {
159
- quantized: true
160
- // Use quantized model for faster download
161
- });
162
- console.log(`[Embedder] Model loaded: ${CONFIG.embeddings.model}`);
34
+ extractor = await pipeline("feature-extraction", model, { quantized: true });
35
+ loadedModel = model;
36
+ console.log(`[Embedder] Model loaded: ${model}`);
163
37
  return extractor;
164
38
  } catch (err) {
165
39
  loadError = err;
@@ -169,10 +43,11 @@ async function getExtractor() {
169
43
  loading = false;
170
44
  }
171
45
  }
172
- async function embedText(text) {
173
- const ext = await getExtractor();
46
+ async function embedText(text, model, maxLength) {
47
+ const m = model || DEFAULT_MODEL;
48
+ const ext = await getExtractor(m);
174
49
  if (!ext) return null;
175
- const truncated = text.slice(0, CONFIG.embeddings.max_text_length);
50
+ const truncated = text.slice(0, maxLength || DEFAULT_MAX_LENGTH);
176
51
  if (!truncated.trim()) return null;
177
52
  try {
178
53
  const output = await ext(truncated, { pooling: "mean", normalize: true });
@@ -182,12 +57,13 @@ async function embedText(text) {
182
57
  return null;
183
58
  }
184
59
  }
185
- async function embedTexts(texts) {
186
- const ext = await getExtractor();
60
+ async function embedTexts(texts, model, maxLength) {
61
+ const m = model || DEFAULT_MODEL;
62
+ const ext = await getExtractor(m);
187
63
  if (!ext) return texts.map(() => null);
188
64
  const results = [];
189
65
  for (const text of texts) {
190
- const truncated = text.slice(0, CONFIG.embeddings.max_text_length);
66
+ const truncated = text.slice(0, maxLength || DEFAULT_MAX_LENGTH);
191
67
  if (!truncated.trim()) {
192
68
  results.push(null);
193
69
  continue;
@@ -204,14 +80,16 @@ async function embedTexts(texts) {
204
80
  function isReady() {
205
81
  return extractor !== null;
206
82
  }
207
- var extractor, loading, loadError;
83
+ var DEFAULT_MODEL, DEFAULT_MAX_LENGTH, extractor, loading, loadError, loadedModel;
208
84
  var init_embedder = __esm({
209
85
  "src/server/embedder.ts"() {
210
86
  "use strict";
211
- init_config();
87
+ DEFAULT_MODEL = "Xenova/all-MiniLM-L6-v2";
88
+ DEFAULT_MAX_LENGTH = 1e4;
212
89
  extractor = null;
213
90
  loading = false;
214
91
  loadError = null;
92
+ loadedModel = "";
215
93
  }
216
94
  });
217
95
 
@@ -432,6 +310,23 @@ var TOOLS = [
432
310
  ];
433
311
 
434
312
  // src/mcp/server.ts
313
+ function getVersion() {
314
+ try {
315
+ const { readFileSync: readFileSync4 } = __require("fs");
316
+ const { resolve: resolve4 } = __require("path");
317
+ const pkg = JSON.parse(readFileSync4(resolve4(__dirname, "../../package.json"), "utf-8"));
318
+ return pkg.version;
319
+ } catch {
320
+ try {
321
+ const { readFileSync: readFileSync4 } = __require("fs");
322
+ const { resolve: resolve4 } = __require("path");
323
+ const pkg = JSON.parse(readFileSync4(resolve4(process.cwd(), "package.json"), "utf-8"));
324
+ return pkg.version;
325
+ } catch {
326
+ return "2.1.0";
327
+ }
328
+ }
329
+ }
435
330
  var McpServer = class {
436
331
  store;
437
332
  toolMap = /* @__PURE__ */ new Map();
@@ -452,7 +347,7 @@ var McpServer = class {
452
347
  return this.ok(req.id, {
453
348
  protocolVersion: "2024-11-05",
454
349
  capabilities: { tools: {}, resources: {}, prompts: {} },
455
- serverInfo: { name: "mnemosyne-mcp", version: "2.0.0" }
350
+ serverInfo: { name: "mnemosyne-mcp", version: getVersion() }
456
351
  });
457
352
  case "tools/list":
458
353
  return this.ok(req.id, {
@@ -479,7 +374,7 @@ var McpServer = class {
479
374
  getManifest() {
480
375
  return {
481
376
  name: "Mnemosyne",
482
- version: "2.0.0",
377
+ version: getVersion(),
483
378
  description: "Knowledge base MCP server for projects, atoms, blocks, and bonds.",
484
379
  protocol: "mcp",
485
380
  transport: ["stdio", "sse"],
@@ -584,7 +479,25 @@ function setCorsHeaders(res) {
584
479
  }
585
480
  function authenticate(store, req) {
586
481
  const token = req.headers.authorization?.replace("Bearer ", "");
587
- return token ? store.getAssistant(token) : void 0;
482
+ if (token) {
483
+ return store.getAssistant(token);
484
+ }
485
+ const host = req.headers.host || "";
486
+ const isLocalhost = host.startsWith("localhost:") || host.startsWith("127.0.0.1:") || host === "localhost" || host === "127.0.0.1";
487
+ if (isLocalhost) {
488
+ return {
489
+ id: "local-dev",
490
+ name: "Local Developer",
491
+ role: "owner",
492
+ permissions: {},
493
+ status: "active",
494
+ provider: null,
495
+ connected_at: Date.now(),
496
+ last_seen: Date.now(),
497
+ metadata: {}
498
+ };
499
+ }
500
+ return void 0;
588
501
  }
589
502
 
590
503
  // src/api/utils.ts
@@ -895,6 +808,16 @@ function handleAssistants(store, pathname, method, res, body) {
895
808
  json(res, 200, { assistants });
896
809
  return true;
897
810
  }
811
+ if (pathname.match(/^\/api\/v1\/assistants\/[^\/]+$/) && method === "GET") {
812
+ const id = pathname.replace("/api/v1/assistants/", "");
813
+ const assistant = store.getAssistant(id);
814
+ if (!assistant) {
815
+ json(res, 404, { error: "assistant_not_found" });
816
+ return true;
817
+ }
818
+ json(res, 200, { assistant });
819
+ return true;
820
+ }
898
821
  if (pathname.match(/^\/api\/v1\/assistants\/[^\/]+$/) && method === "PATCH") {
899
822
  const id = pathname.replace("/api/v1/assistants/", "");
900
823
  const a = body;
@@ -935,6 +858,22 @@ function handleProjects(store, pathname, method, res, body, searchParams) {
935
858
  json(res, 200, { success: true, project });
936
859
  return true;
937
860
  }
861
+ if (pathname.match(/^\/api\/v1\/projects\/[^/]+$/) && method === "GET") {
862
+ const id = pathname.replace("/api/v1/projects/", "");
863
+ const project = store.getProject(id);
864
+ if (!project) {
865
+ json(res, 404, { error: "project_not_found" });
866
+ return true;
867
+ }
868
+ json(res, 200, { project });
869
+ return true;
870
+ }
871
+ if (pathname.match(/^\/api\/v1\/projects\/[^/]+$/) && method === "DELETE") {
872
+ const id = pathname.replace("/api/v1/projects/", "");
873
+ const ok = store.deleteProject(id);
874
+ json(res, ok ? 200 : 404, { success: ok });
875
+ return true;
876
+ }
938
877
  const projectIndexMatch = pathname.match(/^\/api\/v1\/projects\/([^/]+)\/index$/);
939
878
  if (projectIndexMatch && method === "GET") {
940
879
  const projectId = resolveProjectId(store, projectIndexMatch[1]);
@@ -1166,6 +1105,10 @@ function handleAtoms(store, pathname, method, res, body, searchParams, assistant
1166
1105
 
1167
1106
  // src/api/routes/bonds.ts
1168
1107
  function handleBonds(store, pathname, method, res, body) {
1108
+ if (pathname === "/api/v1/bonds" && method === "GET") {
1109
+ json(res, 200, store.getAllBonds());
1110
+ return true;
1111
+ }
1169
1112
  if (pathname.match(/^\/api\/v1\/atoms\/[^\/]+\/bonds$/) && method === "GET") {
1170
1113
  const atomId = pathname.replace("/api/v1/atoms/", "").replace("/bonds", "");
1171
1114
  json(res, 200, store.getBondsByAtom(atomId));
@@ -1293,7 +1236,7 @@ async function handleSearch(store, pathname, method, res, searchParams) {
1293
1236
  let results = [];
1294
1237
  if (semantic) {
1295
1238
  const { embedText: embedText2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
1296
- const queryEmbedding = await embedText2(q);
1239
+ const queryEmbedding = await embedText2(q, store.config.embeddings.model, store.config.embeddings.max_text_length);
1297
1240
  if (queryEmbedding) {
1298
1241
  results = store.searchHybrid(projectId, q, queryEmbedding, limit);
1299
1242
  } else {
@@ -1309,16 +1252,150 @@ async function handleSearch(store, pathname, method, res, searchParams) {
1309
1252
  }
1310
1253
 
1311
1254
  // src/server/files.ts
1312
- init_config();
1313
1255
  import { createHash } from "crypto";
1314
1256
  import { mkdirSync, existsSync as existsSync2, writeFileSync, readFileSync as readFileSync2 } from "fs";
1315
1257
  import { resolve as resolve2, dirname } from "path";
1316
- var FILES_DIR = resolve2(process.cwd(), CONFIG.storage.files_dir);
1258
+
1259
+ // src/config.ts
1260
+ import { readFileSync, existsSync } from "fs";
1261
+ import { resolve } from "path";
1262
+ function parseValue(v) {
1263
+ const trimmed = v.trim();
1264
+ if (trimmed === "true") return true;
1265
+ if (trimmed === "false") return false;
1266
+ if (trimmed === "null" || trimmed === "~") return null;
1267
+ if (/^-?\d+$/.test(trimmed)) return parseInt(trimmed, 10);
1268
+ if (/^-?\d+\.\d+$/.test(trimmed)) return parseFloat(trimmed);
1269
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
1270
+ return trimmed.slice(1, -1);
1271
+ }
1272
+ return trimmed;
1273
+ }
1274
+ function parseYaml(text) {
1275
+ const lines = text.split("\n");
1276
+ const root = {};
1277
+ const stack = [{ obj: root, indent: -1, isArray: false }];
1278
+ for (const rawLine of lines) {
1279
+ const commentIdx = rawLine.indexOf("#");
1280
+ const line = commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine;
1281
+ if (!line.trim()) continue;
1282
+ const indent = line.length - line.trimStart().length;
1283
+ const trimmed = line.trim();
1284
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
1285
+ stack.pop();
1286
+ }
1287
+ const parent = stack[stack.length - 1];
1288
+ if (trimmed.startsWith("- ")) {
1289
+ const valueStr2 = trimmed.slice(2).trim();
1290
+ if (!parent.isArray) {
1291
+ }
1292
+ let target = parent.obj;
1293
+ if (!Array.isArray(target)) {
1294
+ target = [];
1295
+ }
1296
+ if (valueStr2.includes(":")) {
1297
+ const item = {};
1298
+ const colonIdx2 = valueStr2.indexOf(":");
1299
+ const k = valueStr2.slice(0, colonIdx2).trim();
1300
+ const v = valueStr2.slice(colonIdx2 + 1).trim();
1301
+ item[k] = parseValue(v);
1302
+ target.push(item);
1303
+ } else {
1304
+ target.push(parseValue(valueStr2));
1305
+ }
1306
+ continue;
1307
+ }
1308
+ const colonIdx = trimmed.indexOf(":");
1309
+ if (colonIdx === -1) continue;
1310
+ const key = trimmed.slice(0, colonIdx).trim();
1311
+ const valueStr = trimmed.slice(colonIdx + 1).trim();
1312
+ if (!valueStr) {
1313
+ const newObj = {};
1314
+ parent.obj[key] = newObj;
1315
+ stack.push({ obj: newObj, indent, isArray: false });
1316
+ } else {
1317
+ parent.obj[key] = parseValue(valueStr);
1318
+ }
1319
+ }
1320
+ return root;
1321
+ }
1322
+ function loadConfig() {
1323
+ const configPath = resolve(process.cwd(), "config.yaml");
1324
+ if (!existsSync(configPath)) {
1325
+ console.warn("[Config] config.yaml not found, using defaults");
1326
+ return defaultConfig();
1327
+ }
1328
+ try {
1329
+ const raw = readFileSync(configPath, "utf-8");
1330
+ const parsed = parseYaml(raw);
1331
+ return mergeDeep(defaultConfig(), parsed);
1332
+ } catch (err) {
1333
+ console.error("[Config] Failed to parse config.yaml:", err.message);
1334
+ return defaultConfig();
1335
+ }
1336
+ }
1337
+ function getVersion2() {
1338
+ try {
1339
+ const { readFileSync: readFileSync4 } = __require("fs");
1340
+ const { resolve: resolve4 } = __require("path");
1341
+ const pkg = JSON.parse(readFileSync4(resolve4(__dirname, "../package.json"), "utf-8"));
1342
+ return pkg.version;
1343
+ } catch {
1344
+ try {
1345
+ const { readFileSync: readFileSync4 } = __require("fs");
1346
+ const { resolve: resolve4 } = __require("path");
1347
+ const pkg = JSON.parse(readFileSync4(resolve4(process.cwd(), "package.json"), "utf-8"));
1348
+ return pkg.version;
1349
+ } catch {
1350
+ return "2.1.0";
1351
+ }
1352
+ }
1353
+ }
1354
+ function defaultConfig() {
1355
+ return {
1356
+ server: { port: 7321, host: "localhost", version: getVersion2() },
1357
+ database: { path: "data/nexus.db", wal_mode: true, vec_extension_path: "data/vec0" },
1358
+ storage: { files_dir: "data/files", max_file_size_mb: 50, backups_dir: "data/backups", backup_interval_hours: 24, max_backups: 7 },
1359
+ limits: { max_atoms_per_project: 1e4, rate_limit_requests: 100, rate_limit_window_ms: 6e4 },
1360
+ embeddings: { model: "Xenova/all-MiniLM-L6-v2", dimension: 384, max_text_length: 1e4 },
1361
+ features: { mcp_enabled: true, auto_index_enabled: true, file_processing_enabled: true },
1362
+ index: { debounce_ms: 3e4 },
1363
+ search: { semantic_weight: 0.6, fts_weight: 0.4 },
1364
+ bonds: { default_type: "relates" }
1365
+ };
1366
+ }
1367
+ function mergeDeep(target, source) {
1368
+ if (!source || typeof source !== "object") return target;
1369
+ const output = { ...target };
1370
+ for (const key of Object.keys(source)) {
1371
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
1372
+ output[key] = mergeDeep(target[key] || {}, source[key]);
1373
+ } else {
1374
+ output[key] = source[key];
1375
+ }
1376
+ }
1377
+ return output;
1378
+ }
1379
+ var _config = null;
1380
+ function getConfig() {
1381
+ if (!_config) _config = loadConfig();
1382
+ return _config;
1383
+ }
1384
+ var CONFIG = new Proxy({}, {
1385
+ get(_, prop) {
1386
+ return getConfig()[prop];
1387
+ }
1388
+ });
1389
+
1390
+ // src/server/files.ts
1391
+ function getFilesDir() {
1392
+ return resolve2(process.cwd(), CONFIG.storage.files_dir);
1393
+ }
1317
1394
  function ensureDir(path) {
1318
1395
  if (!existsSync2(path)) mkdirSync(path, { recursive: true });
1319
1396
  }
1320
1397
  function hashPath(hash) {
1321
- return resolve2(FILES_DIR, hash.slice(0, 2), hash.slice(2));
1398
+ return resolve2(getFilesDir(), hash.slice(0, 2), hash.slice(2));
1322
1399
  }
1323
1400
  function computeHash(buffer) {
1324
1401
  return createHash("sha256").update(buffer).digest("hex");
@@ -1388,7 +1465,7 @@ import { createHash as createHash2 } from "crypto";
1388
1465
  import { readFileSync as readFileSync3, existsSync as existsSync3, readdirSync, statSync } from "fs";
1389
1466
  import { resolve as resolve3 } from "path";
1390
1467
  var DB_PATH = resolve3(process.cwd(), "data", "nexus.db");
1391
- var FILES_DIR2 = resolve3(process.cwd(), "data", "files");
1468
+ var FILES_DIR = resolve3(process.cwd(), "data", "files");
1392
1469
  function sha256File(path) {
1393
1470
  return createHash2("sha256").update(readFileSync3(path)).digest("hex");
1394
1471
  }
@@ -1408,11 +1485,11 @@ function sha256Dir(dir) {
1408
1485
  function buildMnemosyneExport(projectId, projectName) {
1409
1486
  const zip = new AdmZip();
1410
1487
  zip.addLocalFile(DB_PATH, "", "nexus.db");
1411
- if (existsSync3(FILES_DIR2)) {
1412
- zip.addLocalFolder(FILES_DIR2, "files");
1488
+ if (existsSync3(FILES_DIR)) {
1489
+ zip.addLocalFolder(FILES_DIR, "files");
1413
1490
  }
1414
1491
  const dbChecksum = sha256File(DB_PATH);
1415
- const filesChecksum = existsSync3(FILES_DIR2) ? sha256Dir(FILES_DIR2) : "";
1492
+ const filesChecksum = existsSync3(FILES_DIR) ? sha256Dir(FILES_DIR) : "";
1416
1493
  const manifest = {
1417
1494
  version: "1.1",
1418
1495
  app: "Mnemosyne",
@@ -1540,10 +1617,10 @@ function handleEvents(store, pathname, method, res, searchParams) {
1540
1617
  // src/api/routes/health.ts
1541
1618
  var PKG_VERSION = (() => {
1542
1619
  try {
1543
- const pkg = JSON.parse(__require("fs").readFileSync(__require("path").resolve(__dirname, "../../../package.json"), "utf-8"));
1620
+ const pkg = JSON.parse(__require("fs").readFileSync(__require("path").resolve(__dirname, "../../package.json"), "utf-8"));
1544
1621
  return pkg.version;
1545
1622
  } catch {
1546
- return "2.0.1";
1623
+ return "2.1.0";
1547
1624
  }
1548
1625
  })();
1549
1626
  function handleHealth(store, pathname, method, res) {