/** * Tool fence protocol — shared by the subprocess-backed AgentRunners * (KimiCodeAgentRunner, OpencodeAgentRunner). * * Why this exists: the Claude Agent SDK lets the daemon register org tools * (org_send, ask_human, …) as REAL tools via createSdkMcpServer. Subprocess * backends (the kimi CLI, an opencode server) own their tool surface — an * external caller cannot register tools per-turn. Instead the tools are * rendered INTO the role's system prompt; the model emits ```tool_call * fenced JSON blocks; the runner parses them out of the assistant text, * executes the real OrgToolDef handlers in-process (the same handlers * ClaudeAgentRunner registers with the SDK), and feeds the results back as * ```tool_result fences in the next prompt of the same session. */ import type { OrgToolDef } from './agent-runner.js'; /** Fenced block the model uses to call a tool (see buildToolProtocol). */ export declare const TOOL_CALL_RE: RegExp; /** Max tool_call → tool_result round-trips within a single mailbox prompt. * Guards against a model that keeps calling tools forever. */ export declare const MAX_TOOL_ROUNDS = 10; export interface ToolCall { name: string; arguments: Record; } /** * Render the org tools as a text protocol appended to the role's system * prompt. The model calls a tool by emitting a fenced block: * * ```tool_call * {"name": "org_send", "arguments": {"to": "...", "subject": "...", "message": "..."}} * ``` * * Results come back as a user-role prompt containing ```tool_result fences. * * IMPORTANT wording note: the tools listed here are ORG tools (org_send, * org_recall, …) that exist ONLY through this protocol — the model cannot * reach them natively. But the agent also has NATIVE file/shell tools * (Write, Edit, Bash, …) for doing its actual work. Saying "you have no * native tools" makes the model believe it cannot even write files — the * protocol must name the distinction explicitly. */ export declare function buildToolProtocol(tools: OrgToolDef[]): string; /** Extract tool_call fences from raw assistant texts. A fence whose JSON * cannot be parsed at all is skipped — but NOT silently: `onMalformed` (when * given) is invoked with the raw fence body and the parse error so callers * can surface it (runners emit it as an assistant note, which session.ts * routes to the org bus and scrollback). A parsed object without a string * `name` is skipped quietly — there is nothing actionable to report. */ export declare function parseToolCalls(rawTexts: string[], onMalformed?: (raw: string, error: string) => void): ToolCall[]; /** Execute one tool call against the OrgToolDef handlers, validating args * against the tool's zod shape. Handler errors come back as text so the * model sees the failure instead of the turn dying. * * When `canUseTool` is provided (passed by fence-protocol runners like * CodexAgentRunner that can't use the SDK's native permission gate), it is * invoked AFTER zod validation but BEFORE the handler — a deny decision * short-circuits with a policy-error message instead of executing. */ export declare function executeToolCall(tools: OrgToolDef[], call: ToolCall, canUseTool?: (toolName: string, input: Record) => Promise): Promise; /** Format executed results as the next prompt's tool_result fences. */ export declare function formatToolResults(calls: ToolCall[], results: string[]): string; //# sourceMappingURL=tool-fence.d.ts.map