diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 17695583867..e8e6a8d21b0 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -211,16 +211,18 @@ export namespace Agent { } // Ensure Truncate.DIR is allowed unless explicitly configured + // The pattern must include /* because external-directory.ts creates glob patterns like "dir/*" + const truncateDirGlob = `${Truncate.DIR}/*` for (const name in result) { const agent = result[name] const explicit = agent.permission.some( - (r) => r.permission === "external_directory" && r.pattern === Truncate.DIR && r.action === "deny", + (r) => r.permission === "external_directory" && r.pattern === truncateDirGlob && r.action === "deny", ) if (explicit) continue result[name].permission = PermissionNext.merge( result[name].permission, - PermissionNext.fromConfig({ external_directory: { [Truncate.DIR]: "allow" } }), + PermissionNext.fromConfig({ external_directory: { [truncateDirGlob]: "allow" } }), ) } diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts index 68833c79413..33e0f197824 100644 --- a/packages/opencode/test/agent/agent.test.ts +++ b/packages/opencode/test/agent/agent.test.ts @@ -460,7 +460,8 @@ test("Truncate.DIR is allowed even when user denies external_directory globally" directory: tmp.path, fn: async () => { const build = await Agent.get("build") - expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("allow") + // The pattern must include /* because external-directory.ts creates glob patterns like "dir/*" + expect(PermissionNext.evaluate("external_directory", `${Truncate.DIR}/*`, build!.permission).action).toBe("allow") expect(PermissionNext.evaluate("external_directory", "/some/other/path", build!.permission).action).toBe("deny") }, }) @@ -483,7 +484,8 @@ test("Truncate.DIR is allowed even when user denies external_directory per-agent directory: tmp.path, fn: async () => { const build = await Agent.get("build") - expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("allow") + // The pattern must include /* because external-directory.ts creates glob patterns like "dir/*" + expect(PermissionNext.evaluate("external_directory", `${Truncate.DIR}/*`, build!.permission).action).toBe("allow") expect(PermissionNext.evaluate("external_directory", "/some/other/path", build!.permission).action).toBe("deny") }, }) @@ -496,7 +498,7 @@ test("explicit Truncate.DIR deny is respected", async () => { permission: { external_directory: { "*": "deny", - [Truncate.DIR]: "deny", + [`${Truncate.DIR}/*`]: "deny", }, }, }, @@ -505,7 +507,8 @@ test("explicit Truncate.DIR deny is respected", async () => { directory: tmp.path, fn: async () => { const build = await Agent.get("build") - expect(PermissionNext.evaluate("external_directory", Truncate.DIR, build!.permission).action).toBe("deny") + // The pattern must include /* because external-directory.ts creates glob patterns like "dir/*" + expect(PermissionNext.evaluate("external_directory", `${Truncate.DIR}/*`, build!.permission).action).toBe("deny") }, }) })