/** * KHAELOR * File: src/tools/symbols.ts * Description: The symbols tool — semantic symbol search over 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 SymbolsInput { query: string; kind?: string; scope?: string; } const DESCRIPTION = 'Search the repository\'s symbol index: functions, classes, types, exports. query supports "*" ' + 'wildcards, e.g. "handleAuth" or "class:*Controller". Prefer this over grep when looking for a ' + "definition — it returns the signature and location directly. kind filters to function | class | " + "type | export | variable | method. scope restricts to a glob like src/**."; const MAX_RESULTS = 50; async function executeSymbols(input: SymbolsInput, ctx: ToolContext): Promise { const startedAt = Date.now(); if (ctx.repograph === undefined) { return { content: "The semantic index is unavailable in this session. Use grep to search for the symbol instead.", isError: true, metadata: { title: "symbols · index unavailable", durationMs: Date.now() - startedAt }, }; } const hits = await ctx.repograph.querySymbols(input.query, input.kind, input.scope); if (hits.length === 0) { return { content: `No symbols matched "${input.query}"${input.kind !== undefined ? ` (kind: ${input.kind})` : ""}. ` + "Try a broader query with wildcards, or fall back to grep.", metadata: { title: `Symbols "${input.query}" · 0`, durationMs: Date.now() - startedAt, matches: 0 }, }; } const shown = hits.slice(0, MAX_RESULTS); const lines = shown.map((hit) => { const doc = hit.docComment !== undefined ? `\n ${hit.docComment}` : ""; return `${hit.file}:${hit.line} [${hit.kind}] ${hit.signature}${doc}`; }); const omitted = hits.length - shown.length; const tail = omitted > 0 ? `\n[... ${omitted} more matches omitted — narrow the query]` : ""; return { content: lines.join("\n") + tail, metadata: { title: `Symbols "${input.query}" · ${hits.length}`, durationMs: Date.now() - startedAt, matches: hits.length, }, }; } /** Build the symbols tool (RepoGraph, v2 §3). */ export function createSymbolsTool(): ToolDefinition { return { name: "symbols", description: DESCRIPTION, inputSchema: { type: "object", properties: { query: { type: "string", description: 'Symbol name or pattern, e.g. "handleAuth" or "*Controller".' }, kind: { type: "string", description: "Filter by symbol kind.", enum: ["function", "class", "type", "export", "variable", "method"], }, scope: { type: "string", description: 'Restrict to a path glob, e.g. "src/**".' }, }, required: ["query"], }, capability: "file.read", execute: executeSymbols, }; }