@equationalapplications/core-llm-wiki 4.16.0 → 4.17.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-2BGLPRT3.mjs → chunk-M74FCWLB.mjs} +2 -2
- package/dist/chunk-M74FCWLB.mjs.map +1 -0
- package/dist/index.d.mts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +177 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +179 -11
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-BMsplvLy.d.mts → testing-D02cdI9A.d.mts} +66 -1
- package/dist/{testing-BMsplvLy.d.ts → testing-D02cdI9A.d.ts} +66 -1
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-2BGLPRT3.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { __privateAdd, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, generateId, validateManifest, emptyManifest, mergeOntologyUpdates, resolveNodeType, validateInlineEdges, resolveEdgeDefinition, normalizeTitleKey } from './chunk-
|
|
2
|
-
export { HOOK_TIMEOUT_MARKER, PromptService, PrunePartialFailureError, WikiBusyError, parseEmbedding } from './chunk-
|
|
1
|
+
import { __privateAdd, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, generateId, validateManifest, emptyManifest, mergeOntologyUpdates, resolveNodeType, validateInlineEdges, resolveEdgeDefinition, normalizeTitleKey } from './chunk-M74FCWLB.mjs';
|
|
2
|
+
export { HOOK_TIMEOUT_MARKER, PromptService, PrunePartialFailureError, WikiBusyError, parseEmbedding } from './chunk-M74FCWLB.mjs';
|
|
3
3
|
import { buildConceptDocument, buildLogMd, buildIndexMd, buildRootIndexMd, parseConcept, extractMarkdownLinks, parseLogMd } from '@equationalapplications/core-okf';
|
|
4
4
|
|
|
5
5
|
// src/db/schema.ts
|
|
@@ -1379,6 +1379,11 @@ var EventRepository = class extends BaseRepository {
|
|
|
1379
1379
|
};
|
|
1380
1380
|
|
|
1381
1381
|
// src/repositories/EdgeRepository.ts
|
|
1382
|
+
var CONFIDENCE_RANK = {
|
|
1383
|
+
tentative: 0,
|
|
1384
|
+
inferred: 1,
|
|
1385
|
+
certain: 2
|
|
1386
|
+
};
|
|
1382
1387
|
var EdgeRepository = class extends BaseRepository {
|
|
1383
1388
|
/**
|
|
1384
1389
|
* Insert an edge, silently skipping on primary-key or uniqueness conflicts.
|
|
@@ -1409,21 +1414,111 @@ var EdgeRepository = class extends BaseRepository {
|
|
|
1409
1414
|
`SELECT * FROM ${this.prefix}edges WHERE entity_id = ? ORDER BY created_at ASC`,
|
|
1410
1415
|
[entityId]
|
|
1411
1416
|
);
|
|
1412
|
-
return rows.map(
|
|
1413
|
-
id: String(row.id),
|
|
1414
|
-
entity_id: String(row.entity_id),
|
|
1415
|
-
source_id: String(row.source_id),
|
|
1416
|
-
target_id: String(row.target_id),
|
|
1417
|
-
edge_type: String(row.edge_type),
|
|
1418
|
-
created_at: Number(row.created_at)
|
|
1419
|
-
}));
|
|
1417
|
+
return rows.map(mapRowToEdge);
|
|
1420
1418
|
}
|
|
1421
1419
|
/** Hard delete — edges have no soft-delete concept, only presence/absence. `tx` is REQUIRED. */
|
|
1422
1420
|
async bulkDeleteByEntityId(entityId, tx) {
|
|
1423
1421
|
const executor = this.getExecutor(tx);
|
|
1424
1422
|
await executor.runAsync(`DELETE FROM ${this.prefix}edges WHERE entity_id = ?`, [entityId]);
|
|
1425
1423
|
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Multi-hop traversal from `sourceId` via SQLite `WITH RECURSIVE`. All filtering,
|
|
1426
|
+
* dead-ending, cycle-guarding, capping, and ordering happens in this one query.
|
|
1427
|
+
* The anchor is validated (exists, right entity, not soft-deleted) but never gated
|
|
1428
|
+
* by confidence/source_type — only nodes discovered beyond it are.
|
|
1429
|
+
*/
|
|
1430
|
+
async getNeighborhood(entityId, sourceId, opts, tx) {
|
|
1431
|
+
const executor = this.getExecutor(tx);
|
|
1432
|
+
if (opts.edgeTypes && opts.edgeTypes.length === 0) {
|
|
1433
|
+
const anchor = await executor.getFirstAsync(
|
|
1434
|
+
`SELECT id FROM ${this.prefix}entries WHERE id = ? AND entity_id = ? AND deleted_at IS NULL`,
|
|
1435
|
+
[sourceId, entityId]
|
|
1436
|
+
);
|
|
1437
|
+
return { nodeIds: anchor ? [anchor.id] : [], edges: [] };
|
|
1438
|
+
}
|
|
1439
|
+
const edgeTypesClause = opts.edgeTypes ? `e.edge_type IN (${opts.edgeTypes.map(() => "?").join(",")})` : "1=1";
|
|
1440
|
+
const excludeSourceTypesPlaceholders = opts.excludeSourceTypes.map(() => "?").join(",");
|
|
1441
|
+
const minConfidenceRank = CONFIDENCE_RANK[opts.minConfidence];
|
|
1442
|
+
const sql = `
|
|
1443
|
+
WITH RECURSIVE walk(node_id, depth, visited) AS (
|
|
1444
|
+
SELECT id, 0, ',' || id || ','
|
|
1445
|
+
FROM ${this.prefix}entries
|
|
1446
|
+
WHERE id = ? AND entity_id = ? AND deleted_at IS NULL
|
|
1447
|
+
|
|
1448
|
+
UNION
|
|
1449
|
+
|
|
1450
|
+
SELECT
|
|
1451
|
+
CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END,
|
|
1452
|
+
w.depth + 1,
|
|
1453
|
+
w.visited || (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END) || ','
|
|
1454
|
+
FROM walk w
|
|
1455
|
+
JOIN ${this.prefix}edges e
|
|
1456
|
+
ON e.entity_id = ?
|
|
1457
|
+
AND (
|
|
1458
|
+
(? != 'inbound' AND e.source_id = w.node_id) OR
|
|
1459
|
+
(? != 'outbound' AND e.target_id = w.node_id)
|
|
1460
|
+
)
|
|
1461
|
+
AND (${edgeTypesClause})
|
|
1462
|
+
JOIN ${this.prefix}entries n
|
|
1463
|
+
ON n.id = (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END)
|
|
1464
|
+
AND n.entity_id = ?
|
|
1465
|
+
AND n.deleted_at IS NULL
|
|
1466
|
+
AND (
|
|
1467
|
+
CASE n.confidence
|
|
1468
|
+
WHEN 'tentative' THEN 0
|
|
1469
|
+
WHEN 'inferred' THEN 1
|
|
1470
|
+
WHEN 'certain' THEN 2
|
|
1471
|
+
ELSE -1
|
|
1472
|
+
END
|
|
1473
|
+
) >= ?
|
|
1474
|
+
AND n.source_type NOT IN (${excludeSourceTypesPlaceholders})
|
|
1475
|
+
WHERE w.depth < ?
|
|
1476
|
+
AND instr(w.visited, ',' || (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END) || ',') = 0
|
|
1477
|
+
)
|
|
1478
|
+
SELECT node_id, MIN(depth) AS depth
|
|
1479
|
+
FROM walk
|
|
1480
|
+
GROUP BY node_id
|
|
1481
|
+
ORDER BY depth ASC, (SELECT updated_at FROM ${this.prefix}entries WHERE id = node_id) DESC
|
|
1482
|
+
LIMIT ?
|
|
1483
|
+
`;
|
|
1484
|
+
const params = [
|
|
1485
|
+
sourceId,
|
|
1486
|
+
entityId,
|
|
1487
|
+
entityId,
|
|
1488
|
+
opts.direction,
|
|
1489
|
+
opts.direction,
|
|
1490
|
+
...opts.edgeTypes ?? [],
|
|
1491
|
+
entityId,
|
|
1492
|
+
minConfidenceRank,
|
|
1493
|
+
...opts.excludeSourceTypes,
|
|
1494
|
+
opts.maxDepth,
|
|
1495
|
+
opts.maxNodes
|
|
1496
|
+
];
|
|
1497
|
+
const rows = await executor.getAllAsync(sql, params);
|
|
1498
|
+
const nodeIds = rows.map((r) => r.node_id);
|
|
1499
|
+
if (nodeIds.length === 0) return { nodeIds: [], edges: [] };
|
|
1500
|
+
const valueRows = nodeIds.map(() => "(?)").join(", ");
|
|
1501
|
+
const edgeRows = await executor.getAllAsync(
|
|
1502
|
+
`WITH neighborhood(node_id) AS (VALUES ${valueRows})
|
|
1503
|
+
SELECT e.* FROM ${this.prefix}edges e
|
|
1504
|
+
JOIN neighborhood ns ON e.source_id = ns.node_id
|
|
1505
|
+
JOIN neighborhood nt ON e.target_id = nt.node_id
|
|
1506
|
+
WHERE e.entity_id = ?`,
|
|
1507
|
+
[...nodeIds, entityId]
|
|
1508
|
+
);
|
|
1509
|
+
return { nodeIds, edges: edgeRows.map(mapRowToEdge) };
|
|
1510
|
+
}
|
|
1426
1511
|
};
|
|
1512
|
+
function mapRowToEdge(row) {
|
|
1513
|
+
return {
|
|
1514
|
+
id: String(row.id),
|
|
1515
|
+
entity_id: String(row.entity_id),
|
|
1516
|
+
source_id: String(row.source_id),
|
|
1517
|
+
target_id: String(row.target_id),
|
|
1518
|
+
edge_type: String(row.edge_type),
|
|
1519
|
+
created_at: Number(row.created_at)
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1427
1522
|
|
|
1428
1523
|
// src/repositories/MetadataRepository.ts
|
|
1429
1524
|
var MetadataRepository = class extends BaseRepository {
|
|
@@ -1670,6 +1765,38 @@ var OntologyService = class {
|
|
|
1670
1765
|
}
|
|
1671
1766
|
};
|
|
1672
1767
|
|
|
1768
|
+
// src/services/GraphTraversalService.ts
|
|
1769
|
+
var GraphTraversalService = class {
|
|
1770
|
+
constructor(edgeRepo, entryRepo, config) {
|
|
1771
|
+
this.edgeRepo = edgeRepo;
|
|
1772
|
+
this.entryRepo = entryRepo;
|
|
1773
|
+
this.config = config;
|
|
1774
|
+
}
|
|
1775
|
+
async traverseGraph(entityId, options) {
|
|
1776
|
+
const fallbackMaxNodes = 20;
|
|
1777
|
+
const rawConfigDefault = this.config.maxTraversalNodes ?? fallbackMaxNodes;
|
|
1778
|
+
const defaultMaxNodes = Number.isFinite(rawConfigDefault) && rawConfigDefault >= 1 ? Math.floor(rawConfigDefault) : fallbackMaxNodes;
|
|
1779
|
+
const rawMaxNodes = options.maxTraversalNodes ?? defaultMaxNodes;
|
|
1780
|
+
const maxNodes = Number.isFinite(rawMaxNodes) && rawMaxNodes >= 1 ? Math.floor(rawMaxNodes) : defaultMaxNodes;
|
|
1781
|
+
const opts = {
|
|
1782
|
+
maxDepth: Math.max(1, Math.min(options.maxDepth ?? 1, 3)),
|
|
1783
|
+
direction: options.direction ?? this.config.traversalDirection ?? "both",
|
|
1784
|
+
edgeTypes: options.edgeTypes,
|
|
1785
|
+
minConfidence: options.minTraversalConfidence ?? this.config.minTraversalConfidence ?? "tentative",
|
|
1786
|
+
excludeSourceTypes: options.excludeSourceTypes ?? this.config.excludeSourceTypes ?? [],
|
|
1787
|
+
maxNodes
|
|
1788
|
+
};
|
|
1789
|
+
const { nodeIds, edges } = await this.edgeRepo.getNeighborhood(entityId, options.sourceId, opts);
|
|
1790
|
+
if (nodeIds.length === 0) return { nodes: [], edges: [] };
|
|
1791
|
+
const nodes = await this.entryRepo.findByIds(nodeIds, [entityId]);
|
|
1792
|
+
const hydratedIds = new Set(nodes.map((node) => node.id));
|
|
1793
|
+
const filteredEdges = edges.filter(
|
|
1794
|
+
(edge) => hydratedIds.has(edge.source_id) && hydratedIds.has(edge.target_id)
|
|
1795
|
+
);
|
|
1796
|
+
return { nodes, edges: filteredEdges };
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1799
|
+
|
|
1673
1800
|
// src/WikiMemory.ts
|
|
1674
1801
|
var TABLE_PREFIX_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,30}_$/;
|
|
1675
1802
|
var _testAccessNonTestEnvWarned;
|
|
@@ -1753,6 +1880,11 @@ var WikiMemory = class {
|
|
|
1753
1880
|
this.jobManager,
|
|
1754
1881
|
this.maintenanceService
|
|
1755
1882
|
);
|
|
1883
|
+
this.graphTraversalService = new GraphTraversalService(
|
|
1884
|
+
this.edgeRepo,
|
|
1885
|
+
this.entryRepo,
|
|
1886
|
+
this.options.config ?? {}
|
|
1887
|
+
);
|
|
1756
1888
|
}
|
|
1757
1889
|
/**
|
|
1758
1890
|
* Explicit escape hatch for test suites: typed access to composed services for mocks/spies.
|
|
@@ -1773,6 +1905,7 @@ var WikiMemory = class {
|
|
|
1773
1905
|
searchService: this.searchService,
|
|
1774
1906
|
writeService: this.writeService,
|
|
1775
1907
|
promptService: this.promptService,
|
|
1908
|
+
graphTraversalService: this.graphTraversalService,
|
|
1776
1909
|
entryRepo: this.entryRepo,
|
|
1777
1910
|
metadataRepo: this.metadataRepo,
|
|
1778
1911
|
jobManager: this.jobManager
|
|
@@ -1843,6 +1976,9 @@ var WikiMemory = class {
|
|
|
1843
1976
|
async read(entityId, query, options) {
|
|
1844
1977
|
return this.retrievalService.read(entityId, query, options);
|
|
1845
1978
|
}
|
|
1979
|
+
async traverseGraph(entityId, options) {
|
|
1980
|
+
return this.graphTraversalService.traverseGraph(entityId, options);
|
|
1981
|
+
}
|
|
1846
1982
|
async getMemoryBundle(entityId) {
|
|
1847
1983
|
return this.importExportService.getFullBundle(entityId, { maxEvents: 10 });
|
|
1848
1984
|
}
|
|
@@ -2070,6 +2206,38 @@ function formatContext(bundle, options) {
|
|
|
2070
2206
|
return lines.join("\n");
|
|
2071
2207
|
}
|
|
2072
2208
|
|
|
2209
|
+
// src/utils/formatGraphContext.ts
|
|
2210
|
+
function formatGraphContext(neighborhood) {
|
|
2211
|
+
const { nodes, edges } = neighborhood;
|
|
2212
|
+
if (nodes.length === 0) return "";
|
|
2213
|
+
const nodeById = new Map(nodes.map((n) => [n.id, n]));
|
|
2214
|
+
const nodeIndex = new Map(nodes.map((n, i) => [n.id, i]));
|
|
2215
|
+
const lines = [];
|
|
2216
|
+
for (const node of nodes) {
|
|
2217
|
+
lines.push(`[${node.okf_type ?? "fact"}] ${node.title} (ID: ${node.id})`);
|
|
2218
|
+
const outbound = edgesByDirection(edges, node.id, "source_id", nodeById, nodeIndex);
|
|
2219
|
+
const inbound = edgesByDirection(edges, node.id, "target_id", nodeById, nodeIndex);
|
|
2220
|
+
for (const { edge, other } of outbound) {
|
|
2221
|
+
lines.push(` -[${edge.edge_type}]-> [${other.okf_type ?? "fact"}] ${other.title}`);
|
|
2222
|
+
}
|
|
2223
|
+
for (const { edge, other } of inbound) {
|
|
2224
|
+
lines.push(` <-[${edge.edge_type}]- [${other.okf_type ?? "fact"}] ${other.title}`);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
return lines.join("\n");
|
|
2228
|
+
}
|
|
2229
|
+
function edgesByDirection(edges, nodeId, endpoint, nodeById, nodeIndex) {
|
|
2230
|
+
const otherEndpoint = endpoint === "source_id" ? "target_id" : "source_id";
|
|
2231
|
+
return edges.filter((e) => e[endpoint] === nodeId).filter((e) => {
|
|
2232
|
+
const otherId = e[otherEndpoint];
|
|
2233
|
+
const selfIdx = nodeIndex.get(nodeId);
|
|
2234
|
+
const otherIdx = nodeIndex.get(otherId);
|
|
2235
|
+
return otherIdx !== void 0 && selfIdx < otherIdx;
|
|
2236
|
+
}).map((edge) => ({ edge, other: nodeById.get(edge[otherEndpoint]) })).sort(
|
|
2237
|
+
(a, b) => a.edge.edge_type.localeCompare(b.edge.edge_type) || a.other.title.localeCompare(b.other.title) || a.other.id.localeCompare(b.other.id) || a.edge.id.localeCompare(b.edge.id)
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2073
2241
|
// src/utils/sanitizeForFilename.ts
|
|
2074
2242
|
function shortHash(value) {
|
|
2075
2243
|
let h1 = 5381;
|
|
@@ -2578,6 +2746,6 @@ function createWiki(db, options) {
|
|
|
2578
2746
|
return new WikiMemory(db, options);
|
|
2579
2747
|
}
|
|
2580
2748
|
|
|
2581
|
-
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, WikiMemory, createWiki, formatContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseOkfBundle, validateLibrarianPromptTemplate };
|
|
2749
|
+
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, WikiMemory, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseOkfBundle, validateLibrarianPromptTemplate };
|
|
2582
2750
|
//# sourceMappingURL=index.mjs.map
|
|
2583
2751
|
//# sourceMappingURL=index.mjs.map
|