/** * pi-loom: GraphProvider — pluggable entity-graph interface * * Instead of maintaining its own entity_edges table that duplicates pi-esr's * entity graph, pi-loom delegates all graph operations through this interface. * * Default: SqliteGraphProvider wraps the existing entity_edges table (backward * compatible). Future: EsrGraphProvider queries pi-esr's graph natively. * * This is the strangler-fig step toward true loose coupling: * 1. Define the interface (this file) * 2. Inject via LoomStore constructor * 3. Eventually remove entity_edges table when ESR provider is stable */ /** A typed edge between two ESR entities. */ export interface EntityEdge { source_entity: string; target_entity: string; relation_type: string; confidence: number; } /** One side of an entity relation, as returned by getRelatedEntities. */ export interface RelatedEntity { entity: string; relation_type: string; confidence: number; direction: "out" | "in"; } /** Pluggable entity-graph provider. */ export interface GraphProvider { readonly name: string; /** Create or update a relation between two entities. Returns the edge id. */ linkEntities(params: { source_entity: string; target_entity: string; relation_type: string; memory_id?: string; episode_id?: string; confidence?: number; }): string; /** Get all entities related to entityId (both incoming and outgoing). */ getRelatedEntities(entityId: string): RelatedEntity[]; /** * BFS traversal from startEntities up to maxHops. * Returns all entity IDs reachable, including the seeds. */ traverseGraph(startEntities: string[], maxHops?: number): string[]; /** Return all edges for graph-boost scoring during hybrid search. */ getAllEdges(): EntityEdge[]; } import type Database from "better-sqlite3"; export declare class SqliteGraphProvider implements GraphProvider { private db; readonly name = "sqlite-entity-edges"; constructor(db: Database.Database); linkEntities(params: { source_entity: string; target_entity: string; relation_type: string; memory_id?: string; episode_id?: string; confidence?: number; }): string; getRelatedEntities(entityId: string): RelatedEntity[]; traverseGraph(startEntities: string[], maxHops?: number): string[]; getAllEdges(): EntityEdge[]; }