context-vault 2.3.0 → 2.4.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.
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * postinstall.js — Auto-rebuild native modules on install
5
+ *
6
+ * Detects NODE_MODULE_VERSION mismatches and attempts a rebuild.
7
+ */
8
+
9
+ import { execSync } from "node:child_process";
10
+
11
+ async function main() {
12
+ let needsRebuild = false;
13
+
14
+ try {
15
+ await import("better-sqlite3");
16
+ } catch (e) {
17
+ if (e.message?.includes("NODE_MODULE_VERSION")) {
18
+ needsRebuild = true;
19
+ }
20
+ }
21
+
22
+ try {
23
+ await import("sqlite-vec");
24
+ } catch (e) {
25
+ if (e.message?.includes("NODE_MODULE_VERSION")) {
26
+ needsRebuild = true;
27
+ }
28
+ }
29
+
30
+ if (needsRebuild) {
31
+ console.log("[context-vault] Rebuilding native modules for Node.js " + process.version + "...");
32
+ try {
33
+ execSync("npm rebuild better-sqlite3 sqlite-vec", {
34
+ stdio: "inherit",
35
+ timeout: 60000,
36
+ });
37
+ console.log("[context-vault] Native modules rebuilt successfully.");
38
+ } catch {
39
+ console.error("[context-vault] Warning: native module rebuild failed.");
40
+ console.error("[context-vault] Try manually: npm rebuild better-sqlite3 sqlite-vec");
41
+ }
42
+ }
43
+ }
44
+
45
+ main().catch(() => {});
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * prepack.js — Cross-platform bundle preparation
5
+ *
6
+ * Copies @context-vault/core into node_modules for npm pack bundling.
7
+ * Replaces the Unix shell script in package.json "prepack".
8
+ */
9
+
10
+ import { cpSync, rmSync, mkdirSync } from "node:fs";
11
+ import { join, dirname } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const LOCAL_ROOT = join(__dirname, "..");
16
+ const CORE_SRC = join(LOCAL_ROOT, "..", "core");
17
+ const CORE_DEST = join(LOCAL_ROOT, "node_modules", "@context-vault", "core");
18
+
19
+ // Ensure target directory exists
20
+ mkdirSync(join(LOCAL_ROOT, "node_modules", "@context-vault"), { recursive: true });
21
+
22
+ // Remove old copy if present
23
+ rmSync(CORE_DEST, { recursive: true, force: true });
24
+
25
+ // Copy core package (dereference symlinks)
26
+ cpSync(CORE_SRC, CORE_DEST, { recursive: true, dereference: true });
27
+
28
+ // Remove nested node_modules from the copy
29
+ rmSync(join(CORE_DEST, "node_modules"), { recursive: true, force: true });
30
+
31
+ console.log("[prepack] Bundled @context-vault/core into node_modules");
@@ -11,89 +11,131 @@ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "..", "package.json"),
11
11
 
12
12
  import { resolveConfig } from "@context-vault/core/core/config";
13
13
  import { embed } from "@context-vault/core/index/embed";
14
- import { initDatabase, prepareStatements, insertVec, deleteVec } from "@context-vault/core/index/db";
14
+ import { initDatabase, NativeModuleError, prepareStatements, insertVec, deleteVec } from "@context-vault/core/index/db";
15
15
  import { registerTools } from "@context-vault/core/server/tools";
16
16
 
17
- // ─── Config Resolution ──────────────────────────────────────────────────────
17
+ // ─── Phased Startup ─────────────────────────────────────────────────────────
18
18
 
