SPB Git

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%
3.0 KB · 85 lines typescript
Raw Blame History
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