From f2e1dbda16795e61c6533bd5cb1e842aa293604d Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sun, 1 Feb 2026 12:05:53 -0600 Subject: [PATCH] tweak: adjust instructions resolving logic --- packages/opencode/src/session/instruction.ts | 32 +++---- .../opencode/test/session/instruction.test.ts | 91 +++++++++++++++++++ 2 files changed, 106 insertions(+), 17 deletions(-) diff --git a/packages/opencode/src/session/instruction.ts b/packages/opencode/src/session/instruction.ts index 723439a3fd..b3f0f99a3e 100644 --- a/packages/opencode/src/session/instruction.ts +++ b/packages/opencode/src/session/instruction.ts @@ -16,17 +16,6 @@ const FILES = [ "CONTEXT.md", // deprecated ] -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")) - } - if (Flag.OPENCODE_CONFIG_DIR) { - files.push(path.join(Flag.OPENCODE_CONFIG_DIR, "AGENTS.md")) - } - return files -} - async function resolveRelative(instruction: string): Promise { if (!Flag.OPENCODE_DISABLE_PROJECT_CONFIG) { return Filesystem.globUp(instruction, Instance.directory, Instance.worktree).catch(() => []) @@ -81,18 +70,27 @@ export namespace InstructionPrompt { } } - for (const file of globalFiles()) { - if (await Bun.file(file).exists()) { - paths.add(path.resolve(file)) - break - } + const agentsmd: string[] = [] + if (Flag.OPENCODE_CONFIG_DIR) agentsmd.push(path.join(Flag.OPENCODE_CONFIG_DIR, "AGENTS.md")) + agentsmd.push(path.join(Global.Path.config, "AGENTS.md")) + + const found: string[] = [] + for (const file of agentsmd) { + if (await Bun.file(file).exists()) found.push(path.resolve(file)) } + if (found.length === 0 && !Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT) { + const claude = path.join(Global.Path.home, ".claude", "CLAUDE.md") + if (await Bun.file(claude).exists()) found.push(path.resolve(claude)) + } + + found.forEach((file) => paths.add(file)) + if (config.instructions) { for (let instruction of config.instructions) { if (instruction.startsWith("https://") || instruction.startsWith("http://")) continue if (instruction.startsWith("~/")) { - instruction = path.join(os.homedir(), instruction.slice(2)) + instruction = path.join(Global.Path.home, instruction.slice(2)) } const matches = path.isAbsolute(instruction) ? await Array.fromAsync( diff --git a/packages/opencode/test/session/instruction.test.ts b/packages/opencode/test/session/instruction.test.ts index 67719fa339..14223536f1 100644 --- a/packages/opencode/test/session/instruction.test.ts +++ b/packages/opencode/test/session/instruction.test.ts @@ -1,9 +1,19 @@ import { describe, expect, test } from "bun:test" +import fs from "fs/promises" import path from "path" +import { Global } from "../../src/global" import { InstructionPrompt } from "../../src/session/instruction" import { Instance } from "../../src/project/instance" import { tmpdir } from "../fixture/fixture" +const restore = (key: string, value: string | undefined) => { + if (value === undefined) { + delete process.env[key] + return + } + process.env[key] = value +} + describe("InstructionPrompt.resolve", () => { test("returns empty when AGENTS.md is at project root (already in systemPaths)", async () => { await using tmp = await tmpdir({ @@ -48,3 +58,84 @@ describe("InstructionPrompt.resolve", () => { }) }) }) + +describe("InstructionPrompt.systemPaths", () => { + test("includes config and global AGENTS, skips CLAUDE when agents exist", async () => { + const homeValue = process.env["OPENCODE_TEST_HOME"] + const configValue = process.env["OPENCODE_CONFIG_DIR"] + const disableValue = process.env["OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"] + + await using config = await tmpdir() + await using home = await tmpdir() + await using project = await tmpdir() + + try { + process.env["OPENCODE_CONFIG_DIR"] = config.path + process.env["OPENCODE_TEST_HOME"] = home.path + delete process.env["OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"] + + const configAgent = path.join(config.path, "AGENTS.md") + const globalAgent = path.join(Global.Path.config, "AGENTS.md") + const claudeAgent = path.join(Global.Path.home, ".claude", "CLAUDE.md") + + await fs.mkdir(path.dirname(globalAgent), { recursive: true }) + await fs.mkdir(path.dirname(claudeAgent), { recursive: true }) + + await Bun.write(configAgent, "# Config") + await Bun.write(globalAgent, "# Global") + await Bun.write(claudeAgent, "# Claude") + + await Instance.provide({ + directory: project.path, + fn: async () => { + const system = await InstructionPrompt.systemPaths() + expect(system.has(path.resolve(configAgent))).toBe(true) + expect(system.has(path.resolve(globalAgent))).toBe(true) + expect(system.has(path.resolve(claudeAgent))).toBe(false) + }, + }) + } finally { + await fs.rm(path.join(Global.Path.config, "AGENTS.md"), { force: true }) + restore("OPENCODE_TEST_HOME", homeValue) + restore("OPENCODE_CONFIG_DIR", configValue) + restore("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT", disableValue) + } + }) + + test("uses CLAUDE when no agents exist", async () => { + const homeValue = process.env["OPENCODE_TEST_HOME"] + const configValue = process.env["OPENCODE_CONFIG_DIR"] + const disableValue = process.env["OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"] + + await using config = await tmpdir() + await using home = await tmpdir() + await using project = await tmpdir() + + try { + process.env["OPENCODE_CONFIG_DIR"] = config.path + process.env["OPENCODE_TEST_HOME"] = home.path + delete process.env["OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"] + + const globalAgent = path.join(Global.Path.config, "AGENTS.md") + const claudeAgent = path.join(Global.Path.home, ".claude", "CLAUDE.md") + + await fs.rm(globalAgent, { force: true }) + await fs.mkdir(path.dirname(claudeAgent), { recursive: true }) + await Bun.write(claudeAgent, "# Claude") + + await Instance.provide({ + directory: project.path, + fn: async () => { + const system = await InstructionPrompt.systemPaths() + expect(system.has(path.resolve(globalAgent))).toBe(false) + expect(system.has(path.resolve(claudeAgent))).toBe(true) + }, + }) + } finally { + await fs.rm(path.join(Global.Path.config, "AGENTS.md"), { force: true }) + restore("OPENCODE_TEST_HOME", homeValue) + restore("OPENCODE_CONFIG_DIR", configValue) + restore("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT", disableValue) + } + }) +})