/** * KHAELOR * File: src/tools/refs.ts * Description: The refs tool — who uses what: callers/callees/importers of a symbol via the RepoGraph index (v2 design §3). * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai */ import type { ToolDefinition } from "./registry.js"; import type { ToolContext, ToolResult } from "./types.js"; export interface RefsInput { symbol: string; direction: string; } const DESCRIPTION = "Find usage sites of a symbol via the semantic index. direction: callers (who calls/uses it), " + "callees (what it calls), importers (which files import it). Each site comes with its line of " + "context. Use this to assess blast radius before editing a symbol."; const MAX_RESULTS = 80; async function executeRefs(input: RefsInput, ctx: ToolContext): Promise { const startedAt = Date.now(); if (ctx.repograph === undefined) { return { content: "The semantic index is unavailable in this session. Use grep to find usages instead.", isError: true, metadata: { title: "refs · index unavailable", durationMs: Date.now() - startedAt }, }; } const direction = input.direction === "callers" || input.direction === "callees" || input.direction === "importers" ? input.direction : null; if (direction === null) { return { content: 'Parameter "direction" must be one of: callers, callees, importers.', isError: true, metadata: { title: "refs · invalid direction", durationMs: Date.now() - startedAt }, }; } const hits = await ctx.repograph.queryRefs(input.symbol, direction); if (hits.length === 0) { return { content: `No ${direction} found for "${input.symbol}". The symbol may be unused, dynamic, or misspelled.`, metadata: { title: `Refs ${input.symbol} · 0`, durationMs: Date.now() - startedAt, matches: 0, }, }; } const shown = hits.slice(0, MAX_RESULTS); const lines = shown.map((hit) => `${hit.file}:${hit.line} ${hit.context}`); const omitted = hits.length - shown.length; const tail = omitted > 0 ? `\n[... ${omitted} more sites omitted]` : ""; return { content: lines.join("\n") + tail, metadata: { title: `Refs ${input.symbol} · ${hits.length} ${direction}`, durationMs: Date.now() - startedAt, matches: hits.length, }, }; } /** Build the refs tool (RepoGraph, v2 §3). */ export function createRefsTool(): ToolDefinition { return { name: "refs", description: DESCRIPTION, inputSchema: { type: "object", properties: { symbol: { type: "string", description: "The symbol name to trace." }, direction: { type: "string", description: "callers | callees | importers", enum: ["callers", "callees", "importers"], }, }, required: ["symbol", "direction"], }, capability: "file.read", execute: executeRefs, }; }