@context-vault/core 3.2.1 → 3.2.3

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/db.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,aAAa,EAAE,KAAK,CAAC;gBACT,aAAa,EAAE,KAAK;CAMjC;AAkCD,eAAO,MAAM,UAAU,szEAoDtB,CAAC;AAIF,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAmExE;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,GAAG,kBAAkB,CAiCtE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI,CAIjG;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAOxD"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAiDrD,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,aAAa,EAAE,KAAK,CAAC;gBACT,aAAa,EAAE,KAAK;CAMjC;AAkCD,eAAO,MAAM,UAAU,szEAoDtB,CAAC;AAIF,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAyExE;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,YAAY,GAAG,kBAAkB,CAiCtE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI,CAIjG;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAOxD"}
package/dist/db.js CHANGED
@@ -1,5 +1,60 @@
1
- import { unlinkSync, copyFileSync, existsSync } from 'node:fs';
1
+ import { unlinkSync, copyFileSync, existsSync, openSync, closeSync, mkdirSync, statSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
2
3
  import { DatabaseSync } from 'node:sqlite';
4
+ /**
5
+ * Acquire an exclusive file lock to serialize database initialization.
6
+ * Multiple MCP clients (Claude, Cursor, Windsurf) may each spawn a server
7
+ * instance simultaneously — without serialization, migrations and schema
8
+ * init race against each other.
9
+ *
10
+ * Uses O_EXCL (via 'wx' flag) as a cross-platform advisory lock.
11
+ * Returns a release function that removes the lock file.
12
+ */
13
+ function acquireInitLock(dbPath, timeoutMs = 10_000) {
14
+ const lockPath = dbPath + '.init-lock';
15
+ mkdirSync(dirname(lockPath), { recursive: true });
16
+ const start = Date.now();
17
+ while (true) {
18
+ try {
19
+ const fd = openSync(lockPath, 'wx');
20
+ closeSync(fd);
21
+ return () => {
22
+ try {
23
+ unlinkSync(lockPath);
24
+ }
25
+ catch { }
26
+ };
27
+ }
28
+ catch (err) {
29
+ if (err.code !== 'EEXIST')
30
+ throw err;
31
+ // Stale lock detection — if lock file is older than 30s, it's from a crashed process
32
+ try {
33
+ const { mtimeMs } = statSync(lockPath);
34
+ if (Date.now() - mtimeMs > 30_000) {
35
+ try {
36
+ unlinkSync(lockPath);
37
+ }
38
+ catch { }
39
+ continue;
40
+ }
41
+ }
42
+ catch { }
43
+ if (Date.now() - start > timeoutMs) {
44
+ // Timeout — break the lock and proceed (better than hanging forever)
45
+ console.error('[context-vault] Init lock timed out, breaking stale lock');
46
+ try {
47
+ unlinkSync(lockPath);
48
+ }
49
+ catch { }
50
+ continue;
51
+ }
52
+ // Busy-wait with small sleep (synchronous — we're in sync init code)
53
+ const waitMs = 50 + Math.random() * 100;
54
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, waitMs);
55
+ }
56
+ }
57
+ }
3
58
  export class NativeModuleError extends Error {
4
59
  originalError;
5
60
  constructor(originalError) {
@@ -99,7 +154,7 @@ export async function initDatabase(dbPath) {
99
154
  const db = new DatabaseSync(path, { allowExtension: true });
100
155
  db.exec('PRAGMA journal_mode = WAL');
101
156
  db.exec('PRAGMA foreign_keys = ON');
102
- db.exec('PRAGMA busy_timeout = 3000');
157
+ db.exec('PRAGMA busy_timeout = 5000');
103
158
  try {
104
159
  sqliteVec.load(db);
105
160
  }
@@ -108,50 +163,57 @@ export async function initDatabase(dbPath) {
108
163
  }
109
164
  return db;
110
165
  }
111
- const db = createDb(dbPath);
112
- const version = db.prepare('PRAGMA user_version').get()
113
- .user_version;
114
- if (version > 0 && version < 15) {
115
- console.error(`[context-vault] Schema v${version} is outdated. Rebuilding database...`);
116
- const backupPath = `${dbPath}.v${version}.backup`;
117
- let backupSucceeded = false;
118
- try {
119
- db.close();
120
- if (existsSync(dbPath)) {
121
- copyFileSync(dbPath, backupPath);
122
- console.error(`[context-vault] Backed up old database to: ${backupPath}`);
123
- backupSucceeded = true;
166
+ // Serialize init across concurrent server instances (Claude + Cursor + Windsurf)
167
+ const releaseLock = acquireInitLock(dbPath);
168
+ try {
169
+ const db = createDb(dbPath);
170
+ const version = db.prepare('PRAGMA user_version').get()
171
+ .user_version;
172
+ if (version > 0 && version < 15) {
173
+ console.error(`[context-vault] Schema v${version} is outdated. Rebuilding database...`);
174
+ const backupPath = `${dbPath}.v${version}.backup`;
175
+ let backupSucceeded = false;
176
+ try {
177
+ db.close();
178
+ if (existsSync(dbPath)) {
179
+ copyFileSync(dbPath, backupPath);
180
+ console.error(`[context-vault] Backed up old database to: ${backupPath}`);
181
+ backupSucceeded = true;
182
+ }
183
+ else {
184
+ backupSucceeded = true;
185
+ }
124
186
  }
125
- else {
126
- backupSucceeded = true;
187
+ catch (backupErr) {
188
+ console.error(`[context-vault] Warning: could not backup old database: ${backupErr.message}`);
127
189
  }
190
+ if (!backupSucceeded) {
191
+ throw new Error(`[context-vault] Aborting schema migration: backup failed for ${dbPath}. ` +
192
+ `Fix the backup issue or manually back up the file before upgrading.`);
193
+ }
194
+ unlinkSync(dbPath);
195
+ try {
196
+ unlinkSync(dbPath + '-wal');
197
+ }
198
+ catch { }
199
+ try {
200
+ unlinkSync(dbPath + '-shm');
201
+ }
202
+ catch { }
203
+ const freshDb = createDb(dbPath);
204
+ freshDb.exec(SCHEMA_DDL);
205
+ freshDb.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
206
+ return freshDb;
128
207
  }
129
- catch (backupErr) {
130
- console.error(`[context-vault] Warning: could not backup old database: ${backupErr.message}`);
131
- }
132
- if (!backupSucceeded) {
133
- throw new Error(`[context-vault] Aborting schema migration: backup failed for ${dbPath}. ` +
134
- `Fix the backup issue or manually back up the file before upgrading.`);
135
- }
136
- unlinkSync(dbPath);
137
- try {
138
- unlinkSync(dbPath + '-wal');
139
- }
140
- catch { }
141
- try {
142
- unlinkSync(dbPath + '-shm');
208
+ if (version < 15) {
209
+ db.exec(SCHEMA_DDL);
210
+ db.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
143
211
  }
144
- catch { }
145
- const freshDb = createDb(dbPath);
146
- freshDb.exec(SCHEMA_DDL);
147
- freshDb.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
148
- return freshDb;
212
+ return db;
149
213
  }
150
- if (version < 15) {
151
- db.exec(SCHEMA_DDL);
152
- db.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
214
+ finally {
215
+ releaseLock();
153
216
  }
154
- return db;
155
217
  }
156
218
  export function prepareStatements(db) {
157
219
  try {
package/dist/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,aAAa,CAAQ;IACrB,YAAY,aAAoB;QAC9B,MAAM,UAAU,GAAG,uBAAuB,CAAC,aAAa,CAAC,CAAC;QAC1D,KAAK,CAAC,UAAU,CAAC,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF;AAED,SAAS,uBAAuB,CAAC,GAAU;IACzC,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC;IAC9B,OAAO;QACL,wCAAwC,GAAG,EAAE;QAC7C,EAAE;QACF,sBAAsB,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG;QAC7D,EAAE;QACF,iCAAiC;QACjC,uCAAuC;KACxC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,IAAI,UAAU,GAAgD,IAAI,CAAC;AAEnE,KAAK,UAAU,aAAa;IAC1B,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAClC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1C,UAAU,GAAG,MAAM,CAAC;IACpB,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,cAAc,CAAC,EAAgB,EAAE,EAAc;IACtD,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjB,IAAI,CAAC;QACH,EAAE,EAAE,CAAC;QACL,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpB,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDzB,CAAC;AAEF,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc;IAC/C,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAC;IAExC,SAAS,QAAQ,CAAC,IAAY;QAC5B,MAAM,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACrC,EAAE,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACpC,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,IAAI,iBAAiB,CAAC,CAAU,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,OAAO,GAAI,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAA+B;SAClF,YAAY,CAAC;IAEhB,IAAI,OAAO,GAAG,CAAC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,2BAA2B,OAAO,sCAAsC,CAAC,CAAC;QAExF,MAAM,UAAU,GAAG,GAAG,MAAM,KAAK,OAAO,SAAS,CAAC;QAClD,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,IAAI,CAAC;YACH,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvB,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBACjC,OAAO,CAAC,KAAK,CAAC,8CAA8C,UAAU,EAAE,CAAC,CAAC;gBAC1E,eAAe,GAAG,IAAI,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,eAAe,GAAG,IAAI,CAAC;YACzB,CAAC;QACH,CAAC;QAAC,OAAO,SAAS,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CACX,2DAA4D,SAAmB,CAAC,OAAO,EAAE,CAC1F,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACb,gEAAgE,MAAM,IAAI;gBACxE,qEAAqE,CACxE,CAAC;QACJ,CAAC;QAED,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QACV,IAAI,CAAC;YACH,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,yBAAyB,eAAe,EAAE,CAAC,CAAC;QACzD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpB,EAAE,CAAC,IAAI,CAAC,yBAAyB,eAAe,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAAgB;IAChD,IAAI,CAAC;QACH,OAAO;YACL,WAAW,EAAE,EAAE,CAAC,OAAO,CACrB,+MAA+M,CAChN;YACD,WAAW,EAAE,EAAE,CAAC,OAAO,CACrB,wKAAwK,CACzK;YACD,WAAW,EAAE,EAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC;YACzD,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC;YAC5D,cAAc,EAAE,EAAE,CAAC,OAAO,CAAC,6CAA6C,CAAC;YACzE,YAAY,EAAE,EAAE,CAAC,OAAO,CAAC,kCAAkC,CAAC;YAC5D,gBAAgB,EAAE,EAAE,CAAC,OAAO,CAAC,yDAAyD,CAAC;YACvF,mBAAmB,EAAE,EAAE,CAAC,OAAO,CAC7B,uMAAuM,CACxM;YACD,iBAAiB,EAAE,EAAE,CAAC,OAAO,CAAC,gDAAgD,CAAC;YAC/E,eAAe,EAAE,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC;YAC3E,aAAa,EAAE,EAAE,CAAC,OAAO,CAAC,wDAAwD,CAAC;YACnF,aAAa,EAAE,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC;YAClE,kBAAkB,EAAE,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC;YACjF,oBAAoB,EAAE,EAAE,CAAC,OAAO,CAC9B,+DAA+D,CAChE;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,yEAAyE;YACvE,sDAAsD;YACtD,mBAAoB,CAAW,CAAC,OAAO,EAAE,CAC5C,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAyB,EAAE,KAAa,EAAE,SAAuB;IACzF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,SAAS,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAyB,EAAE,KAAa;IAChE,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,SAAS,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC;IAC/D,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAgB;IAC7C,IAAI,CAAC;QACH,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"AAuCA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAYtE;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,CAmBlF;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAED,wBAAgB,gBAAgB,IAAI,OAAO,GAAG,IAAI,CAEjD"}
1
+ {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"AA+CA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAYtE;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,CAmBlF;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAED,wBAAgB,gBAAgB,IAAI,OAAO,GAAG,IAAI,CAEjD"}
package/dist/embed.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { join } from 'node:path';
2
2
  import { homedir } from 'node:os';
3
3
  import { mkdirSync } from 'node:fs';
4
+ import { availableParallelism } from 'node:os';
5
+ const MAX_EMBED_THREADS = Math.max(1, Math.min(2, Math.floor(availableParallelism() / 4)));
4
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
7
  let extractor = null;
6
8
  let embedAvailable = null;
@@ -15,10 +17,14 @@ async function ensurePipeline() {
15
17
  loadingPromise = (async () => {
16
18
  try {
17
19
  const { pipeline, env } = await import('@huggingface/transformers');
20
+ const threads = Number(process.env.CONTEXT_VAULT_EMBED_THREADS) || MAX_EMBED_THREADS;
21
+ if (env.backends?.onnx?.wasm) {
22
+ env.backends.onnx.wasm.numThreads = threads;
23
+ }
18
24
  const modelCacheDir = join(homedir(), '.context-mcp', 'models');
19
25
  mkdirSync(modelCacheDir, { recursive: true });
20
26
  env.cacheDir = modelCacheDir;
21
- console.error('[context-vault] Loading embedding model (first run may download ~22MB)...');
27
+ console.error(`[context-vault] Loading embedding model (threads=${threads})...`);
22
28
  extractor = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
23
29
  embedAvailable = true;
24
30
  return extractor;
package/dist/embed.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"embed.js","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@context-vault/core",
3
- "version": "3.2.1",
3
+ "version": "3.2.3",
4
4
  "type": "module",
5
5
  "description": "Pure local engine: capture, index, search, and utilities for context-vault",
6
6
  "main": "dist/main.js",
package/src/db.ts CHANGED
@@ -1,7 +1,55 @@
1
- import { unlinkSync, copyFileSync, existsSync } from 'node:fs';
1
+ import { unlinkSync, copyFileSync, existsSync, openSync, closeSync, mkdirSync, statSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
2
3
  import { DatabaseSync } from 'node:sqlite';
3
4
  import type { PreparedStatements } from './types.js';
4
5
 
6
+ /**
7
+ * Acquire an exclusive file lock to serialize database initialization.
8
+ * Multiple MCP clients (Claude, Cursor, Windsurf) may each spawn a server
9
+ * instance simultaneously — without serialization, migrations and schema
10
+ * init race against each other.
11
+ *
12
+ * Uses O_EXCL (via 'wx' flag) as a cross-platform advisory lock.
13
+ * Returns a release function that removes the lock file.
14
+ */
15
+ function acquireInitLock(dbPath: string, timeoutMs = 10_000): () => void {
16
+ const lockPath = dbPath + '.init-lock';
17
+ mkdirSync(dirname(lockPath), { recursive: true });
18
+
19
+ const start = Date.now();
20
+ while (true) {
21
+ try {
22
+ const fd = openSync(lockPath, 'wx');
23
+ closeSync(fd);
24
+ return () => {
25
+ try { unlinkSync(lockPath); } catch {}
26
+ };
27
+ } catch (err: any) {
28
+ if (err.code !== 'EEXIST') throw err;
29
+
30
+ // Stale lock detection — if lock file is older than 30s, it's from a crashed process
31
+ try {
32
+ const { mtimeMs } = statSync(lockPath);
33
+ if (Date.now() - mtimeMs > 30_000) {
34
+ try { unlinkSync(lockPath); } catch {}
35
+ continue;
36
+ }
37
+ } catch {}
38
+
39
+ if (Date.now() - start > timeoutMs) {
40
+ // Timeout — break the lock and proceed (better than hanging forever)
41
+ console.error('[context-vault] Init lock timed out, breaking stale lock');
42
+ try { unlinkSync(lockPath); } catch {}
43
+ continue;
44
+ }
45
+
46
+ // Busy-wait with small sleep (synchronous — we're in sync init code)
47
+ const waitMs = 50 + Math.random() * 100;
48
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, waitMs);
49
+ }
50
+ }
51
+ }
52
+
5
53
  export class NativeModuleError extends Error {
6
54
  originalError: Error;
7
55
  constructor(originalError: Error) {
@@ -107,7 +155,7 @@ export async function initDatabase(dbPath: string): Promise<DatabaseSync> {
107
155
  const db = new DatabaseSync(path, { allowExtension: true });
108
156
  db.exec('PRAGMA journal_mode = WAL');
109
157
  db.exec('PRAGMA foreign_keys = ON');
110
- db.exec('PRAGMA busy_timeout = 3000');
158
+ db.exec('PRAGMA busy_timeout = 5000');
111
159
  try {
112
160
  sqliteVec.load(db);
113
161
  } catch (e) {
@@ -116,57 +164,63 @@ export async function initDatabase(dbPath: string): Promise<DatabaseSync> {
116
164
  return db;
117
165
  }
118
166
 
119
- const db = createDb(dbPath);
120
- const version = (db.prepare('PRAGMA user_version').get() as { user_version: number })
121
- .user_version;
167
+ // Serialize init across concurrent server instances (Claude + Cursor + Windsurf)
168
+ const releaseLock = acquireInitLock(dbPath);
169
+ try {
170
+ const db = createDb(dbPath);
171
+ const version = (db.prepare('PRAGMA user_version').get() as { user_version: number })
172
+ .user_version;
122
173
 
123
- if (version > 0 && version < 15) {
124
- console.error(`[context-vault] Schema v${version} is outdated. Rebuilding database...`);
174
+ if (version > 0 && version < 15) {
175
+ console.error(`[context-vault] Schema v${version} is outdated. Rebuilding database...`);
125
176
 
126
- const backupPath = `${dbPath}.v${version}.backup`;
127
- let backupSucceeded = false;
128
- try {
129
- db.close();
130
- if (existsSync(dbPath)) {
131
- copyFileSync(dbPath, backupPath);
132
- console.error(`[context-vault] Backed up old database to: ${backupPath}`);
133
- backupSucceeded = true;
134
- } else {
135
- backupSucceeded = true;
177
+ const backupPath = `${dbPath}.v${version}.backup`;
178
+ let backupSucceeded = false;
179
+ try {
180
+ db.close();
181
+ if (existsSync(dbPath)) {
182
+ copyFileSync(dbPath, backupPath);
183
+ console.error(`[context-vault] Backed up old database to: ${backupPath}`);
184
+ backupSucceeded = true;
185
+ } else {
186
+ backupSucceeded = true;
187
+ }
188
+ } catch (backupErr) {
189
+ console.error(
190
+ `[context-vault] Warning: could not backup old database: ${(backupErr as Error).message}`
191
+ );
136
192
  }
137
- } catch (backupErr) {
138
- console.error(
139
- `[context-vault] Warning: could not backup old database: ${(backupErr as Error).message}`
140
- );
141
- }
142
193
 
143
- if (!backupSucceeded) {
144
- throw new Error(
145
- `[context-vault] Aborting schema migration: backup failed for ${dbPath}. ` +
146
- `Fix the backup issue or manually back up the file before upgrading.`
147
- );
148
- }
194
+ if (!backupSucceeded) {
195
+ throw new Error(
196
+ `[context-vault] Aborting schema migration: backup failed for ${dbPath}. ` +
197
+ `Fix the backup issue or manually back up the file before upgrading.`
198
+ );
199
+ }
149
200
 
150
- unlinkSync(dbPath);
151
- try {
152
- unlinkSync(dbPath + '-wal');
153
- } catch {}
154
- try {
155
- unlinkSync(dbPath + '-shm');
156
- } catch {}
201
+ unlinkSync(dbPath);
202
+ try {
203
+ unlinkSync(dbPath + '-wal');
204
+ } catch {}
205
+ try {
206
+ unlinkSync(dbPath + '-shm');
207
+ } catch {}
157
208
 
158
- const freshDb = createDb(dbPath);
159
- freshDb.exec(SCHEMA_DDL);
160
- freshDb.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
161
- return freshDb;
162
- }
209
+ const freshDb = createDb(dbPath);
210
+ freshDb.exec(SCHEMA_DDL);
211
+ freshDb.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
212
+ return freshDb;
213
+ }
163
214
 
164
- if (version < 15) {
165
- db.exec(SCHEMA_DDL);
166
- db.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
167
- }
215
+ if (version < 15) {
216
+ db.exec(SCHEMA_DDL);
217
+ db.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
218
+ }
168
219
 
169
- return db;
220
+ return db;
221
+ } finally {
222
+ releaseLock();
223
+ }
170
224
  }
171
225
 
172
226
  export function prepareStatements(db: DatabaseSync): PreparedStatements {
package/src/embed.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import { join } from 'node:path';
2
2
  import { homedir } from 'node:os';
3
3
  import { mkdirSync } from 'node:fs';
4
+ import { availableParallelism } from 'node:os';
5
+
6
+ const MAX_EMBED_THREADS = Math.max(1, Math.min(2, Math.floor(availableParallelism() / 4)));
4
7
 
5
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
9
  let extractor: any = null;
@@ -16,11 +19,16 @@ async function ensurePipeline(): Promise<typeof extractor> {
16
19
  try {
17
20
  const { pipeline, env } = await import('@huggingface/transformers');
18
21
 
22
+ const threads = Number(process.env.CONTEXT_VAULT_EMBED_THREADS) || MAX_EMBED_THREADS;
23
+ if (env.backends?.onnx?.wasm) {
24
+ env.backends.onnx.wasm.numThreads = threads;
25
+ }
26
+
19
27
  const modelCacheDir = join(homedir(), '.context-mcp', 'models');
20
28
  mkdirSync(modelCacheDir, { recursive: true });
21
29
  env.cacheDir = modelCacheDir;
22
30
 
23
- console.error('[context-vault] Loading embedding model (first run may download ~22MB)...');
31
+ console.error(`[context-vault] Loading embedding model (threads=${threads})...`);
24
32
  extractor = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
25
33
  embedAvailable = true;
26
34
  return extractor;