|
|
@@ -1,9 +1,26 @@
|
|
|
import { test, expect } from "bun:test"
|
|
|
import { Skill } from "../../src/skill"
|
|
|
-import { SystemPrompt } from "../../src/session/system"
|
|
|
import { Instance } from "../../src/project/instance"
|
|
|
import { tmpdir } from "../fixture/fixture"
|
|
|
import path from "path"
|
|
|
+import fs from "fs/promises"
|
|
|
+
|
|
|
+async function createGlobalSkill(homeDir: string) {
|
|
|
+ const skillDir = path.join(homeDir, ".claude", "skills", "global-test-skill")
|
|
|
+ await fs.mkdir(skillDir, { recursive: true })
|
|
|
+ await Bun.write(
|
|
|
+ path.join(skillDir, "SKILL.md"),
|
|
|
+ `---
|
|
|
+name: global-test-skill
|
|
|
+description: A global skill from ~/.claude/skills for testing.
|
|
|
+---
|
|
|
+
|
|
|
+# Global Test Skill
|
|
|
+
|
|
|
+This skill is loaded from the global home directory.
|
|
|
+`,
|
|
|
+ )
|
|
|
+}
|
|
|
|
|
|
test("discovers skills from .opencode/skill/ directory", async () => {
|
|
|
await using tmp = await tmpdir({
|
|
|
@@ -30,9 +47,10 @@ Instructions here.
|
|
|
fn: async () => {
|
|
|
const skills = await Skill.all()
|
|
|
expect(skills.length).toBe(1)
|
|
|
- expect(skills[0].name).toBe("test-skill")
|
|
|
- expect(skills[0].description).toBe("A test skill for verification.")
|
|
|
- expect(skills[0].location).toContain("skill/test-skill/SKILL.md")
|
|
|
+ const testSkill = skills.find((s) => s.name === "test-skill")
|
|
|
+ expect(testSkill).toBeDefined()
|
|
|
+ expect(testSkill!.description).toBe("A test skill for verification.")
|
|
|
+ expect(testSkill!.location).toContain("skill/test-skill/SKILL.md")
|
|
|
},
|
|
|
})
|
|
|
})
|
|
|
@@ -41,15 +59,26 @@ test("discovers multiple skills from .opencode/skill/ directory", async () => {
|
|
|
await using tmp = await tmpdir({
|
|
|
git: true,
|
|
|
init: async (dir) => {
|
|
|
- const skillDir = path.join(dir, ".opencode", "skill", "my-skill")
|
|
|
+ const skillDir1 = path.join(dir, ".opencode", "skill", "skill-one")
|
|
|
+ const skillDir2 = path.join(dir, ".opencode", "skill", "skill-two")
|
|
|
await Bun.write(
|
|
|
- path.join(skillDir, "SKILL.md"),
|
|
|
+ path.join(skillDir1, "SKILL.md"),
|
|
|
`---
|
|
|
-name: my-skill
|
|
|
-description: Another test skill.
|
|
|
+name: skill-one
|
|
|
+description: First test skill.
|
|
|
---
|
|
|
|
|
|
-# My Skill
|
|
|
+# Skill One
|
|
|
+`,
|
|
|
+ )
|
|
|
+ await Bun.write(
|
|
|
+ path.join(skillDir2, "SKILL.md"),
|
|
|
+ `---
|
|
|
+name: skill-two
|
|
|
+description: Second test skill.
|
|
|
+---
|
|
|
+
|
|
|
+# Skill Two
|
|
|
`,
|
|
|
)
|
|
|
},
|
|
|
@@ -59,8 +88,9 @@ description: Another test skill.
|
|
|
directory: tmp.path,
|
|
|
fn: async () => {
|
|
|
const skills = await Skill.all()
|
|
|
- expect(skills.length).toBe(1)
|
|
|
- expect(skills[0].name).toBe("my-skill")
|
|
|
+ expect(skills.length).toBe(2)
|
|
|
+ expect(skills.find((s) => s.name === "skill-one")).toBeDefined()
|
|
|
+ expect(skills.find((s) => s.name === "skill-two")).toBeDefined()
|
|
|
},
|
|
|
})
|
|
|
})
|
|
|
@@ -89,18 +119,6 @@ Just some content without YAML frontmatter.
|
|
|
})
|
|
|
})
|
|
|
|
|
|
-test("returns empty array when no skills exist", async () => {
|
|
|
- await using tmp = await tmpdir({ git: true })
|
|
|
-
|
|
|
- await Instance.provide({
|
|
|
- directory: tmp.path,
|
|
|
- fn: async () => {
|
|
|
- const skills = await Skill.all()
|
|
|
- expect(skills).toEqual([])
|
|
|
- },
|
|
|
- })
|
|
|
-})
|
|
|
-
|
|
|
test("discovers skills from .claude/skills/ directory", async () => {
|
|
|
await using tmp = await tmpdir({
|
|
|
git: true,
|
|
|
@@ -124,8 +142,44 @@ description: A skill in the .claude/skills directory.
|
|
|
fn: async () => {
|
|
|
const skills = await Skill.all()
|
|
|
expect(skills.length).toBe(1)
|
|
|
- expect(skills[0].name).toBe("claude-skill")
|
|
|
- expect(skills[0].location).toContain(".claude/skills/claude-skill/SKILL.md")
|
|
|
+ const claudeSkill = skills.find((s) => s.name === "claude-skill")
|
|
|
+ expect(claudeSkill).toBeDefined()
|
|
|
+ expect(claudeSkill!.location).toContain(".claude/skills/claude-skill/SKILL.md")
|
|
|
+ },
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+test("discovers global skills from ~/.claude/skills/ directory", async () => {
|
|
|
+ await using tmp = await tmpdir({ git: true })
|
|
|
+
|
|
|
+ const originalHome = process.env.OPENCODE_TEST_HOME
|
|
|
+ process.env.OPENCODE_TEST_HOME = tmp.path
|
|
|
+
|
|
|
+ try {
|
|
|
+ await createGlobalSkill(tmp.path)
|
|
|
+ await Instance.provide({
|
|
|
+ directory: tmp.path,
|
|
|
+ fn: async () => {
|
|
|
+ const skills = await Skill.all()
|
|
|
+ expect(skills.length).toBe(1)
|
|
|
+ expect(skills[0].name).toBe("global-test-skill")
|
|
|
+ expect(skills[0].description).toBe("A global skill from ~/.claude/skills for testing.")
|
|
|
+ expect(skills[0].location).toContain(".claude/skills/global-test-skill/SKILL.md")
|
|
|
+ },
|
|
|
+ })
|
|
|
+ } finally {
|
|
|
+ process.env.OPENCODE_TEST_HOME = originalHome
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+test("returns empty array when no skills exist", async () => {
|
|
|
+ await using tmp = await tmpdir({ git: true })
|
|
|
+
|
|
|
+ await Instance.provide({
|
|
|
+ directory: tmp.path,
|
|
|
+ fn: async () => {
|
|
|
+ const skills = await Skill.all()
|
|
|
+ expect(skills).toEqual([])
|
|
|
},
|
|
|
})
|
|
|
})
|