workspace-adaptor.test.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { afterAll, afterEach, describe, expect, test } from "bun:test"
  2. import { Effect } from "effect"
  3. import path from "path"
  4. import { pathToFileURL } from "url"
  5. import { tmpdir } from "../fixture/fixture"
  6. const disableDefault = process.env.KILO_DISABLE_DEFAULT_PLUGINS
  7. process.env.KILO_DISABLE_DEFAULT_PLUGINS = "1"
  8. const { Plugin } = await import("../../src/plugin/index")
  9. const { Workspace } = await import("../../src/control-plane/workspace")
  10. const { Instance } = await import("../../src/project/instance")
  11. afterEach(async () => {
  12. await Instance.disposeAll()
  13. })
  14. afterAll(() => {
  15. if (disableDefault === undefined) {
  16. delete process.env.KILO_DISABLE_DEFAULT_PLUGINS
  17. return
  18. }
  19. process.env.KILO_DISABLE_DEFAULT_PLUGINS = disableDefault
  20. })
  21. describe("plugin.workspace", () => {
  22. test("plugin can install a workspace adaptor", async () => {
  23. await using tmp = await tmpdir({
  24. init: async (dir) => {
  25. const type = `plug-${Math.random().toString(36).slice(2)}`
  26. const file = path.join(dir, "plugin.ts")
  27. const mark = path.join(dir, "created.json")
  28. const space = path.join(dir, "space")
  29. await Bun.write(
  30. file,
  31. [
  32. "export default async ({ experimental_workspace }) => {",
  33. ` experimental_workspace.register(${JSON.stringify(type)}, {`,
  34. ' name: "plug",',
  35. ' description: "plugin workspace adaptor",',
  36. " configure(input) {",
  37. ` return { ...input, name: \"plug\", branch: \"plug/main\", directory: ${JSON.stringify(space)} }`,
  38. " },",
  39. " async create(input) {",
  40. ` await Bun.write(${JSON.stringify(mark)}, JSON.stringify(input))`,
  41. " },",
  42. " async remove() {},",
  43. " target(input) {",
  44. ' return { type: "local", directory: input.directory }',
  45. " },",
  46. " })",
  47. " return {}",
  48. "}",
  49. "",
  50. ].join("\n"),
  51. )
  52. await Bun.write(
  53. path.join(dir, "opencode.json"),
  54. JSON.stringify(
  55. {
  56. $schema: "https://opencode.ai/config.json",
  57. plugin: [pathToFileURL(file).href],
  58. },
  59. null,
  60. 2,
  61. ),
  62. )
  63. return { mark, space, type }
  64. },
  65. })
  66. const info = await Instance.provide({
  67. directory: tmp.path,
  68. fn: async () =>
  69. Effect.gen(function* () {
  70. const plugin = yield* Plugin.Service
  71. yield* plugin.init()
  72. return Workspace.create({
  73. type: tmp.extra.type,
  74. branch: null,
  75. extra: { key: "value" },
  76. projectID: Instance.project.id,
  77. })
  78. }).pipe(Effect.provide(Plugin.defaultLayer), Effect.runPromise),
  79. })
  80. expect(info.type).toBe(tmp.extra.type)
  81. expect(info.name).toBe("plug")
  82. expect(info.branch).toBe("plug/main")
  83. expect(info.directory).toBe(tmp.extra.space)
  84. expect(info.extra).toEqual({ key: "value" })
  85. expect(JSON.parse(await Bun.file(tmp.extra.mark).text())).toMatchObject({
  86. type: tmp.extra.type,
  87. name: "plug",
  88. branch: "plug/main",
  89. directory: tmp.extra.space,
  90. extra: { key: "value" },
  91. })
  92. })
  93. })