mnemosyne-core 2.0.0 → 2.0.2
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.
- package/dist/{Store-N3j0Vaj6.d.mts → Store-BtdYuiUx.d.mts} +19 -1
- package/dist/{Store-N3j0Vaj6.d.ts → Store-BtdYuiUx.d.ts} +19 -1
- package/dist/cli/index.js +310 -55
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +294 -39
- package/dist/cli/index.mjs.map +1 -1
- package/dist/dashboard/index.html +9401 -0
- package/dist/index-B2oTMNlL.d.ts +115 -0
- package/dist/index-B8PTQKy9.d.mts +115 -0
- package/dist/index-DWk78ifo.d.ts +98 -0
- package/dist/index-yTOihMUk.d.mts +98 -0
- package/dist/index.d.mts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +13008 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +12978 -0
- package/dist/index.mjs.map +1 -0
- package/dist/mcp/index.d.mts +3 -93
- package/dist/mcp/index.d.ts +3 -93
- package/dist/server/api.d.mts +1 -1
- package/dist/server/api.d.ts +1 -1
- package/dist/server/api.js +24 -3
- package/dist/server/api.js.map +1 -1
- package/dist/server/api.mjs +30 -3
- package/dist/server/api.mjs.map +1 -1
- package/dist/server/index.d.mts +7 -110
- package/dist/server/index.d.ts +7 -110
- package/dist/server/index.js +252 -20
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +251 -19
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/websocket.d.mts +1 -1
- package/dist/server/websocket.d.ts +1 -1
- package/dist/ws/index.d.mts +1 -1
- package/dist/ws/index.d.ts +1 -1
- package/package.json +12 -12
package/dist/cli/index.js
CHANGED
|
@@ -3548,9 +3548,22 @@ function loadConfig() {
|
|
|
3548
3548
|
return defaultConfig();
|
|
3549
3549
|
}
|
|
3550
3550
|
}
|
|
3551
|
+
function getVersion() {
|
|
3552
|
+
try {
|
|
3553
|
+
const pkg = JSON.parse((0, import_fs.readFileSync)((0, import_path.resolve)(__dirname, "../package.json"), "utf-8"));
|
|
3554
|
+
return pkg.version;
|
|
3555
|
+
} catch {
|
|
3556
|
+
try {
|
|
3557
|
+
const pkg = JSON.parse((0, import_fs.readFileSync)((0, import_path.resolve)(process.cwd(), "package.json"), "utf-8"));
|
|
3558
|
+
return pkg.version;
|
|
3559
|
+
} catch {
|
|
3560
|
+
return "2.0.1";
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3551
3564
|
function defaultConfig() {
|
|
3552
3565
|
return {
|
|
3553
|
-
server: { port: 7321, host: "localhost", version:
|
|
3566
|
+
server: { port: 7321, host: "localhost", version: getVersion() },
|
|
3554
3567
|
database: { path: "data/nexus.db", wal_mode: true, vec_extension_path: "data/vec0" },
|
|
3555
3568
|
storage: { files_dir: "data/files", max_file_size_mb: 50, backups_dir: "data/backups", backup_interval_hours: 24, max_backups: 7 },
|
|
3556
3569
|
limits: { max_atoms_per_project: 1e4, rate_limit_requests: 100, rate_limit_window_ms: 6e4 },
|
|
@@ -4351,7 +4364,7 @@ var require_filesystem = __commonJS({
|
|
|
4351
4364
|
var LDD_PATH = "/usr/bin/ldd";
|
|
4352
4365
|
var SELF_PATH = "/proc/self/exe";
|
|
4353
4366
|
var MAX_LENGTH = 2048;
|
|
4354
|
-
var
|
|
4367
|
+
var readFileSync7 = (path) => {
|
|
4355
4368
|
const fd = fs.openSync(path, "r");
|
|
4356
4369
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
4357
4370
|
const bytesRead = fs.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
@@ -4376,7 +4389,7 @@ var require_filesystem = __commonJS({
|
|
|
4376
4389
|
module2.exports = {
|
|
4377
4390
|
LDD_PATH,
|
|
4378
4391
|
SELF_PATH,
|
|
4379
|
-
readFileSync:
|
|
4392
|
+
readFileSync: readFileSync7,
|
|
4380
4393
|
readFile
|
|
4381
4394
|
};
|
|
4382
4395
|
}
|
|
@@ -4425,7 +4438,7 @@ var require_detect_libc = __commonJS({
|
|
|
4425
4438
|
"use strict";
|
|
4426
4439
|
var childProcess = require("child_process");
|
|
4427
4440
|
var { isLinux, getReport } = require_process();
|
|
4428
|
-
var { LDD_PATH, SELF_PATH, readFile, readFileSync:
|
|
4441
|
+
var { LDD_PATH, SELF_PATH, readFile, readFileSync: readFileSync7 } = require_filesystem();
|
|
4429
4442
|
var { interpreterPath } = require_elf();
|
|
4430
4443
|
var cachedFamilyInterpreter;
|
|
4431
4444
|
var cachedFamilyFilesystem;
|
|
@@ -4517,7 +4530,7 @@ var require_detect_libc = __commonJS({
|
|
|
4517
4530
|
}
|
|
4518
4531
|
cachedFamilyFilesystem = null;
|
|
4519
4532
|
try {
|
|
4520
|
-
const lddContent =
|
|
4533
|
+
const lddContent = readFileSync7(LDD_PATH);
|
|
4521
4534
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
4522
4535
|
} catch (e) {
|
|
4523
4536
|
}
|
|
@@ -4542,7 +4555,7 @@ var require_detect_libc = __commonJS({
|
|
|
4542
4555
|
}
|
|
4543
4556
|
cachedFamilyInterpreter = null;
|
|
4544
4557
|
try {
|
|
4545
|
-
const selfContent =
|
|
4558
|
+
const selfContent = readFileSync7(SELF_PATH);
|
|
4546
4559
|
const path = interpreterPath(selfContent);
|
|
4547
4560
|
cachedFamilyInterpreter = familyFromInterpreterPath(path);
|
|
4548
4561
|
} catch (e) {
|
|
@@ -4606,7 +4619,7 @@ var require_detect_libc = __commonJS({
|
|
|
4606
4619
|
}
|
|
4607
4620
|
cachedVersionFilesystem = null;
|
|
4608
4621
|
try {
|
|
4609
|
-
const lddContent =
|
|
4622
|
+
const lddContent = readFileSync7(LDD_PATH);
|
|
4610
4623
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
4611
4624
|
if (versionMatch) {
|
|
4612
4625
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -13103,7 +13116,6 @@ var import_path9 = require("path");
|
|
|
13103
13116
|
|
|
13104
13117
|
// src/core/Mnemosyne.ts
|
|
13105
13118
|
var import_better_sqlite32 = __toESM(require("better-sqlite3"));
|
|
13106
|
-
var import_fs5 = require("fs");
|
|
13107
13119
|
var import_path5 = require("path");
|
|
13108
13120
|
|
|
13109
13121
|
// src/core/types.ts
|
|
@@ -14327,9 +14339,26 @@ function parseYaml2(text) {
|
|
|
14327
14339
|
}
|
|
14328
14340
|
return root;
|
|
14329
14341
|
}
|
|
14342
|
+
function getVersion2() {
|
|
14343
|
+
try {
|
|
14344
|
+
const { readFileSync: readFileSync7 } = require("fs");
|
|
14345
|
+
const { resolve: resolve13 } = require("path");
|
|
14346
|
+
const pkg = JSON.parse(readFileSync7(resolve13(__dirname, "../../package.json"), "utf-8"));
|
|
14347
|
+
return pkg.version;
|
|
14348
|
+
} catch {
|
|
14349
|
+
try {
|
|
14350
|
+
const { readFileSync: readFileSync7 } = require("fs");
|
|
14351
|
+
const { resolve: resolve13 } = require("path");
|
|
14352
|
+
const pkg = JSON.parse(readFileSync7(resolve13(process.cwd(), "package.json"), "utf-8"));
|
|
14353
|
+
return pkg.version;
|
|
14354
|
+
} catch {
|
|
14355
|
+
return "2.0.1";
|
|
14356
|
+
}
|
|
14357
|
+
}
|
|
14358
|
+
}
|
|
14330
14359
|
function defaultConfig2() {
|
|
14331
14360
|
return {
|
|
14332
|
-
server: { port: 7321, host: "localhost", version:
|
|
14361
|
+
server: { port: 7321, host: "localhost", version: getVersion2() },
|
|
14333
14362
|
database: { path: "data/nexus.db", wal_mode: true, vec_extension_path: "data/vec0" },
|
|
14334
14363
|
storage: { files_dir: "data/files", max_file_size_mb: 50, backups_dir: "data/backups", backup_interval_hours: 24, max_backups: 7 },
|
|
14335
14364
|
limits: { max_atoms_per_project: 1e4, rate_limit_requests: 100, rate_limit_window_ms: 6e4 },
|
|
@@ -14352,8 +14381,8 @@ function mergeDeep2(target, source) {
|
|
|
14352
14381
|
}
|
|
14353
14382
|
return output;
|
|
14354
14383
|
}
|
|
14355
|
-
function loadConfig2(configPath) {
|
|
14356
|
-
const path = configPath ? (0, import_path4.resolve)(configPath) : (0, import_path4.resolve)(
|
|
14384
|
+
function loadConfig2(configPath, baseDir = process.cwd()) {
|
|
14385
|
+
const path = configPath ? (0, import_path4.resolve)(configPath) : (0, import_path4.resolve)(baseDir, "config.yaml");
|
|
14357
14386
|
if (!(0, import_fs4.existsSync)(path)) {
|
|
14358
14387
|
if (!configPath) console.warn("[Config] config.yaml not found, using defaults");
|
|
14359
14388
|
return defaultConfig2();
|
|
@@ -14369,23 +14398,237 @@ function loadConfig2(configPath) {
|
|
|
14369
14398
|
}
|
|
14370
14399
|
var MnemosyneConfig = class {
|
|
14371
14400
|
config;
|
|
14401
|
+
baseDir;
|
|
14372
14402
|
constructor(options) {
|
|
14373
|
-
this.
|
|
14403
|
+
this.baseDir = options?.baseDir || process.cwd();
|
|
14404
|
+
this.config = loadConfig2(options?.configPath, this.baseDir);
|
|
14374
14405
|
if (options?.overrides) {
|
|
14375
14406
|
this.config = mergeDeep2(this.config, options.overrides);
|
|
14376
14407
|
}
|
|
14377
14408
|
}
|
|
14378
14409
|
get dbPath() {
|
|
14379
|
-
return (0, import_path4.resolve)(
|
|
14410
|
+
return (0, import_path4.resolve)(this.baseDir, this.config.database.path);
|
|
14380
14411
|
}
|
|
14381
14412
|
get filesDir() {
|
|
14382
|
-
return (0, import_path4.resolve)(
|
|
14413
|
+
return (0, import_path4.resolve)(this.baseDir, this.config.storage.files_dir);
|
|
14383
14414
|
}
|
|
14384
14415
|
get backupsDir() {
|
|
14385
|
-
return (0, import_path4.resolve)(
|
|
14416
|
+
return (0, import_path4.resolve)(this.baseDir, this.config.storage.backups_dir);
|
|
14417
|
+
}
|
|
14418
|
+
get baseDirPath() {
|
|
14419
|
+
return this.baseDir;
|
|
14386
14420
|
}
|
|
14387
14421
|
};
|
|
14388
14422
|
|
|
14423
|
+
// src/db/schema.ts
|
|
14424
|
+
var SCHEMA_SQL = `-- Mnemosyne v1.1 Database Schema
|
|
14425
|
+
-- SQLite with sqlite-vec extension for semantic search
|
|
14426
|
+
|
|
14427
|
+
-- PROJECTS (Spaces)
|
|
14428
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
14429
|
+
id TEXT PRIMARY KEY,
|
|
14430
|
+
name TEXT NOT NULL UNIQUE,
|
|
14431
|
+
description TEXT,
|
|
14432
|
+
icon TEXT DEFAULT '\u25C9',
|
|
14433
|
+
color TEXT DEFAULT '#6366f1',
|
|
14434
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
14435
|
+
updated_at INTEGER DEFAULT (unixepoch()),
|
|
14436
|
+
owner TEXT DEFAULT 'human',
|
|
14437
|
+
metadata TEXT DEFAULT '{}'
|
|
14438
|
+
);
|
|
14439
|
+
|
|
14440
|
+
-- ATOMS (Ideas/Nodes)
|
|
14441
|
+
CREATE TABLE IF NOT EXISTS atoms (
|
|
14442
|
+
id TEXT PRIMARY KEY,
|
|
14443
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
14444
|
+
parent_id TEXT REFERENCES atoms(id) ON DELETE CASCADE,
|
|
14445
|
+
title TEXT NOT NULL,
|
|
14446
|
+
summary TEXT,
|
|
14447
|
+
icon TEXT DEFAULT '\u25CF',
|
|
14448
|
+
color TEXT,
|
|
14449
|
+
x REAL,
|
|
14450
|
+
y REAL,
|
|
14451
|
+
auto_path TEXT,
|
|
14452
|
+
path_overridden INTEGER DEFAULT 0,
|
|
14453
|
+
status TEXT DEFAULT 'draft',
|
|
14454
|
+
status_updated_at INTEGER DEFAULT (unixepoch()),
|
|
14455
|
+
embedding_status TEXT DEFAULT 'pending',
|
|
14456
|
+
embedding_error TEXT,
|
|
14457
|
+
block_count INTEGER DEFAULT 0,
|
|
14458
|
+
bond_count INTEGER DEFAULT 0,
|
|
14459
|
+
template_id TEXT,
|
|
14460
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
14461
|
+
updated_at INTEGER DEFAULT (unixepoch()),
|
|
14462
|
+
version INTEGER DEFAULT 1,
|
|
14463
|
+
locked_by TEXT,
|
|
14464
|
+
locked_at INTEGER,
|
|
14465
|
+
locked_reason TEXT,
|
|
14466
|
+
owner TEXT DEFAULT 'human',
|
|
14467
|
+
metadata TEXT DEFAULT '{}'
|
|
14468
|
+
);
|
|
14469
|
+
|
|
14470
|
+
-- BLOCKS (Content pieces inside atoms)
|
|
14471
|
+
CREATE TABLE IF NOT EXISTS blocks (
|
|
14472
|
+
id TEXT PRIMARY KEY,
|
|
14473
|
+
atom_id TEXT NOT NULL REFERENCES atoms(id) ON DELETE CASCADE,
|
|
14474
|
+
type TEXT NOT NULL DEFAULT 'text',
|
|
14475
|
+
content TEXT,
|
|
14476
|
+
order_index INTEGER DEFAULT 0,
|
|
14477
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
14478
|
+
updated_at INTEGER DEFAULT (unixepoch()),
|
|
14479
|
+
metadata TEXT DEFAULT '{}'
|
|
14480
|
+
);
|
|
14481
|
+
|
|
14482
|
+
-- BONDS (Graph connections between atoms)
|
|
14483
|
+
CREATE TABLE IF NOT EXISTS bonds (
|
|
14484
|
+
id TEXT PRIMARY KEY,
|
|
14485
|
+
source_id TEXT NOT NULL REFERENCES atoms(id) ON DELETE CASCADE,
|
|
14486
|
+
target_id TEXT NOT NULL REFERENCES atoms(id) ON DELETE CASCADE,
|
|
14487
|
+
label TEXT DEFAULT 'connects',
|
|
14488
|
+
color TEXT,
|
|
14489
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
14490
|
+
UNIQUE(source_id, target_id)
|
|
14491
|
+
);
|
|
14492
|
+
|
|
14493
|
+
-- ATTACHMENTS (Files in CAS)
|
|
14494
|
+
CREATE TABLE IF NOT EXISTS attachments (
|
|
14495
|
+
id TEXT PRIMARY KEY,
|
|
14496
|
+
block_id TEXT REFERENCES blocks(id) ON DELETE CASCADE,
|
|
14497
|
+
file_name TEXT NOT NULL,
|
|
14498
|
+
file_hash TEXT NOT NULL,
|
|
14499
|
+
file_size INTEGER,
|
|
14500
|
+
mime_type TEXT,
|
|
14501
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
14502
|
+
UNIQUE(file_hash)
|
|
14503
|
+
);
|
|
14504
|
+
|
|
14505
|
+
-- EVENT LOG (Immutable audit trail)
|
|
14506
|
+
CREATE TABLE IF NOT EXISTS event_log (
|
|
14507
|
+
id TEXT PRIMARY KEY,
|
|
14508
|
+
timestamp INTEGER DEFAULT (unixepoch()),
|
|
14509
|
+
event_type TEXT NOT NULL,
|
|
14510
|
+
project_id TEXT,
|
|
14511
|
+
atom_id TEXT,
|
|
14512
|
+
block_id TEXT,
|
|
14513
|
+
bond_id TEXT,
|
|
14514
|
+
actor TEXT NOT NULL DEFAULT 'system',
|
|
14515
|
+
actor_type TEXT DEFAULT 'system',
|
|
14516
|
+
diff TEXT,
|
|
14517
|
+
trigger TEXT,
|
|
14518
|
+
metadata TEXT DEFAULT '{}'
|
|
14519
|
+
);
|
|
14520
|
+
|
|
14521
|
+
-- ASSISTANTS (AI Agents)
|
|
14522
|
+
CREATE TABLE IF NOT EXISTS assistants (
|
|
14523
|
+
id TEXT PRIMARY KEY,
|
|
14524
|
+
name TEXT NOT NULL,
|
|
14525
|
+
role TEXT DEFAULT 'worker',
|
|
14526
|
+
permissions TEXT DEFAULT '{"read":["*"],"write":[],"delete":false}',
|
|
14527
|
+
status TEXT DEFAULT 'active',
|
|
14528
|
+
provider TEXT,
|
|
14529
|
+
connected_at INTEGER DEFAULT (unixepoch()),
|
|
14530
|
+
last_seen INTEGER DEFAULT (unixepoch()),
|
|
14531
|
+
metadata TEXT DEFAULT '{}'
|
|
14532
|
+
);
|
|
14533
|
+
|
|
14534
|
+
-- QUEUE (Agent waitlist for locked atoms)
|
|
14535
|
+
CREATE TABLE IF NOT EXISTS queue (
|
|
14536
|
+
id TEXT PRIMARY KEY,
|
|
14537
|
+
atom_id TEXT NOT NULL REFERENCES atoms(id) ON DELETE CASCADE,
|
|
14538
|
+
assistant_id TEXT NOT NULL REFERENCES assistants(id) ON DELETE CASCADE,
|
|
14539
|
+
requested_at INTEGER DEFAULT (unixepoch()),
|
|
14540
|
+
priority INTEGER DEFAULT 5,
|
|
14541
|
+
status TEXT DEFAULT 'waiting',
|
|
14542
|
+
reason TEXT
|
|
14543
|
+
);
|
|
14544
|
+
|
|
14545
|
+
-- INDICES
|
|
14546
|
+
CREATE INDEX IF NOT EXISTS idx_atoms_project ON atoms(project_id);
|
|
14547
|
+
CREATE INDEX IF NOT EXISTS idx_atoms_parent ON atoms(parent_id);
|
|
14548
|
+
CREATE INDEX IF NOT EXISTS idx_atoms_locked ON atoms(locked_by) WHERE locked_by IS NOT NULL;
|
|
14549
|
+
-- idx_atoms_path_project is created by migration after auto_path column is added
|
|
14550
|
+
CREATE INDEX IF NOT EXISTS idx_blocks_atom ON blocks(atom_id);
|
|
14551
|
+
CREATE INDEX IF NOT EXISTS idx_bonds_source ON bonds(source_id);
|
|
14552
|
+
CREATE INDEX IF NOT EXISTS idx_bonds_target ON bonds(target_id);
|
|
14553
|
+
CREATE INDEX IF NOT EXISTS idx_event_log_time ON event_log(timestamp);
|
|
14554
|
+
CREATE INDEX IF NOT EXISTS idx_event_log_atom ON event_log(atom_id);
|
|
14555
|
+
CREATE INDEX IF NOT EXISTS idx_queue_atom ON queue(atom_id);
|
|
14556
|
+
CREATE INDEX IF NOT EXISTS idx_attachments_hash ON attachments(file_hash);
|
|
14557
|
+
|
|
14558
|
+
-- Auto-update block_count and bond_count triggers
|
|
14559
|
+
CREATE TRIGGER IF NOT EXISTS update_block_count_insert AFTER INSERT ON blocks BEGIN
|
|
14560
|
+
UPDATE atoms SET block_count = block_count + 1 WHERE id = NEW.atom_id;
|
|
14561
|
+
END;
|
|
14562
|
+
|
|
14563
|
+
CREATE TRIGGER IF NOT EXISTS update_block_count_delete AFTER DELETE ON blocks BEGIN
|
|
14564
|
+
UPDATE atoms SET block_count = block_count - 1 WHERE id = OLD.atom_id;
|
|
14565
|
+
END;
|
|
14566
|
+
|
|
14567
|
+
CREATE TRIGGER IF NOT EXISTS update_bond_count_insert AFTER INSERT ON bonds BEGIN
|
|
14568
|
+
UPDATE atoms SET bond_count = bond_count + 1 WHERE id = NEW.source_id OR id = NEW.target_id;
|
|
14569
|
+
END;
|
|
14570
|
+
|
|
14571
|
+
CREATE TRIGGER IF NOT EXISTS update_bond_count_delete AFTER DELETE ON bonds BEGIN
|
|
14572
|
+
UPDATE atoms SET bond_count = bond_count - 1 WHERE id = OLD.source_id OR id = OLD.target_id;
|
|
14573
|
+
END;
|
|
14574
|
+
|
|
14575
|
+
-- FTS5 FULL-TEXT SEARCH
|
|
14576
|
+
-- Separate tables to avoid rowid collisions between atoms and blocks
|
|
14577
|
+
|
|
14578
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS search_atoms USING fts5(
|
|
14579
|
+
title, summary,
|
|
14580
|
+
content='atoms', content_rowid='rowid'
|
|
14581
|
+
);
|
|
14582
|
+
|
|
14583
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS search_blocks USING fts5(
|
|
14584
|
+
content,
|
|
14585
|
+
content='blocks', content_rowid='rowid'
|
|
14586
|
+
);
|
|
14587
|
+
|
|
14588
|
+
-- Triggers to keep search_atoms in sync
|
|
14589
|
+
CREATE TRIGGER IF NOT EXISTS trig_search_atoms_insert AFTER INSERT ON atoms BEGIN
|
|
14590
|
+
INSERT INTO search_atoms(rowid, title, summary) VALUES (new.rowid, new.title, COALESCE(new.summary, ''));
|
|
14591
|
+
END;
|
|
14592
|
+
|
|
14593
|
+
CREATE TRIGGER IF NOT EXISTS trig_search_atoms_update AFTER UPDATE ON atoms BEGIN
|
|
14594
|
+
UPDATE search_atoms SET title = new.title, summary = COALESCE(new.summary, '') WHERE rowid = new.rowid;
|
|
14595
|
+
END;
|
|
14596
|
+
|
|
14597
|
+
CREATE TRIGGER IF NOT EXISTS trig_search_atoms_delete AFTER DELETE ON atoms BEGIN
|
|
14598
|
+
DELETE FROM search_atoms WHERE rowid = old.rowid;
|
|
14599
|
+
END;
|
|
14600
|
+
|
|
14601
|
+
-- Triggers to keep search_blocks in sync
|
|
14602
|
+
CREATE TRIGGER IF NOT EXISTS trig_search_blocks_insert AFTER INSERT ON blocks BEGIN
|
|
14603
|
+
INSERT INTO search_blocks(rowid, content) VALUES (new.rowid, COALESCE(new.content, ''));
|
|
14604
|
+
END;
|
|
14605
|
+
|
|
14606
|
+
CREATE TRIGGER IF NOT EXISTS trig_search_blocks_update AFTER UPDATE ON blocks BEGIN
|
|
14607
|
+
UPDATE search_blocks SET content = COALESCE(new.content, '') WHERE rowid = new.rowid;
|
|
14608
|
+
END;
|
|
14609
|
+
|
|
14610
|
+
CREATE TRIGGER IF NOT EXISTS trig_search_blocks_delete AFTER DELETE ON blocks BEGIN
|
|
14611
|
+
DELETE FROM search_blocks WHERE rowid = old.rowid;
|
|
14612
|
+
END;
|
|
14613
|
+
|
|
14614
|
+
|
|
14615
|
+
-- PER-ATOM PERMISSIONS (Granular access control)
|
|
14616
|
+
CREATE TABLE IF NOT EXISTS atom_permissions (
|
|
14617
|
+
id TEXT PRIMARY KEY,
|
|
14618
|
+
atom_id TEXT NOT NULL REFERENCES atoms(id) ON DELETE CASCADE,
|
|
14619
|
+
assistant_id TEXT NOT NULL REFERENCES assistants(id) ON DELETE CASCADE,
|
|
14620
|
+
level TEXT NOT NULL DEFAULT 'view',
|
|
14621
|
+
granted_by TEXT,
|
|
14622
|
+
granted_at INTEGER DEFAULT (unixepoch()),
|
|
14623
|
+
metadata TEXT DEFAULT '{}',
|
|
14624
|
+
UNIQUE(atom_id, assistant_id)
|
|
14625
|
+
);
|
|
14626
|
+
|
|
14627
|
+
-- sqlite-vec virtual table for semantic embeddings
|
|
14628
|
+
-- Created dynamically by connection.ts after loading the extension
|
|
14629
|
+
-- CREATE VIRTUAL TABLE IF NOT EXISTS atom_vectors USING vec0(atom_id TEXT PRIMARY KEY, embedding float[384]);
|
|
14630
|
+
`;
|
|
14631
|
+
|
|
14389
14632
|
// src/core/Mnemosyne.ts
|
|
14390
14633
|
var Mnemosyne = class {
|
|
14391
14634
|
store;
|
|
@@ -14393,7 +14636,7 @@ var Mnemosyne = class {
|
|
|
14393
14636
|
vecEnabled;
|
|
14394
14637
|
db;
|
|
14395
14638
|
constructor(options = {}) {
|
|
14396
|
-
this.config = new MnemosyneConfig({ configPath: options.configPath });
|
|
14639
|
+
this.config = new MnemosyneConfig({ configPath: options.configPath, baseDir: options.baseDir });
|
|
14397
14640
|
const cfg = this.config.config;
|
|
14398
14641
|
const dbPath = options.dbPath || this.config.dbPath;
|
|
14399
14642
|
this.db = new import_better_sqlite32.default(dbPath);
|
|
@@ -14402,17 +14645,21 @@ var Mnemosyne = class {
|
|
|
14402
14645
|
this.db.pragma("synchronous = NORMAL");
|
|
14403
14646
|
this.vecEnabled = false;
|
|
14404
14647
|
try {
|
|
14405
|
-
|
|
14648
|
+
let vecPath;
|
|
14649
|
+
try {
|
|
14650
|
+
const sqliteVec = require("sqlite-vec");
|
|
14651
|
+
vecPath = sqliteVec.getLoadablePath();
|
|
14652
|
+
} catch {
|
|
14653
|
+
vecPath = (0, import_path5.resolve)(this.config.baseDirPath || process.cwd(), cfg.database.vec_extension_path);
|
|
14654
|
+
}
|
|
14406
14655
|
this.db.loadExtension(vecPath);
|
|
14407
14656
|
this.vecEnabled = true;
|
|
14408
14657
|
console.log("[DB] sqlite-vec extension loaded");
|
|
14409
14658
|
} catch (err) {
|
|
14410
14659
|
console.warn("[DB] sqlite-vec not available:", err.message);
|
|
14411
14660
|
}
|
|
14412
|
-
const schemaPath = (0, import_path5.resolve)(process.cwd(), "src", "db", "schema.sql");
|
|
14413
14661
|
try {
|
|
14414
|
-
|
|
14415
|
-
this.db.exec(schema);
|
|
14662
|
+
this.db.exec(SCHEMA_SQL);
|
|
14416
14663
|
} catch (err) {
|
|
14417
14664
|
console.error("[DB] Failed to load schema:", err.message);
|
|
14418
14665
|
}
|
|
@@ -14456,7 +14703,7 @@ var Mnemosyne = class {
|
|
|
14456
14703
|
|
|
14457
14704
|
// src/server/MnemosyneServer.ts
|
|
14458
14705
|
var import_http = require("http");
|
|
14459
|
-
var
|
|
14706
|
+
var import_fs6 = require("fs");
|
|
14460
14707
|
var import_path8 = require("path");
|
|
14461
14708
|
|
|
14462
14709
|
// node_modules/ws/wrapper.mjs
|
|
@@ -15611,21 +15858,21 @@ function handleFiles(store, pathname, method, req, res, maxFileSizeMb) {
|
|
|
15611
15858
|
// src/server/export-format.ts
|
|
15612
15859
|
var import_adm_zip2 = __toESM(require("adm-zip"));
|
|
15613
15860
|
var import_crypto2 = require("crypto");
|
|
15614
|
-
var
|
|
15861
|
+
var import_fs5 = require("fs");
|
|
15615
15862
|
var import_path6 = require("path");
|
|
15616
15863
|
var DB_PATH = (0, import_path6.resolve)(process.cwd(), "data", "nexus.db");
|
|
15617
15864
|
var FILES_DIR2 = (0, import_path6.resolve)(process.cwd(), "data", "files");
|
|
15618
15865
|
function sha256File(path) {
|
|
15619
|
-
return (0, import_crypto2.createHash)("sha256").update((0,
|
|
15866
|
+
return (0, import_crypto2.createHash)("sha256").update((0, import_fs5.readFileSync)(path)).digest("hex");
|
|
15620
15867
|
}
|
|
15621
15868
|
function sha256Dir(dir) {
|
|
15622
15869
|
const hash = (0, import_crypto2.createHash)("sha256");
|
|
15623
15870
|
function walk(p) {
|
|
15624
|
-
const stat = (0,
|
|
15871
|
+
const stat = (0, import_fs5.statSync)(p);
|
|
15625
15872
|
if (stat.isFile()) {
|
|
15626
|
-
hash.update((0,
|
|
15873
|
+
hash.update((0, import_fs5.readFileSync)(p));
|
|
15627
15874
|
} else if (stat.isDirectory()) {
|
|
15628
|
-
for (const child of (0,
|
|
15875
|
+
for (const child of (0, import_fs5.readdirSync)(p).sort()) walk((0, import_path6.resolve)(p, child));
|
|
15629
15876
|
}
|
|
15630
15877
|
}
|
|
15631
15878
|
walk(dir);
|
|
@@ -15634,11 +15881,11 @@ function sha256Dir(dir) {
|
|
|
15634
15881
|
function buildMnemosyneExport(projectId, projectName) {
|
|
15635
15882
|
const zip = new import_adm_zip2.default();
|
|
15636
15883
|
zip.addLocalFile(DB_PATH, "", "nexus.db");
|
|
15637
|
-
if ((0,
|
|
15884
|
+
if ((0, import_fs5.existsSync)(FILES_DIR2)) {
|
|
15638
15885
|
zip.addLocalFolder(FILES_DIR2, "files");
|
|
15639
15886
|
}
|
|
15640
15887
|
const dbChecksum = sha256File(DB_PATH);
|
|
15641
|
-
const filesChecksum = (0,
|
|
15888
|
+
const filesChecksum = (0, import_fs5.existsSync)(FILES_DIR2) ? sha256Dir(FILES_DIR2) : "";
|
|
15642
15889
|
const manifest = {
|
|
15643
15890
|
version: "1.1",
|
|
15644
15891
|
app: "Mnemosyne",
|
|
@@ -15764,12 +16011,20 @@ function handleEvents(store, pathname, method, res, searchParams) {
|
|
|
15764
16011
|
}
|
|
15765
16012
|
|
|
15766
16013
|
// src/api/routes/health.ts
|
|
16014
|
+
var PKG_VERSION = (() => {
|
|
16015
|
+
try {
|
|
16016
|
+
const pkg = JSON.parse(require("fs").readFileSync(require("path").resolve(__dirname, "../../../package.json"), "utf-8"));
|
|
16017
|
+
return pkg.version;
|
|
16018
|
+
} catch {
|
|
16019
|
+
return "2.0.1";
|
|
16020
|
+
}
|
|
16021
|
+
})();
|
|
15767
16022
|
function handleHealth(store, pathname, method, res) {
|
|
15768
|
-
if (pathname === "/health" && method === "GET") {
|
|
16023
|
+
if ((pathname === "/health" || pathname === "/api/v1/health") && method === "GET") {
|
|
15769
16024
|
const stats = store.getStats();
|
|
15770
16025
|
json(res, 200, {
|
|
15771
16026
|
status: "ok",
|
|
15772
|
-
version:
|
|
16027
|
+
version: PKG_VERSION,
|
|
15773
16028
|
storage: "sqlite",
|
|
15774
16029
|
database: store.config.database.path,
|
|
15775
16030
|
uptime: process.uptime(),
|
|
@@ -15994,7 +16249,6 @@ var WebSocketHandler = class {
|
|
|
15994
16249
|
|
|
15995
16250
|
// src/db/connection.ts
|
|
15996
16251
|
var import_better_sqlite33 = __toESM(require("better-sqlite3"));
|
|
15997
|
-
var import_fs7 = require("fs");
|
|
15998
16252
|
var import_path7 = require("path");
|
|
15999
16253
|
init_config();
|
|
16000
16254
|
var DB_PATH2 = process.env.MNEMOSYNE_DB_PATH || (0, import_path7.resolve)(process.cwd(), CONFIG.database.path);
|
|
@@ -16015,8 +16269,7 @@ function getDb() {
|
|
|
16015
16269
|
console.warn("[DB] sqlite-vec not available:", err.message);
|
|
16016
16270
|
vecEnabled = false;
|
|
16017
16271
|
}
|
|
16018
|
-
|
|
16019
|
-
db.exec(schema);
|
|
16272
|
+
db.exec(SCHEMA_SQL);
|
|
16020
16273
|
if (vecEnabled) {
|
|
16021
16274
|
try {
|
|
16022
16275
|
db.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS atom_vectors USING vec0(atom_id TEXT PRIMARY KEY, embedding float[${CONFIG.embeddings.dimension}])`);
|
|
@@ -16048,7 +16301,6 @@ var Store2 = class extends Store {
|
|
|
16048
16301
|
};
|
|
16049
16302
|
|
|
16050
16303
|
// src/server/MnemosyneServer.ts
|
|
16051
|
-
init_config();
|
|
16052
16304
|
var MnemosyneServer = class {
|
|
16053
16305
|
store;
|
|
16054
16306
|
api;
|
|
@@ -16056,8 +16308,9 @@ var MnemosyneServer = class {
|
|
|
16056
16308
|
httpServer;
|
|
16057
16309
|
brain;
|
|
16058
16310
|
constructor(options = {}, brain) {
|
|
16059
|
-
const
|
|
16060
|
-
const
|
|
16311
|
+
const cfg = brain?.config?.config;
|
|
16312
|
+
const port = options.port ?? cfg?.server?.port ?? 7321;
|
|
16313
|
+
const host = options.host ?? cfg?.server?.host ?? "localhost";
|
|
16061
16314
|
const enableDashboard = options.dashboard !== false;
|
|
16062
16315
|
const enableWebsocket = options.websocket !== false;
|
|
16063
16316
|
process.on("uncaughtException", (err) => {
|
|
@@ -16085,8 +16338,9 @@ var MnemosyneServer = class {
|
|
|
16085
16338
|
const wss = new import_websocket_server.default({ server: this.httpServer });
|
|
16086
16339
|
this.wsHandler = new WebSocketHandler(wss, this.store);
|
|
16087
16340
|
}
|
|
16341
|
+
const version = cfg?.server?.version || "2.0.1";
|
|
16088
16342
|
this.httpServer.listen(port, () => {
|
|
16089
|
-
console.log(`Mnemosyne v${
|
|
16343
|
+
console.log(`Mnemosyne v${version} \u2014 port ${port}`);
|
|
16090
16344
|
console.log(`Dashboard: http://${host}:${port}/dashboard`);
|
|
16091
16345
|
console.log(`API: http://${host}:${port}/api/v1`);
|
|
16092
16346
|
console.log(`MCP: http://${host}:${port}/mcp/manifest`);
|
|
@@ -16111,12 +16365,13 @@ var MnemosyneServer = class {
|
|
|
16111
16365
|
};
|
|
16112
16366
|
const dirs = [
|
|
16113
16367
|
(0, import_path8.resolve)(process.cwd(), "src/dashboard"),
|
|
16114
|
-
(0, import_path8.resolve)(process.cwd(), "dashboard")
|
|
16368
|
+
(0, import_path8.resolve)(process.cwd(), "dashboard"),
|
|
16369
|
+
(0, import_path8.resolve)(__dirname, "../dashboard")
|
|
16115
16370
|
];
|
|
16116
16371
|
for (const dir of dirs) {
|
|
16117
16372
|
const filePath = (0, import_path8.resolve)(dir, urlPath);
|
|
16118
|
-
if ((0,
|
|
16119
|
-
const data = (0,
|
|
16373
|
+
if ((0, import_fs6.existsSync)(filePath)) {
|
|
16374
|
+
const data = (0, import_fs6.readFileSync)(filePath);
|
|
16120
16375
|
res.writeHead(200, { "Content-Type": mime[ext] || "application/octet-stream" });
|
|
16121
16376
|
res.end(data);
|
|
16122
16377
|
return;
|
|
@@ -16138,7 +16393,7 @@ var MnemosyneServer = class {
|
|
|
16138
16393
|
async function startCommand(options) {
|
|
16139
16394
|
const dataDir = (0, import_path9.resolve)(options.dataDir);
|
|
16140
16395
|
const dbPath = (0, import_path9.resolve)(dataDir, "nexus.db");
|
|
16141
|
-
const brain = new Mnemosyne({ dbPath, configPath: options.config });
|
|
16396
|
+
const brain = new Mnemosyne({ dbPath, configPath: options.config, baseDir: dataDir });
|
|
16142
16397
|
await brain.init();
|
|
16143
16398
|
if (options.mcpTransport === "stdio" && options.mcp) {
|
|
16144
16399
|
if (options.verbose) {
|
|
@@ -16182,7 +16437,7 @@ ${signal} received. Shutting down...`);
|
|
|
16182
16437
|
|
|
16183
16438
|
// src/cli/commands/init.ts
|
|
16184
16439
|
var import_path10 = require("path");
|
|
16185
|
-
var
|
|
16440
|
+
var import_fs7 = require("fs");
|
|
16186
16441
|
var DEFAULT_CONFIG = `database:
|
|
16187
16442
|
path: ./data/nexus.db
|
|
16188
16443
|
wal: true
|
|
@@ -16207,28 +16462,28 @@ server:
|
|
|
16207
16462
|
async function initCommand(options) {
|
|
16208
16463
|
const dataDir = (0, import_path10.resolve)(options.dataDir);
|
|
16209
16464
|
const configPath = options.config ? (0, import_path10.resolve)(options.config) : (0, import_path10.resolve)(dataDir, "config.yaml");
|
|
16210
|
-
if ((0,
|
|
16465
|
+
if ((0, import_fs7.existsSync)(dataDir)) {
|
|
16211
16466
|
console.log(`\u{1F4C1} Data directory already exists: ${dataDir}`);
|
|
16212
16467
|
} else {
|
|
16213
|
-
(0,
|
|
16468
|
+
(0, import_fs7.mkdirSync)(dataDir, { recursive: true });
|
|
16214
16469
|
console.log(`\u2705 Created data directory: ${dataDir}`);
|
|
16215
16470
|
}
|
|
16216
16471
|
for (const sub of ["backups", "files", "exports"]) {
|
|
16217
16472
|
const dir = (0, import_path10.resolve)(dataDir, sub);
|
|
16218
|
-
if (!(0,
|
|
16219
|
-
(0,
|
|
16473
|
+
if (!(0, import_fs7.existsSync)(dir)) {
|
|
16474
|
+
(0, import_fs7.mkdirSync)(dir, { recursive: true });
|
|
16220
16475
|
console.log(`\u2705 Created ${sub}/`);
|
|
16221
16476
|
}
|
|
16222
16477
|
}
|
|
16223
|
-
if (!(0,
|
|
16224
|
-
(0,
|
|
16478
|
+
if (!(0, import_fs7.existsSync)(configPath)) {
|
|
16479
|
+
(0, import_fs7.writeFileSync)(configPath, DEFAULT_CONFIG, "utf-8");
|
|
16225
16480
|
console.log(`\u2705 Created config: ${configPath}`);
|
|
16226
16481
|
} else {
|
|
16227
16482
|
console.log(`\u{1F4C4} Config already exists: ${configPath}`);
|
|
16228
16483
|
}
|
|
16229
16484
|
const dbPath = (0, import_path10.resolve)(dataDir, "nexus.db");
|
|
16230
|
-
if (!(0,
|
|
16231
|
-
const brain = new Mnemosyne({ dbPath, configPath });
|
|
16485
|
+
if (!(0, import_fs7.existsSync)(dbPath)) {
|
|
16486
|
+
const brain = new Mnemosyne({ dbPath, configPath, baseDir: dataDir });
|
|
16232
16487
|
await brain.init();
|
|
16233
16488
|
await brain.close();
|
|
16234
16489
|
console.log(`\u2705 Initialized database: ${dbPath}`);
|
|
@@ -16242,14 +16497,14 @@ async function initCommand(options) {
|
|
|
16242
16497
|
|
|
16243
16498
|
// src/cli/commands/migrate.ts
|
|
16244
16499
|
var import_path11 = require("path");
|
|
16245
|
-
var
|
|
16500
|
+
var import_fs8 = require("fs");
|
|
16246
16501
|
async function migrateCommand(options) {
|
|
16247
16502
|
const fromPath = (0, import_path11.resolve)(options.from);
|
|
16248
16503
|
const toPath = (0, import_path11.resolve)(options.to);
|
|
16249
16504
|
console.log(`\u{1F504} Migrating v1.0 JSON \u2192 v2.0 SQLite`);
|
|
16250
16505
|
console.log(` From: ${fromPath}`);
|
|
16251
16506
|
console.log(` To: ${toPath}`);
|
|
16252
|
-
const raw = (0,
|
|
16507
|
+
const raw = (0, import_fs8.readFileSync)(fromPath, "utf-8");
|
|
16253
16508
|
const v1 = JSON.parse(raw);
|
|
16254
16509
|
const brain = new Mnemosyne({ dbPath: toPath });
|
|
16255
16510
|
await brain.init();
|
|
@@ -16300,7 +16555,7 @@ async function migrateCommand(options) {
|
|
|
16300
16555
|
|
|
16301
16556
|
// src/cli/commands/export.ts
|
|
16302
16557
|
var import_path12 = require("path");
|
|
16303
|
-
var
|
|
16558
|
+
var import_fs9 = require("fs");
|
|
16304
16559
|
async function exportCommand(options) {
|
|
16305
16560
|
const dataDir = (0, import_path12.resolve)(options.dataDir || "./data");
|
|
16306
16561
|
const format = options.format || "mnemosyne";
|
|
@@ -16316,12 +16571,12 @@ async function exportCommand(options) {
|
|
|
16316
16571
|
if (format === "mnemosyne") {
|
|
16317
16572
|
const buffer = buildMnemosyneExport(project.id, project.name);
|
|
16318
16573
|
const outPath = output || (0, import_path12.resolve)(`${project.name}.mnemosyne`);
|
|
16319
|
-
(0,
|
|
16574
|
+
(0, import_fs9.writeFileSync)(outPath, buffer);
|
|
16320
16575
|
console.log(`\u2705 Exported to ${outPath} (${buffer.length} bytes)`);
|
|
16321
16576
|
} else if (format === "markdown") {
|
|
16322
16577
|
const md = exportMarkdown(brain.store, project.id);
|
|
16323
16578
|
const outPath = output || (0, import_path12.resolve)(`${project.name}.md`);
|
|
16324
|
-
(0,
|
|
16579
|
+
(0, import_fs9.writeFileSync)(outPath, md, "utf-8");
|
|
16325
16580
|
console.log(`\u2705 Exported to ${outPath} (${md.length} chars)`);
|
|
16326
16581
|
} else {
|
|
16327
16582
|
console.error(`\u274C Unsupported format: ${format}`);
|