import type { AgentTool, AgentToolResult, AgentToolUpdateCallback, } from "@mariozechner/pi-agent-core"; import type { ToolDefinition } from "@mariozechner/pi-coding-agent"; import { logError } from "../logger.js"; import { jsonResult } from "./tools/common.js"; // biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-agent-core uses a different module instance. type AnyAgentTool = AgentTool; export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] { return tools.map((tool) => { const name = tool.name || "tool"; return { name, label: tool.label ?? name, description: tool.description ?? "", // biome-ignore lint/suspicious/noExplicitAny: TypeBox schema from pi-agent-core uses a different module instance. parameters: tool.parameters as any, execute: async ( toolCallId, params, onUpdate: AgentToolUpdateCallback | undefined, _ctx, signal, ): Promise> => { // KNOWN: pi-coding-agent `ToolDefinition.execute` has a different signature/order // than pi-agent-core `AgentTool.execute`. This adapter keeps our existing tools intact. try { return await tool.execute(toolCallId, params, signal, onUpdate); } catch (err) { if (signal?.aborted) throw err; const name = err && typeof err === "object" && "name" in err ? String((err as { name?: unknown }).name) : ""; if (name === "AbortError") throw err; const message = err instanceof Error ? (err.stack ?? err.message) : String(err); logError(`[tools] ${tool.name} failed: ${message}`); return jsonResult({ status: "error", tool: tool.name, error: message, }); } }, } satisfies ToolDefinition; }); }