@equationalapplications/core-llm-wiki 5.1.1 → 5.2.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.
- package/dist/{chunk-YKXCMOHH.mjs → chunk-J3N3WRK7.mjs} +84 -7
- package/dist/chunk-J3N3WRK7.mjs.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +304 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +224 -20
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-DCRNie7k.d.mts → testing-DyXISRwS.d.mts} +137 -1
- package/dist/{testing-DCRNie7k.d.ts → testing-DyXISRwS.d.ts} +137 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +81 -4
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-YKXCMOHH.mjs.map +0 -1
|
@@ -64,6 +64,15 @@ var WikiBusyError = class extends Error {
|
|
|
64
64
|
this.entityId = entityId;
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
|
+
var WikiDuplicateHashError = class extends Error {
|
|
68
|
+
constructor(params) {
|
|
69
|
+
super(`Duplicate source hash for entity ${params.entityId}; another ref already holds this content`);
|
|
70
|
+
this.name = "WikiDuplicateHashError";
|
|
71
|
+
this.canonical = params.canonical;
|
|
72
|
+
this.sourceHash = params.sourceHash;
|
|
73
|
+
this.entityId = params.entityId;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
67
76
|
var WikiTransactionError = class extends Error {
|
|
68
77
|
constructor(message, options) {
|
|
69
78
|
super(message, options);
|
|
@@ -693,6 +702,19 @@ var JobManager = class {
|
|
|
693
702
|
return this.activeMaintenanceJobs.has(this.lockKeyFns[operation](entityId)) || this.activeMaintenanceJobs.has(this._pruneKey(entityId)) || this._isReembedActive(entityId) || this._isImportActiveFor(entityId) || this._isForgetActiveFor(entityId);
|
|
694
703
|
case "prune":
|
|
695
704
|
return this.activeMaintenanceJobs.has(this._pruneKey(entityId)) || this.activeMaintenanceJobs.has(this._librarianKey(entityId)) || this.activeMaintenanceJobs.has(this._healKey(entityId)) || this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId)) || this._isReembedActive(entityId) || this._isIngestActiveFor(entityId) || this._isImportActiveFor(entityId) || this._isForgetActiveFor(entityId);
|
|
705
|
+
case "reembed":
|
|
706
|
+
return this.activeMaintenanceJobs.has(this._reembedKey(entityId)) || this.activeMaintenanceJobs.has(this._globalReembedKey()) || this.activeMaintenanceJobs.has(this._pruneKey(entityId)) || this.activeMaintenanceJobs.has(this._librarianKey(entityId)) || this.activeMaintenanceJobs.has(this._healKey(entityId)) || this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId)) || this._isIngestActiveFor(entityId) || this._isImportActiveFor(entityId) || this._isForgetActiveFor(entityId);
|
|
707
|
+
case "global_reembed":
|
|
708
|
+
return this.activeMaintenanceJobs.has(this._globalReembedKey()) || this._isAnyMaintenanceActiveWithSuffix(":reembed") || this._isAnyMaintenanceActiveWithSuffix(":prune") || this._isAnyMaintenanceActiveWithSuffix(":librarian") || this._isAnyMaintenanceActiveWithSuffix(":heal") || this._isAnyMaintenanceActiveWithSuffix(":ontologyBackfill") || this.activeIngestJobs.size > 0 || this._isAnyMaintenanceActiveWithSuffix(":import") || this._isAnyMaintenanceActiveWithSuffix(":forget");
|
|
709
|
+
case "import":
|
|
710
|
+
case "forget": {
|
|
711
|
+
const selfKey = operation === "import" ? this._importKey(entityId) : this._forgetKey(entityId);
|
|
712
|
+
return this.activeMaintenanceJobs.has(selfKey) || this.activeMaintenanceJobs.has(this._librarianKey(entityId)) || this.activeMaintenanceJobs.has(this._healKey(entityId)) || this.activeMaintenanceJobs.has(this._ontologyBackfillKey(entityId)) || this.activeMaintenanceJobs.has(this._pruneKey(entityId)) || this._isReembedActive(entityId) || this._isIngestActiveFor(entityId) || this._isImportActiveFor(entityId) || this._isForgetActiveFor(entityId);
|
|
713
|
+
}
|
|
714
|
+
case "global_import":
|
|
715
|
+
return this.activeMaintenanceJobs.has(this._globalImportKey());
|
|
716
|
+
case "ingest":
|
|
717
|
+
return this._hasIngestJob(entityId) || this.activeMaintenanceJobs.has(this._pruneKey(entityId)) || this._isReembedActive(entityId) || this._isImportActiveFor(entityId) || this._isForgetActiveFor(entityId);
|
|
696
718
|
default:
|
|
697
719
|
return false;
|
|
698
720
|
}
|
|
@@ -1159,11 +1181,23 @@ var IngestionService = class {
|
|
|
1159
1181
|
this.ontologyService = ontologyService;
|
|
1160
1182
|
this.promptService = promptService ?? new PromptService(this.options.config?.prompts);
|
|
1161
1183
|
}
|
|
1162
|
-
async ingestDocument(entityId, params) {
|
|
1184
|
+
async ingestDocument(entityId, params, opts) {
|
|
1163
1185
|
const sourceRef = normalizeSourceRef(params.sourceRef);
|
|
1164
1186
|
if (!sourceRef) throw new Error("Invalid sourceRef");
|
|
1165
1187
|
const sourceHash = normalizeSourceHash(params.sourceHash);
|
|
1166
1188
|
if (!sourceHash) throw new Error("Invalid sourceHash (must be 64-char hex string)");
|
|
1189
|
+
const onDuplicateHash = opts?.onDuplicateHash ?? "ingest";
|
|
1190
|
+
if (onDuplicateHash !== "ingest") {
|
|
1191
|
+
const refs = await this.entryRepo.findSourceRefsByHash(entityId, sourceHash);
|
|
1192
|
+
const others = refs.filter((r) => r !== sourceRef);
|
|
1193
|
+
if (others.length > 0) {
|
|
1194
|
+
const canonical = others[0];
|
|
1195
|
+
if (onDuplicateHash === "throw") {
|
|
1196
|
+
throw new WikiDuplicateHashError({ canonical, sourceHash, entityId });
|
|
1197
|
+
}
|
|
1198
|
+
return { truncated: false, chunks: 0, duplicateOf: canonical };
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1167
1201
|
const maxChunkLength = params.maxChunkLength ?? this.options.config?.maxChunkLength ?? DEFAULT_MAX_CHUNK_LENGTH;
|
|
1168
1202
|
const rawOverlap = params.chunkOverlap ?? this.options.config?.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;
|
|
1169
1203
|
const chunkOverlap = Math.min(
|
|
@@ -1739,10 +1773,13 @@ var MaintenanceService = class {
|
|
|
1739
1773
|
this.jobManager.releaseLock(op, entityId ?? "*");
|
|
1740
1774
|
}
|
|
1741
1775
|
}
|
|
1742
|
-
async forget(entityId, params) {
|
|
1776
|
+
async forget(entityId, params, opts) {
|
|
1743
1777
|
if (params.clearAll && (params.entryId !== void 0 || params.taskId !== void 0 || params.sourceRef !== void 0 || params.sourceHash !== void 0)) {
|
|
1744
1778
|
throw new Error("forget() clearAll is mutually exclusive with entryId, taskId, sourceRef, and sourceHash");
|
|
1745
1779
|
}
|
|
1780
|
+
if (opts?.dryRun === true) {
|
|
1781
|
+
return this.forgetDryRun(entityId, params);
|
|
1782
|
+
}
|
|
1746
1783
|
this.jobManager.acquireLock("forget", entityId);
|
|
1747
1784
|
try {
|
|
1748
1785
|
const now = Date.now();
|
|
@@ -1803,11 +1840,42 @@ var MaintenanceService = class {
|
|
|
1803
1840
|
throw new Error(`forget(${entityId}/${factId}) failed: ANN cleanup hook rejected`, { cause: this._sanitizeRankerError(hookErr) });
|
|
1804
1841
|
}
|
|
1805
1842
|
}
|
|
1806
|
-
return { deleted: { entries: deletedEntries, tasks: deletedTasks } };
|
|
1843
|
+
return params.clearAll ? { deleted: { entries: deletedEntries, tasks: deletedTasks }, metadataReset: true } : { deleted: { entries: deletedEntries, tasks: deletedTasks } };
|
|
1807
1844
|
} finally {
|
|
1808
1845
|
this.jobManager.releaseLock("forget", entityId);
|
|
1809
1846
|
}
|
|
1810
1847
|
}
|
|
1848
|
+
/**
|
|
1849
|
+
* Read-only dry-run preview of {@link forget}. Returns the same shape as a
|
|
1850
|
+
* real call would, without acquiring the lock, opening a transaction, staging
|
|
1851
|
+
* outbox events, or firing embedding hooks. Counts may be off-by-N during a
|
|
1852
|
+
* concurrent real forget — this is accepted, not considered a bug.
|
|
1853
|
+
*
|
|
1854
|
+
* `metadataReset` mirrors the real call: only `clearAll: true` returns true,
|
|
1855
|
+
* because only `clearAll` actually resets the metadata checkpoint.
|
|
1856
|
+
* `standard` (sourceRef/sourceHash) returns no metadataReset field, just like
|
|
1857
|
+
* the real call. `entryId`/`taskId` selectors are rejected with a clear error
|
|
1858
|
+
* (the spec keeps dry-run narrow).
|
|
1859
|
+
*/
|
|
1860
|
+
async forgetDryRun(entityId, params) {
|
|
1861
|
+
if (params.entryId !== void 0 || params.taskId !== void 0) {
|
|
1862
|
+
throw new Error("forget({ dryRun: true }) does not support entryId/taskId selectors; use sourceRef/sourceHash or clearAll");
|
|
1863
|
+
}
|
|
1864
|
+
if (params.clearAll) {
|
|
1865
|
+
const entries2 = await this.entryRepo.countLiveByEntityId(entityId);
|
|
1866
|
+
const tasks = await this.taskRepo.countLiveByEntityId(entityId);
|
|
1867
|
+
return { deleted: { entries: entries2, tasks }, metadataReset: true };
|
|
1868
|
+
}
|
|
1869
|
+
const sourceRef = params.sourceRef !== void 0 ? normalizeSourceRef(params.sourceRef) : null;
|
|
1870
|
+
if (params.sourceRef !== void 0 && !sourceRef) throw new Error("Invalid sourceRef");
|
|
1871
|
+
const sourceHash = params.sourceHash !== void 0 ? normalizeSourceHash(params.sourceHash) : null;
|
|
1872
|
+
if (params.sourceHash !== void 0 && !sourceHash) throw new Error("Invalid sourceHash (must be 64-char hex string)");
|
|
1873
|
+
if (sourceRef === null && sourceHash === null) {
|
|
1874
|
+
return { deleted: { entries: 0, tasks: 0 } };
|
|
1875
|
+
}
|
|
1876
|
+
const entries = await this.entryRepo.countLiveBySource(entityId, sourceRef, sourceHash);
|
|
1877
|
+
return { deleted: { entries, tasks: 0 } };
|
|
1878
|
+
}
|
|
1811
1879
|
/** Core librarian pass (locks handled by {@link runLibrarian}). Package-internal orchestration hook. */
|
|
1812
1880
|
async doRunLibrarian(entityId, promptOverride) {
|
|
1813
1881
|
const events = await this.eventRepo.getRecent(entityId, 50);
|
|
@@ -2531,6 +2599,15 @@ var ImportExportService = class {
|
|
|
2531
2599
|
const safeTitle = clip(String(fact.title ?? ""), IMPORT_TITLE_MAX);
|
|
2532
2600
|
const safeBody = clip(String(fact.body ?? ""), IMPORT_BODY_MAX);
|
|
2533
2601
|
clippedTextByFactId.set(fact.id, { title: safeTitle, body: safeBody });
|
|
2602
|
+
let normalizedSourceRef = null;
|
|
2603
|
+
if (fact.source_ref !== null && fact.source_ref !== void 0) {
|
|
2604
|
+
normalizedSourceRef = normalizeSourceRef(fact.source_ref);
|
|
2605
|
+
if (normalizedSourceRef === null) {
|
|
2606
|
+
throw new Error(
|
|
2607
|
+
`importDump: invalid source_ref ${JSON.stringify(fact.source_ref)} for entity "${entityId}" fact "${fact.id}" (must normalize to a non-empty string; see ingestDocument's sourceRef validation)`
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2534
2611
|
const factObj = {
|
|
2535
2612
|
id: fact.id,
|
|
2536
2613
|
entity_id: entityId,
|
|
@@ -2540,7 +2617,7 @@ var ImportExportService = class {
|
|
|
2540
2617
|
confidence: fact.confidence,
|
|
2541
2618
|
source_type: sourceType,
|
|
2542
2619
|
source_hash: fact.source_hash,
|
|
2543
|
-
source_ref:
|
|
2620
|
+
source_ref: normalizedSourceRef,
|
|
2544
2621
|
created_at: fact.created_at,
|
|
2545
2622
|
updated_at: safeUpdatedAt,
|
|
2546
2623
|
last_accessed_at: fact.last_accessed_at,
|
|
@@ -3553,6 +3630,6 @@ var WriteService = class {
|
|
|
3553
3630
|
}
|
|
3554
3631
|
};
|
|
3555
3632
|
|
|
3556
|
-
export { BaseRepository, DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, EmbeddingService, HEAL_BATCH_SIZE, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ImportExportService, IngestionService, JobManager, MaintenanceService, MetadataRepository, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, RetrievalService, SearchService, WikiBusyError, WikiTransactionError, WriteService, __privateAdd, __privateGet, __privateSet, chunkText, configureRandomSource, emptyManifest, entitySummaryMetaKey, extractSqliteCode, generateId, normalizeSourceHash, normalizeSourceRef, normalizeTitleKey, parseEmbedding, resolveEdgeDefinitions, resolveNodeType, safeSlice, validateInlineEdges, validateManifest };
|
|
3557
|
-
//# sourceMappingURL=chunk-
|
|
3558
|
-
//# sourceMappingURL=chunk-
|
|
3633
|
+
export { BaseRepository, DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, EmbeddingService, HEAL_BATCH_SIZE, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ImportExportService, IngestionService, JobManager, MaintenanceService, MetadataRepository, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, RetrievalService, SearchService, WikiBusyError, WikiDuplicateHashError, WikiTransactionError, WriteService, __privateAdd, __privateGet, __privateSet, chunkText, configureRandomSource, emptyManifest, entitySummaryMetaKey, extractSqliteCode, generateId, normalizeSourceHash, normalizeSourceRef, normalizeTitleKey, parseEmbedding, resolveEdgeDefinitions, resolveNodeType, safeSlice, validateInlineEdges, validateManifest };
|
|
3634
|
+
//# sourceMappingURL=chunk-J3N3WRK7.mjs.map
|
|
3635
|
+
//# sourceMappingURL=chunk-J3N3WRK7.mjs.map
|