19
- const config = resolveConfig();
19
+ async function main() {
20
+ let phase = "CONFIG";
21
+ let db;
20
22
 
21
- // Create directories
22
- mkdirSync(config.dataDir, { recursive: true });
23
- mkdirSync(config.vaultDir, { recursive: true });
23
+ try {
24
+ // ── Phase: CONFIG ────────────────────────────────────────────────────────
25
+ const config = resolveConfig();
24
26
 
25
- // Write .context-mcp marker (always update to reflect current version)
26
- const markerPath = join(config.vaultDir, ".context-mcp");
27
- const markerData = existsSync(markerPath) ? JSON.parse(readFileSync(markerPath, "utf-8")) : {};
28
- writeFileSync(markerPath, JSON.stringify({ created: markerData.created || new Date().toISOString(), version: pkg.version }, null, 2) + "\n");
27
+ // ── Phase: DIRS ──────────────────────────────────────────────────────────
28
+ phase = "DIRS";
29
+ mkdirSync(config.dataDir, { recursive: true });
30
+ mkdirSync(config.vaultDir, { recursive: true });
29
31
 
30
- // Update existence flag after directory creation
31
- config.vaultDirExists = existsSync(config.vaultDir);
32
-
33
- // Startup diagnostics
34
- console.error(`[context-mcp] Vault: ${config.vaultDir}`);
35
- console.error(`[context-mcp] Database: ${config.dbPath}`);
36
- console.error(`[context-mcp] Dev dir: ${config.devDir}`);
37
- if (!config.vaultDirExists) {
38
- console.error(`[context-mcp] WARNING: Vault directory not found!`);
32
+ // Write .context-mcp marker (non-fatal)
33
+ try {
34
+ const markerPath = join(config.vaultDir, ".context-mcp");
35
+ const markerData = existsSync(markerPath) ? JSON.parse(readFileSync(markerPath, "utf-8")) : {};
36
+ writeFileSync(markerPath, JSON.stringify({ created: markerData.created || new Date().toISOString(), version: pkg.version }, null, 2) + "\n");
37
+ } catch (markerErr) {
38
+ console.error(`[context-mcp] Warning: could not write marker file: ${markerErr.message}`);
39
+ }
40
+
41
+ config.vaultDirExists = existsSync(config.vaultDir);
42
+
43
+ // Startup diagnostics
44
+ console.error(`[context-mcp] Vault: ${config.vaultDir}`);
45
+ console.error(`[context-mcp] Database: ${config.dbPath}`);
46
+ console.error(`[context-mcp] Dev dir: ${config.devDir}`);
47
+ if (!config.vaultDirExists) {
48
+ console.error(`[context-mcp] WARNING: Vault directory not found!`);
49
+ }
50
+
51
+ // ── Phase: DB ────────────────────────────────────────────────────────────
52
+ phase = "DB";
53
+ db = await initDatabase(config.dbPath);
54
+ const stmts = prepareStatements(db);
55
+
56
+ const ctx = {
57
+ db,
58
+ config,
59
+ stmts,
60
+ embed,
61
+ insertVec: (rowid, embedding) => insertVec(stmts, rowid, embedding),
62
+ deleteVec: (rowid) => deleteVec(stmts, rowid),
63
+ };
64
+
65
+ // ── Phase: SERVER ────────────────────────────────────────────────────────
66
+ phase = "SERVER";
67
+ const server = new McpServer(
68
+ { name: "context-mcp", version: pkg.version },
69
+ { capabilities: { tools: {} } }
70
+ );
71
+
72
+ registerTools(server, ctx);
73
+
74
+ // ── Graceful Shutdown ────────────────────────────────────────────────────
75
+ function shutdown(signal) {
76
+ console.error(`[context-mcp] Received ${signal}, shutting down...`);
77
+ try {
78
+ if (db.inTransaction) {
79
+ console.error("[context-mcp] Rolling back active transaction...");
80
+ db.exec("ROLLBACK");
81
+ }
82
+ db.pragma("wal_checkpoint(TRUNCATE)");
83
+ db.close();
84
+ console.error("[context-mcp] Database closed cleanly.");
85
+ } catch (shutdownErr) {
86
+ console.error(`[context-mcp] Shutdown error: ${shutdownErr.message}`);
87
+ }
88
+ process.exit(0);
89
+ }
90
+ process.on("SIGINT", () => shutdown("SIGINT"));
91
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
92
+
93
+ // ── Phase: CONNECTED ─────────────────────────────────────────────────────
94
+ phase = "CONNECTED";
95
+ const transport = new StdioServerTransport();
96
+ await server.connect(transport);
97
+
98
+ // ── Non-blocking Update Check ────────────────────────────────────────────
99
+ setTimeout(() => {
100
+ import("node:child_process").then(({ execSync }) => {
101
+ try {
102
+ const latest = execSync("npm view context-vault version", {
103
+ encoding: "utf-8",
104
+ timeout: 5000,
105
+ stdio: ["pipe", "pipe", "pipe"],
106
+ }).trim();
107
+ if (latest && latest !== pkg.version) {
108
+ console.error(`[context-mcp] Update available: v${pkg.version} → v${latest}. Run: context-mcp update`);
109
+ }
110
+ } catch {}
111
+ }).catch(() => {});
112
+ }, 3000);
113
+
114
+ } catch (err) {
115
+ if (err instanceof NativeModuleError) {
116
+ // Boxed diagnostic for native module mismatch
117
+ console.error("");
118
+ console.error("╔══════════════════════════════════════════════════════════════╗");
119
+ console.error("║ context-mcp: Native Module Error ║");
120
+ console.error("╚══════════════════════════════════════════════════════════════╝");
121
+ console.error("");
122
+ console.error(err.message);
123
+ console.error("");
124
+ console.error(` Node.js path: ${process.execPath}`);
125
+ console.error(` Node.js version: ${process.version}`);
126
+ console.error("");
127
+ process.exit(78); // EX_CONFIG
128
+ }
129
+
130
+ console.error(`[context-mcp] Fatal error during ${phase} phase: ${err.message}`);
131
+ if (phase === "DB") {
132
+ console.error(`[context-mcp] Try deleting the DB file and restarting: rm "${err.dbPath || "vault.db"}"`);
133
+ }
134
+ process.exit(1);
135
+ }
39
136
  }
40
137
 
41
- // ─── Database Init ───────────────────────────────────────────────────────────
42
-
43
- let db, stmts;
44
- try {
45
- db = initDatabase(config.dbPath);
46
- stmts = prepareStatements(db);
47
- } catch (e) {
48
- console.error(`[context-mcp] Database init failed: ${e.message}`);
49
- console.error(`[context-mcp] DB path: ${config.dbPath}`);
50
- console.error(`[context-mcp] Try deleting the DB file and restarting: rm "${config.dbPath}"`);
138
+ main().catch((err) => {
139
+ console.error(`[context-mcp] Unexpected fatal error: ${err.message}`);
51
140
  process.exit(1);
52
- }
53
-
54
- const ctx = {
55
- db,
56
- config,
57
- stmts,
58
- embed,
59
- insertVec: (rowid, embedding) => insertVec(stmts, rowid, embedding),
60
- deleteVec: (rowid) => deleteVec(stmts, rowid),
61
- };
62
-
63
- // ─── MCP Server ──────────────────────────────────────────────────────────────
64
-
65
- const server = new McpServer(
66
- { name: "context-mcp", version: pkg.version },
67
- { capabilities: { tools: {} } }
68
- );
69
-
70
- registerTools(server, ctx);
71
-
72
- // ─── Graceful Shutdown ───────────────────────────────────────────────────────
73
-
74
- function shutdown() {
75
- try { db.close(); } catch {}
76
- process.exit(0);
77
- }
78
- process.on("SIGINT", shutdown);
79
- process.on("SIGTERM", shutdown);
80
-
81
- const transport = new StdioServerTransport();
82
- await server.connect(transport);
83
-
84
- // ─── Non-blocking Update Check ──────────────────────────────────────────────
85
-
86
- setTimeout(() => {
87
- import("node:child_process").then(({ execSync }) => {
88
- try {
89
- const latest = execSync("npm view context-vault version", {
90
- encoding: "utf-8",
91
- timeout: 5000,
92
- stdio: ["pipe", "pipe", "pipe"],
93
- }).trim();
94
- if (latest && latest !== pkg.version) {
95
- console.error(`[context-mcp] Update available: v${pkg.version} → v${latest}. Run: context-mcp update`);
96
- }
97
- } catch {}
98
- }).catch(() => {});
99
- }, 3000);
141
+ });