( graph: GraphStore, nodeId: string, depth: number, maxDepth: number, pathLabels: string[], visited: Set<string>, results: TraversalResult[], edgeFilter?: RelationType[], )
| 332 | } |
| 333 | |
| 334 | function collectTraversal( |
| 335 | graph: GraphStore, nodeId: string, depth: number, maxDepth: number, |
| 336 | pathLabels: string[], visited: Set<string>, results: TraversalResult[], edgeFilter?: RelationType[], |
| 337 | ): void { |
| 338 | if (depth > maxDepth) return; |
| 339 | |
| 340 | for (const edge of getEdgesForNode(graph, nodeId)) { |
| 341 | if (edgeFilter && !edgeFilter.includes(edge.relation)) continue; |
| 342 | const neighborId = getNeighborId(edge, nodeId); |
| 343 | if (visited.has(neighborId)) continue; |
| 344 | |
| 345 | const neighbor = graph.nodes[neighborId]; |
| 346 | if (!neighbor) continue; |
| 347 | |
| 348 | visited.add(neighborId); |
| 349 | neighbor.lastAccessed = Date.now(); |
| 350 | |
| 351 | const decayed = decayWeight(edge); |
| 352 | const depthPenalty = 1 / (1 + depth * 0.3); |
| 353 | const score = decayed * depthPenalty * 100; |
| 354 | |
| 355 | results.push({ |
| 356 | node: neighbor, |
| 357 | depth, |
| 358 | pathRelations: [...pathLabels, `--[${edge.relation}]-->`, neighbor.label], |
| 359 | relevanceScore: Math.round(score * 10) / 10, |
| 360 | }); |
| 361 | |
| 362 | collectTraversal(graph, neighborId, depth + 1, maxDepth, [...pathLabels, `--[${edge.relation}]-->`, neighbor.label], visited, results, edgeFilter); |
| 363 | } |
| 364 | } |
| 365 | |
| 366 | export async function getGraphStats(rootDir: string): Promise<{ nodes: number; edges: number; types: Record<string, number>; relations: Record<string, number> }> { |
| 367 | const graph = await loadGraph(rootDir); |
no test coverage detected