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/registry.ts4 * Description: ToolDefinition interface and ToolRegistry — schema export for the Anthropic tools parameter.5 *6 * Author: Simon-Pierre Boucher7 * Contact: contact@spboucher.ai8 */910import { KhaelorError } from "../shared/index.js";11import type { ParsedInput, ToolJsonSchema } from "./schema.js";12import { validateToolInput } from "./schema.js";13import type { ToolCapabilityHint, ToolContext, ToolName, ToolResult } from "./types.js";1415/**16 * A tool the model can call (TOOL_PROTOCOL §1.2). The JSON schema is the17 * source of truth for the Anthropic `input_schema`; `capability` is the18 * coarse hint the executor's permission layer refines into capability19 * requests before `execute` runs. Tools never check permissions themselves.20 */21export interface ToolDefinition<P = unknown> {22 readonly name: ToolName;23 /** Model-facing description — the exact text sent in the tools array. */24 readonly description: string;25 /** Flat object schema, ≤5 properties (ADR-8). */26 readonly inputSchema: ToolJsonSchema;27 /** Coarse capability hint for the permission layer. */28 readonly capability: ToolCapabilityHint;29 /** Runs only after approval. Must respect ctx.signal. */30 execute(input: P, ctx: ToolContext): Promise<ToolResult>;31}3233/** One entry of the Anthropic request's `tools` array. */34export interface AnthropicToolParam {35 name: string;36 description: string;37 input_schema: ToolJsonSchema;38}3940/** Validate a raw tool_use input against a tool's schema (repair prose on failure). */41export function parseToolInput<P>(tool: ToolDefinition<P>, input: unknown): ParsedInput<P> {42 return validateToolInput<P>(tool.name, tool.inputSchema, input);43}4445/** Registry of the tools available to the model (TOOL_PROTOCOL §1.2). */46export class ToolRegistry {47 private readonly tools = new Map<ToolName, ToolDefinition>();4849 register(tool: ToolDefinition): void {50 if (this.tools.has(tool.name)) {51 throw new KhaelorError("internal", `Tool "${tool.name}" is already registered.`);52 }53 if (Object.keys(tool.inputSchema.properties).length > 5) {54 throw new KhaelorError("internal", `Tool "${tool.name}" exceeds the 5-parameter limit (ADR-8).`);55 }56 this.tools.set(tool.name, tool);57 }5859 list(): ToolDefinition[] {60 return [...this.tools.values()];61 }6263 get(name: string): ToolDefinition | undefined {64 return this.tools.get(name as ToolName);65 }6667 /** `[{name, description, input_schema}]` for the Anthropic request. */68 toAnthropicTools(): AnthropicToolParam[] {69 return this.list().map((tool) => ({70 name: tool.name,71 description: tool.description,72 input_schema: tool.inputSchema,73 }));74 }75}76