/** * Tool execution - runs agent tool calls against the filesystem and shell. * * validatePath() ensures all file operations stay within the project root. * executeTool() dispatches to individual tool handlers. * listDirectory() and htmlToText() are private helpers. * createActionLog() converts a ToolCall+ToolResult into a history ActionLog. * trustBearingWrite() names the writes that decide what runs later. */ import { ToolCall, ToolResult, ActionLog } from './tools'; export { isBlockedIp, assertFetchUrlAllowed } from './ssrfGuard'; /** * Validate path is within project root. * Uses realpathSync to resolve symlinks, preventing symlink traversal attacks * where a symlink inside the project could point to files outside it. */ export declare function validatePath(path: string, projectRoot: string): { valid: boolean; absolutePath: string; error?: string; }; /** Drop the cached hook directories. Call before spawning a command line. */ export declare function forgetHooksDirectory(): void; /** * The tail of the refusal one of these writes gets when the run has nobody to * ask — no permission callback at all, which is how `codeep review --fix` * runs in CI. agent.ts builds the refusal; headlessReview.ts recognises it by * this text so it can say so in the run output rather than leave it buried in * the agent's tool log. * * One constant, in the module that owns the classification rather than in * agent.ts, for two reasons: a reworded refusal that stopped matching would * put CI back to failing silently, and agent.js is a module the fix-run tests * replace wholesale — a constant read from there would have been undefined in * exactly the test that guards this. */ export declare const NO_CONFIRMER_REFUSAL = "Nobody could be asked to confirm it, so nothing was written."; export interface TrustBearingWrite { /** The path exactly as the tool call named it, for the prompt. */ path: string; /** The absolute path the classification matched — one spelling per file, so * a "never again" answer given for `.git/config` also covers * `./.git/config` and the symlink that reaches it. Never shown to anyone; * it exists to key that answer (see agent.ts). */ file: string; /** One plain sentence about what the file controls. */ reason: string; } /** * What a tool call would write that decides what runs later, or null. * * Callers use this for two things: to force a confirmation the mode would * otherwise skip (see agent.ts), and to tell the person answering it what * they are approving. * * A symlink inside the project can point at one of these names — `ln -s .git * tools/cfg` makes a write to `tools/cfg/config` land in the real `.git`, and * validatePath allows it because it never leaves the project — so the * resolved path is classified alongside the one the model asked for. */ export declare function trustBearingWrite(toolCall: ToolCall, projectRoot: string): TrustBearingWrite | null; /** * Optional filesystem delegation. When an ACP client advertises `fs` * capability (Zed always does, VS Code may), the server should route * read/write through the client instead of touching disk directly — that * way the client's unsaved buffers, undo history, and virtual filesystems * stay authoritative. Callbacks must already use absolute paths. * * A writeTextFile that rejects with AcpRequestError means the client * answered and refused the write; the tool then fails instead of writing * to disk behind the editor. */ export interface FsCallbacks { readTextFile?: (absolutePath: string) => Promise; writeTextFile?: (absolutePath: string, content: string) => Promise; } /** * Execute a tool call and return the result. * * `fs` is optional — if provided and the relevant method is defined, file * read/write is delegated to the client. Otherwise we fall back to direct * disk I/O. A delegated call that throws also falls back to disk so a * single client hiccup doesn't kill the agent loop — except a write the * client explicitly refused, which fails the tool (see isRefusedWrite). * * `signal` stops a running execute_command when it fires. */ export declare function executeTool(toolCall: ToolCall, projectRoot: string, fs?: FsCallbacks, mcpSessionId?: string, signal?: AbortSignal): Promise; /** * Create action log from tool result */ export declare function createActionLog(toolCall: ToolCall, result: ToolResult): ActionLog;