@equationalapplications/core-llm-wiki 4.16.0 → 4.17.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.
@@ -113,6 +113,14 @@ interface WikiConfig {
113
113
  */
114
114
  enableOutbox?: boolean;
115
115
  ontology?: OntologyConfig;
116
+ /** Default node cap for traverseGraph(), unless overridden per-call. Default 20. */
117
+ maxTraversalNodes?: number;
118
+ /** Default minimum confidence tier for discovered traversal nodes. Default 'tentative'. */
119
+ minTraversalConfidence?: 'certain' | 'inferred' | 'tentative';
120
+ /** Default traversal direction. Default 'both'. */
121
+ traversalDirection?: 'inbound' | 'outbound' | 'both';
122
+ /** Default source_type dead-end list for discovered traversal nodes. Default []. */
123
+ excludeSourceTypes?: Array<WikiFact['source_type']>;
116
124
  }
117
125
  interface ReadOptions {
118
126
  maxResults?: number;
@@ -208,6 +216,30 @@ interface WikiEdge {
208
216
  edge_type: string;
209
217
  created_at: number;
210
218
  }
219
+ interface GraphTraversalOptions {
220
+ sourceId: string;
221
+ /** Hop count. Default 1. Clamped to [1, 3] regardless of input. */
222
+ maxDepth?: number;
223
+ /** Default 'both'. Falls back to WikiConfig.traversalDirection, then 'both'. */
224
+ direction?: 'inbound' | 'outbound' | 'both';
225
+ /**
226
+ * Allowed edge types. `undefined` = no filter (all types).
227
+ * `[]` (explicit empty array) = match nothing — distinct from `undefined`.
228
+ */
229
+ edgeTypes?: string[];
230
+ /** Total node cap (anchor + neighbors). Default 20 via WikiConfig.maxTraversalNodes. */
231
+ maxTraversalNodes?: number;
232
+ /** Minimum confidence tier for *discovered* nodes. Does not gate the anchor. Default 'tentative'. */
233
+ minTraversalConfidence?: 'certain' | 'inferred' | 'tentative';
234
+ /** source_type values to dead-end on for *discovered* nodes. Does not gate the anchor. Default []. */
235
+ excludeSourceTypes?: Array<WikiFact['source_type']>;
236
+ }
237
+ interface GraphNeighborhood {
238
+ /** Anchor node first, then discovered neighbors ordered by depth ASC, then updated_at DESC. */
239
+ nodes: WikiFact[];
240
+ /** Only edges where both endpoints are present in `nodes`. */
241
+ edges: WikiEdge[];
242
+ }
211
243
  interface WikiCheckpoint {
212
244
  entity_id: string;
213
245
  heal_checkpoint: number;
@@ -840,6 +872,14 @@ declare class EmbeddingService {
840
872
  notifyEmbeddingPersistedOrThrow(entityId: string, factId: string, vector: Float32Array | null): Promise<void>;
841
873
  }
842
874
 
875
+ interface NeighborhoodQueryOptions {
876
+ maxDepth: number;
877
+ direction: 'inbound' | 'outbound' | 'both';
878
+ edgeTypes?: string[];
879
+ minConfidence: 'certain' | 'inferred' | 'tentative';
880
+ excludeSourceTypes: string[];
881
+ maxNodes: number;
882
+ }
843
883
  declare class EdgeRepository extends BaseRepository {
844
884
  /**
845
885
  * Insert an edge, silently skipping on primary-key or uniqueness conflicts.
@@ -849,6 +889,16 @@ declare class EdgeRepository extends BaseRepository {
849
889
  getByEntityId(entityId: string, tx?: SQLiteAdapter): Promise<WikiEdge[]>;
850
890
  /** Hard delete — edges have no soft-delete concept, only presence/absence. `tx` is REQUIRED. */
851
891
  bulkDeleteByEntityId(entityId: string, tx: SQLiteAdapter): Promise<void>;
892
+ /**
893
+ * Multi-hop traversal from `sourceId` via SQLite `WITH RECURSIVE`. All filtering,
894
+ * dead-ending, cycle-guarding, capping, and ordering happens in this one query.
895
+ * The anchor is validated (exists, right entity, not soft-deleted) but never gated
896
+ * by confidence/source_type — only nodes discovered beyond it are.
897
+ */
898
+ getNeighborhood(entityId: string, sourceId: string, opts: NeighborhoodQueryOptions, tx?: SQLiteAdapter): Promise<{
899
+ nodeIds: string[];
900
+ edges: WikiEdge[];
901
+ }>;
852
902
  }
853
903
 
854
904
  type TitleIndexEntry = {
@@ -1152,6 +1202,18 @@ declare class WriteService {
1152
1202
  private runLibrarianThenMaybeHeal;
1153
1203
  }
1154
1204
 
1205
+ /**
1206
+ * Pure orchestrator — no SQL. Merges WikiConfig defaults with per-call options,
1207
+ * delegates the recursive walk to EdgeRepository, then hydrates node IDs into facts.
1208
+ */
1209
+ declare class GraphTraversalService {
1210
+ private edgeRepo;
1211
+ private entryRepo;
1212
+ private config;
1213
+ constructor(edgeRepo: EdgeRepository, entryRepo: EntryRepository, config: WikiConfig);
1214
+ traverseGraph(entityId: string, options: GraphTraversalOptions): Promise<GraphNeighborhood>;
1215
+ }
1216
+
1155
1217
  /** Typed escape hatch for tests — not part of the supported consumer API. */
1156
1218
  interface WikiMemoryTestAccess {
1157
1219
  embeddingService: EmbeddingService;
@@ -1162,6 +1224,7 @@ interface WikiMemoryTestAccess {
1162
1224
  searchService: SearchService;
1163
1225
  writeService: WriteService;
1164
1226
  promptService: PromptService;
1227
+ graphTraversalService: GraphTraversalService;
1165
1228
  entryRepo: EntryRepository;
1166
1229
  metadataRepo: MetadataRepository;
1167
1230
  jobManager: JobManager;
@@ -1187,6 +1250,7 @@ declare class WikiMemory {
1187
1250
  private writeService;
1188
1251
  private promptService;
1189
1252
  private ontologyService;
1253
+ private graphTraversalService;
1190
1254
  constructor(db: SQLiteAdapter, options: WikiOptions);
1191
1255
  /**
1192
1256
  * Explicit escape hatch for test suites: typed access to composed services for mocks/spies.
@@ -1205,6 +1269,7 @@ declare class WikiMemory {
1205
1269
  events: number;
1206
1270
  }>;
1207
1271
  read(entityId: string | string[], query: string, options?: ReadOptions): Promise<MemoryBundle>;
1272
+ traverseGraph(entityId: string, options: GraphTraversalOptions): Promise<GraphNeighborhood>;
1208
1273
  getMemoryBundle(entityId: string): Promise<MemoryBundle>;
1209
1274
  write(entityId: string, event: Omit<WikiEvent, 'id' | 'entity_id' | 'created_at'>): Promise<void>;
1210
1275
  /**
@@ -1295,4 +1360,4 @@ declare class WikiMemory {
1295
1360
  }): Promise<void>;
1296
1361
  }
1297
1362
 
1298
- export { type WikiOutboxEvent as A, type WikiTask as B, EmbeddingService as C, IngestionService as D, type EntityStatus as E, type FormatContextOptions as F, MaintenanceService as G, HOOK_TIMEOUT_MARKER as H, ImportExportService as I, JobManager as J, RetrievalService as K, type LLMProvider as L, type MemoryBundle as M, SearchService as N, type OntologyConfig as O, type PromptOverrides as P, WriteService as Q, type ReadOptions as R, type SQLiteAdapter as S, type VectorRanker as V, type WikiOptions as W, type MemoryDump as a, type FormattedMemoryDump as b, WikiMemory as c, type ExtractedFact as d, type ExtractedFactEdge as e, type ExtractedFactWithOntology as f, type ExtractedTask as g, type OntologyEdgeType as h, type OntologyManifest as i, type OntologyMode as j, type OntologyNodeType as k, type OntologyPromptContext as l, type OntologyUpdates as m, PromptService as n, PrunePartialFailureError as o, type VectorRankerFallback as p, type VectorRankerRankArgs as q, type VectorRankerSemanticResult as r, WikiBusyError as s, type WikiBusyOperation as t, type WikiCheckpoint as u, type WikiConfig as v, type WikiEdge as w, type WikiEvent as x, type WikiFact as y, type WikiMemoryTestAccess as z };
1363
+ export { type WikiMemoryTestAccess as A, type WikiOutboxEvent as B, type WikiTask as C, EmbeddingService as D, type EntityStatus as E, type FormatContextOptions as F, type GraphNeighborhood as G, HOOK_TIMEOUT_MARKER as H, ImportExportService as I, IngestionService as J, JobManager as K, type LLMProvider as L, type MemoryBundle as M, MaintenanceService as N, type OntologyConfig as O, type PromptOverrides as P, RetrievalService as Q, type ReadOptions as R, type SQLiteAdapter as S, SearchService as T, WriteService as U, type VectorRanker as V, type WikiOptions as W, type MemoryDump as a, type FormattedMemoryDump as b, WikiMemory as c, type ExtractedFact as d, type ExtractedFactEdge as e, type ExtractedFactWithOntology as f, type ExtractedTask as g, type GraphTraversalOptions as h, type OntologyEdgeType as i, type OntologyManifest as j, type OntologyMode as k, type OntologyNodeType as l, type OntologyPromptContext as m, type OntologyUpdates as n, PromptService as o, PrunePartialFailureError as p, type VectorRankerFallback as q, type VectorRankerRankArgs as r, type VectorRankerSemanticResult as s, WikiBusyError as t, type WikiBusyOperation as u, type WikiCheckpoint as v, type WikiConfig as w, type WikiEdge as x, type WikiEvent as y, type WikiFact as z };
@@ -113,6 +113,14 @@ interface WikiConfig {
113
113
  */
114
114
  enableOutbox?: boolean;
115
115
  ontology?: OntologyConfig;
116
+ /** Default node cap for traverseGraph(), unless overridden per-call. Default 20. */
117
+ maxTraversalNodes?: number;
118
+ /** Default minimum confidence tier for discovered traversal nodes. Default 'tentative'. */
119
+ minTraversalConfidence?: 'certain' | 'inferred' | 'tentative';
120
+ /** Default traversal direction. Default 'both'. */
121
+ traversalDirection?: 'inbound' | 'outbound' | 'both';
122
+ /** Default source_type dead-end list for discovered traversal nodes. Default []. */
123
+ excludeSourceTypes?: Array<WikiFact['source_type']>;
116
124
  }
117
125
  interface ReadOptions {
118
126
  maxResults?: number;
@@ -208,6 +216,30 @@ interface WikiEdge {
208
216
  edge_type: string;
209
217
  created_at: number;
210
218
  }
219
+ interface GraphTraversalOptions {
220
+ sourceId: string;
221
+ /** Hop count. Default 1. Clamped to [1, 3] regardless of input. */
222
+ maxDepth?: number;
223
+ /** Default 'both'. Falls back to WikiConfig.traversalDirection, then 'both'. */
224
+ direction?: 'inbound' | 'outbound' | 'both';
225
+ /**
226
+ * Allowed edge types. `undefined` = no filter (all types).
227
+ * `[]` (explicit empty array) = match nothing — distinct from `undefined`.
228
+ */
229
+ edgeTypes?: string[];
230
+ /** Total node cap (anchor + neighbors). Default 20 via WikiConfig.maxTraversalNodes. */
231
+ maxTraversalNodes?: number;
232
+ /** Minimum confidence tier for *discovered* nodes. Does not gate the anchor. Default 'tentative'. */
233
+ minTraversalConfidence?: 'certain' | 'inferred' | 'tentative';
234
+ /** source_type values to dead-end on for *discovered* nodes. Does not gate the anchor. Default []. */
235
+ excludeSourceTypes?: Array<WikiFact['source_type']>;
236
+ }
237
+ interface GraphNeighborhood {
238
+ /** Anchor node first, then discovered neighbors ordered by depth ASC, then updated_at DESC. */
239
+ nodes: WikiFact[];
240
+ /** Only edges where both endpoints are present in `nodes`. */
241
+ edges: WikiEdge[];
242
+ }
211
243
  interface WikiCheckpoint {
212
244
  entity_id: string;
213
245
  heal_checkpoint: number;
@@ -840,6 +872,14 @@ declare class EmbeddingService {
840
872
  notifyEmbeddingPersistedOrThrow(entityId: string, factId: string, vector: Float32Array | null): Promise<void>;
841
873
  }
842
874
 
875
+ interface NeighborhoodQueryOptions {
876
+ maxDepth: number;
877
+ direction: 'inbound' | 'outbound' | 'both';
878
+ edgeTypes?: string[];
879
+ minConfidence: 'certain' | 'inferred' | 'tentative';
880
+ excludeSourceTypes: string[];
881
+ maxNodes: number;
882
+ }
843
883
  declare class EdgeRepository extends BaseRepository {
844
884
  /**
845
885
  * Insert an edge, silently skipping on primary-key or uniqueness conflicts.
@@ -849,6 +889,16 @@ declare class EdgeRepository extends BaseRepository {
849
889
  getByEntityId(entityId: string, tx?: SQLiteAdapter): Promise<WikiEdge[]>;
850
890
  /** Hard delete — edges have no soft-delete concept, only presence/absence. `tx` is REQUIRED. */
851
891
  bulkDeleteByEntityId(entityId: string, tx: SQLiteAdapter): Promise<void>;
892
+ /**
893
+ * Multi-hop traversal from `sourceId` via SQLite `WITH RECURSIVE`. All filtering,
894
+ * dead-ending, cycle-guarding, capping, and ordering happens in this one query.
895
+ * The anchor is validated (exists, right entity, not soft-deleted) but never gated
896
+ * by confidence/source_type — only nodes discovered beyond it are.
897
+ */
898
+ getNeighborhood(entityId: string, sourceId: string, opts: NeighborhoodQueryOptions, tx?: SQLiteAdapter): Promise<{
899
+ nodeIds: string[];
900
+ edges: WikiEdge[];
901
+ }>;
852
902
  }
853
903
 
854
904
  type TitleIndexEntry = {
@@ -1152,6 +1202,18 @@ declare class WriteService {
1152
1202
  private runLibrarianThenMaybeHeal;
1153
1203
  }
1154
1204
 
1205
+ /**
1206
+ * Pure orchestrator — no SQL. Merges WikiConfig defaults with per-call options,
1207
+ * delegates the recursive walk to EdgeRepository, then hydrates node IDs into facts.
1208
+ */
1209
+ declare class GraphTraversalService {
1210
+ private edgeRepo;
1211
+ private entryRepo;
1212
+ private config;
1213
+ constructor(edgeRepo: EdgeRepository, entryRepo: EntryRepository, config: WikiConfig);
1214
+ traverseGraph(entityId: string, options: GraphTraversalOptions): Promise<GraphNeighborhood>;
1215
+ }
1216
+
1155
1217
  /** Typed escape hatch for tests — not part of the supported consumer API. */
1156
1218
  interface WikiMemoryTestAccess {
1157
1219
  embeddingService: EmbeddingService;
@@ -1162,6 +1224,7 @@ interface WikiMemoryTestAccess {
1162
1224
  searchService: SearchService;
1163
1225
  writeService: WriteService;
1164
1226
  promptService: PromptService;
1227
+ graphTraversalService: GraphTraversalService;
1165
1228
  entryRepo: EntryRepository;
1166
1229
  metadataRepo: MetadataRepository;
1167
1230
  jobManager: JobManager;
@@ -1187,6 +1250,7 @@ declare class WikiMemory {
1187
1250
  private writeService;
1188
1251
  private promptService;
1189
1252
  private ontologyService;
1253
+ private graphTraversalService;
1190
1254
  constructor(db: SQLiteAdapter, options: WikiOptions);
1191
1255
  /**
1192
1256
  * Explicit escape hatch for test suites: typed access to composed services for mocks/spies.
@@ -1205,6 +1269,7 @@ declare class WikiMemory {
1205
1269
  events: number;
1206
1270
  }>;
1207
1271
  read(entityId: string | string[], query: string, options?: ReadOptions): Promise<MemoryBundle>;
1272
+ traverseGraph(entityId: string, options: GraphTraversalOptions): Promise<GraphNeighborhood>;
1208
1273
  getMemoryBundle(entityId: string): Promise<MemoryBundle>;
1209
1274
  write(entityId: string, event: Omit<WikiEvent, 'id' | 'entity_id' | 'created_at'>): Promise<void>;
1210
1275
  /**
@@ -1295,4 +1360,4 @@ declare class WikiMemory {
1295
1360
  }): Promise<void>;
1296
1361
  }
1297
1362
 
1298
- export { type WikiOutboxEvent as A, type WikiTask as B, EmbeddingService as C, IngestionService as D, type EntityStatus as E, type FormatContextOptions as F, MaintenanceService as G, HOOK_TIMEOUT_MARKER as H, ImportExportService as I, JobManager as J, RetrievalService as K, type LLMProvider as L, type MemoryBundle as M, SearchService as N, type OntologyConfig as O, type PromptOverrides as P, WriteService as Q, type ReadOptions as R, type SQLiteAdapter as S, type VectorRanker as V, type WikiOptions as W, type MemoryDump as a, type FormattedMemoryDump as b, WikiMemory as c, type ExtractedFact as d, type ExtractedFactEdge as e, type ExtractedFactWithOntology as f, type ExtractedTask as g, type OntologyEdgeType as h, type OntologyManifest as i, type OntologyMode as j, type OntologyNodeType as k, type OntologyPromptContext as l, type OntologyUpdates as m, PromptService as n, PrunePartialFailureError as o, type VectorRankerFallback as p, type VectorRankerRankArgs as q, type VectorRankerSemanticResult as r, WikiBusyError as s, type WikiBusyOperation as t, type WikiCheckpoint as u, type WikiConfig as v, type WikiEdge as w, type WikiEvent as x, type WikiFact as y, type WikiMemoryTestAccess as z };
1363
+ export { type WikiMemoryTestAccess as A, type WikiOutboxEvent as B, type WikiTask as C, EmbeddingService as D, type EntityStatus as E, type FormatContextOptions as F, type GraphNeighborhood as G, HOOK_TIMEOUT_MARKER as H, ImportExportService as I, IngestionService as J, JobManager as K, type LLMProvider as L, type MemoryBundle as M, MaintenanceService as N, type OntologyConfig as O, type PromptOverrides as P, RetrievalService as Q, type ReadOptions as R, type SQLiteAdapter as S, SearchService as T, WriteService as U, type VectorRanker as V, type WikiOptions as W, type MemoryDump as a, type FormattedMemoryDump as b, WikiMemory as c, type ExtractedFact as d, type ExtractedFactEdge as e, type ExtractedFactWithOntology as f, type ExtractedTask as g, type GraphTraversalOptions as h, type OntologyEdgeType as i, type OntologyManifest as j, type OntologyMode as k, type OntologyNodeType as l, type OntologyPromptContext as m, type OntologyUpdates as n, PromptService as o, PrunePartialFailureError as p, type VectorRankerFallback as q, type VectorRankerRankArgs as r, type VectorRankerSemanticResult as s, WikiBusyError as t, type WikiBusyOperation as u, type WikiCheckpoint as v, type WikiConfig as w, type WikiEdge as x, type WikiEvent as y, type WikiFact as z };
@@ -1,2 +1,2 @@
1
- export { C as EmbeddingService, I as ImportExportService, D as IngestionService, J as JobManager, J as JobManagerType, G as MaintenanceService, K as RetrievalService, N as SearchService, N as SearchServiceType, z as WikiMemoryTestAccess, Q as WriteService } from './testing-BMsplvLy.mjs';
1
+ export { D as EmbeddingService, I as ImportExportService, J as IngestionService, K as JobManager, K as JobManagerType, N as MaintenanceService, Q as RetrievalService, T as SearchService, T as SearchServiceType, A as WikiMemoryTestAccess, U as WriteService } from './testing-D02cdI9A.mjs';
2
2
  import 'minisearch';
package/dist/testing.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { C as EmbeddingService, I as ImportExportService, D as IngestionService, J as JobManager, J as JobManagerType, G as MaintenanceService, K as RetrievalService, N as SearchService, N as SearchServiceType, z as WikiMemoryTestAccess, Q as WriteService } from './testing-BMsplvLy.js';
1
+ export { D as EmbeddingService, I as ImportExportService, J as IngestionService, K as JobManager, K as JobManagerType, N as MaintenanceService, Q as RetrievalService, T as SearchService, T as SearchServiceType, A as WikiMemoryTestAccess, U as WriteService } from './testing-D02cdI9A.js';
2
2
  import 'minisearch';
package/dist/testing.js CHANGED
@@ -800,8 +800,6 @@ After running the migration SQL, restart your application.`
800
800
  function normalizeTitleKey(title) {
801
801
  return title.trim().toLowerCase().replace(/\s+/g, " ");
802
802
  }
803
-
804
- // src/utils/ids.ts
805
803
  function generateId(prefix = "") {
806
804
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
807
805
  return prefix + crypto.randomUUID().replace(/-/g, "").substring(0, 24);
@@ -812,7 +810,7 @@ function generateId(prefix = "") {
812
810
  return prefix + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("").substring(0, 24);
813
811
  }
814
812
  throw new Error(
815
- "generateId: no cryptographically secure random source available (crypto.randomUUID and crypto.getRandomValues are both missing)."
813
+ "generateId: no cryptographically secure random source available (crypto.randomUUID and crypto.getRandomValues are both missing, and no configureRandomSource() injection was provided)."
816
814
  );
817
815
  }
818
816