MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / computeGraphRelevance

Method computeGraphRelevance

src/mcp/tools.ts:2436–2489  ·  view source on GitHub ↗

* Graph-connectivity relevance via Random-Walk-with-Restart (personalized * PageRank) from the query's matched SEED nodes over the call/reference graph. * * This is the ranking signal text search (FTS/bm25) CANNOT provide, and it's * codegraph's home turf: relevance by STRUCTURE, not wor

(
    nodeIds: string[],
    edges: Edge[],
    seedIds: Set<string>,
  )

Source from the content-addressed store, hash-verified

2434 * it's a few hundred nodes × ~25 iterations — negligible cost.
2435 */
2436 private computeGraphRelevance(
2437 nodeIds: string[],
2438 edges: Edge[],
2439 seedIds: Set<string>,
2440 ): Map<string, number> {
2441 const out = new Map<string, number>();
2442 const n = nodeIds.length;
2443 if (n === 0) return out;
2444 const idx = new Map<string, number>();
2445 for (let i = 0; i < n; i++) idx.set(nodeIds[i]!, i);
2446
2447 const RANK_EDGES = new Set<string>([
2448 'calls', 'references', 'extends', 'implements', 'overrides',
2449 'instantiates', 'returns', 'type_of', 'imports',
2450 ]);
2451 const adj: number[][] = Array.from({ length: n }, () => []);
2452 for (const e of edges) {
2453 if (!RANK_EDGES.has(e.kind)) continue;
2454 const i = idx.get(e.source);
2455 const j = idx.get(e.target);
2456 if (i === undefined || j === undefined || i === j) continue;
2457 adj[i]!.push(j);
2458 adj[j]!.push(i); // undirected — reachable either direction
2459 }
2460
2461 // Restart vector: uniform over seeds present in the candidate set. (Falls
2462 // back to uniform-over-all if no seed landed in the set, so we never return
2463 // all-zero.)
2464 const r = new Array<number>(n).fill(0);
2465 let rsum = 0;
2466 for (const id of seedIds) {
2467 const i = idx.get(id);
2468 if (i !== undefined) { r[i] = 1; rsum += 1; }
2469 }
2470 if (rsum === 0) { for (let i = 0; i < n; i++) r[i] = 1; rsum = n; }
2471 for (let i = 0; i < n; i++) r[i]! /= rsum;
2472
2473 const alpha = 0.25;
2474 let s = r.slice();
2475 for (let iter = 0; iter < 25; iter++) {
2476 const next = new Array<number>(n).fill(0);
2477 for (let i = 0; i < n; i++) {
2478 const si = s[i]!;
2479 if (si === 0) continue;
2480 const d = adj[i]!.length;
2481 if (d === 0) { next[i]! += si; continue; } // dangling: keep its mass
2482 const share = si / d;
2483 for (const j of adj[i]!) next[j]! += share;
2484 }
2485 for (let i = 0; i < n; i++) s[i] = (1 - alpha) * next[i]! + alpha * r[i]!;
2486 }
2487 for (let i = 0; i < n; i++) out.set(nodeIds[i]!, s[i]!);
2488 return out;
2489 }
2490
2491 /**
2492 * Handle codegraph_explore — deep exploration in a single call

Callers 1

handleExploreMethod · 0.95

Calls 3

hasMethod · 0.80
getMethod · 0.65
setMethod · 0.45

Tested by

no test coverage detected