|
|
@@ -1,4 +1,6 @@
|
|
|
import { describe, expect } from "bun:test"
|
|
|
+import fs from "fs/promises"
|
|
|
+import os from "os"
|
|
|
import path from "path"
|
|
|
import { Effect, Layer } from "effect"
|
|
|
import { GrepTool } from "../../src/tool/grep"
|
|
|
@@ -11,6 +13,8 @@ import { Ripgrep } from "../../src/file/ripgrep"
|
|
|
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
|
|
import { testEffect } from "../lib/effect"
|
|
|
import { Reference } from "@/reference/reference"
|
|
|
+import { Permission } from "../../src/permission"
|
|
|
+import type * as Tool from "../../src/tool/tool"
|
|
|
|
|
|
const it = testEffect(
|
|
|
Layer.mergeAll(
|
|
|
@@ -110,4 +114,53 @@ describe("tool.grep", () => {
|
|
|
expect(result.output).toContain("Line 2: line2")
|
|
|
}),
|
|
|
)
|
|
|
+
|
|
|
+ it.instance("does not ask for external_directory when alias path is allowed", () =>
|
|
|
+ Effect.gen(function* () {
|
|
|
+ if (process.platform === "win32") return
|
|
|
+
|
|
|
+ yield* TestInstance
|
|
|
+ const tmp = yield* Effect.acquireRelease(
|
|
|
+ Effect.promise(() => fs.mkdtemp(path.join(os.tmpdir(), "opencode-grep-alias-"))),
|
|
|
+ (dir) => Effect.promise(() => fs.rm(dir, { recursive: true, force: true })),
|
|
|
+ )
|
|
|
+ const real = path.join(tmp, "real")
|
|
|
+ const alias = path.join(tmp, "alias")
|
|
|
+ yield* Effect.promise(() => fs.mkdir(real))
|
|
|
+ yield* Effect.promise(() => fs.symlink(real, alias, "dir"))
|
|
|
+ yield* Effect.promise(() => Bun.write(path.join(real, "test.txt"), "needle"))
|
|
|
+
|
|
|
+ const ruleset = Permission.fromConfig({
|
|
|
+ grep: "allow",
|
|
|
+ external_directory: {
|
|
|
+ [path.join(alias, "*")]: "allow",
|
|
|
+ },
|
|
|
+ })
|
|
|
+ const requests: Array<Omit<Permission.Request, "id" | "sessionID" | "tool">> = []
|
|
|
+ const next: Tool.Context = {
|
|
|
+ ...ctx,
|
|
|
+ ask: (req) =>
|
|
|
+ Effect.sync(() => {
|
|
|
+ const needsAsk = req.patterns.some(
|
|
|
+ (pattern) => Permission.evaluate(req.permission, pattern, ruleset).action !== "allow",
|
|
|
+ )
|
|
|
+ if (needsAsk) requests.push(req)
|
|
|
+ }),
|
|
|
+ }
|
|
|
+
|
|
|
+ const info = yield* GrepTool
|
|
|
+ const grep = yield* info.init()
|
|
|
+ const result = yield* grep.execute(
|
|
|
+ {
|
|
|
+ pattern: "needle",
|
|
|
+ path: alias,
|
|
|
+ include: "*.txt",
|
|
|
+ },
|
|
|
+ next,
|
|
|
+ )
|
|
|
+
|
|
|
+ expect(result.metadata.matches).toBe(1)
|
|
|
+ expect(requests.find((req) => req.permission === "external_directory")).toBeUndefined()
|
|
|
+ }),
|
|
|
+ )
|
|
|
})
|