skill.test.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import { describe, expect, test } from "bun:test"
  2. import path from "path"
  3. import { pathToFileURL } from "url"
  4. import type { PermissionNext } from "../../src/permission/next"
  5. import type { Tool } from "../../src/tool/tool"
  6. import { Instance } from "../../src/project/instance"
  7. import { SkillTool } from "../../src/tool/skill"
  8. import { tmpdir } from "../fixture/fixture"
  9. const baseCtx: Omit<Tool.Context, "ask"> = {
  10. sessionID: "test",
  11. messageID: "",
  12. callID: "",
  13. agent: "build",
  14. abort: AbortSignal.any([]),
  15. messages: [],
  16. metadata: () => {},
  17. }
  18. describe("tool.skill", () => {
  19. test("description lists skill location URL", async () => {
  20. await using tmp = await tmpdir({
  21. git: true,
  22. init: async (dir) => {
  23. const skillDir = path.join(dir, ".opencode", "skill", "tool-skill")
  24. await Bun.write(
  25. path.join(skillDir, "SKILL.md"),
  26. `---
  27. name: tool-skill
  28. description: Skill for tool tests.
  29. ---
  30. # Tool Skill
  31. `,
  32. )
  33. },
  34. })
  35. const home = process.env.OPENCODE_TEST_HOME
  36. process.env.OPENCODE_TEST_HOME = tmp.path
  37. try {
  38. await Instance.provide({
  39. directory: tmp.path,
  40. fn: async () => {
  41. const tool = await SkillTool.init()
  42. const skillPath = path.join(tmp.path, ".opencode", "skill", "tool-skill", "SKILL.md")
  43. expect(tool.description).toContain(`<location>${pathToFileURL(skillPath).href}</location>`)
  44. },
  45. })
  46. } finally {
  47. process.env.OPENCODE_TEST_HOME = home
  48. }
  49. })
  50. test("execute returns skill content block with files", async () => {
  51. await using tmp = await tmpdir({
  52. git: true,
  53. init: async (dir) => {
  54. const skillDir = path.join(dir, ".opencode", "skill", "tool-skill")
  55. await Bun.write(
  56. path.join(skillDir, "SKILL.md"),
  57. `---
  58. name: tool-skill
  59. description: Skill for tool tests.
  60. ---
  61. # Tool Skill
  62. Use this skill.
  63. `,
  64. )
  65. await Bun.write(path.join(skillDir, "scripts", "demo.txt"), "demo")
  66. },
  67. })
  68. const home = process.env.OPENCODE_TEST_HOME
  69. process.env.OPENCODE_TEST_HOME = tmp.path
  70. try {
  71. await Instance.provide({
  72. directory: tmp.path,
  73. fn: async () => {
  74. const tool = await SkillTool.init()
  75. const requests: Array<Omit<PermissionNext.Request, "id" | "sessionID" | "tool">> = []
  76. const ctx: Tool.Context = {
  77. ...baseCtx,
  78. ask: async (req) => {
  79. requests.push(req)
  80. },
  81. }
  82. const result = await tool.execute({ name: "tool-skill" }, ctx)
  83. const dir = path.join(tmp.path, ".opencode", "skill", "tool-skill")
  84. const file = path.resolve(dir, "scripts", "demo.txt")
  85. expect(requests.length).toBe(1)
  86. expect(requests[0].permission).toBe("skill")
  87. expect(requests[0].patterns).toContain("tool-skill")
  88. expect(requests[0].always).toContain("tool-skill")
  89. expect(result.metadata.dir).toBe(dir)
  90. expect(result.output).toContain(`<skill_content name="tool-skill">`)
  91. expect(result.output).toContain(`Base directory for this skill: ${pathToFileURL(dir).href}`)
  92. expect(result.output).toContain(`<file>${file}</file>`)
  93. },
  94. })
  95. } finally {
  96. process.env.OPENCODE_TEST_HOME = home
  97. }
  98. })
  99. })