diff --git a/src/tools/executor.ts b/src/tools/executor.ts index db03866..6772822 100644 --- a/src/tools/executor.ts +++ b/src/tools/executor.ts @@ -7,6 +7,7 @@ import { writeFileSync, } from "node:fs"; import { join, resolve } from "node:path"; +import { getSkillContent, loadSkills } from "../skills/registry"; import type { ToolCall, ToolDefinition, ToolResult } from "../types"; const BLOCKED_COMMANDS = [ @@ -108,6 +109,18 @@ async function executeBuiltin( success: true, result: await getWebpage(args.url ?? ""), }; + case "read_skill": { + const skills = loadSkills(projectDir); + const content = getSkillContent(skills, args.name ?? ""); + return { + toolCallId: id, + name, + success: content !== null, + result: + content ?? + `No skill named "${args.name}". Available: ${skills.map((s) => s.name).join(", ")}`, + }; + } case "read_file": return { toolCallId: id, diff --git a/src/tools/registry.ts b/src/tools/registry.ts index 7b23bdd..cba638f 100644 --- a/src/tools/registry.ts +++ b/src/tools/registry.ts @@ -60,6 +60,25 @@ function loadBundledTools(): ToolDefinition[] { sandbox: false, destructive: false, }, + { + name: "read_skill", + description: + "Load the full instructions for one of the Available Skills by name. Call this before using a skill whose task you are about to perform.", + parameters: { + type: "object", + properties: { + name: { + type: "string", + description: + "The skill name, exactly as listed in Available Skills", + }, + }, + required: ["name"], + }, + handler: "builtin", + sandbox: false, + destructive: false, + }, { name: "read_file", description: