import path from "path" import { Effect } from "effect" import { EffectLogger } from "@/effect/logger" import { InstanceState } from "@/effect" import type { Tool } from "./tool" import { Instance } from "../project/instance" import { AppFileSystem } from "@opencode-ai/shared/filesystem" type Kind = "file" | "directory" type Options = { bypass?: boolean kind?: Kind } export const assertExternalDirectoryEffect = Effect.fn("Tool.assertExternalDirectory")(function* ( ctx: Tool.Context, target?: string, options?: Options, ) { if (!target) return if (options?.bypass) return const ins = yield* InstanceState.context const full = process.platform === "win32" ? AppFileSystem.normalizePath(target) : target if (Instance.containsPath(full, ins)) return const kind = options?.kind ?? "file" const dir = kind === "directory" ? full : path.dirname(full) const glob = process.platform === "win32" ? AppFileSystem.normalizePathPattern(path.join(dir, "*")) : path.join(dir, "*").replaceAll("\\", "/") yield* ctx.ask({ permission: "external_directory", patterns: [glob], always: [glob], metadata: { filepath: full, parentDir: dir, }, }) }) export async function assertExternalDirectory(ctx: Tool.Context, target?: string, options?: Options) { return Effect.runPromise(assertExternalDirectoryEffect(ctx, target, options).pipe(Effect.provide(EffectLogger.layer))) }