@context-vault/core 3.2.0 → 3.2.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/db.d.ts.map +1 -1
- package/dist/db.js +102 -40
- package/dist/db.js.map +1 -1
- package/dist/embed.d.ts.map +1 -1
- package/dist/embed.js +7 -1
- package/dist/embed.js.map +1 -1
- package/dist/frontmatter.d.ts.map +1 -1
- package/dist/frontmatter.js +7 -2
- package/dist/frontmatter.js.map +1 -1
- package/package.json +1 -1
- package/src/db.ts +99 -45
- package/src/embed.ts +9 -1
- package/src/frontmatter.ts +7 -2
package/dist/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"
|
|
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 } 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 } = require('node:fs').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 =
|
|
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
|
-
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
126
|
-
|
|
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
|
-
|
|
130
|
-
|
|
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
|
-
|
|
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
|
-
|
|
151
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|
package/dist/embed.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"
|
|
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(
|
|
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":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"embed.js","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAavE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd,CAoCA;
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"AAEA,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAavE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd,CAoCA;AAeD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMjG;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B;IACD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACtC,CA+BA"}
|
package/dist/frontmatter.js
CHANGED
|
@@ -56,6 +56,7 @@ export function parseFrontmatter(text) {
|
|
|
56
56
|
}
|
|
57
57
|
const RESERVED_FM_KEYS = new Set([
|
|
58
58
|
'id',
|
|
59
|
+
'title',
|
|
59
60
|
'tags',
|
|
60
61
|
'source',
|
|
61
62
|
'created',
|
|
@@ -75,7 +76,10 @@ export function extractCustomMeta(fmMeta) {
|
|
|
75
76
|
}
|
|
76
77
|
export function parseEntryFromMarkdown(kind, body, fmMeta) {
|
|
77
78
|
if (kind === 'insight') {
|
|
78
|
-
|
|
79
|
+
const fmTitle = typeof fmMeta.title === 'string' ? fmMeta.title : null;
|
|
80
|
+
const headingMatch = body.match(/^#+ (.+)/);
|
|
81
|
+
const title = fmTitle || (headingMatch ? headingMatch[1].trim() : null);
|
|
82
|
+
return { title, body, meta: extractCustomMeta(fmMeta) };
|
|
79
83
|
}
|
|
80
84
|
if (kind === 'decision') {
|
|
81
85
|
const titleMatch = body.match(/^## Decision\s*\n+([\s\S]*?)(?=\n## |\n*$)/);
|
|
@@ -91,9 +95,10 @@ export function parseEntryFromMarkdown(kind, body, fmMeta) {
|
|
|
91
95
|
const content = codeMatch ? codeMatch[1].trim() : body;
|
|
92
96
|
return { title, body: content, meta: extractCustomMeta(fmMeta) };
|
|
93
97
|
}
|
|
98
|
+
const fmTitle = typeof fmMeta.title === 'string' ? fmMeta.title : null;
|
|
94
99
|
const headingMatch = body.match(/^#+ (.+)/);
|
|
95
100
|
return {
|
|
96
|
-
title: headingMatch ? headingMatch[1].trim() : null,
|
|
101
|
+
title: fmTitle || (headingMatch ? headingMatch[1].trim() : null),
|
|
97
102
|
body,
|
|
98
103
|
meta: extractCustomMeta(fmMeta),
|
|
99
104
|
};
|
package/dist/frontmatter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../src/frontmatter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
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 =
|
|
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
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
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
|
-
|
|
124
|
-
|
|
174
|
+
if (version > 0 && version < 15) {
|
|
175
|
+
console.error(`[context-vault] Schema v${version} is outdated. Rebuilding database...`);
|
|
125
176
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
201
|
+
unlinkSync(dbPath);
|
|
202
|
+
try {
|
|
203
|
+
unlinkSync(dbPath + '-wal');
|
|
204
|
+
} catch {}
|
|
205
|
+
try {
|
|
206
|
+
unlinkSync(dbPath + '-shm');
|
|
207
|
+
} catch {}
|
|
157
208
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
215
|
+
if (version < 15) {
|
|
216
|
+
db.exec(SCHEMA_DDL);
|
|
217
|
+
db.exec(`PRAGMA user_version = ${CURRENT_VERSION}`);
|
|
218
|
+
}
|
|
168
219
|
|
|
169
|
-
|
|
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(
|
|
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;
|
package/src/frontmatter.ts
CHANGED
|
@@ -58,6 +58,7 @@ export function parseFrontmatter(text: string): {
|
|
|
58
58
|
|
|
59
59
|
const RESERVED_FM_KEYS = new Set([
|
|
60
60
|
'id',
|
|
61
|
+
'title',
|
|
61
62
|
'tags',
|
|
62
63
|
'source',
|
|
63
64
|
'created',
|
|
@@ -86,7 +87,10 @@ export function parseEntryFromMarkdown(
|
|
|
86
87
|
meta: Record<string, unknown> | null;
|
|
87
88
|
} {
|
|
88
89
|
if (kind === 'insight') {
|
|
89
|
-
|
|
90
|
+
const fmTitle = typeof fmMeta.title === 'string' ? fmMeta.title : null;
|
|
91
|
+
const headingMatch = body.match(/^#+ (.+)/);
|
|
92
|
+
const title = fmTitle || (headingMatch ? headingMatch[1].trim() : null);
|
|
93
|
+
return { title, body, meta: extractCustomMeta(fmMeta) };
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
if (kind === 'decision') {
|
|
@@ -105,9 +109,10 @@ export function parseEntryFromMarkdown(
|
|
|
105
109
|
return { title, body: content, meta: extractCustomMeta(fmMeta) };
|
|
106
110
|
}
|
|
107
111
|
|
|
112
|
+
const fmTitle = typeof fmMeta.title === 'string' ? fmMeta.title : null;
|
|
108
113
|
const headingMatch = body.match(/^#+ (.+)/);
|
|
109
114
|
return {
|
|
110
|
-
title: headingMatch ? headingMatch[1].trim() : null,
|
|
115
|
+
title: fmTitle || (headingMatch ? headingMatch[1].trim() : null),
|
|
111
116
|
body,
|
|
112
117
|
meta: extractCustomMeta(fmMeta),
|
|
113
118
|
};
|