import type { ToolDefinition, ReadFilesArgs, WriteFileArgs, ApplyDiffArgs, ExecuteCommandArgs, ListDirArgs, GlobSearchArgs, GrepSearchArgs, MoveFileArgs, DeleteFileArgs, SearchReplaceArgs, FetchUrlArgs, RememberArgs, WebSearchArgs } from './types.js'; import type { SandboxSpec } from './sandbox.js'; export declare const TOOL_DEFINITIONS: ToolDefinition[]; /** * Lines returned for one file unless a window is asked for. * * There was no cap at all: a five thousand line file went whole into the context window and * crowded out everything the run had learned before it. What follows is a model that has read a * great deal and remembers almost none of it — which is most of what looks like an agent losing * the thread. */ export declare const MAX_READ_LINES = 800; export declare function readFiles(args: ReadFilesArgs, cwd: string): Promise; export declare function writeFile(args: WriteFileArgs, cwd: string, requireApproval: boolean): Promise; export declare function applyDiff(args: ApplyDiffArgs, cwd: string, requireApproval: boolean): Promise; /** * The longest any single command may run. * * The model chooses the timeout, and nothing used to bound it: one asked for long enough to sit on * `npm install` for thirty-four minutes, with no output, on a machine where it was never going to * finish quickly. Ten minutes is generous for a build or an install and short enough that a user * watching it knows something is wrong. A command that genuinely needs longer should be started in * the background and polled, which the ceiling message says. */ export declare const MAX_COMMAND_MS: number; /** What a command is given when nobody says otherwise. */ export declare function defaultTimeoutFor(command: string): number; export declare function resolveTimeout(requested: number | undefined, command?: string): { ms: number; clamped: boolean; }; /** Keeps the tail of a stream without holding a gigabyte of build log in memory. */ export declare function lastLine(text: string): string; /** * How to run a command line, per platform. * * KONECK used to run everything through `bash -c` with a POSIX process group. On Windows there is * no bash on PATH — or worse, `bash.exe` is the WSL launcher, which starts a Linux VM that cannot * see the Windows working directory. Every command then failed on a timeout, `cd` included, and * the model concluded it was in "a constrained environment" and gave up on a real task. * * `detached` is POSIX-only in the same way: it exists here to make the shell a process-group * leader so a timeout can signal the whole tree, and Windows has neither process groups in that * sense nor `kill(-pid)`. There, a timeout is enforced with taskkill instead. */ export declare function shellFor(command: string, platform?: string, env?: NodeJS.ProcessEnv): { file: string; args: string[]; options: Record; }; /** * The shell the model should be told it has. * * It was reported as `/bin/sh` on every platform, because SHELL is not set on Windows. So the * model was told the operating system was Windows and the shell was POSIX, and wrote commands * that were neither — Windows built-ins piped through `2>nul`, run under bash. */ export declare function describeShell(platform?: string, env?: NodeJS.ProcessEnv): string; export declare function executeCommand(args: ExecuteCommandArgs, cwd: string, requireApproval: boolean, onOutput?: (lastLine: string) => void, sandbox?: SandboxSpec, signal?: AbortSignal): Promise; /** * What a tool says when the user stopped it. * * One wording, because the model reads these and "cancelled", "aborted" and "interrupted" invite * three different guesses about whether to try again. It should not: the person asked for it to * stop, and a model that immediately retries has undone the stop. */ export declare const STOPPED_BY_USER = "STOPPED: the user stopped this. Do not retry it. Wait for their next instruction."; /** * A deadline and the user's stop, as one signal. * * Every network call here had a timeout and no way to be cut short, so pressing stop during a fetch * meant waiting out the remaining fifteen seconds with nothing on screen to say why. */ export declare function stopOrTimeout(ms: number, signal?: AbortSignal): AbortSignal; export declare function listDir(args: ListDirArgs, cwd: string): Promise; export declare function globSearch(args: GlobSearchArgs, cwd: string): Promise; export declare function grepSearch(args: GrepSearchArgs, cwd: string): Promise; export declare function moveFile(args: MoveFileArgs, cwd: string): Promise; export declare function deleteFile(args: DeleteFileArgs, cwd: string, requireApproval: boolean): Promise; export declare function searchReplace(args: SearchReplaceArgs, cwd: string, requireApproval: boolean): Promise; export interface MultiEditArgs { path: string; edits: Array<{ search: string; replace: string; replace_all?: boolean; }>; } export declare function multiEdit(args: MultiEditArgs, cwd: string, requireApproval: boolean): Promise; /** * Finds a search string in text, forgiving whitespace, but only if it lands in exactly one place. * * Runs of spaces and tabs are treated as equivalent and line endings normalised, which covers the * near-totality of "not found" misses: the model has the right lines and the wrong indentation, or * LF against the file's CRLF. Returns the actual substring of the file that matched, so the caller * replaces the real bytes rather than the model's approximation of them. * * One place only. A pattern that could match two spots is not a mismatch to forgive, it is an * ambiguity to refuse — editing the wrong one of two is worse than editing neither. */ export declare function fuzzyFindOnce(haystack: string, needle: string): string | null; /** * The not-found message, showing the file's own nearby text so a correction is possible. * * "Search string not found. Use read_files and retry" sends the model to read a file it had just * read. What it actually needs is to see how what it looked for differs from what is there, so this * finds the line most like the search's first line and shows it, which is usually enough to spot a * renamed identifier or a changed indent without another full read. */ export declare function searchNotFound(pathLabel: string, original: string, search: string): string; export declare function fetchUrl(args: FetchUrlArgs, signal?: AbortSignal): Promise; export declare function webSearch(args: WebSearchArgs, signal?: AbortSignal): Promise; /** * Whether a note belongs in a file that every future session reads as fact. * * A real one: "User is attempting to run Git commands outside of a Git repo" — written after the * agent itself called git_status in a folder that was not a repository. The user had not asked * for git at all. That note was then replayed to every later session in that directory as * something the user had done, alongside "Unable to execute commands due to system limitations", * which was a bug in KONECK and not a fact about the project. * * Two things are rejected: narration of the current session, and claims about what the user is * doing. Both are true for a minute and misleading for months. A durable statement about a real * defect still passes — "the CSV export drops the last row" is a fact about the project; "I am * unable to read the file" is a fact about one moment. */ export declare function durableNoteProblem(content: string): string | null; export declare function remember(args: RememberArgs, cwd: string): Promise; /** * Names models reach for that mean one of ours. * * A run called `create_file` with a path and the file contents — unmistakably `write_file` — and * was told no tool by that name exists. It then abandoned the write and went back to listing * directories. Refusing a call whose intent is unambiguous wastes the turn and often the task, * so these are honoured, and the model is told the real name so the next call is right. * * Only names meaning exactly one of ours, taking the same arguments, are here. Anything * ambiguous is better refused with a suggestion than guessed at. */ export declare const TOOL_ALIASES: Readonly>; /** The real tool a name means, if it means one that exists here. */ export declare function resolveToolAlias(name: string, available: readonly string[]): string | null; /** Said with the result of an aliased call, so the next one uses the right name. */ export declare function aliasNotice(called: string, actual: string): string; /** * The error a model gets for a tool that does not exist and cannot be guessed. * * It used to fall through to the plugin loader and come back "Plugin tool \"run\" is not loaded", * which names a mechanism the model has never heard of and says nothing about what it does have. * A real run guessed `run`, was told that, guessed `glob`, was told the same, and was still * guessing when the loop detector stopped it. Naming the tools ends that in one turn. */ export declare function unknownToolError(name: string, available: readonly string[]): string; /** * The arguments as the tool that will run expects them. * * Applied to every builtin call, not only aliased ones: a model that writes `cmd` instead of * `command` has made the same mistake whatever name it used for the tool. */ export declare function normalizeToolArgs(tool: string, argsJson: string): string; /** * A list field that did not arrive as a list, made into one. * * The ordinary case is a model writing {"paths": "src/App.jsx"} where an array was asked for, and * wrapping that in brackets is obviously right. The case that was not handled is a model whose * whole argument object collapsed into the string: * * {"paths": "[\"src/engine.ts\"], \"offset\": 1, \"limit\": 60}"} * * Wrapped, that becomes a one-element array holding a filename that is really a fragment of JSON, * which resolves to a path that cannot exist and fails with a Node internal — "The paths[0] * argument must be of type string. Received an instance of Object" — naming an argument index and a * type, and saying nothing a model can act on. Watched in a real run: the same call was made three * times, and between the attempts it re-read files it already had, because nothing told it what was * actually wrong. * * So the fragment is read rather than swallowed. If a real array can be recovered from it, it is * used, and any offset or limit trailing behind it is honoured too — the model said what it meant, * it merely said it in the wrong shape. */ export declare function asList(value: unknown, into: Record): unknown[]; /** * Required arguments a call is missing, checked against the schema the model was given. * * Done once here rather than in each tool, because the failure is the same everywhere and the * consequence was ugly: `write_file` without a path reached path.resolve and returned * `The "paths[1]" argument must be of type string. Received undefined` — a Node internal naming * an argument index and a parameter the tool does not have. A run hit that five times running, * announcing each time that it would "create the project structure", because nothing in the * message said what was wrong. */ export declare function missingRequiredArgs(tool: string, parsed: unknown): string | null; /** The paths a call would change, so the sandbox can be applied in one place. */ export declare function writeTargets(tool: string, parsed: unknown): string[]; /** * Whether a tool result reports a failure. * * One definition, used by the engine and by everything that draws a result, because they had * drifted: a sandbox denial was recorded as a failure by the engine and drawn with a green tick * by the CI writer, which printed one unconditionally. The outcome a user most needs to see — * "that write did not happen" — looked exactly like success. */ export { isToolFailure } from './tool-outcome.js'; export declare function dispatchTool(name: string, argsJson: string, cwd: string, requireApproval: boolean, onOutput?: (lastLine: string) => void, sandbox?: SandboxSpec, signal?: AbortSignal): Promise; export interface CodeLookupArgs { what?: string; path?: string; symbol?: string; } export interface BrowserArgs { action?: string; url?: string; fields?: Array<{ ref?: number; label?: string; selector?: string; text?: string; }>; ref?: number; label?: string; selector?: string; text?: string; key?: string; submit?: boolean; /** For fill: the control to press once the fields are in. */ then?: { ref?: number; label?: string; selector?: string; }; by?: number; /** For spotlight: open (true, default) or close (false) the full-screen view. */ on?: boolean; /** For spotlight: a line shown to the person about why to watch. */ reason?: string; } /** The live browser, for an interface that wants to show what the agent is looking at. */ export declare function currentBrowser(): import('./browser.js').Browser | null; /** Shuts it down. Called when a run ends, so a headless Chromium is not left behind. */ export declare function closeBrowser(): Promise; //# sourceMappingURL=tools.d.ts.map