Skip to content
5 changes: 3 additions & 2 deletions packages/opencode/src/tool/external-directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ export async function assertExternalDirectory(ctx: Tool.Context, target?: string

const kind = options?.kind ?? "file"
const parentDir = kind === "directory" ? target : path.dirname(target)
const glob = path.join(parentDir, "*")
const relativeParentDir = path.relative(Instance.directory, parentDir)
const glob = path.join(relativeParentDir, "*")

await ctx.ask({
permission: "external_directory",
patterns: [glob],
always: [glob],
metadata: {
filepath: target,
parentDir,
parentDir: relativeParentDir,
},
})
}
4 changes: 2 additions & 2 deletions packages/opencode/test/tool/external-directory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe("tool.assertExternalDirectory", () => {

const directory = "/tmp/project"
const target = "/tmp/outside/file.txt"
const expected = path.join(path.dirname(target), "*")
const expected = path.join(path.relative(directory, path.dirname(target)), "*")

await Instance.provide({
directory,
Expand All @@ -90,7 +90,7 @@ describe("tool.assertExternalDirectory", () => {

const directory = "/tmp/project"
const target = "/tmp/outside"
const expected = path.join(target, "*")
const expected = path.join(path.relative(directory, target), "*")

await Instance.provide({
directory,
Expand Down
3 changes: 2 additions & 1 deletion packages/opencode/test/tool/read.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ describe("tool.read external_directory permission", () => {
await read.execute({ filePath: path.join(outerTmp.path, "secret.txt") }, testCtx)
const extDirReq = requests.find((r) => r.permission === "external_directory")
expect(extDirReq).toBeDefined()
expect(extDirReq!.patterns.some((p) => p.includes(outerTmp.path))).toBe(true)
// Pattern should be a relative path like "../tmpXXX/*"
expect(extDirReq!.patterns.some((p) => p.startsWith("..") && p.endsWith("*"))).toBe(true)
},
})
})
Expand Down