import type { ActionEntry } from "../agent/production-agent.js"; export interface CodingCommandResult { code: number | null; stdout: string; stderr: string; timedOut: boolean; durationMs?: number; outputStillOpen?: boolean; } export interface BashToolMetadata { toolKind: "bash"; command: string; cwd: string; exitCode?: number | null; durationMs?: number; timedOut?: boolean; } export interface EditToolMetadata { toolKind: "edit"; filePath: string; oldText?: string; newText?: string; truncated?: boolean; } export interface WriteToolMetadata { toolKind: "write"; filePath: string; content?: string; truncated?: boolean; lineCount?: number; } export interface ReadToolMetadata { toolKind: "read"; filePath: string; lineCount?: number; } export type StructuredToolMetadata = BashToolMetadata | EditToolMetadata | WriteToolMetadata | ReadToolMetadata; export type BashOutputChunkCallback = (chunk: string) => void; export interface CreateCodingToolRegistryOptions { cwd?: string; restrictToCwd?: boolean; commandTimeoutMs?: number; maxOutputChars?: number; maxFileReadChars?: number; bashThrowsOnNonZero?: boolean; canWrite?: (toolName: "edit" | "write") => string | null; beforeBash?: (input: { command: string; cwd: string; timeoutMs: number; }) => string | null | Promise; onBashOutputChunk?: BashOutputChunkCallback; onToolMetadata?: (toolName: string, phase: "start" | "done", meta: StructuredToolMetadata) => void; } export declare const BASH_OUTPUT_HEAD_CHARS = 4096; export declare const BASH_OUTPUT_TAIL_CHARS = 16384; export declare const EDIT_CONTENT_MAX_CHARS = 49152; export declare function createCodingToolRegistry(options?: CreateCodingToolRegistryOptions): Record<"bash" | "read" | "edit" | "write", ActionEntry>; export declare function runCodingCommand(command: string, cwd: string, timeoutMs: number, options?: { stdin?: string; onChunk?: BashOutputChunkCallback; signal?: AbortSignal; }): Promise; export declare function spawnBackgroundCommand(command: string, cwd: string): string; export declare function formatCodingCommandResult(result: CodingCommandResult, maxChars?: number, options?: { omitEmptyExitCode?: boolean; }): string; export declare function truncateCodingOutput(value: string, max: number): string; export declare function truncateBashOutput(value: string, headChars?: number, tailChars?: number): string; /** * Strip shell quoting so a policy regex sees the word the shell will actually * run. Bash removes quotes before the command word exists, so `git 'checkout'` * and `gi''t checkout` both execute `git checkout` while matching no rule * written against the literal text — every denylist entry is otherwise one pair * of quotes away from being bypassed. * * `unanalyzable` reports constructs whose executed text this pass cannot * recover, so no rule matched against the canonical form can be trusted: * `$'…'` ANSI-C escapes (`$'\x67it'` → `git`) and command substitution * (`$(printf git) $(printf checkout) main` runs the forbidden operation while * the string contains neither token). Callers must escalate rather than clear a * command when this is set. Substitution inside single quotes is literal, so it * does not set the flag. * * ponytail: plain parameter expansion (`$VAR`, `${VAR}`) can also build a token * at runtime and is NOT flagged — doing so would make ordinary `cd $TMPDIR` * commands require approval. Closing that needs a real shell parser, which is * the upgrade path if this boundary ever has to hold against a determined * attacker rather than a misbehaving model. */ export declare function canonicalizeShellCommand(command: string): { canonical: string; unanalyzable: boolean; }; export declare function isReadOnlyShellCommand(command: string): boolean;