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/symbols.ts4 * Description: The symbols tool — semantic symbol search over 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 SymbolsInput {14 query: string;15 kind?: string;16 scope?: string;17}1819const DESCRIPTION =20 'Search the repository\'s symbol index: functions, classes, types, exports. query supports "*" ' +21 'wildcards, e.g. "handleAuth" or "class:*Controller". Prefer this over grep when looking for a ' +22 "definition — it returns the signature and location directly. kind filters to function | class | " +23 "type | export | variable | method. scope restricts to a glob like src/**.";2425const MAX_RESULTS = 50;2627async function executeSymbols(input: SymbolsInput, ctx: ToolContext): Promise<ToolResult> {28 const startedAt = Date.now();29 if (ctx.repograph === undefined) {30 return {31 content:32 "The semantic index is unavailable in this session. Use grep to search for the symbol instead.",33 isError: true,34 metadata: { title: "symbols · index unavailable", durationMs: Date.now() - startedAt },35 };36 }37 const hits = await ctx.repograph.querySymbols(input.query, input.kind, input.scope);38 if (hits.length === 0) {39 return {40 content:41 `No symbols matched "${input.query}"${input.kind !== undefined ? ` (kind: ${input.kind})` : ""}. ` +42 "Try a broader query with wildcards, or fall back to grep.",43 metadata: { title: `Symbols "${input.query}" · 0`, durationMs: Date.now() - startedAt, matches: 0 },44 };45 }46 const shown = hits.slice(0, MAX_RESULTS);47 const lines = shown.map((hit) => {48 const doc = hit.docComment !== undefined ? `\n ${hit.docComment}` : "";49 return `${hit.file}:${hit.line} [${hit.kind}] ${hit.signature}${doc}`;50 });51 const omitted = hits.length - shown.length;52 const tail = omitted > 0 ? `\n[... ${omitted} more matches omitted — narrow the query]` : "";53 return {54 content: lines.join("\n") + tail,55 metadata: {56 title: `Symbols "${input.query}" · ${hits.length}`,57 durationMs: Date.now() - startedAt,58 matches: hits.length,59 },60 };61}6263/** Build the symbols tool (RepoGraph, v2 §3). */64export function createSymbolsTool(): ToolDefinition<SymbolsInput> {65 return {66 name: "symbols",67 description: DESCRIPTION,68 inputSchema: {69 type: "object",70 properties: {71 query: { type: "string", description: 'Symbol name or pattern, e.g. "handleAuth" or "*Controller".' },72 kind: {73 type: "string",74 description: "Filter by symbol kind.",75 enum: ["function", "class", "type", "export", "variable", "method"],76 },77 scope: { type: "string", description: 'Restrict to a path glob, e.g. "src/**".' },78 },79 required: ["query"],80 },81 capability: "file.read",82 execute: executeSymbols,83 };84}85