@context-vault/core 2.8.15 → 2.8.17
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/package.json +1 -1
- package/src/index/embed.js +2 -2
- package/src/index/index.js +16 -13
- package/src/server/helpers.js +1 -1
- package/src/server/tools/get-context.js +4 -1
package/package.json
CHANGED
package/src/index/embed.js
CHANGED
|
@@ -11,10 +11,10 @@ import { mkdirSync } from "node:fs";
|
|
|
11
11
|
|
|
12
12
|
let extractor = null;
|
|
13
13
|
|
|
14
|
-
/** @type {null | true | false} null =
|
|
14
|
+
/** @type {null | true | false} null = uninitialized/retry, true = ready, false = permanently failed */
|
|
15
15
|
let embedAvailable = null;
|
|
16
16
|
|
|
17
|
-
/**
|
|
17
|
+
/** In-flight load promise — coalesces concurrent callers onto a single pipeline() call */
|
|
18
18
|
let loadingPromise = null;
|
|
19
19
|
|
|
20
20
|
async function ensurePipeline() {
|
package/src/index/index.js
CHANGED
|
@@ -49,6 +49,11 @@ export async function indexEntry(
|
|
|
49
49
|
userId,
|
|
50
50
|
},
|
|
51
51
|
) {
|
|
52
|
+
// Don't index entries that have already expired
|
|
53
|
+
if (expires_at && new Date(expires_at) <= new Date()) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
52
57
|
const tagsJson = tags ? JSON.stringify(tags) : null;
|
|
53
58
|
const metaJson = meta ? JSON.stringify(meta) : null;
|
|
54
59
|
const cat = category || categoryFor(kind);
|
|
@@ -239,8 +244,7 @@ export async function reindex(ctx, opts = {}) {
|
|
|
239
244
|
// Phase 1: Sync DB ops in a transaction — FTS is searchable immediately after COMMIT.
|
|
240
245
|
// Phase 2: Async embedding runs post-transaction so it can't hold the write lock
|
|
241
246
|
// or roll back DB state on failure.
|
|
242
|
-
const pendingEmbeds = []; // { rowid, text }
|
|
243
|
-
const staleVecRowids = []; // rowids whose old vectors need deleting before re-embed
|
|
247
|
+
const pendingEmbeds = []; // { rowid, text, isUpdate }
|
|
244
248
|
|
|
245
249
|
ctx.db.exec("BEGIN");
|
|
246
250
|
try {
|
|
@@ -347,11 +351,14 @@ export async function reindex(ctx, opts = {}) {
|
|
|
347
351
|
if (bodyChanged || titleChanged) {
|
|
348
352
|
const rowid = ctx.stmts.getRowid.get(existing.id)?.rowid;
|
|
349
353
|
if (rowid) {
|
|
350
|
-
staleVecRowids.push(rowid);
|
|
351
354
|
const embeddingText = [parsed.title, parsed.body]
|
|
352
355
|
.filter(Boolean)
|
|
353
356
|
.join(" ");
|
|
354
|
-
pendingEmbeds.push({
|
|
357
|
+
pendingEmbeds.push({
|
|
358
|
+
rowid,
|
|
359
|
+
text: embeddingText,
|
|
360
|
+
isUpdate: true,
|
|
361
|
+
});
|
|
355
362
|
}
|
|
356
363
|
}
|
|
357
364
|
stats.updated++;
|
|
@@ -433,20 +440,16 @@ export async function reindex(ctx, opts = {}) {
|
|
|
433
440
|
|
|
434
441
|
// Phase 2: Async embedding — runs after COMMIT so FTS is already searchable.
|
|
435
442
|
// Failures here are non-fatal; semantic search catches up on next reindex.
|
|
436
|
-
|
|
437
|
-
//
|
|
438
|
-
for (const rowid of staleVecRowids) {
|
|
439
|
-
try {
|
|
440
|
-
ctx.deleteVec(rowid);
|
|
441
|
-
} catch {}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Batch embed all pending texts
|
|
443
|
+
// Vec delete happens atomically with insert (only on success) to avoid
|
|
444
|
+
// leaving entries permanently without vectors if embedBatch() fails mid-batch.
|
|
445
445
|
for (let i = 0; i < pendingEmbeds.length; i += EMBED_BATCH_SIZE) {
|
|
446
446
|
const batch = pendingEmbeds.slice(i, i + EMBED_BATCH_SIZE);
|
|
447
447
|
const embeddings = await embedBatch(batch.map((e) => e.text));
|
|
448
448
|
for (let j = 0; j < batch.length; j++) {
|
|
449
449
|
if (embeddings[j]) {
|
|
450
|
+
try {
|
|
451
|
+
ctx.deleteVec(batch[j].rowid);
|
|
452
|
+
} catch {}
|
|
450
453
|
ctx.insertVec(batch[j].rowid, embeddings[j]);
|
|
451
454
|
}
|
|
452
455
|
}
|
package/src/server/helpers.js
CHANGED
|
@@ -13,7 +13,7 @@ export function err(text, code = "UNKNOWN") {
|
|
|
13
13
|
export function ensureVaultExists(config) {
|
|
14
14
|
if (!config.vaultDirExists) {
|
|
15
15
|
return err(
|
|
16
|
-
`Vault directory not found: ${config.vaultDir}. Run
|
|
16
|
+
`Vault directory not found: ${config.vaultDir}. Run context-status for diagnostics.`,
|
|
17
17
|
"VAULT_NOT_FOUND",
|
|
18
18
|
);
|
|
19
19
|
}
|
|
@@ -110,7 +110,10 @@ export async function handler(
|
|
|
110
110
|
|
|
111
111
|
const effectiveLimit = limit || 10;
|
|
112
112
|
// When tag-filtering, over-fetch to compensate for post-filter reduction
|
|
113
|
-
const
|
|
113
|
+
const MAX_FETCH_LIMIT = 500;
|
|
114
|
+
const fetchLimit = tags?.length
|
|
115
|
+
? Math.min(effectiveLimit * 10, MAX_FETCH_LIMIT)
|
|
116
|
+
: effectiveLimit;
|
|
114
117
|
|
|
115
118
|
let filtered;
|
|
116
119
|
if (hasQuery) {
|