mnemosyne-core 2.0.3 → 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 +387 -5744
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/index.mjs +387 -5744
  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 +281 -5726
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +281 -5726
  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 +1 -1
  21. package/dist/mcp/index.js.map +1 -1
  22. package/dist/mcp/index.mjs +1 -1
  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 +205 -160
  33. package/dist/server/api.js.map +1 -1
  34. package/dist/server/api.mjs +205 -160
  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 +245 -5694
  39. package/dist/server/index.js.map +1 -1
  40. package/dist/server/index.mjs +245 -5694
  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
@@ -30,143 +30,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/config.ts
34
- function parseValue(v) {
35
- const trimmed = v.trim();
36
- if (trimmed === "true") return true;
37
- if (trimmed === "false") return false;
38
- if (trimmed === "null" || trimmed === "~") return null;
39
- if (/^-?\d+$/.test(trimmed)) return parseInt(trimmed, 10);
40
- if (/^-?\d+\.\d+$/.test(trimmed)) return parseFloat(trimmed);
41
- if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
42
- return trimmed.slice(1, -1);
43
- }
44
- return trimmed;
45
- }
46
- function parseYaml(text) {
47
- const lines = text.split("\n");
48
- const root = {};
49
- const stack = [{ obj: root, indent: -1, isArray: false }];
50
- for (const rawLine of lines) {
51
- const commentIdx = rawLine.indexOf("#");
52
- const line = commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine;
53
- if (!line.trim()) continue;
54
- const indent = line.length - line.trimStart().length;
55
- const trimmed = line.trim();
56
- while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
57
- stack.pop();
58
- }
59
- const parent = stack[stack.length - 1];
60
- if (trimmed.startsWith("- ")) {
61
- const valueStr2 = trimmed.slice(2).trim();
62
- if (!parent.isArray) {
63
- }
64
- let target = parent.obj;
65
- if (!Array.isArray(target)) {
66
- target = [];
67
- }
68
- if (valueStr2.includes(":")) {
69
- const item = {};
70
- const colonIdx2 = valueStr2.indexOf(":");
71
- const k = valueStr2.slice(0, colonIdx2).trim();
72
- const v = valueStr2.slice(colonIdx2 + 1).trim();
73
- item[k] = parseValue(v);
74
- target.push(item);
75
- } else {
76
- target.push(parseValue(valueStr2));
77
- }
78
- continue;
79
- }
80
- const colonIdx = trimmed.indexOf(":");
81
- if (colonIdx === -1) continue;
82
- const key = trimmed.slice(0, colonIdx).trim();
83
- const valueStr = trimmed.slice(colonIdx + 1).trim();
84
- if (!valueStr) {
85
- const newObj = {};
86
- parent.obj[key] = newObj;
87
- stack.push({ obj: newObj, indent, isArray: false });
88
- } else {
89
- parent.obj[key] = parseValue(valueStr);
90
- }
91
- }
92
- return root;
93
- }
94
- function loadConfig() {
95
- const configPath = (0, import_path.resolve)(process.cwd(), "config.yaml");
96
- if (!(0, import_fs.existsSync)(configPath)) {
97
- console.warn("[Config] config.yaml not found, using defaults");
98
- return defaultConfig();
99
- }
100
- try {
101
- const raw = (0, import_fs.readFileSync)(configPath, "utf-8");
102
- const parsed = parseYaml(raw);
103
- return mergeDeep(defaultConfig(), parsed);
104
- } catch (err) {
105
- console.error("[Config] Failed to parse config.yaml:", err.message);
106
- return defaultConfig();
107
- }
108
- }
109
- function getVersion2() {
110
- try {
111
- const { readFileSync: readFileSync4 } = require("fs");
112
- const { resolve: resolve4 } = require("path");
113
- const pkg = JSON.parse(readFileSync4(resolve4(__dirname, "../package.json"), "utf-8"));
114
- return pkg.version;
115
- } catch {
116
- try {
117
- const { readFileSync: readFileSync4 } = require("fs");
118
- const { resolve: resolve4 } = require("path");
119
- const pkg = JSON.parse(readFileSync4(resolve4(process.cwd(), "package.json"), "utf-8"));
120
- return pkg.version;
121
- } catch {
122
- return "2.0.3";
123
- }
124
- }
125
- }
126
- function defaultConfig() {
127
- return {
128
- server: { port: 7321, host: "localhost", version: getVersion2() },
129
- database: { path: "data/nexus.db", wal_mode: true, vec_extension_path: "data/vec0" },
130
- storage: { files_dir: "data/files", max_file_size_mb: 50, backups_dir: "data/backups", backup_interval_hours: 24, max_backups: 7 },
131
- limits: { max_atoms_per_project: 1e4, rate_limit_requests: 100, rate_limit_window_ms: 6e4 },
132
- embeddings: { model: "Xenova/all-MiniLM-L6-v2", dimension: 384, max_text_length: 1e4 },
133
- features: { mcp_enabled: true, auto_index_enabled: true, file_processing_enabled: true },
134
- index: { debounce_ms: 3e4 },
135
- search: { semantic_weight: 0.6, fts_weight: 0.4 },
136
- bonds: { default_type: "relates" }
137
- };
138
- }
139
- function mergeDeep(target, source) {
140
- if (!source || typeof source !== "object") return target;
141
- const output = { ...target };
142
- for (const key of Object.keys(source)) {
143
- if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
144
- output[key] = mergeDeep(target[key] || {}, source[key]);
145
- } else {
146
- output[key] = source[key];
147
- }
148
- }
149
- return output;
150
- }
151
- function getConfig() {
152
- if (!_config) _config = loadConfig();
153
- return _config;
154
- }
155
- var import_fs, import_path, _config, CONFIG;
156
- var init_config = __esm({
157
- "src/config.ts"() {
158
- "use strict";
159
- import_fs = require("fs");
160
- import_path = require("path");
161
- _config = null;
162
- CONFIG = new Proxy({}, {
163
- get(_, prop) {
164
- return getConfig()[prop];
165
- }
166
- });
167
- }
168
- });
169
-
170
33
  // src/server/embedder.ts
