/** * Tool Executor - Unified tool execution wrapper. * * Adds: * - Timeout protection (tools that hang would otherwise stall the turn). * - Optional retry for tools explicitly marked `idempotent`. * * Pi-agent contract (from `AgentTool.execute` docstring): "Throw on failure * instead of encoding errors in `content`." Pi-agent turns thrown errors into * `tool_execution_end` events with `isError=true`, which feeds the loop guard, * error tracker, and error-pattern matcher. This wrapper therefore re-throws * instead of synthesising fake-success results. */ import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from '@earendil-works/pi-agent-core'; import type { XopcToolMetadata } from './metadata.js'; import { ToolConcurrencyController } from './concurrency.js'; import type { ToolConcurrencyController as ToolConcurrencyControllerType } from './concurrency.js'; export interface ToolExecutorConfig { /** Default per-tool timeout when the tool does not declare its own `timeoutMs`. */ defaultTimeoutMs: number; /** Per-session policy override resolved from the effective agent manifest. */ resolveTimeoutMs?: (toolName: string) => number | undefined; /** Max retry attempts for tools opted into retry via `idempotent: true`. */ maxRetries: number; /** Initial backoff between retries (passed straight to `withRetry`). */ retryDelayMs: number; /** Master switches; default both on so the wrapper is still effective. */ enableTimeout: boolean; enableRetry: boolean; } declare const DEFAULT_CONFIG: ToolExecutorConfig; /** * Optional xopc-side hints that any tool may attach. They are not part of the * pi-agent `AgentTool` contract; the wrapper reads them via structural typing. * * - `timeoutMs`: per-tool override of the default execution timeout. * - `idempotent`: marks a tool as safe to retry. The wrapper retries only * tools that opt in — write/edit-like tools must leave this `false`. */ export interface XopcToolHints extends XopcToolMetadata { timeoutMs?: number; } /** * Execute tool with timeout (always) and retry (only for idempotent tools). * Re-throws on failure so pi-agent records `isError=true`. */ export declare function executeToolWithProtection(tool: AgentTool, toolCallId: string, params: any, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback, config?: Partial): Promise>; /** * Wrap a single tool with the protection pipeline. Preserves the original * `execute` signature so streaming `signal` / `onUpdate` reach the tool. */ export declare function wrapToolWithProtection(tool: AgentTool, config?: Partial, concurrency?: ToolConcurrencyControllerType): AgentTool; /** * Wrap a batch of tools with protection. */ export declare function wrapToolsWithProtection(tools: AgentTool[], config?: Partial, concurrency?: ToolConcurrencyController): AgentTool[]; export { DEFAULT_CONFIG as DEFAULT_TOOL_EXECUTOR_CONFIG };