@equationalapplications/core-llm-wiki 7.12.0 → 7.13.1
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/{chunk-KN4XSLLB.mjs → chunk-PCRYIUV5.mjs} +232 -18
- package/dist/chunk-PCRYIUV5.mjs.map +1 -0
- package/dist/index.d.mts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +730 -146
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +502 -133
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-7d76Ptlq.d.mts → testing-CqsXv2_l.d.mts} +111 -18
- package/dist/{testing-7d76Ptlq.d.ts → testing-CqsXv2_l.d.ts} +111 -18
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +80 -15
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-KN4XSLLB.mjs.map +0 -1
package/dist/testing.js
CHANGED
|
@@ -38,6 +38,8 @@ var SQLITE_RESULT_CODE_NAMES = {
|
|
|
38
38
|
// prefix and we normalize it back to the symbolic name so callers can branch on
|
|
39
39
|
// the same string the rest of the ecosystem uses.
|
|
40
40
|
2067: "SQLITE_CONSTRAINT_UNIQUE",
|
|
41
|
+
// 267 = SQLITE_CORRUPT_VTAB — a corrupt FTS5 shadow table (ftsCorruptionClass).
|
|
42
|
+
267: "SQLITE_CORRUPT_VTAB",
|
|
41
43
|
100: "SQLITE_ROW",
|
|
42
44
|
101: "SQLITE_DONE"
|
|
43
45
|
};
|
|
@@ -1407,7 +1409,7 @@ var ImportExportService = class {
|
|
|
1407
1409
|
if (merge) {
|
|
1408
1410
|
await this.searchService.syncEntries(entityId, [...upsertedFactIds]);
|
|
1409
1411
|
} else {
|
|
1410
|
-
await this.searchService.sync(entityId);
|
|
1412
|
+
await this.searchService.sync(entityId, { ids: [.../* @__PURE__ */ new Set([...upsertedFactIds, ...softDeletedFactIds])] });
|
|
1411
1413
|
}
|
|
1412
1414
|
for (const fact of bundle.facts) {
|
|
1413
1415
|
if (!fact.deleted_at && upsertedFactIds.has(fact.id) && !factsWithPreservedBlob.has(fact.id)) {
|
|
@@ -2340,7 +2342,8 @@ var IngestionService = class {
|
|
|
2340
2342
|
*
|
|
2341
2343
|
* @returns Counts: nodesWritten (validated nodes persisted), edgesWritten
|
|
2342
2344
|
* (manifest-valid edges persisted), superseded (prior facts soft-deleted
|
|
2343
|
-
* plus prior source-ref edges hard-deleted)
|
|
2345
|
+
* plus prior source-ref edges hard-deleted), and supersededFactIds (the
|
|
2346
|
+
* ids of those soft-deleted facts, for the caller's post-commit index sync).
|
|
2344
2347
|
*
|
|
2345
2348
|
* Node-ownership pre-flight (spec §3, REQ-GRAPH-01): the first statement
|
|
2346
2349
|
* is `assertGraphNodeOwnership(entityId, params.nodes, tx)`, which runs
|
|
@@ -2468,7 +2471,8 @@ var IngestionService = class {
|
|
|
2468
2471
|
return {
|
|
2469
2472
|
nodesWritten: wikiFacts.length,
|
|
2470
2473
|
edgesWritten: edgesInsertedCount,
|
|
2471
|
-
superseded: deletedFactIds.length + deletedEdgeCount
|
|
2474
|
+
superseded: deletedFactIds.length + deletedEdgeCount,
|
|
2475
|
+
supersededFactIds: deletedFactIds
|
|
2472
2476
|
};
|
|
2473
2477
|
}
|
|
2474
2478
|
/**
|
|
@@ -2882,6 +2886,17 @@ async function createTemporalIndexesIfColumnsExist(db, prefix) {
|
|
|
2882
2886
|
}
|
|
2883
2887
|
}
|
|
2884
2888
|
|
|
2889
|
+
// src/services/search/fts5Sql.ts
|
|
2890
|
+
var FTS5_STATE_KEY = "fts5_index_state";
|
|
2891
|
+
var FTS5_REBUILD_WM_KEY = "fts5_rebuild_wm";
|
|
2892
|
+
var FTS5_REBUILD_SNAPSHOT_KEY = "fts5_rebuild_snapshot";
|
|
2893
|
+
var FTS5_SWEEP_CURSOR_KEY = "fts5_orphan_sweep_cursor";
|
|
2894
|
+
function fts5PendingIndexesDdl(p) {
|
|
2895
|
+
return `
|
|
2896
|
+
CREATE INDEX IF NOT EXISTS ${p}fts_pending_id ON ${p}fts_pending(id);
|
|
2897
|
+
CREATE INDEX IF NOT EXISTS ${p}fts_pending_entity ON ${p}fts_pending(entity_id);`;
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2885
2900
|
// src/db/migrations.ts
|
|
2886
2901
|
var MIGRATIONS = [
|
|
2887
2902
|
{
|
|
@@ -3162,6 +3177,17 @@ var MIGRATIONS = [
|
|
|
3162
3177
|
run: async (db, prefix) => {
|
|
3163
3178
|
await createLegacySourceTypeIndex(db, prefix);
|
|
3164
3179
|
}
|
|
3180
|
+
},
|
|
3181
|
+
{
|
|
3182
|
+
version: 15,
|
|
3183
|
+
description: "fts_pending(id) and fts_pending(entity_id) indexes for the ids-first and entity-targeted drains",
|
|
3184
|
+
run: async (db, prefix) => {
|
|
3185
|
+
const row = await db.getFirstAsync(
|
|
3186
|
+
`SELECT count(*) AS n FROM sqlite_master WHERE type = 'table' AND name = ?`,
|
|
3187
|
+
[`${prefix}fts_pending`]
|
|
3188
|
+
);
|
|
3189
|
+
if (row?.n) await db.execAsync(fts5PendingIndexesDdl(prefix));
|
|
3190
|
+
}
|
|
3165
3191
|
}
|
|
3166
3192
|
];
|
|
3167
3193
|
async function createLegacySourceTypeIndex(db, prefix) {
|
|
@@ -3186,6 +3212,21 @@ async function resetNormalizeWatermarks(meta) {
|
|
|
3186
3212
|
await meta.deleteMeta(SRI_WM_KEY);
|
|
3187
3213
|
}
|
|
3188
3214
|
|
|
3215
|
+
// src/services/search/fts5Progress.ts
|
|
3216
|
+
async function writeRebuildStart(tx, prefix, meta) {
|
|
3217
|
+
const e = await tx.getFirstAsync(`SELECT coalesce(max(rowid), 0) AS hi FROM ${prefix}entries`);
|
|
3218
|
+
const m = await tx.getFirstAsync(`SELECT coalesce(max(fts_rowid), 0) AS hi FROM ${prefix}fts_map`);
|
|
3219
|
+
await meta.setMeta(FTS5_REBUILD_WM_KEY, JSON.stringify({ rowid: 0, id: null }), tx);
|
|
3220
|
+
await meta.setMeta(FTS5_REBUILD_SNAPSHOT_KEY, JSON.stringify({ entries: e?.hi ?? 0, map: m?.hi ?? 0 }), tx);
|
|
3221
|
+
await meta.setMeta(FTS5_SWEEP_CURSOR_KEY, "0", tx);
|
|
3222
|
+
}
|
|
3223
|
+
async function restartRebuildAfterVacuum(db, prefix, meta) {
|
|
3224
|
+
await db.withTransactionAsync(async (tx) => {
|
|
3225
|
+
if (await meta.getMeta(FTS5_STATE_KEY, tx) !== "rebuilding") return;
|
|
3226
|
+
await writeRebuildStart(tx, prefix, meta);
|
|
3227
|
+
});
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3189
3230
|
// src/services/librarian/constants.ts
|
|
3190
3231
|
var FUZZY_THRESHOLD = 0.5;
|
|
3191
3232
|
var MIN_TOKENS_TO_QUALIFY = 3;
|
|
@@ -4121,6 +4162,7 @@ var MaintenanceService = class {
|
|
|
4121
4162
|
if (vacuum) {
|
|
4122
4163
|
await resetNormalizeWatermarks(this.metadataRepo);
|
|
4123
4164
|
await this.metadataRepo.vacuum();
|
|
4165
|
+
await restartRebuildAfterVacuum(this.db, this.prefix, this.metadataRepo);
|
|
4124
4166
|
}
|
|
4125
4167
|
await this.searchService.syncEntries(entityId, syncedIds);
|
|
4126
4168
|
return { entries: deletedEntries, tasks: deletedTasks, events: deletedEvents };
|
|
@@ -5814,7 +5856,7 @@ var UnavailableIndexStrategy = class {
|
|
|
5814
5856
|
hasIndexedEntity(_entityId) {
|
|
5815
5857
|
return false;
|
|
5816
5858
|
}
|
|
5817
|
-
async drain() {
|
|
5859
|
+
async drain(_opts) {
|
|
5818
5860
|
}
|
|
5819
5861
|
};
|
|
5820
5862
|
|
|
@@ -5860,24 +5902,31 @@ var _SearchService = class _SearchService {
|
|
|
5860
5902
|
isKeywordAvailable() {
|
|
5861
5903
|
return !(this.indexStrategy instanceof UnavailableIndexStrategy);
|
|
5862
5904
|
}
|
|
5905
|
+
/** True when the installed strategy drains a durable ledger (FTS5, or the degraded stand-in). */
|
|
5906
|
+
hasLedger() {
|
|
5907
|
+
return this.indexStrategy.drain !== void 0;
|
|
5908
|
+
}
|
|
5863
5909
|
/**
|
|
5864
5910
|
* One serialized drain turn for strategies with a durable ledger. Like
|
|
5865
5911
|
* sync(), it never rejects: the keyword index is rebuildable, and a failed
|
|
5866
|
-
* drain leaves the ledger rows in place for the next turn.
|
|
5912
|
+
* drain leaves the ledger rows in place for the next turn. Resolves false
|
|
5913
|
+
* when the drain failed.
|
|
5867
5914
|
*/
|
|
5868
|
-
drainTurn(entityId) {
|
|
5915
|
+
drainTurn(entityId, opts) {
|
|
5869
5916
|
const work = this.syncChain.then(async () => {
|
|
5870
5917
|
try {
|
|
5871
5918
|
try {
|
|
5872
|
-
await this.indexStrategy.drain();
|
|
5919
|
+
await this.indexStrategy.drain(opts);
|
|
5873
5920
|
} finally {
|
|
5874
5921
|
this.evictCache(entityId);
|
|
5875
5922
|
}
|
|
5923
|
+
return true;
|
|
5876
5924
|
} catch (err) {
|
|
5877
5925
|
console.warn(`[WikiMemory] search index drain failed for ${entityId ?? "*"}:`, err);
|
|
5926
|
+
return false;
|
|
5878
5927
|
}
|
|
5879
5928
|
});
|
|
5880
|
-
this.syncChain = work;
|
|
5929
|
+
this.syncChain = work.then(() => void 0);
|
|
5881
5930
|
return work;
|
|
5882
5931
|
}
|
|
5883
5932
|
/**
|
|
@@ -5887,9 +5936,18 @@ var _SearchService = class _SearchService {
|
|
|
5887
5936
|
* Rebuilds are serialized per instance and never reject: the keyword index
|
|
5888
5937
|
* is a rebuildable cache over SQLite, so degraded keyword search is the
|
|
5889
5938
|
* correct failure mode and killing the host process is not.
|
|
5939
|
+
*
|
|
5940
|
+
* With a ledger strategy, `sync()` runs one full quantum bounded by
|
|
5941
|
+
* `opts.deadline`; `sync(entityId)` is a write turn (ledger only).
|
|
5942
|
+
* `opts.ids` are the caller's touched ids: a ledger strategy drains them
|
|
5943
|
+
* first, to completion; MiniSearch ignores them and rebuilds the entity in
|
|
5944
|
+
* one scan.
|
|
5890
5945
|
*/
|
|
5891
|
-
async sync(entityId) {
|
|
5892
|
-
if (this.indexStrategy.drain)
|
|
5946
|
+
async sync(entityId, opts) {
|
|
5947
|
+
if (this.indexStrategy.drain) {
|
|
5948
|
+
await this.drainTurn(entityId, entityId === void 0 ? { mode: "full", deadline: opts?.deadline, ids: opts?.ids } : { mode: "ledger", entityId, ids: opts?.ids });
|
|
5949
|
+
return;
|
|
5950
|
+
}
|
|
5893
5951
|
const work = this.syncChain.then(async () => {
|
|
5894
5952
|
try {
|
|
5895
5953
|
try {
|
|
@@ -5930,13 +5988,17 @@ var _SearchService = class _SearchService {
|
|
|
5930
5988
|
* — including on an empty `ids` list, which is a no-op only for an entity
|
|
5931
5989
|
* the index already tracks, and even then one that waits for rebuilds
|
|
5932
5990
|
* already queued on the chain.
|
|
5991
|
+
*
|
|
5992
|
+
* Resolves false only when a ledger drain failed: the caller's ids were not
|
|
5993
|
+
* applied (their ledger rows remain), so a caller holding them retries.
|
|
5933
5994
|
*/
|
|
5934
5995
|
async syncEntries(entityId, ids) {
|
|
5935
|
-
if (this.indexStrategy.drain) return this.drainTurn(entityId);
|
|
5996
|
+
if (this.indexStrategy.drain) return this.drainTurn(entityId, { mode: "ledger", entityId, ids: [...new Set(ids)] });
|
|
5936
5997
|
const uniqueIds = [...new Set(ids)];
|
|
5937
5998
|
const indexed = this.indexStrategy.hasIndexedEntity?.(entityId);
|
|
5938
5999
|
if (uniqueIds.length === 0 && !this.staleEntities.has(entityId) && indexed === true) {
|
|
5939
|
-
|
|
6000
|
+
await this.syncChain;
|
|
6001
|
+
return true;
|
|
5940
6002
|
}
|
|
5941
6003
|
const work = this.syncChain.then(async () => {
|
|
5942
6004
|
try {
|
|
@@ -5965,7 +6027,8 @@ var _SearchService = class _SearchService {
|
|
|
5965
6027
|
}
|
|
5966
6028
|
});
|
|
5967
6029
|
this.syncChain = work;
|
|
5968
|
-
|
|
6030
|
+
await work;
|
|
6031
|
+
return true;
|
|
5969
6032
|
}
|
|
5970
6033
|
/**
|
|
5971
6034
|
* Forces the entity's next syncEntries to rebuild it in full. For writes core
|
|
@@ -5981,11 +6044,13 @@ var _SearchService = class _SearchService {
|
|
|
5981
6044
|
* so only those entities are rebuilt. Each rebuild still takes its own turn
|
|
5982
6045
|
* on the sync chain, and like syncEntries this never rejects. With nothing
|
|
5983
6046
|
* stale it resolves at once, without waiting on work already on the chain.
|
|
6047
|
+
* Resolves false only when a ledger drain failed (see syncEntries).
|
|
5984
6048
|
*/
|
|
5985
|
-
async syncStale() {
|
|
5986
|
-
if (this.indexStrategy.drain) return this.drainTurn();
|
|
6049
|
+
async syncStale(opts) {
|
|
6050
|
+
if (this.indexStrategy.drain) return this.drainTurn(void 0, { mode: "full", ids: opts?.ids });
|
|
5987
6051
|
const ids = [...this.staleEntities];
|
|
5988
6052
|
await Promise.all(ids.map((id) => this.syncEntries(id, [])));
|
|
6053
|
+
return true;
|
|
5989
6054
|
}
|
|
5990
6055
|
/**
|
|
5991
6056
|
* Clears the parsed vector cache. Useful for mid-loop flush guarantees
|