From 89e8ebe8b6913844c3c57f8310df45d129d8a4d7 Mon Sep 17 00:00:00 2001 From: Haohao-end <2227625024@qq.com> Date: Mon, 23 Mar 2026 14:12:49 +0800 Subject: [PATCH] fix: avoid external directory prompt for global AGENTS.md --- packages/opencode/src/config/paths.ts | 9 +++- .../opencode/src/tool/external-directory.ts | 10 +++- .../test/tool/external-directory.test.ts | 54 +++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/config/paths.ts b/packages/opencode/src/config/paths.ts index 396417e9a5bf..d6af7204e647 100644 --- a/packages/opencode/src/config/paths.ts +++ b/packages/opencode/src/config/paths.ts @@ -8,6 +8,10 @@ import { Flag } from "@/flag/flag" import { Global } from "@/global" export namespace ConfigPaths { + export function globalDirectories() { + return [Global.Path.config, ...(Flag.OPENCODE_CONFIG_DIR ? [Flag.OPENCODE_CONFIG_DIR] : [])] + } + export async function projectFiles(name: string, directory: string, worktree: string) { const files: string[] = [] for (const file of [`${name}.jsonc`, `${name}.json`]) { @@ -20,8 +24,9 @@ export namespace ConfigPaths { } export async function directories(directory: string, worktree: string) { + const global = globalDirectories() return [ - Global.Path.config, + global[0], ...(!Flag.OPENCODE_DISABLE_PROJECT_CONFIG ? await Array.fromAsync( Filesystem.up({ @@ -38,7 +43,7 @@ export namespace ConfigPaths { stop: Global.Path.home, }), )), - ...(Flag.OPENCODE_CONFIG_DIR ? [Flag.OPENCODE_CONFIG_DIR] : []), + ...global.slice(1), ] } diff --git a/packages/opencode/src/tool/external-directory.ts b/packages/opencode/src/tool/external-directory.ts index 5d8885b2ad46..220ed3c511dd 100644 --- a/packages/opencode/src/tool/external-directory.ts +++ b/packages/opencode/src/tool/external-directory.ts @@ -1,6 +1,8 @@ import path from "path" import type { Tool } from "./tool" +import { ConfigPaths } from "../config/paths" import { Instance } from "../project/instance" +import { Filesystem } from "../util/filesystem" type Kind = "file" | "directory" @@ -9,12 +11,18 @@ type Options = { kind?: Kind } +function internal(target: string) { + const file = path.isAbsolute(target) ? target : path.join(Instance.directory, target) + if (Instance.containsPath(file)) return true + return ConfigPaths.globalDirectories().some((dir) => Filesystem.contains(path.resolve(dir), file)) +} + export async function assertExternalDirectory(ctx: Tool.Context, target?: string, options?: Options) { if (!target) return if (options?.bypass) return - if (Instance.containsPath(target)) return + if (internal(target)) return const kind = options?.kind ?? "file" const parentDir = kind === "directory" ? target : path.dirname(target) diff --git a/packages/opencode/test/tool/external-directory.test.ts b/packages/opencode/test/tool/external-directory.test.ts index 0188cbada044..2ec2fbf82982 100644 --- a/packages/opencode/test/tool/external-directory.test.ts +++ b/packages/opencode/test/tool/external-directory.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test" import path from "path" +import { Global } from "../../src/global" import type { Tool } from "../../src/tool/tool" import { Instance } from "../../src/project/instance" import { assertExternalDirectory } from "../../src/tool/external-directory" @@ -55,6 +56,59 @@ describe("tool.assertExternalDirectory", () => { expect(requests.length).toBe(0) }) + test("no-ops for AGENTS.md inside Global.Path.config", async () => { + const requests: Array> = [] + const ctx: Tool.Context = { + ...baseCtx, + ask: async (req) => { + requests.push(req) + }, + } + + const prev = Global.Path.config + ;(Global.Path as { config: string }).config = "/tmp/opencode-config" + + try { + await Instance.provide({ + directory: "/tmp/project", + fn: async () => { + await assertExternalDirectory(ctx, path.join(Global.Path.config, "AGENTS.md")) + }, + }) + } finally { + ;(Global.Path as { config: string }).config = prev + } + + expect(requests.length).toBe(0) + }) + + test("no-ops for AGENTS.md inside OPENCODE_CONFIG_DIR", async () => { + const requests: Array> = [] + const ctx: Tool.Context = { + ...baseCtx, + ask: async (req) => { + requests.push(req) + }, + } + + const prev = process.env["OPENCODE_CONFIG_DIR"] + process.env["OPENCODE_CONFIG_DIR"] = "/tmp/opencode-profile" + + try { + await Instance.provide({ + directory: "/tmp/project", + fn: async () => { + await assertExternalDirectory(ctx, path.join(process.env["OPENCODE_CONFIG_DIR"]!, "AGENTS.md")) + }, + }) + } finally { + if (prev === undefined) delete process.env["OPENCODE_CONFIG_DIR"] + else process.env["OPENCODE_CONFIG_DIR"] = prev + } + + expect(requests.length).toBe(0) + }) + test("asks with a single canonical glob", async () => { const requests: Array> = [] const ctx: Tool.Context = {