Browse Source

fix: prioritize OPENCODE_CONFIG_DIR for AGENTS.md (#11536)

Łukasz Gładysz 2 months ago
parent
commit
6daa962aaa

+ 5 - 4
packages/opencode/src/session/instruction.ts

@@ -17,13 +17,14 @@ const FILES = [
 ]
 
 function globalFiles() {
-  const files = [path.join(Global.Path.config, "AGENTS.md")]
-  if (!Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT) {
-    files.push(path.join(os.homedir(), ".claude", "CLAUDE.md"))
-  }
+  const files = []
   if (Flag.OPENCODE_CONFIG_DIR) {
     files.push(path.join(Flag.OPENCODE_CONFIG_DIR, "AGENTS.md"))
   }
+  files.push(path.join(Global.Path.config, "AGENTS.md"))
+  if (!Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT) {
+    files.push(path.join(os.homedir(), ".claude", "CLAUDE.md"))
+  }
   return files
 }
 

+ 101 - 1
packages/opencode/test/session/instruction.test.ts

@@ -1,7 +1,8 @@
-import { describe, expect, test } from "bun:test"
+import { afterEach, beforeEach, describe, expect, test } from "bun:test"
 import path from "path"
 import { InstructionPrompt } from "../../src/session/instruction"
 import { Instance } from "../../src/project/instance"
+import { Global } from "../../src/global"
 import { tmpdir } from "../fixture/fixture"
 
 describe("InstructionPrompt.resolve", () => {
@@ -68,3 +69,102 @@ describe("InstructionPrompt.resolve", () => {
     })
   })
 })
+
+describe("InstructionPrompt.systemPaths OPENCODE_CONFIG_DIR", () => {
+  let originalConfigDir: string | undefined
+
+  beforeEach(() => {
+    originalConfigDir = process.env["OPENCODE_CONFIG_DIR"]
+  })
+
+  afterEach(() => {
+    if (originalConfigDir === undefined) {
+      delete process.env["OPENCODE_CONFIG_DIR"]
+    } else {
+      process.env["OPENCODE_CONFIG_DIR"] = originalConfigDir
+    }
+  })
+
+  test("prefers OPENCODE_CONFIG_DIR AGENTS.md over global when both exist", async () => {
+    await using profileTmp = await tmpdir({
+      init: async (dir) => {
+        await Bun.write(path.join(dir, "AGENTS.md"), "# Profile Instructions")
+      },
+    })
+    await using globalTmp = await tmpdir({
+      init: async (dir) => {
+        await Bun.write(path.join(dir, "AGENTS.md"), "# Global Instructions")
+      },
+    })
+    await using projectTmp = await tmpdir()
+
+    process.env["OPENCODE_CONFIG_DIR"] = profileTmp.path
+    const originalGlobalConfig = Global.Path.config
+    ;(Global.Path as { config: string }).config = globalTmp.path
+
+    try {
+      await Instance.provide({
+        directory: projectTmp.path,
+        fn: async () => {
+          const paths = await InstructionPrompt.systemPaths()
+          expect(paths.has(path.join(profileTmp.path, "AGENTS.md"))).toBe(true)
+          expect(paths.has(path.join(globalTmp.path, "AGENTS.md"))).toBe(false)
+        },
+      })
+    } finally {
+      ;(Global.Path as { config: string }).config = originalGlobalConfig
+    }
+  })
+
+  test("falls back to global AGENTS.md when OPENCODE_CONFIG_DIR has no AGENTS.md", async () => {
+    await using profileTmp = await tmpdir()
+    await using globalTmp = await tmpdir({
+      init: async (dir) => {
+        await Bun.write(path.join(dir, "AGENTS.md"), "# Global Instructions")
+      },
+    })
+    await using projectTmp = await tmpdir()
+
+    process.env["OPENCODE_CONFIG_DIR"] = profileTmp.path
+    const originalGlobalConfig = Global.Path.config
+    ;(Global.Path as { config: string }).config = globalTmp.path
+
+    try {
+      await Instance.provide({
+        directory: projectTmp.path,
+        fn: async () => {
+          const paths = await InstructionPrompt.systemPaths()
+          expect(paths.has(path.join(profileTmp.path, "AGENTS.md"))).toBe(false)
+          expect(paths.has(path.join(globalTmp.path, "AGENTS.md"))).toBe(true)
+        },
+      })
+    } finally {
+      ;(Global.Path as { config: string }).config = originalGlobalConfig
+    }
+  })
+
+  test("uses global AGENTS.md when OPENCODE_CONFIG_DIR is not set", async () => {
+    await using globalTmp = await tmpdir({
+      init: async (dir) => {
+        await Bun.write(path.join(dir, "AGENTS.md"), "# Global Instructions")
+      },
+    })
+    await using projectTmp = await tmpdir()
+
+    delete process.env["OPENCODE_CONFIG_DIR"]
+    const originalGlobalConfig = Global.Path.config
+    ;(Global.Path as { config: string }).config = globalTmp.path
+
+    try {
+      await Instance.provide({
+        directory: projectTmp.path,
+        fn: async () => {
+          const paths = await InstructionPrompt.systemPaths()
+          expect(paths.has(path.join(globalTmp.path, "AGENTS.md"))).toBe(true)
+        },
+      })
+    } finally {
+      ;(Global.Path as { config: string }).config = originalGlobalConfig
+    }
+  })
+})