| 9 | * Provides functionality for searching nodes and retrieving graph data. |
| 10 | */ |
| 11 | export class SearchManager extends IManager implements ISearchManager { |
| 12 | /** |
| 13 | * Searches for nodes in the knowledge graph based on a query. |
| 14 | * Includes both matching nodes and their immediate neighbors. |
| 15 | */ |
| 16 | async searchNodes(query: string): Promise<Graph> { |
| 17 | try { |
| 18 | this.emit('beforeSearch', {query}); |
| 19 | |
| 20 | const graph = await this.storage.loadGraph(); |
| 21 | |
| 22 | // Find directly matching nodes |
| 23 | const matchingNodes = graph.nodes.filter(node => |
| 24 | node.name.toLowerCase().includes(query.toLowerCase()) || |
| 25 | node.nodeType.toLowerCase().includes(query.toLowerCase()) || |
| 26 | node.metadata.some(meta => |
| 27 | meta.toLowerCase().includes(query.toLowerCase()) |
| 28 | ) |
| 29 | ); |
| 30 | |
| 31 | // Get names of matching nodes for efficient lookup |
| 32 | const matchingNodeNames = new Set(matchingNodes.map(node => node.name)); |
| 33 | |
| 34 | // Find all edges connected to matching nodes |
| 35 | const connectedEdges = graph.edges.filter(edge => |
| 36 | matchingNodeNames.has(edge.from) || matchingNodeNames.has(edge.to) |
| 37 | ); |
| 38 | |
| 39 | // Get names of all neighbor nodes from the edges |
| 40 | const neighborNodeNames = new Set<string>(); |
| 41 | connectedEdges.forEach(edge => { |
| 42 | if (matchingNodeNames.has(edge.from)) { |
| 43 | neighborNodeNames.add(edge.to); |
| 44 | } |
| 45 | if (matchingNodeNames.has(edge.to)) { |
| 46 | neighborNodeNames.add(edge.from); |
| 47 | } |
| 48 | }); |
| 49 | |
| 50 | // Get all neighbor nodes |
| 51 | const neighborNodes = graph.nodes.filter(node => |
| 52 | !matchingNodeNames.has(node.name) && neighborNodeNames.has(node.name) |
| 53 | ); |
| 54 | |
| 55 | // Combine matching nodes and their neighbors |
| 56 | const resultNodes = [...matchingNodes, ...neighborNodes]; |
| 57 | |
| 58 | const result: Graph = { |
| 59 | nodes: resultNodes, |
| 60 | edges: connectedEdges |
| 61 | }; |
| 62 | |
| 63 | this.emit('afterSearch', result); |
| 64 | return result; |
| 65 | } catch (error) { |
| 66 | const message = error instanceof Error ? error.message : 'Unknown error occurred'; |
| 67 | throw new Error(`Search operation failed: ${message}`); |
| 68 | } |
nothing calls this directly
no outgoing calls
no test coverage detected