import type { Context } from '../core/context.js'; import type { ToolResultBlock, ToolUseBlock } from '../types/blocks.js'; import type { Tool, ToolErrorCategory } from '../types/tool.js'; import { type ToolBatchResult, type ToolExecutorOptions, type ToolExecutorStrategy } from '../types/tool-executor.js'; export declare class ToolExecutor { private readonly registry; private opts; /** Minimum gap between coalesced `partial_output` tool.progress emits. */ static readonly PROGRESS_EMIT_INTERVAL_MS = 100; /** Max chars of accumulated stream text carried per coalesced emit (tail). */ static readonly PROGRESS_TAIL_CHARS = 16384; /** Max chars of the head (beginning of output) kept alongside the tail. */ static readonly PROGRESS_HEAD_CHARS = 16384; private readonly serializer; private readonly iterationTimeoutMs; private readonly maxToolTimeoutMs; constructor(registry: { get(name: string): Tool | undefined; list(): Tool[]; }, opts: ToolExecutorOptions); /** * Clear the interactive confirm awaiter so the executor returns * `ToolConfirmPendingResult` instead of blocking on stdin. Used by * the CLI to switch from inline prompts (REPL) to event-driven * confirmation (TUI) at runtime. */ clearConfirmAwaiter(): void; /** * Push the tool's per-tool result-render mode into the renderer as the * next-result render mode. The config key is `tools.resultRenderMode[name]` * — independent of the LLM-side `descriptionMode` so the two can be * toggled separately (`/tool read desc simple` vs `/tool read result * simple`). Defaults to `extend` when no entry is set. * * The hint is one-shot: the renderer consumes it on the next * `writeToolResult` call so an unset follow-up doesn't inherit a * previous tool's mode. Safe no-op when the renderer doesn't implement * `setResultRenderMode` (e.g. headless/test renderers). */ private hintRenderMode; private toolLogBase; private logToolSuccess; private logToolFailure; /** * Execute a batch of tool uses using the configured strategy. * Returns the execution results and the remaining output budget. */ executeBatch(toolUses: ToolUseBlock[], ctx: Context, strategy: ToolExecutorStrategy): Promise; /** * Internal batch implementation. Nested meta-tool calls enter here through * the governed bridge so they traverse the same validation, hooks, * permission/capability, timeout, scrubbing, and audit path without * replacing the bridge that is already active for the outer call. */ private executeBatchInternal; /** * Install the executor-owned bridge used by meta-tools for nested calls. * The bridge deliberately returns the governed, scrubbed ToolResultBlock * content rather than the raw tool value. This prevents a meta-tool from * bypassing output controls while preserving structured success/failure. */ private withGovernedExecutionBridge; /** * Execute a single tool with timeout and output capping after its permission * decision has already been resolved by executeBatch/the confirmation flow. * Also installs the governed bridge because confirmed tools are re-run * through this method after a pending confirmation. */ executeTool(tool: Tool, use: ToolUseBlock, ctx: Context, budget: number): Promise<{ block: ToolResultBlock; bytes: number; }>; /** * Async "produce" phase: run the tool, serialize, scrub, and spill an * oversized output to a disk artifact. Returns the pre-cap text. This is * the long-running, concurrency-safe part — it touches NO shared budget * state, so multiple invocations can run in parallel without racing. * * The `budgetHint` only gates the disk-spill threshold (a heuristic for * "is this output large enough to persist"); it is NOT the output cap. * The authoritative cap is applied synchronously in settleToolOutput() * against the live budget. */ private produceToolOutput; /** * Synchronous "settle" phase: enforce the output cap against the CURRENT * budget, render, and build the result block. This MUST stay synchronous * (no awaits) so that, in the parallel/smart strategies, two tools settling * one after another against the shared closure budget can't interleave a * stale read with a write. The first to settle consumes its bytes; the next * settles against the reduced budget; once the budget hits 0, enforceCap * truncates — making the per-iteration cap genuinely CUMULATIVE across * parallel tools instead of degrading into a per-tool cap. */ private settleToolOutput; private runWithTimeout; /** Best-effort tool cleanup; never let it mask the original error. */ private runToolCleanup; private runStreamedTool; private unknownToolResult; private malformedInputResult; private deniedResult; private blockedByHookResult; /** * Subtract a string-content result's UTF-8 byte length from the * iteration output budget. Used for synthesized results (unknown tool, * validation error, blocked, threw) where the content is a small * string built in the executor. The success path no longer goes * through here — `executeTool` carries the exact byte count it spent * in its return value, derived from `enforceCap`'s `newBudget`. * * Floors the result at 0 to match the pre-fix `decrementBudget` * semantics (over-budget spends don't underflow the running total). */ private budgetForString; } /** * Classify a tool execution error into a structured ToolErrorCategory. * Used for observability (span attributes) and retry strategy decisions. */ export declare function classifyToolError(err: unknown): { category: ToolErrorCategory; retryable: boolean; detail?: string; }; //# sourceMappingURL=tool-executor.d.ts.map