Browse Source

fix(tool/read): match permission patterns against worktree-relative path

Read permission checks now use the same worktree-relative path basis as edit/write/apply_patch, so configured patterns apply consistently.
Kit Langton 4 months ago
parent
commit
ba9e4b67ed
2 changed files with 15 additions and 2 deletions
  1. 1 1
      packages/opencode/src/tool/read.ts
  2. 14 1
      packages/opencode/test/tool/read.test.ts

+ 1 - 1
packages/opencode/src/tool/read.ts

@@ -178,7 +178,7 @@ export const ReadTool = Tool.define(
 
 
       yield* ctx.ask({
       yield* ctx.ask({
         permission: "read",
         permission: "read",
-        patterns: [filepath],
+        patterns: [path.relative(instance.worktree, filepath)],
         always: ["*"],
         always: ["*"],
         metadata: {},
         metadata: {},
       })
       })

+ 14 - 1
packages/opencode/test/tool/read.test.ts

@@ -155,11 +155,24 @@ describe("tool.read external_directory permission", () => {
         yield* exec(dir, { filePath: alt }, next)
         yield* exec(dir, { filePath: alt }, next)
         const read = items.find((item) => item.permission === "read")
         const read = items.find((item) => item.permission === "read")
         expect(read).toBeDefined()
         expect(read).toBeDefined()
-        expect(read!.patterns).toEqual([full(target)])
+        expect(read!.patterns).toEqual([path.relative(dir, full(target))])
       }),
       }),
     )
     )
   }
   }
 
 
+  it.live("uses worktree-relative path for read permission so user rules match like edit/write", () =>
+    Effect.gen(function* () {
+      const dir = yield* tmpdirScoped({ git: true })
+      yield* put(path.join(dir, "src", "secret.ts"), "shh")
+
+      const { items, next } = asks()
+      yield* exec(dir, { filePath: path.join(dir, "src", "secret.ts") }, next)
+      const read = items.find((item) => item.permission === "read")
+      expect(read).toBeDefined()
+      expect(read!.patterns).toEqual([path.join("src", "secret.ts")])
+    }),
+  )
+
   it.live("asks for directory-scoped external_directory permission when reading external directory", () =>
   it.live("asks for directory-scoped external_directory permission when reading external directory", () =>
     Effect.gen(function* () {
     Effect.gen(function* () {
       const outer = yield* tmpdirScoped()
       const outer = yield* tmpdirScoped()