fix(skill): support YAML array format for allowed-tools field (#1163)
Fixes #1021 The allowed-tools field in skill frontmatter now supports both formats: - Space-separated string: 'allowed-tools: Read Write Edit Bash' - YAML array: 'allowed-tools: [Read, Write, Edit, Bash]' - Multi-line YAML array format also works Previously, skills using YAML array format would silently fail to parse, causing them to not appear in the <available_skills> list. Changes: - Updated parseAllowedTools() in loader.ts, async-loader.ts, and merger.ts to handle both string and string[] types - Updated SkillMetadata type to accept string | string[] for allowed-tools - Added 4 test cases covering all allowed-tools formats
This commit is contained in:
@@ -268,6 +268,123 @@ Skill body.
|
||||
} finally {
|
||||
process.chdir(originalCwd)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("allowed-tools parsing", () => {
|
||||
it("parses space-separated allowed-tools string", async () => {
|
||||
// #given
|
||||
const skillContent = `---
|
||||
name: space-separated-tools
|
||||
description: Skill with space-separated allowed-tools
|
||||
allowed-tools: Read Write Edit Bash
|
||||
---
|
||||
Skill body.
|
||||
`
|
||||
createTestSkill("space-separated-tools", skillContent)
|
||||
|
||||
// #when
|
||||
const { discoverSkills } = await import("./loader")
|
||||
const originalCwd = process.cwd()
|
||||
process.chdir(TEST_DIR)
|
||||
|
||||
try {
|
||||
const skills = await discoverSkills({ includeClaudeCodePaths: false })
|
||||
const skill = skills.find(s => s.name === "space-separated-tools")
|
||||
|
||||
// #then
|
||||
expect(skill).toBeDefined()
|
||||
expect(skill?.allowedTools).toEqual(["Read", "Write", "Edit", "Bash"])
|
||||
} finally {
|
||||
process.chdir(originalCwd)
|
||||
}
|
||||
})
|
||||
|
||||
it("parses YAML inline array allowed-tools", async () => {
|
||||
// #given
|
||||
const skillContent = `---
|
||||
name: yaml-inline-array
|
||||
description: Skill with YAML inline array allowed-tools
|
||||
allowed-tools: [Read, Write, Edit, Bash]
|
||||
---
|
||||
Skill body.
|
||||
`
|
||||
createTestSkill("yaml-inline-array", skillContent)
|
||||
|
||||
// #when
|
||||
const { discoverSkills } = await import("./loader")
|
||||
const originalCwd = process.cwd()
|
||||
process.chdir(TEST_DIR)
|
||||
|
||||
try {
|
||||
const skills = await discoverSkills({ includeClaudeCodePaths: false })
|
||||
const skill = skills.find(s => s.name === "yaml-inline-array")
|
||||
|
||||
// #then
|
||||
expect(skill).toBeDefined()
|
||||
expect(skill?.allowedTools).toEqual(["Read", "Write", "Edit", "Bash"])
|
||||
} finally {
|
||||
process.chdir(originalCwd)
|
||||
}
|
||||
})
|
||||
|
||||
it("parses YAML multi-line array allowed-tools", async () => {
|
||||
// #given
|
||||
const skillContent = `---
|
||||
name: yaml-multiline-array
|
||||
description: Skill with YAML multi-line array allowed-tools
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
- Edit
|
||||
- Bash
|
||||
---
|
||||
Skill body.
|
||||
`
|
||||
createTestSkill("yaml-multiline-array", skillContent)
|
||||
|
||||
// #when
|
||||
const { discoverSkills } = await import("./loader")
|
||||
const originalCwd = process.cwd()
|
||||
process.chdir(TEST_DIR)
|
||||
|
||||
try {
|
||||
const skills = await discoverSkills({ includeClaudeCodePaths: false })
|
||||
const skill = skills.find(s => s.name === "yaml-multiline-array")
|
||||
|
||||
// #then
|
||||
expect(skill).toBeDefined()
|
||||
expect(skill?.allowedTools).toEqual(["Read", "Write", "Edit", "Bash"])
|
||||
} finally {
|
||||
process.chdir(originalCwd)
|
||||
}
|
||||
})
|
||||
|
||||
it("returns undefined for skill without allowed-tools", async () => {
|
||||
// #given
|
||||
const skillContent = `---
|
||||
name: no-allowed-tools
|
||||
description: Skill without allowed-tools field
|
||||
---
|
||||
Skill body.
|
||||
`
|
||||
createTestSkill("no-allowed-tools", skillContent)
|
||||
|
||||
// #when
|
||||
const { discoverSkills } = await import("./loader")
|
||||
const originalCwd = process.cwd()
|
||||
process.chdir(TEST_DIR)
|
||||
|
||||
try {
|
||||
const skills = await discoverSkills({ includeClaudeCodePaths: false })
|
||||
const skill = skills.find(s => s.name === "no-allowed-tools")
|
||||
|
||||
// #then
|
||||
expect(skill).toBeDefined()
|
||||
expect(skill?.allowedTools).toBeUndefined()
|
||||
} finally {
|
||||
process.chdir(originalCwd)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user