spb/khaelor Public
KHAELOR — a terminal-native autonomous engineering agent powered by Anthropic.
TypeScript 82.9%
HTML 14.9%
CSS 1.1%
JavaScript 0.7%
1/**2 * KHAELOR3 * File: src/tools/refs.ts4 * Description: The refs tool — who uses what: callers/callees/importers of a symbol via the RepoGraph index (v2 design §3).5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import type { ToolDefinition } from "./registry.js";11import type { ToolContext, ToolResult } from "./types.js";1213export interface RefsInput {14 symbol: string;15 direction: string;16}1718const DESCRIPTION =19 "Find usage sites of a symbol via the semantic index. direction: callers (who calls/uses it), " +20 "callees (what it calls), importers (which files import it). Each site comes with its line of " +21 "context. Use this to assess blast radius before editing a symbol.";2223const MAX_RESULTS = 80;2425async function executeRefs(input: RefsInput, ctx: ToolContext): Promise<ToolResult> {26 const startedAt = Date.now();27 if (ctx.repograph === undefined) {28 return {29 content:30 "The semantic index is unavailable in this session. Use grep to find usages instead.",31 isError: true,32 metadata: { title: "refs · index unavailable", durationMs: Date.now() - startedAt },33 };34 }35 const direction =36 input.direction === "callers" || input.direction === "callees" || input.direction === "importers"37 ? input.direction38 : null;39 if (direction === null) {40 return {41 content: 'Parameter "direction" must be one of: callers, callees, importers.',42 isError: true,43 metadata: { title: "refs · invalid direction", durationMs: Date.now() - startedAt },44 };45 }46 const hits = await ctx.repograph.queryRefs(input.symbol, direction);47 if (hits.length === 0) {48 return {49 content: `No ${direction} found for "${input.symbol}". The symbol may be unused, dynamic, or misspelled.`,50 metadata: {51 title: `Refs ${input.symbol} · 0`,52 durationMs: Date.now() - startedAt,53 matches: 0,54 },55 };56 }57 const shown = hits.slice(0, MAX_RESULTS);58 const lines = shown.map((hit) => `${hit.file}:${hit.line} ${hit.context}`);59 const omitted = hits.length - shown.length;60 const tail = omitted > 0 ? `\n[... ${omitted} more sites omitted]` : "";61 return {62 content: lines.join("\n") + tail,63 metadata: {64 title: `Refs ${input.symbol} · ${hits.length} ${direction}`,65 durationMs: Date.now() - startedAt,66 matches: hits.length,67 },68 };69}7071/** Build the refs tool (RepoGraph, v2 §3). */72export function createRefsTool(): ToolDefinition<RefsInput> {73 return {74 name: "refs",75 description: DESCRIPTION,76 inputSchema: {77 type: "object",78 properties: {79 symbol: { type: "string", description: "The symbol name to trace." },80 direction: {81 type: "string",82 description: "callers | callees | importers",83 enum: ["callers", "callees", "importers"],84 },85 },86 required: ["symbol", "direction"],87 },88 capability: "file.read",89 execute: executeRefs,90 };91}92