fix(skill): unify command listing format and trim verbose description

This commit is contained in:
YeonGyu-Kim 2026-02-19 13:53:15 +09:00
parent e70539fe5f
commit 17d3184e7a
3 changed files with 67 additions and 9 deletions

View File

@ -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.
`

View File

@ -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: "<patch|minor|major>" },
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("<available_commands>")
expect(tool.description).toContain("</available_commands>")
expect(tool.description).toContain("<command>")
expect(tool.description).toContain("<name>/publish <patch|minor|major></name>")
expect(tool.description).toContain("<description>Publish to npm</description>")
expect(tool.description).toContain("<scope>opencode-project</scope>")
expect(tool.description).toContain("<name>/commit</name>")
expect(tool.description).toContain("<scope>builtin</scope>")
})
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("<available_skills>")
expect(tool.description).toContain("<available_commands>")
expect(tool.description).toContain("<command>")
expect(tool.description).toContain("<name>/deploy</name>")
})
})
describe("skill tool - agent restriction", () => {
it("allows skill without agent restriction to any agent", async () => {
// given

View File

@ -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 = [
" <command>",
` <name>/${cmd.name}${hint}</name>`,
` <description>${cmd.metadata.description || "(no description)"}</description>`,
` <scope>${cmd.scope}</scope>`,
" </command>",
]
return parts.join("\n")
}).join("\n")
lines.push(`\n<available_commands>\n${commandLines}\n</available_commands>`)
lines.push(`\n<available_commands>\n${commandsXml}\n</available_commands>`)
}
return TOOL_DESCRIPTION_PREFIX + lines.join("")