agent.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import { test, expect } from "bun:test"
  2. import path from "path"
  3. import fs from "fs/promises"
  4. import { tmpdir } from "../fixture/fixture"
  5. import { Instance } from "../../src/project/instance"
  6. import { Agent } from "../../src/agent/agent"
  7. test("loads built-in agents when no custom agents configured", async () => {
  8. await using tmp = await tmpdir()
  9. await Instance.provide({
  10. directory: tmp.path,
  11. fn: async () => {
  12. const agents = await Agent.list()
  13. const names = agents.map((a) => a.name)
  14. expect(names).toContain("build")
  15. expect(names).toContain("plan")
  16. },
  17. })
  18. })
  19. test("custom subagent works alongside built-in primary agents", async () => {
  20. await using tmp = await tmpdir({
  21. init: async (dir) => {
  22. const opencodeDir = path.join(dir, ".opencode")
  23. await fs.mkdir(opencodeDir, { recursive: true })
  24. const agentDir = path.join(opencodeDir, "agent")
  25. await fs.mkdir(agentDir, { recursive: true })
  26. await Bun.write(
  27. path.join(agentDir, "helper.md"),
  28. `---
  29. model: test/model
  30. mode: subagent
  31. ---
  32. Helper subagent prompt`,
  33. )
  34. },
  35. })
  36. await Instance.provide({
  37. directory: tmp.path,
  38. fn: async () => {
  39. const agents = await Agent.list()
  40. const helper = agents.find((a) => a.name === "helper")
  41. expect(helper).toBeDefined()
  42. expect(helper?.mode).toBe("subagent")
  43. // Built-in primary agents should still exist
  44. const build = agents.find((a) => a.name === "build")
  45. expect(build).toBeDefined()
  46. expect(build?.mode).toBe("primary")
  47. },
  48. })
  49. })
  50. test("throws error when all primary agents are disabled", async () => {
  51. await using tmp = await tmpdir({
  52. init: async (dir) => {
  53. await Bun.write(
  54. path.join(dir, "opencode.json"),
  55. JSON.stringify({
  56. $schema: "https://opencode.ai/config.json",
  57. agent: {
  58. build: { disable: true },
  59. plan: { disable: true },
  60. },
  61. }),
  62. )
  63. },
  64. })
  65. await Instance.provide({
  66. directory: tmp.path,
  67. fn: async () => {
  68. try {
  69. await Agent.list()
  70. expect(true).toBe(false) // should not reach here
  71. } catch (e: any) {
  72. expect(e.data?.message).toContain("No primary agents are available")
  73. }
  74. },
  75. })
  76. })
  77. test("does not throw when at least one primary agent remains", async () => {
  78. await using tmp = await tmpdir({
  79. init: async (dir) => {
  80. await Bun.write(
  81. path.join(dir, "opencode.json"),
  82. JSON.stringify({
  83. $schema: "https://opencode.ai/config.json",
  84. agent: {
  85. build: { disable: true },
  86. },
  87. }),
  88. )
  89. },
  90. })
  91. await Instance.provide({
  92. directory: tmp.path,
  93. fn: async () => {
  94. const agents = await Agent.list()
  95. const plan = agents.find((a) => a.name === "plan")
  96. expect(plan).toBeDefined()
  97. expect(plan?.mode).toBe("primary")
  98. },
  99. })
  100. })
  101. test("custom primary agent satisfies requirement when built-ins disabled", async () => {
  102. await using tmp = await tmpdir({
  103. init: async (dir) => {
  104. const opencodeDir = path.join(dir, ".opencode")
  105. await fs.mkdir(opencodeDir, { recursive: true })
  106. const agentDir = path.join(opencodeDir, "agent")
  107. await fs.mkdir(agentDir, { recursive: true })
  108. await Bun.write(
  109. path.join(agentDir, "custom.md"),
  110. `---
  111. model: test/model
  112. mode: primary
  113. ---
  114. Custom primary agent`,
  115. )
  116. await Bun.write(
  117. path.join(dir, "opencode.json"),
  118. JSON.stringify({
  119. $schema: "https://opencode.ai/config.json",
  120. agent: {
  121. build: { disable: true },
  122. plan: { disable: true },
  123. },
  124. }),
  125. )
  126. },
  127. })
  128. await Instance.provide({
  129. directory: tmp.path,
  130. fn: async () => {
  131. const agents = await Agent.list()
  132. const custom = agents.find((a) => a.name === "custom")
  133. expect(custom).toBeDefined()
  134. expect(custom?.mode).toBe("primary")
  135. },
  136. })
  137. })