@equationalapplications/core-llm-wiki 7.2.1 → 7.4.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/README.md +48 -0
- package/dist/{chunk-TTECJ3S3.mjs → chunk-G5OR2VWD.mjs} +371 -49
- package/dist/chunk-G5OR2VWD.mjs.map +1 -0
- package/dist/index.d.mts +3 -5
- package/dist/index.d.ts +3 -5
- package/dist/index.js +501 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +134 -13
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-DYeMd9d1.d.mts → testing-Dmh1kfkd.d.mts} +171 -7
- package/dist/{testing-DYeMd9d1.d.ts → testing-Dmh1kfkd.d.ts} +171 -7
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +353 -46
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-TTECJ3S3.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __privateAdd, MetadataRepository, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, entitySummaryMetaKey, WikiSourceRefHashCollision, validateManifest, generateId, BaseRepository, WikiGraphNodeOwnershipConflict, emptyManifest, resolveNodeType, WikiStrictOntologyViolation, validateInlineEdges, resolveEdgeDefinitions, typeSatisfies, normalizeTitleKey, WikiTransactionError, extractSqliteCode } from './chunk-
|
|
2
|
-
export { DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, WikiBusyError, WikiDuplicateHashError, WikiGraphNodeOwnershipConflict, WikiIngestEmptyError, WikiInvalidReadOptions, WikiParseError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiTransactionError, chunkText, configureRandomSource, parseEmbedding, safeSlice, validateManifest } from './chunk-
|
|
1
|
+
import { __privateAdd, MetadataRepository, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, entitySummaryMetaKey, WikiSourceRefHashCollision, DiagnosticBuffer, validateManifest, WikiDraftNotFound, generateId, BaseRepository, WikiGraphNodeOwnershipConflict, emptyManifest, resolveNodeType, WikiStrictOntologyViolation, validateInlineEdges, resolveEdgeDefinitions, typeSatisfies, normalizeTitleKey, WikiTransactionError, extractSqliteCode } from './chunk-G5OR2VWD.mjs';
|
|
2
|
+
export { DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, WikiBusyError, WikiDraftNotFound, WikiDuplicateHashError, WikiGraphNodeOwnershipConflict, WikiIngestEmptyError, WikiInvalidReadOptions, WikiParseError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiTransactionError, chunkText, configureRandomSource, parseEmbedding, safeSlice, validateManifest } from './chunk-G5OR2VWD.mjs';
|
|
3
3
|
import { appendRelatedSection, buildConceptDocument, buildLogMd, buildEntityIndexMd, buildRootIndexMd, isAllowedOkfPath, parseRootIndexMd, parseEntityIndexMd, parseConcept, splitRelatedSection, extractMarkdownLinks, parseLogMd, parseEventIdComment, latestVerified, formatSourcesJson, appendEventIdComment, parseVerifiedFlexible, parseCitationsList, deriveTrustTier, isStaleAfter } from '@equationalapplications/core-okf';
|
|
4
4
|
|
|
5
5
|
// src/db/schema.ts
|
|
@@ -1569,16 +1569,52 @@ var EntryRepository = class extends BaseRepository {
|
|
|
1569
1569
|
`UPDATE ${this.prefix}entries SET source_type = 'librarian_inferred' WHERE source_type = 'agent_inferred';`
|
|
1570
1570
|
].join("\n");
|
|
1571
1571
|
}
|
|
1572
|
-
async findRecentByEntityIds(entityIds, limit, tx) {
|
|
1572
|
+
async findRecentByEntityIds(entityIds, limit, tx, opts) {
|
|
1573
1573
|
if (entityIds.length === 0) return [];
|
|
1574
1574
|
const executor = this.getExecutor(tx);
|
|
1575
1575
|
const placeholders = entityIds.map(() => "?").join(",");
|
|
1576
|
+
const draftClause = opts?.excludeDrafts === true ? ` AND lifecycle_status != 'draft'` : "";
|
|
1576
1577
|
const rows = await executor.getAllAsync(
|
|
1577
|
-
`SELECT * FROM ${this.prefix}entries WHERE entity_id IN (${placeholders}) AND deleted_at IS NULL ORDER BY updated_at DESC LIMIT ?`,
|
|
1578
|
+
`SELECT * FROM ${this.prefix}entries WHERE entity_id IN (${placeholders}) AND deleted_at IS NULL${draftClause} ORDER BY updated_at DESC LIMIT ?`,
|
|
1578
1579
|
[...entityIds, limit]
|
|
1579
1580
|
);
|
|
1580
1581
|
return rows.map(mapRowToFact);
|
|
1581
1582
|
}
|
|
1583
|
+
/** IDs of live draft facts for the given entities (spec §5.1). Callers pass ≤ 100 entity ids. */
|
|
1584
|
+
async findDraftIdsByEntityIds(entityIds, tx) {
|
|
1585
|
+
if (entityIds.length === 0) return /* @__PURE__ */ new Set();
|
|
1586
|
+
const executor = this.getExecutor(tx);
|
|
1587
|
+
const placeholders = entityIds.map(() => "?").join(",");
|
|
1588
|
+
const rows = await executor.getAllAsync(
|
|
1589
|
+
`SELECT id FROM ${this.prefix}entries
|
|
1590
|
+
WHERE entity_id IN (${placeholders}) AND deleted_at IS NULL AND lifecycle_status = 'draft'`,
|
|
1591
|
+
[...entityIds]
|
|
1592
|
+
);
|
|
1593
|
+
return new Set(rows.map((r) => r.id));
|
|
1594
|
+
}
|
|
1595
|
+
/** Live drafts for one entity, newest first, keyset-paged by (created_at, id). */
|
|
1596
|
+
async listDraftsByEntityId(entityId, limit, after, tx) {
|
|
1597
|
+
const executor = this.getExecutor(tx);
|
|
1598
|
+
const afterClause = after ? ` AND (created_at < ? OR (created_at = ? AND id < ?))` : "";
|
|
1599
|
+
const args = after ? [entityId, after.createdAt, after.createdAt, after.id, limit] : [entityId, limit];
|
|
1600
|
+
const rows = await executor.getAllAsync(
|
|
1601
|
+
`SELECT * FROM ${this.prefix}entries
|
|
1602
|
+
WHERE entity_id = ? AND deleted_at IS NULL AND lifecycle_status = 'draft'${afterClause}
|
|
1603
|
+
ORDER BY created_at DESC, id DESC LIMIT ?`,
|
|
1604
|
+
args
|
|
1605
|
+
);
|
|
1606
|
+
return rows.map(mapRowToFact);
|
|
1607
|
+
}
|
|
1608
|
+
/** True iff `entryId` is a live draft owned by `entityId`. */
|
|
1609
|
+
async isLiveDraft(entryId, entityId, tx) {
|
|
1610
|
+
const executor = this.getExecutor(tx);
|
|
1611
|
+
const row = await executor.getFirstAsync(
|
|
1612
|
+
`SELECT id FROM ${this.prefix}entries
|
|
1613
|
+
WHERE id = ? AND entity_id = ? AND deleted_at IS NULL AND lifecycle_status = 'draft'`,
|
|
1614
|
+
[entryId, entityId]
|
|
1615
|
+
);
|
|
1616
|
+
return row != null;
|
|
1617
|
+
}
|
|
1582
1618
|
/**
|
|
1583
1619
|
* Live untyped facts eligible for ontology backfill, oldest first.
|
|
1584
1620
|
* Skips facts checked within the recheck cooldown (ontology_checked_at > recheckCutoff).
|
|
@@ -2365,6 +2401,7 @@ var EdgeRepository = class extends BaseRepository {
|
|
|
2365
2401
|
END
|
|
2366
2402
|
) >= ?
|
|
2367
2403
|
AND n.source_type NOT IN (${excludeSourceTypesPlaceholders})
|
|
2404
|
+
AND (? = 0 OR n.lifecycle_status != 'draft')
|
|
2368
2405
|
WHERE w.depth < ?
|
|
2369
2406
|
AND instr(w.visited, ',' || (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END) || ',') = 0
|
|
2370
2407
|
)
|
|
@@ -2384,6 +2421,7 @@ var EdgeRepository = class extends BaseRepository {
|
|
|
2384
2421
|
entityId,
|
|
2385
2422
|
minConfidenceRank,
|
|
2386
2423
|
...opts.excludeSourceTypes,
|
|
2424
|
+
opts.excludeDrafts === true ? 1 : 0,
|
|
2387
2425
|
opts.maxDepth,
|
|
2388
2426
|
opts.maxNodes
|
|
2389
2427
|
];
|
|
@@ -2499,6 +2537,17 @@ var OntologyService = class {
|
|
|
2499
2537
|
const canonical = resolveNodeType(rawType, manifest);
|
|
2500
2538
|
if (!canonical) {
|
|
2501
2539
|
if (strict) throw new WikiStrictOntologyViolation(opts?.entityId ?? "", "node", rawType);
|
|
2540
|
+
if (opts?.drops && Array.isArray(fact.edges)) {
|
|
2541
|
+
for (const edge of fact.edges) {
|
|
2542
|
+
opts.drops.push({
|
|
2543
|
+
reason: "no_source_type",
|
|
2544
|
+
sourceId: null,
|
|
2545
|
+
edgeType: typeof edge?.edge_type === "string" ? edge.edge_type : null,
|
|
2546
|
+
sourceNodeType: null,
|
|
2547
|
+
targetNodeType: null
|
|
2548
|
+
});
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2502
2551
|
return { okf_type: null, edges: [] };
|
|
2503
2552
|
}
|
|
2504
2553
|
const edges = validateInlineEdges(canonical, null, fact.edges ?? [], manifest, opts);
|
|
@@ -2511,18 +2560,39 @@ var OntologyService = class {
|
|
|
2511
2560
|
* writes inside their own transaction (e.g. `IngestionService.ingestDocument`
|
|
2512
2561
|
* when delegating to `upsertGraphCore`).
|
|
2513
2562
|
*/
|
|
2514
|
-
resolveEdges(entityId, sourceId, sourceType, edges, manifest, titleIndex, now) {
|
|
2515
|
-
if (
|
|
2563
|
+
resolveEdges(entityId, sourceId, sourceType, edges, manifest, titleIndex, now, drops) {
|
|
2564
|
+
if (edges.length === 0) return [];
|
|
2565
|
+
if (!sourceType) {
|
|
2566
|
+
for (const edge of edges) {
|
|
2567
|
+
drops?.push({ reason: "no_source_type", sourceId, edgeType: edge.edge_type, sourceNodeType: null, targetNodeType: null });
|
|
2568
|
+
}
|
|
2569
|
+
return [];
|
|
2570
|
+
}
|
|
2516
2571
|
const out = [];
|
|
2517
2572
|
for (const edge of edges) {
|
|
2518
2573
|
const candidates = resolveEdgeDefinitions(edge.edge_type, manifest).filter((d) => typeSatisfies(d.source_type, sourceType, manifest));
|
|
2519
|
-
if (candidates.length === 0)
|
|
2574
|
+
if (candidates.length === 0) {
|
|
2575
|
+
drops?.push({ reason: "type_not_in_manifest", sourceId, edgeType: edge.edge_type, sourceNodeType: sourceType, targetNodeType: null });
|
|
2576
|
+
continue;
|
|
2577
|
+
}
|
|
2520
2578
|
const targetKey = normalizeTitleKey(edge.target_title);
|
|
2521
2579
|
const target = titleIndex.get(targetKey);
|
|
2522
|
-
if (!target)
|
|
2580
|
+
if (!target) {
|
|
2581
|
+
drops?.push({ reason: "target_not_found", sourceId, edgeType: edge.edge_type, sourceNodeType: sourceType, targetNodeType: null });
|
|
2582
|
+
continue;
|
|
2583
|
+
}
|
|
2523
2584
|
const targetType = (target.okf_type ?? "").trim().toLowerCase();
|
|
2524
2585
|
const def = candidates.find((d) => d.target_type.trim().toLowerCase() === targetType) ?? candidates.find((d) => typeSatisfies(d.target_type, targetType, manifest));
|
|
2525
|
-
if (!def)
|
|
2586
|
+
if (!def) {
|
|
2587
|
+
drops?.push({
|
|
2588
|
+
reason: "target_type_mismatch",
|
|
2589
|
+
sourceId,
|
|
2590
|
+
edgeType: edge.edge_type,
|
|
2591
|
+
sourceNodeType: sourceType,
|
|
2592
|
+
targetNodeType: target.okf_type ?? null
|
|
2593
|
+
});
|
|
2594
|
+
continue;
|
|
2595
|
+
}
|
|
2526
2596
|
out.push({
|
|
2527
2597
|
id: generateId(),
|
|
2528
2598
|
entity_id: entityId,
|
|
@@ -2541,8 +2611,8 @@ var OntologyService = class {
|
|
|
2541
2611
|
* want self-contained edge persistence (e.g. MaintenanceService heal /
|
|
2542
2612
|
* backfill callers that do not have a separate edge-write step).
|
|
2543
2613
|
*/
|
|
2544
|
-
async resolveAndPersistEdges(entityId, sourceId, sourceType, edges, manifest, titleIndex, tx, now) {
|
|
2545
|
-
const resolved = this.resolveEdges(entityId, sourceId, sourceType, edges, manifest, titleIndex, now);
|
|
2614
|
+
async resolveAndPersistEdges(entityId, sourceId, sourceType, edges, manifest, titleIndex, tx, now, drops) {
|
|
2615
|
+
const resolved = this.resolveEdges(entityId, sourceId, sourceType, edges, manifest, titleIndex, now, drops);
|
|
2546
2616
|
let persisted = 0;
|
|
2547
2617
|
for (const edge of resolved) {
|
|
2548
2618
|
const inserted = await this.edgeRepo.addIgnoreDuplicate(edge, tx);
|
|
@@ -2571,6 +2641,7 @@ var GraphTraversalService = class {
|
|
|
2571
2641
|
edgeTypes: options.edgeTypes,
|
|
2572
2642
|
minConfidence: options.minTraversalConfidence ?? this.config.minTraversalConfidence ?? "tentative",
|
|
2573
2643
|
excludeSourceTypes: options.excludeSourceTypes ?? this.config.excludeSourceTypes ?? [],
|
|
2644
|
+
excludeDrafts: options.excludeDrafts ?? this.config.excludeDrafts ?? false,
|
|
2574
2645
|
maxNodes
|
|
2575
2646
|
};
|
|
2576
2647
|
const { nodeIds, edges } = await this.edgeRepo.getNeighborhood(entityId, options.sourceId, opts);
|
|
@@ -2744,6 +2815,15 @@ var OkfTrustWritesRepository = class {
|
|
|
2744
2815
|
|
|
2745
2816
|
// src/WikiMemory.ts
|
|
2746
2817
|
var TABLE_PREFIX_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,30}_$/;
|
|
2818
|
+
function decodeDraftCursor(cursor) {
|
|
2819
|
+
const sep = typeof cursor === "string" ? cursor.indexOf(":") : -1;
|
|
2820
|
+
const createdAt = sep > 0 ? Number(cursor.slice(0, sep)) : Number.NaN;
|
|
2821
|
+
const id = sep > 0 ? cursor.slice(sep + 1) : "";
|
|
2822
|
+
if (!Number.isSafeInteger(createdAt) || id.length === 0) {
|
|
2823
|
+
throw new TypeError("Invalid listDrafts cursor.");
|
|
2824
|
+
}
|
|
2825
|
+
return { createdAt, id };
|
|
2826
|
+
}
|
|
2747
2827
|
var _testAccessNonTestEnvWarned;
|
|
2748
2828
|
var WikiMemory = class {
|
|
2749
2829
|
constructor(db, options) {
|
|
@@ -3163,11 +3243,15 @@ var WikiMemory = class {
|
|
|
3163
3243
|
attemptedSourceRef: sourceRef
|
|
3164
3244
|
});
|
|
3165
3245
|
}
|
|
3166
|
-
|
|
3246
|
+
const diagBuffer = new DiagnosticBuffer();
|
|
3247
|
+
const result = await this.ingestionService.upsertGraphCore(
|
|
3167
3248
|
entityId,
|
|
3168
3249
|
{ sourceRef, sourceHash, nodes: params.nodes, edges: params.edges },
|
|
3169
|
-
adapter
|
|
3250
|
+
adapter,
|
|
3251
|
+
{ diag: { buffer: diagBuffer, operation: "upsertGraph" } }
|
|
3170
3252
|
);
|
|
3253
|
+
diagBuffer.flush(this.options);
|
|
3254
|
+
return result;
|
|
3171
3255
|
}
|
|
3172
3256
|
/**
|
|
3173
3257
|
* Returns up to `limit` unprocessed outbox events, oldest first.
|
|
@@ -3284,6 +3368,43 @@ var WikiMemory = class {
|
|
|
3284
3368
|
async setLifecycleStatus(entryId, entityId, status) {
|
|
3285
3369
|
return this.okfTrustWrites.setLifecycleStatus(entryId, entityId, status);
|
|
3286
3370
|
}
|
|
3371
|
+
/**
|
|
3372
|
+
* Live draft facts for one entity, newest first (spec §5.2). Default page
|
|
3373
|
+
* size 50, clamped to [1, 500]. Pass `nextCursor` back unchanged for the next page.
|
|
3374
|
+
*/
|
|
3375
|
+
async listDrafts(entityId, options) {
|
|
3376
|
+
const rawLimit = options?.limit;
|
|
3377
|
+
const limit = typeof rawLimit === "number" && Number.isFinite(rawLimit) ? Math.min(500, Math.max(1, Math.floor(rawLimit))) : 50;
|
|
3378
|
+
const after = options?.cursor === void 0 ? null : decodeDraftCursor(options.cursor);
|
|
3379
|
+
const rows = await this.entryRepo.listDraftsByEntityId(entityId, limit + 1, after);
|
|
3380
|
+
const facts = rows.slice(0, limit);
|
|
3381
|
+
const last = facts[facts.length - 1];
|
|
3382
|
+
return {
|
|
3383
|
+
facts,
|
|
3384
|
+
nextCursor: rows.length > limit && last ? `${last.created_at}:${last.id}` : null
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3387
|
+
/**
|
|
3388
|
+
* Promote a draft to `stable` and record who reviewed it, atomically
|
|
3389
|
+
* (spec §5.2). Metadata writes only: `updated_at` is not bumped and no
|
|
3390
|
+
* outbox event is pushed. Pass `by: 'human:<id>'` so `trustTier` becomes
|
|
3391
|
+
* `'human-reviewed'`.
|
|
3392
|
+
*
|
|
3393
|
+
* @throws WikiDraftNotFound when no live draft with that id exists for the entity.
|
|
3394
|
+
*/
|
|
3395
|
+
async promoteDraft(entryId, entityId, reviewer) {
|
|
3396
|
+
const by = reviewer?.by;
|
|
3397
|
+
if (typeof by !== "string" || by.trim().length === 0) {
|
|
3398
|
+
throw new TypeError("promoteDraft requires reviewer.by to be a non-empty string.");
|
|
3399
|
+
}
|
|
3400
|
+
await this.db.withTransactionAsync(async (tx) => {
|
|
3401
|
+
if (!await this.entryRepo.isLiveDraft(entryId, entityId, tx)) {
|
|
3402
|
+
throw new WikiDraftNotFound();
|
|
3403
|
+
}
|
|
3404
|
+
await this.okfTrustWrites.setLifecycleStatus(entryId, entityId, "stable", tx);
|
|
3405
|
+
await this.okfTrustWrites.writeOkfTrust(entryId, entityId, [{ by, at: (/* @__PURE__ */ new Date()).toISOString() }], tx);
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3287
3408
|
/** Set a fact's stale_after (epoch ms) or clear it. Does NOT touch `updated_at`. */
|
|
3288
3409
|
async setStaleAfter(entryId, entityId, date) {
|
|
3289
3410
|
return this.okfTrustWrites.setStaleAfter(entryId, entityId, date);
|