@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.d.mts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import { M as MemoryBundle, F as FormatContextOptions, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-
|
|
2
|
-
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, H as HOOK_TIMEOUT_MARKER, L as LLMProvider, O as OntologyConfig,
|
|
1
|
+
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-D02cdI9A.mjs';
|
|
2
|
+
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, h as GraphTraversalOptions, H as HOOK_TIMEOUT_MARKER, L as LLMProvider, O as OntologyConfig, i as OntologyEdgeType, j as OntologyManifest, k as OntologyMode, l as OntologyNodeType, m as OntologyPromptContext, n as OntologyUpdates, P as PromptOverrides, o as PromptService, p as PrunePartialFailureError, V as VectorRanker, q as VectorRankerFallback, r as VectorRankerRankArgs, s as VectorRankerSemanticResult, t as WikiBusyError, u as WikiBusyOperation, v as WikiCheckpoint, w as WikiConfig, x as WikiEdge, y as WikiEvent, z as WikiFact, A as WikiMemoryTestAccess, B as WikiOutboxEvent, C as WikiTask } from './testing-D02cdI9A.mjs';
|
|
3
3
|
import { OkfFile } from '@equationalapplications/core-okf';
|
|
4
4
|
import 'minisearch';
|
|
5
5
|
|
|
6
6
|
declare function formatContext(bundle: MemoryBundle, options?: FormatContextOptions): string;
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Pure presenter — dense text serialization of a GraphNeighborhood for LLM prompt
|
|
10
|
+
* injection. Deterministic: same input always produces byte-identical output
|
|
11
|
+
* (matters for prompt caching).
|
|
12
|
+
*/
|
|
13
|
+
declare function formatGraphContext(neighborhood: GraphNeighborhood): string;
|
|
14
|
+
|
|
8
15
|
declare function formatMemoryDump(dump: MemoryDump): FormattedMemoryDump;
|
|
9
16
|
|
|
10
17
|
declare function formatOkfBundle(dump: MemoryDump): {
|
|
@@ -43,4 +50,4 @@ declare function mapLibrarianOptionsToReadOptions(options: LibrarianOptions): Pi
|
|
|
43
50
|
|
|
44
51
|
declare function createWiki(db: SQLiteAdapter, options: WikiOptions): WikiMemory;
|
|
45
52
|
|
|
46
|
-
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, FormatContextOptions, FormattedMemoryDump, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, type OkfImportOptions, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, createWiki, formatContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, validateLibrarianPromptTemplate };
|
|
53
|
+
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, FormatContextOptions, FormattedMemoryDump, GraphNeighborhood, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, type OkfImportOptions, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, validateLibrarianPromptTemplate };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import { M as MemoryBundle, F as FormatContextOptions, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-
|
|
2
|
-
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, H as HOOK_TIMEOUT_MARKER, L as LLMProvider, O as OntologyConfig,
|
|
1
|
+
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-D02cdI9A.js';
|
|
2
|
+
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, h as GraphTraversalOptions, H as HOOK_TIMEOUT_MARKER, L as LLMProvider, O as OntologyConfig, i as OntologyEdgeType, j as OntologyManifest, k as OntologyMode, l as OntologyNodeType, m as OntologyPromptContext, n as OntologyUpdates, P as PromptOverrides, o as PromptService, p as PrunePartialFailureError, V as VectorRanker, q as VectorRankerFallback, r as VectorRankerRankArgs, s as VectorRankerSemanticResult, t as WikiBusyError, u as WikiBusyOperation, v as WikiCheckpoint, w as WikiConfig, x as WikiEdge, y as WikiEvent, z as WikiFact, A as WikiMemoryTestAccess, B as WikiOutboxEvent, C as WikiTask } from './testing-D02cdI9A.js';
|
|
3
3
|
import { OkfFile } from '@equationalapplications/core-okf';
|
|
4
4
|
import 'minisearch';
|
|
5
5
|
|
|
6
6
|
declare function formatContext(bundle: MemoryBundle, options?: FormatContextOptions): string;
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Pure presenter — dense text serialization of a GraphNeighborhood for LLM prompt
|
|
10
|
+
* injection. Deterministic: same input always produces byte-identical output
|
|
11
|
+
* (matters for prompt caching).
|
|
12
|
+
*/
|
|
13
|
+
declare function formatGraphContext(neighborhood: GraphNeighborhood): string;
|
|
14
|
+
|
|
8
15
|
declare function formatMemoryDump(dump: MemoryDump): FormattedMemoryDump;
|
|
9
16
|
|
|
10
17
|
declare function formatOkfBundle(dump: MemoryDump): {
|
|
@@ -43,4 +50,4 @@ declare function mapLibrarianOptionsToReadOptions(options: LibrarianOptions): Pi
|
|
|
43
50
|
|
|
44
51
|
declare function createWiki(db: SQLiteAdapter, options: WikiOptions): WikiMemory;
|
|
45
52
|
|
|
46
|
-
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, FormatContextOptions, FormattedMemoryDump, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, type OkfImportOptions, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, createWiki, formatContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, validateLibrarianPromptTemplate };
|
|
53
|
+
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, FormatContextOptions, FormattedMemoryDump, GraphNeighborhood, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, type OkfImportOptions, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, validateLibrarianPromptTemplate };
|
package/dist/index.js
CHANGED
|
@@ -1407,6 +1407,11 @@ var EventRepository = class extends BaseRepository {
|
|
|
1407
1407
|
};
|
|
1408
1408
|
|
|
1409
1409
|
// src/repositories/EdgeRepository.ts
|
|
1410
|
+
var CONFIDENCE_RANK = {
|
|
1411
|
+
tentative: 0,
|
|
1412
|
+
inferred: 1,
|
|
1413
|
+
certain: 2
|
|
1414
|
+
};
|
|
1410
1415
|
var EdgeRepository = class extends BaseRepository {
|
|
1411
1416
|
/**
|
|
1412
1417
|
* Insert an edge, silently skipping on primary-key or uniqueness conflicts.
|
|
@@ -1437,21 +1442,111 @@ var EdgeRepository = class extends BaseRepository {
|
|
|
1437
1442
|
`SELECT * FROM ${this.prefix}edges WHERE entity_id = ? ORDER BY created_at ASC`,
|
|
1438
1443
|
[entityId]
|
|
1439
1444
|
);
|
|
1440
|
-
return rows.map(
|
|
1441
|
-
id: String(row.id),
|
|
1442
|
-
entity_id: String(row.entity_id),
|
|
1443
|
-
source_id: String(row.source_id),
|
|
1444
|
-
target_id: String(row.target_id),
|
|
1445
|
-
edge_type: String(row.edge_type),
|
|
1446
|
-
created_at: Number(row.created_at)
|
|
1447
|
-
}));
|
|
1445
|
+
return rows.map(mapRowToEdge);
|
|
1448
1446
|
}
|
|
1449
1447
|
/** Hard delete — edges have no soft-delete concept, only presence/absence. `tx` is REQUIRED. */
|
|
1450
1448
|
async bulkDeleteByEntityId(entityId, tx) {
|
|
1451
1449
|
const executor = this.getExecutor(tx);
|
|
1452
1450
|
await executor.runAsync(`DELETE FROM ${this.prefix}edges WHERE entity_id = ?`, [entityId]);
|
|
1453
1451
|
}
|
|
1452
|
+
/**
|
|
1453
|
+
* Multi-hop traversal from `sourceId` via SQLite `WITH RECURSIVE`. All filtering,
|
|
1454
|
+
* dead-ending, cycle-guarding, capping, and ordering happens in this one query.
|
|
1455
|
+
* The anchor is validated (exists, right entity, not soft-deleted) but never gated
|
|
1456
|
+
* by confidence/source_type — only nodes discovered beyond it are.
|
|
1457
|
+
*/
|
|
1458
|
+
async getNeighborhood(entityId, sourceId, opts, tx) {
|
|
1459
|
+
const executor = this.getExecutor(tx);
|
|
1460
|
+
if (opts.edgeTypes && opts.edgeTypes.length === 0) {
|
|
1461
|
+
const anchor = await executor.getFirstAsync(
|
|
1462
|
+
`SELECT id FROM ${this.prefix}entries WHERE id = ? AND entity_id = ? AND deleted_at IS NULL`,
|
|
1463
|
+
[sourceId, entityId]
|
|
1464
|
+
);
|
|
1465
|
+
return { nodeIds: anchor ? [anchor.id] : [], edges: [] };
|
|
1466
|
+
}
|
|
1467
|
+
const edgeTypesClause = opts.edgeTypes ? `e.edge_type IN (${opts.edgeTypes.map(() => "?").join(",")})` : "1=1";
|
|
1468
|
+
const excludeSourceTypesPlaceholders = opts.excludeSourceTypes.map(() => "?").join(",");
|
|
1469
|
+
const minConfidenceRank = CONFIDENCE_RANK[opts.minConfidence];
|
|
1470
|
+
const sql = `
|
|
1471
|
+
WITH RECURSIVE walk(node_id, depth, visited) AS (
|
|
1472
|
+
SELECT id, 0, ',' || id || ','
|
|
1473
|
+
FROM ${this.prefix}entries
|
|
1474
|
+
WHERE id = ? AND entity_id = ? AND deleted_at IS NULL
|
|
1475
|
+
|
|
1476
|
+
UNION
|
|
1477
|
+
|
|
1478
|
+
SELECT
|
|
1479
|
+
CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END,
|
|
1480
|
+
w.depth + 1,
|
|
1481
|
+
w.visited || (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END) || ','
|
|
1482
|
+
FROM walk w
|
|
1483
|
+
JOIN ${this.prefix}edges e
|
|
1484
|
+
ON e.entity_id = ?
|
|
1485
|
+
AND (
|
|
1486
|
+
(? != 'inbound' AND e.source_id = w.node_id) OR
|
|
1487
|
+
(? != 'outbound' AND e.target_id = w.node_id)
|
|
1488
|
+
)
|
|
1489
|
+
AND (${edgeTypesClause})
|
|
1490
|
+
JOIN ${this.prefix}entries n
|
|
1491
|
+
ON n.id = (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END)
|
|
1492
|
+
AND n.entity_id = ?
|
|
1493
|
+
AND n.deleted_at IS NULL
|
|
1494
|
+
AND (
|
|
1495
|
+
CASE n.confidence
|
|
1496
|
+
WHEN 'tentative' THEN 0
|
|
1497
|
+
WHEN 'inferred' THEN 1
|
|
1498
|
+
WHEN 'certain' THEN 2
|
|
1499
|
+
ELSE -1
|
|
1500
|
+
END
|
|
1501
|
+
) >= ?
|
|
1502
|
+
AND n.source_type NOT IN (${excludeSourceTypesPlaceholders})
|
|
1503
|
+
WHERE w.depth < ?
|
|
1504
|
+
AND instr(w.visited, ',' || (CASE WHEN e.source_id = w.node_id THEN e.target_id ELSE e.source_id END) || ',') = 0
|
|
1505
|
+
)
|
|
1506
|
+
SELECT node_id, MIN(depth) AS depth
|
|
1507
|
+
FROM walk
|
|
1508
|
+
GROUP BY node_id
|
|
1509
|
+
ORDER BY depth ASC, (SELECT updated_at FROM ${this.prefix}entries WHERE id = node_id) DESC
|
|
1510
|
+
LIMIT ?
|
|
1511
|
+
`;
|
|
1512
|
+
const params = [
|
|
1513
|
+
sourceId,
|
|
1514
|
+
entityId,
|
|
1515
|
+
entityId,
|
|
1516
|
+
opts.direction,
|
|
1517
|
+
opts.direction,
|
|
1518
|
+
...opts.edgeTypes ?? [],
|
|
1519
|
+
entityId,
|
|
1520
|
+
minConfidenceRank,
|
|
1521
|
+
...opts.excludeSourceTypes,
|
|
1522
|
+
opts.maxDepth,
|
|
1523
|
+
opts.maxNodes
|
|
1524
|
+
];
|
|
1525
|
+
const rows = await executor.getAllAsync(sql, params);
|
|
1526
|
+
const nodeIds = rows.map((r) => r.node_id);
|
|
1527
|
+
if (nodeIds.length === 0) return { nodeIds: [], edges: [] };
|
|
1528
|
+
const valueRows = nodeIds.map(() => "(?)").join(", ");
|
|
1529
|
+
const edgeRows = await executor.getAllAsync(
|
|
1530
|
+
`WITH neighborhood(node_id) AS (VALUES ${valueRows})
|
|
1531
|
+
SELECT e.* FROM ${this.prefix}edges e
|
|
1532
|
+
JOIN neighborhood ns ON e.source_id = ns.node_id
|
|
1533
|
+
JOIN neighborhood nt ON e.target_id = nt.node_id
|
|
1534
|
+
WHERE e.entity_id = ?`,
|
|
1535
|
+
[...nodeIds, entityId]
|
|
1536
|
+
);
|
|
1537
|
+
return { nodeIds, edges: edgeRows.map(mapRowToEdge) };
|
|
1538
|
+
}
|
|
1454
1539
|
};
|
|
1540
|
+
function mapRowToEdge(row) {
|
|
1541
|
+
return {
|
|
1542
|
+
id: String(row.id),
|
|
1543
|
+
entity_id: String(row.entity_id),
|
|
1544
|
+
source_id: String(row.source_id),
|
|
1545
|
+
target_id: String(row.target_id),
|
|
1546
|
+
edge_type: String(row.edge_type),
|
|
1547
|
+
created_at: Number(row.created_at)
|
|
1548
|
+
};
|
|
1549
|
+
}
|
|
1455
1550
|
|
|
1456
1551
|
// src/utils/ontology.ts
|
|
1457
1552
|
function emptyManifest() {
|
|
@@ -4481,6 +4576,38 @@ var OntologyService = class {
|
|
|
4481
4576
|
}
|
|
4482
4577
|
};
|
|
4483
4578
|
|
|
4579
|
+
// src/services/GraphTraversalService.ts
|
|
4580
|
+
var GraphTraversalService = class {
|
|
4581
|
+
constructor(edgeRepo, entryRepo, config) {
|
|
4582
|
+
this.edgeRepo = edgeRepo;
|
|
4583
|
+
this.entryRepo = entryRepo;
|
|
4584
|
+
this.config = config;
|
|
4585
|
+
}
|
|
4586
|
+
async traverseGraph(entityId, options) {
|
|
4587
|
+
const fallbackMaxNodes = 20;
|
|
4588
|
+
const rawConfigDefault = this.config.maxTraversalNodes ?? fallbackMaxNodes;
|
|
4589
|
+
const defaultMaxNodes = Number.isFinite(rawConfigDefault) && rawConfigDefault >= 1 ? Math.floor(rawConfigDefault) : fallbackMaxNodes;
|
|
4590
|
+
const rawMaxNodes = options.maxTraversalNodes ?? defaultMaxNodes;
|
|
4591
|
+
const maxNodes = Number.isFinite(rawMaxNodes) && rawMaxNodes >= 1 ? Math.floor(rawMaxNodes) : defaultMaxNodes;
|
|
4592
|
+
const opts = {
|
|
4593
|
+
maxDepth: Math.max(1, Math.min(options.maxDepth ?? 1, 3)),
|
|
4594
|
+
direction: options.direction ?? this.config.traversalDirection ?? "both",
|
|
4595
|
+
edgeTypes: options.edgeTypes,
|
|
4596
|
+
minConfidence: options.minTraversalConfidence ?? this.config.minTraversalConfidence ?? "tentative",
|
|
4597
|
+
excludeSourceTypes: options.excludeSourceTypes ?? this.config.excludeSourceTypes ?? [],
|
|
4598
|
+
maxNodes
|
|
4599
|
+
};
|
|
4600
|
+
const { nodeIds, edges } = await this.edgeRepo.getNeighborhood(entityId, options.sourceId, opts);
|
|
4601
|
+
if (nodeIds.length === 0) return { nodes: [], edges: [] };
|
|
4602
|
+
const nodes = await this.entryRepo.findByIds(nodeIds, [entityId]);
|
|
4603
|
+
const hydratedIds = new Set(nodes.map((node) => node.id));
|
|
4604
|
+
const filteredEdges = edges.filter(
|
|
4605
|
+
(edge) => hydratedIds.has(edge.source_id) && hydratedIds.has(edge.target_id)
|
|
4606
|
+
);
|
|
4607
|
+
return { nodes, edges: filteredEdges };
|
|
4608
|
+
}
|
|
4609
|
+
};
|
|
4610
|
+
|
|
4484
4611
|
// src/WikiMemory.ts
|
|
4485
4612
|
var TABLE_PREFIX_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,30}_$/;
|
|
4486
4613
|
var _testAccessNonTestEnvWarned;
|
|
@@ -4564,6 +4691,11 @@ var WikiMemory = class {
|
|
|
4564
4691
|
this.jobManager,
|
|
4565
4692
|
this.maintenanceService
|
|
4566
4693
|
);
|
|
4694
|
+
this.graphTraversalService = new GraphTraversalService(
|
|
4695
|
+
this.edgeRepo,
|
|
4696
|
+
this.entryRepo,
|
|
4697
|
+
this.options.config ?? {}
|
|
4698
|
+
);
|
|
4567
4699
|
}
|
|
4568
4700
|
/**
|
|
4569
4701
|
* Explicit escape hatch for test suites: typed access to composed services for mocks/spies.
|
|
@@ -4584,6 +4716,7 @@ var WikiMemory = class {
|
|
|
4584
4716
|
searchService: this.searchService,
|
|
4585
4717
|
writeService: this.writeService,
|
|
4586
4718
|
promptService: this.promptService,
|
|
4719
|
+
graphTraversalService: this.graphTraversalService,
|
|
4587
4720
|
entryRepo: this.entryRepo,
|
|
4588
4721
|
metadataRepo: this.metadataRepo,
|
|
4589
4722
|
jobManager: this.jobManager
|
|
@@ -4654,6 +4787,9 @@ var WikiMemory = class {
|
|
|
4654
4787
|
async read(entityId, query, options) {
|
|
4655
4788
|
return this.retrievalService.read(entityId, query, options);
|
|
4656
4789
|
}
|
|
4790
|
+
async traverseGraph(entityId, options) {
|
|
4791
|
+
return this.graphTraversalService.traverseGraph(entityId, options);
|
|
4792
|
+
}
|
|
4657
4793
|
async getMemoryBundle(entityId) {
|
|
4658
4794
|
return this.importExportService.getFullBundle(entityId, { maxEvents: 10 });
|
|
4659
4795
|
}
|
|
@@ -4881,6 +5017,38 @@ function formatContext(bundle, options) {
|
|
|
4881
5017
|
return lines.join("\n");
|
|
4882
5018
|
}
|
|
4883
5019
|
|
|
5020
|
+
// src/utils/formatGraphContext.ts
|
|
5021
|
+
function formatGraphContext(neighborhood) {
|
|
5022
|
+
const { nodes, edges } = neighborhood;
|
|
5023
|
+
if (nodes.length === 0) return "";
|
|
5024
|
+
const nodeById = new Map(nodes.map((n) => [n.id, n]));
|
|
5025
|
+
const nodeIndex = new Map(nodes.map((n, i) => [n.id, i]));
|
|
5026
|
+
const lines = [];
|
|
5027
|
+
for (const node of nodes) {
|
|
5028
|
+
lines.push(`[${node.okf_type ?? "fact"}] ${node.title} (ID: ${node.id})`);
|
|
5029
|
+
const outbound = edgesByDirection(edges, node.id, "source_id", nodeById, nodeIndex);
|
|
5030
|
+
const inbound = edgesByDirection(edges, node.id, "target_id", nodeById, nodeIndex);
|
|
5031
|
+
for (const { edge, other } of outbound) {
|
|
5032
|
+
lines.push(` -[${edge.edge_type}]-> [${other.okf_type ?? "fact"}] ${other.title}`);
|
|
5033
|
+
}
|
|
5034
|
+
for (const { edge, other } of inbound) {
|
|
5035
|
+
lines.push(` <-[${edge.edge_type}]- [${other.okf_type ?? "fact"}] ${other.title}`);
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
return lines.join("\n");
|
|
5039
|
+
}
|
|
5040
|
+
function edgesByDirection(edges, nodeId, endpoint, nodeById, nodeIndex) {
|
|
5041
|
+
const otherEndpoint = endpoint === "source_id" ? "target_id" : "source_id";
|
|
5042
|
+
return edges.filter((e) => e[endpoint] === nodeId).filter((e) => {
|
|
5043
|
+
const otherId = e[otherEndpoint];
|
|
5044
|
+
const selfIdx = nodeIndex.get(nodeId);
|
|
5045
|
+
const otherIdx = nodeIndex.get(otherId);
|
|
5046
|
+
return otherIdx !== void 0 && selfIdx < otherIdx;
|
|
5047
|
+
}).map((edge) => ({ edge, other: nodeById.get(edge[otherEndpoint]) })).sort(
|
|
5048
|
+
(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)
|
|
5049
|
+
);
|
|
5050
|
+
}
|
|
5051
|
+
|
|
4884
5052
|
// src/utils/sanitizeForFilename.ts
|
|
4885
5053
|
function shortHash(value) {
|
|
4886
5054
|
let h1 = 5381;
|
|
@@ -5397,6 +5565,7 @@ exports.WikiBusyError = WikiBusyError;
|
|
|
5397
5565
|
exports.WikiMemory = WikiMemory;
|
|
5398
5566
|
exports.createWiki = createWiki;
|
|
5399
5567
|
exports.formatContext = formatContext;
|
|
5568
|
+
exports.formatGraphContext = formatGraphContext;
|
|
5400
5569
|
exports.formatMemoryDump = formatMemoryDump;
|
|
5401
5570
|
exports.formatOkfBundle = formatOkfBundle;
|
|
5402
5571
|
exports.hydrateLibrarianPrompt = hydrateLibrarianPrompt;
|