plugin-agent-regression.test.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import { expect } from "bun:test"
  2. import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
  3. import { Effect, Layer } from "effect"
  4. import path from "path"
  5. import { pathToFileURL } from "url"
  6. import { Agent } from "../../src/agent/agent"
  7. import { InstanceRef } from "../../src/effect/instance-ref"
  8. import { InstanceLayer } from "../../src/project/instance-layer"
  9. import { InstanceStore } from "../../src/project/instance-store"
  10. import { tmpdirScoped } from "../fixture/fixture"
  11. import { testEffect } from "../lib/effect"
  12. const pluginAgent = {
  13. name: "plugin_added",
  14. description: "Added by a plugin via the config hook",
  15. mode: "subagent",
  16. } as const
  17. const it = testEffect(Layer.mergeAll(Agent.defaultLayer, InstanceLayer.layer, CrossSpawnSpawner.defaultLayer))
  18. it.live("plugin-registered agents appear in Agent.list", () =>
  19. Effect.gen(function* () {
  20. const dir = yield* tmpdirScoped()
  21. const pluginFile = path.join(dir, "plugin.ts")
  22. yield* Effect.promise(async () => {
  23. await Promise.all([
  24. Bun.write(
  25. pluginFile,
  26. [
  27. "export default async () => ({",
  28. " config: async (cfg) => {",
  29. " cfg.agent = cfg.agent ?? {}",
  30. ` cfg.agent[${JSON.stringify(pluginAgent.name)}] = {`,
  31. ` description: ${JSON.stringify(pluginAgent.description)},`,
  32. ` mode: ${JSON.stringify(pluginAgent.mode)},`,
  33. " }",
  34. " },",
  35. "})",
  36. "",
  37. ].join("\n"),
  38. ),
  39. Bun.write(
  40. path.join(dir, "opencode.json"),
  41. JSON.stringify({
  42. $schema: "https://opencode.ai/config.json",
  43. plugin: [pathToFileURL(pluginFile).href],
  44. }),
  45. ),
  46. ])
  47. })
  48. const agents = yield* InstanceStore.Service.use((store) =>
  49. Effect.gen(function* () {
  50. const ctx = yield* store.load({ directory: dir })
  51. yield* Effect.addFinalizer(() => store.dispose(ctx).pipe(Effect.ignore))
  52. return yield* Agent.Service.use((svc) => svc.list()).pipe(Effect.provideService(InstanceRef, ctx))
  53. }),
  54. )
  55. const added = agents.find((agent) => agent.name === pluginAgent.name)
  56. expect(added?.description).toBe(pluginAgent.description)
  57. expect(added?.mode).toBe(pluginAgent.mode)
  58. }),
  59. )