skill.test.ts 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import path from "path"
  2. import { describe, expect } from "bun:test"
  3. import { Effect, Layer, Schema } from "effect"
  4. import { Config } from "@opencode-ai/core/config"
  5. import { ConfigSkillPlugin } from "@opencode-ai/core/config/plugin/skill"
  6. import { Global } from "@opencode-ai/core/global"
  7. import { Location } from "@opencode-ai/core/location"
  8. import { AbsolutePath } from "@opencode-ai/core/schema"
  9. import { SkillV2 } from "@opencode-ai/core/skill"
  10. import { location } from "../fixture/location"
  11. import { testEffect } from "../lib/effect"
  12. const it = testEffect(Layer.empty)
  13. const decode = Schema.decodeUnknownSync(Config.Info)
  14. describe("ConfigSkillPlugin.Plugin", () => {
  15. it.effect("registers configured skill directories and URLs", () =>
  16. Effect.gen(function* () {
  17. const directory = AbsolutePath.make("/repo/packages/app")
  18. const sources: SkillV2.Source[] = []
  19. const transform = Effect.fnUntraced(function* () {
  20. return Effect.fnUntraced(function* (update: (editor: SkillV2.Editor) => void) {
  21. update({
  22. source: (source) => sources.push(source),
  23. list: () => sources,
  24. })
  25. })
  26. })
  27. yield* ConfigSkillPlugin.Plugin.effect.pipe(
  28. Effect.provideService(
  29. Config.Service,
  30. Config.Service.of({
  31. entries: () =>
  32. Effect.succeed([
  33. new Config.Directory({ type: "directory", path: AbsolutePath.make("/repo/.opencode") }),
  34. new Config.Document({
  35. type: "document",
  36. info: decode({
  37. skills: ["./skills", "~/shared-skills", "/opt/skills", "https://example.test/skills/"],
  38. }),
  39. }),
  40. ]),
  41. }),
  42. ),
  43. Effect.provideService(Global.Service, Global.Service.of(Global.make({ home: "/home/test" }))),
  44. Effect.provideService(Location.Service, Location.Service.of(location({ directory }))),
  45. Effect.provideService(
  46. SkillV2.Service,
  47. SkillV2.Service.of({
  48. transform,
  49. sources: () => Effect.succeed(sources),
  50. list: () => Effect.succeed([]),
  51. }),
  52. ),
  53. )
  54. expect(sources).toEqual([
  55. new SkillV2.DirectorySource({
  56. type: "directory",
  57. path: AbsolutePath.make(path.join("/repo/.opencode", "skill")),
  58. }),
  59. new SkillV2.DirectorySource({
  60. type: "directory",
  61. path: AbsolutePath.make(path.join("/repo/.opencode", "skills")),
  62. }),
  63. new SkillV2.DirectorySource({ type: "directory", path: AbsolutePath.make(path.join(directory, "skills")) }),
  64. new SkillV2.DirectorySource({
  65. type: "directory",
  66. path: AbsolutePath.make(path.join("/home/test", "shared-skills")),
  67. }),
  68. new SkillV2.DirectorySource({ type: "directory", path: AbsolutePath.make("/opt/skills") }),
  69. new SkillV2.UrlSource({ type: "url", url: "https://example.test/skills/" }),
  70. ])
  71. }),
  72. )
  73. })