diff --git a/src/tools/skill/constants.ts b/src/tools/skill/constants.ts index 735772d8..e65e66e4 100644 --- a/src/tools/skill/constants.ts +++ b/src/tools/skill/constants.ts @@ -2,13 +2,8 @@ export const TOOL_NAME = "skill" as const export const TOOL_DESCRIPTION_NO_SKILLS = "Load a skill or execute a slash command to get detailed instructions for a specific task. No skills are currently available." -export const TOOL_DESCRIPTION_PREFIX = `Load a skill or execute a slash command to get detailed instructions for a specific task. +export const TOOL_DESCRIPTION_PREFIX = `Load a skill or execute a command to get detailed instructions for a specific task. Skills and commands provide specialized knowledge and step-by-step guidance. Use this when a task matches an available skill's or command's description. - -**How to use:** -- Call with a skill name: name='code-review' -- Call with a command name (without leading slash): name='publish' -- The tool will return detailed instructions with your context applied. ` diff --git a/src/tools/skill/tools.test.ts b/src/tools/skill/tools.test.ts index 52d69bb5..b74af012 100644 --- a/src/tools/skill/tools.test.ts +++ b/src/tools/skill/tools.test.ts @@ -4,6 +4,7 @@ import * as fs from "node:fs" import { createSkillTool } from "./tools" import { SkillMcpManager } from "../../features/skill-mcp-manager" import type { LoadedSkill } from "../../features/opencode-skill-loader/types" +import type { CommandInfo } from "../slashcommand/types" import type { Tool as McpTool } from "@modelcontextprotocol/sdk/types.js" const originalReadFileSync = fs.readFileSync.bind(fs) @@ -105,6 +106,61 @@ describe("skill tool - synchronous description", () => { }) }) +describe("skill tool - command listing format", () => { + it("uses XML format for commands in description", () => { + // given + const commands: CommandInfo[] = [ + { + name: "publish", + path: "/test/commands/publish", + metadata: { name: "publish", description: "Publish to npm", argumentHint: "" }, + scope: "opencode-project", + }, + { + name: "commit", + path: "/test/commands/commit", + metadata: { name: "commit", description: "Commits changes" }, + scope: "builtin", + }, + ] + + // when + const tool = createSkillTool({ skills: [], commands }) + + // then + expect(tool.description).toContain("") + expect(tool.description).toContain("") + expect(tool.description).toContain("") + expect(tool.description).toContain("/publish ") + expect(tool.description).toContain("Publish to npm") + expect(tool.description).toContain("opencode-project") + expect(tool.description).toContain("/commit") + expect(tool.description).toContain("builtin") + }) + + it("uses XML format for both skills and commands together", () => { + // given + const loadedSkills = [createMockSkill("test-skill")] + const commands: CommandInfo[] = [ + { + name: "deploy", + path: "/test/commands/deploy", + metadata: { name: "deploy", description: "Deploy app" }, + scope: "user", + }, + ] + + // when + const tool = createSkillTool({ skills: loadedSkills, commands }) + + // then + expect(tool.description).toContain("") + expect(tool.description).toContain("") + expect(tool.description).toContain("") + expect(tool.description).toContain("/deploy") + }) +}) + describe("skill tool - agent restriction", () => { it("allows skill without agent restriction to any agent", async () => { // given diff --git a/src/tools/skill/tools.ts b/src/tools/skill/tools.ts index 151190cc..5a7f05b1 100644 --- a/src/tools/skill/tools.ts +++ b/src/tools/skill/tools.ts @@ -48,11 +48,18 @@ function formatCombinedDescription(skills: SkillInfo[], commands: CommandInfo[]) } if (commands.length > 0) { - const commandLines = commands.map(cmd => { + const commandsXml = commands.map(cmd => { const hint = cmd.metadata.argumentHint ? ` ${cmd.metadata.argumentHint}` : "" - return ` - /${cmd.name}${hint}: ${cmd.metadata.description || "(no description)"} (${cmd.scope})` + const parts = [ + " ", + ` /${cmd.name}${hint}`, + ` ${cmd.metadata.description || "(no description)"}`, + ` ${cmd.scope}`, + " ", + ] + return parts.join("\n") }).join("\n") - lines.push(`\n\n${commandLines}\n`) + lines.push(`\n\n${commandsXml}\n`) } return TOOL_DESCRIPTION_PREFIX + lines.join("")