171
34
  var embedder_exports = {};
172
35
  __export(embedder_exports, {
@@ -174,20 +37,18 @@ __export(embedder_exports, {
174
37
  embedTexts: () => embedTexts,
175
38
  isReady: () => isReady
176
39
  });
177
- async function getExtractor() {
178
- if (extractor) return extractor;
179
- if (loadError) return null;
40
+ async function getExtractor(model) {
41
+ if (extractor && loadedModel === model) return extractor;
42
+ if (loadError && loadedModel === model) return null;
180
43
  if (loading) {
181
44
  while (loading) await new Promise((r) => setTimeout(r, 100));
182
- return extractor;
45
+ return extractor && loadedModel === model ? extractor : null;
183
46
  }
184
47
  loading = true;
185
48
  try {
186
- extractor = await (0, import_transformers.pipeline)("feature-extraction", CONFIG.embeddings.model, {
187
- quantized: true
188
- // Use quantized model for faster download
189
- });
190
- console.log(`[Embedder] Model loaded: ${CONFIG.embeddings.model}`);
49
+ extractor = await (0, import_transformers.pipeline)("feature-extraction", model, { quantized: true });
50
+ loadedModel = model;
51
+ console.log(`[Embedder] Model loaded: ${model}`);
191
52
  return extractor;
192
53
  } catch (err) {
193
54
  loadError = err;
@@ -197,10 +58,11 @@ async function getExtractor() {
197
58
  loading = false;
198
59
  }
199
60
  }
200
- async function embedText(text) {
201
- const ext = await getExtractor();
61
+ async function embedText(text, model, maxLength) {
62
+ const m = model || DEFAULT_MODEL;
63
+ const ext = await getExtractor(m);
202
64
  if (!ext) return null;
203
- const truncated = text.slice(0, CONFIG.embeddings.max_text_length);
65
+ const truncated = text.slice(0, maxLength || DEFAULT_MAX_LENGTH);
204
66
  if (!truncated.trim()) return null;
205
67
  try {
206
68
  const output = await ext(truncated, { pooling: "mean", normalize: true });
@@ -210,12 +72,13 @@ async function embedText(text) {
210
72
  return null;
211
73
  }
212
74
  }
213
- async function embedTexts(texts) {
214
- const ext = await getExtractor();
75
+ async function embedTexts(texts, model, maxLength) {
76
+ const m = model || DEFAULT_MODEL;
77
+ const ext = await getExtractor(m);
215
78
  if (!ext) return texts.map(() => null);
216
79
  const results = [];
217
80
  for (const text of texts) {
218
- const truncated = text.slice(0, CONFIG.embeddings.max_text_length);
81
+ const truncated = text.slice(0, maxLength || DEFAULT_MAX_LENGTH);
219
82
  if (!truncated.trim()) {
220
83
  results.push(null);
221
84
  continue;
@@ -232,15 +95,17 @@ async function embedTexts(texts) {
232
95
  function isReady() {
233
96
  return extractor !== null;
234
97
  }
235
- var import_transformers, extractor, loading, loadError;
98
+ var import_transformers, DEFAULT_MODEL, DEFAULT_MAX_LENGTH, extractor, loading, loadError, loadedModel;
236
99
  var init_embedder = __esm({
237
100
  "src/server/embedder.ts"() {
238
101
  "use strict";
239
102
  import_transformers = require("@xenova/transformers");
240
- init_config();
103
+ DEFAULT_MODEL = "Xenova/all-MiniLM-L6-v2";
104
+ DEFAULT_MAX_LENGTH = 1e4;
241
105
  extractor = null;
242
106
  loading = false;
243
107
  loadError = null;
108
+ loadedModel = "";
244
109
  }
245
110
  });
246
111
 
@@ -481,7 +346,7 @@ function getVersion() {
481
346
  const pkg = JSON.parse(readFileSync4(resolve4(process.cwd(), "package.json"), "utf-8"));
482
347
  return pkg.version;
483
348
  } catch {
484
- return "2.0.3";
349
+ return "2.1.0";
485
350
  }
486
351
  }
487
352
  }
@@ -637,7 +502,25 @@ function setCorsHeaders(res) {
637
502
  }
638
503
  function authenticate(store, req) {
639
504
  const token = req.headers.authorization?.replace("Bearer ", "");
640
- return token ? store.getAssistant(token) : void 0;
505
+ if (token) {
506
+ return store.getAssistant(token);
507
+ }
508
+ const host = req.headers.host || "";
509
+ const isLocalhost = host.startsWith("localhost:") || host.startsWith("127.0.0.1:") || host === "localhost" || host === "127.0.0.1";
510
+ if (isLocalhost) {
511
+ return {
512
+ id: "local-dev",
513
+ name: "Local Developer",
514
+ role: "owner",
515
+ permissions: {},
516
+ status: "active",
517
+ provider: null,
518
+ connected_at: Date.now(),
519
+ last_seen: Date.now(),
520
+ metadata: {}
521
+ };
522
+ }
523
+ return void 0;
641
524
  }
642
525
 
643
526
  // src/api/utils.ts
@@ -948,6 +831,16 @@ function handleAssistants(store, pathname, method, res, body) {
948
831
  json(res, 200, { assistants });
949
832
  return true;
950
833
  }
834
+ if (pathname.match(/^\/api\/v1\/assistants\/[^\/]+$/) && method === "GET") {
835
+ const id = pathname.replace("/api/v1/assistants/", "");
836
+ const assistant = store.getAssistant(id);
837
+ if (!assistant) {
838
+ json(res, 404, { error: "assistant_not_found" });
839
+ return true;
840
+ }
841
+ json(res, 200, { assistant });
842
+ return true;
843
+ }
951
844
  if (pathname.match(/^\/api\/v1\/assistants\/[^\/]+$/) && method === "PATCH") {
952
845
  const id = pathname.replace("/api/v1/assistants/", "");
953
846
  const a = body;
@@ -988,6 +881,22 @@ function handleProjects(store, pathname, method, res, body, searchParams) {
988
881
  json(res, 200, { success: true, project });
989
882
  return true;
990
883
  }
884
+ if (pathname.match(/^\/api\/v1\/projects\/[^/]+$/) && method === "GET") {
885
+ const id = pathname.replace("/api/v1/projects/", "");
886
+ const project = store.getProject(id);
887
+ if (!project) {
888
+ json(res, 404, { error: "project_not_found" });
889
+ return true;
890
+ }
891
+ json(res, 200, { project });
892
+ return true;
893
+ }
894
+ if (pathname.match(/^\/api\/v1\/projects\/[^/]+$/) && method === "DELETE") {
895
+ const id = pathname.replace("/api/v1/projects/", "");
896
+ const ok = store.deleteProject(id);
897
+ json(res, ok ? 200 : 404, { success: ok });
898
+ return true;
899
+ }
991
900
  const projectIndexMatch = pathname.match(/^\/api\/v1\/projects\/([^/]+)\/index$/);
992
901
  if (projectIndexMatch && method === "GET") {
993
902
  const projectId = resolveProjectId(store, projectIndexMatch[1]);
@@ -1219,6 +1128,10 @@ function handleAtoms(store, pathname, method, res, body, searchParams, assistant
1219
1128
 
1220
1129
  // src/api/routes/bonds.ts
1221
1130
  function handleBonds(store, pathname, method, res, body) {
1131
+ if (pathname === "/api/v1/bonds" && method === "GET") {
1132
+ json(res, 200, store.getAllBonds());
1133
+ return true;
1134
+ }
1222
1135
  if (pathname.match(/^\/api\/v1\/atoms\/[^\/]+\/bonds$/) && method === "GET") {
1223
1136
  const atomId = pathname.replace("/api/v1/atoms/", "").replace("/bonds", "");
1224
1137
  json(res, 200, store.getBondsByAtom(atomId));
@@ -1346,7 +1259,7 @@ async function handleSearch(store, pathname, method, res, searchParams) {
1346
1259
  let results = [];
1347
1260
  if (semantic) {
1348
1261
  const { embedText: embedText2 } = await Promise.resolve().then(() => (init_embedder(), embedder_exports));
1349
- const queryEmbedding = await embedText2(q);
1262
+ const queryEmbedding = await embedText2(q, store.config.embeddings.model, store.config.embeddings.max_text_length);
1350
1263
  if (queryEmbedding) {
1351
1264
  results = store.searchHybrid(projectId, q, queryEmbedding, limit);
1352
1265
  } else {
@@ -1365,7 +1278,139 @@ async function handleSearch(store, pathname, method, res, searchParams) {
1365
1278
  var import_crypto = require("crypto");
1366
1279
  var import_fs2 = require("fs");
1367
1280
  var import_path2 = require("path");
1368
- init_config();
1281
+
1282
+ // src/config.ts
1283
+ var import_fs = require("fs");
1284
+ var import_path = require("path");
1285
+ function parseValue(v) {
1286
+ const trimmed = v.trim();
1287
+ if (trimmed === "true") return true;
1288
+ if (trimmed === "false") return false;
1289
+ if (trimmed === "null" || trimmed === "~") return null;
1290
+ if (/^-?\d+$/.test(trimmed)) return parseInt(trimmed, 10);
1291
+ if (/^-?\d+\.\d+$/.test(trimmed)) return parseFloat(trimmed);
1292
+ if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
1293
+ return trimmed.slice(1, -1);
1294
+ }
1295
+ return trimmed;
1296
+ }
1297
+ function parseYaml(text) {
1298
+ const lines = text.split("\n");
1299
+ const root = {};
1300
+ const stack = [{ obj: root, indent: -1, isArray: false }];
1301
+ for (const rawLine of lines) {
1302
+ const commentIdx = rawLine.indexOf("#");
1303
+ const line = commentIdx >= 0 ? rawLine.slice(0, commentIdx) : rawLine;
1304
+ if (!line.trim()) continue;
1305
+ const indent = line.length - line.trimStart().length;
1306
+ const trimmed = line.trim();
1307
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
1308
+ stack.pop();
1309
+ }
1310
+ const parent = stack[stack.length - 1];
1311
+ if (trimmed.startsWith("- ")) {
1312
+ const valueStr2 = trimmed.slice(2).trim();
1313
+ if (!parent.isArray) {
1314
+ }
1315
+ let target = parent.obj;
1316
+ if (!Array.isArray(target)) {
1317
+ target = [];
1318
+ }
1319
+ if (valueStr2.includes(":")) {
1320
+ const item = {};
1321
+ const colonIdx2 = valueStr2.indexOf(":");
1322
+ const k = valueStr2.slice(0, colonIdx2).trim();
1323
+ const v = valueStr2.slice(colonIdx2 + 1).trim();
1324
+ item[k] = parseValue(v);
1325
+ target.push(item);
1326
+ } else {
1327
+ target.push(parseValue(valueStr2));
1328
+ }
1329
+ continue;
1330
+ }
1331
+ const colonIdx = trimmed.indexOf(":");
1332
+ if (colonIdx === -1) continue;
1333
+ const key = trimmed.slice(0, colonIdx).trim();
1334
+ const valueStr = trimmed.slice(colonIdx + 1).trim();
1335
+ if (!valueStr) {
1336
+ const newObj = {};
1337
+ parent.obj[key] = newObj;
1338
+ stack.push({ obj: newObj, indent, isArray: false });
1339
+ } else {
1340
+ parent.obj[key] = parseValue(valueStr);
1341
+ }
1342
+ }
1343
+ return root;
1344
+ }
1345
+ function loadConfig() {
1346
+ const configPath = (0, import_path.resolve)(process.cwd(), "config.yaml");
1347
+ if (!(0, import_fs.existsSync)(configPath)) {
1348
+ console.warn("[Config] config.yaml not found, using defaults");
1349
+ return defaultConfig();
1350
+ }
1351
+ try {
1352
+ const raw = (0, import_fs.readFileSync)(configPath, "utf-8");
1353
+ const parsed = parseYaml(raw);
1354
+ return mergeDeep(defaultConfig(), parsed);
1355
+ } catch (err) {
1356
+ console.error("[Config] Failed to parse config.yaml:", err.message);
1357
+ return defaultConfig();
1358
+ }
1359
+ }
1360
+ function getVersion2() {
1361
+ try {
1362
+ const { readFileSync: readFileSync4 } = require("fs");
1363
+ const { resolve: resolve4 } = require("path");
1364
+ const pkg = JSON.parse(readFileSync4(resolve4(__dirname, "../package.json"), "utf-8"));
1365
+ return pkg.version;
1366
+ } catch {
1367
+ try {
1368
+ const { readFileSync: readFileSync4 } = require("fs");
1369
+ const { resolve: resolve4 } = require("path");
1370
+ const pkg = JSON.parse(readFileSync4(resolve4(process.cwd(), "package.json"), "utf-8"));
1371
+ return pkg.version;
1372
+ } catch {
1373
+ return "2.1.0";
1374
+ }
1375
+ }
1376
+ }
1377
+ function defaultConfig() {
1378
+ return {
1379
+ server: { port: 7321, host: "localhost", version: getVersion2() },
1380
+ database: { path: "data/nexus.db", wal_mode: true, vec_extension_path: "data/vec0" },
1381
+ storage: { files_dir: "data/files", max_file_size_mb: 50, backups_dir: "data/backups", backup_interval_hours: 24, max_backups: 7 },
1382
+ limits: { max_atoms_per_project: 1e4, rate_limit_requests: 100, rate_limit_window_ms: 6e4 },
1383
+ embeddings: { model: "Xenova/all-MiniLM-L6-v2", dimension: 384, max_text_length: 1e4 },
1384
+ features: { mcp_enabled: true, auto_index_enabled: true, file_processing_enabled: true },
1385
+ index: { debounce_ms: 3e4 },
1386
+ search: { semantic_weight: 0.6, fts_weight: 0.4 },
1387
+ bonds: { default_type: "relates" }
1388
+ };
1389
+ }
1390
+ function mergeDeep(target, source) {
1391
+ if (!source || typeof source !== "object") return target;
1392
+ const output = { ...target };
1393
+ for (const key of Object.keys(source)) {
1394
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
1395
+ output[key] = mergeDeep(target[key] || {}, source[key]);
1396
+ } else {
1397
+ output[key] = source[key];
1398
+ }
1399
+ }
1400
+ return output;
1401
+ }
1402
+ var _config = null;
1403
+ function getConfig() {
1404
+ if (!_config) _config = loadConfig();
1405
+ return _config;
1406
+ }
1407
+ var CONFIG = new Proxy({}, {
1408
+ get(_, prop) {
1409
+ return getConfig()[prop];
1410
+ }
1411
+ });
1412
+
1413
+ // src/server/files.ts
1369
1414
  function getFilesDir() {
1370
1415
  return (0, import_path2.resolve)(process.cwd(), CONFIG.storage.files_dir);
1371
1416
  }
@@ -1595,10 +1640,10 @@ function handleEvents(store, pathname, method, res, searchParams) {
1595
1640
  // src/api/routes/health.ts
1596
1641
  var PKG_VERSION = (() => {
1597
1642
  try {
1598
- const pkg = JSON.parse(require("fs").readFileSync(require("path").resolve(__dirname, "../../../package.json"), "utf-8"));
1643
+ const pkg = JSON.parse(require("fs").readFileSync(require("path").resolve(__dirname, "../../package.json"), "utf-8"));
1599
1644
  return pkg.version;
1600
1645
  } catch {
1601
- return "2.0.3";
1646
+ return "2.1.0";
1602
1647
  }
1603
1648
  })();
1604
1649
  function handleHealth(store, pathname, method, res) {