diff options
Diffstat (limited to 'packages/core/src/tools')
| -rw-r--r-- | packages/core/src/tools/registry.ts | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/packages/core/src/tools/registry.ts b/packages/core/src/tools/registry.ts index 0c7b110..a09535e 100644 --- a/packages/core/src/tools/registry.ts +++ b/packages/core/src/tools/registry.ts @@ -1,7 +1,25 @@ -import { tool } from "ai"; -import { z } from "zod"; +import type { Tool } from "ai"; +import { jsonSchema, tool } from "ai"; +import { zodToJsonSchema } from "zod-to-json-schema"; import type { ToolDefinition } from "../types/index.js"; +/** + * Convert an internal `ToolDefinition` (Zod-parameterised) to an AI SDK v6 + * `Tool` object. + * + * Critically, NO `execute` function is attached. The agent's manual tool + * loop (see agent.ts) handles execution itself — for permission prompts, + * shell-output streaming, and queued-message injection. Without `execute`, + * the SDK never auto-runs tools; it only surfaces `tool-call` events from + * `fullStream` that agent.ts collects and dispatches. + */ +function toAISDKTool(def: ToolDefinition): Tool { + return tool({ + description: def.description, + inputSchema: jsonSchema(zodToJsonSchema(def.parameters)), + }); +} + export function createToolRegistry(tools: ToolDefinition[]) { const toolMap = new Map<string, ToolDefinition>(tools.map((t) => [t.name, t])); @@ -14,19 +32,21 @@ export function createToolRegistry(tools: ToolDefinition[]) { return toolMap.get(name); }, - getAISDKTools() { - const result: Record<string, ReturnType<typeof tool>> = {}; + /** + * Returns AI SDK v6 `Tool` objects keyed by tool name, for passing + * directly to `streamText({ tools })`. + * + * Each tool has: + * - `description` — forwarded verbatim from the internal definition. + * - `inputSchema` — Zod schema converted to JSONSchema7 via + * `zod-to-json-schema`, then wrapped with the v6 + * `jsonSchema()` helper. + * - NO `execute` — intentional; see `toAISDKTool` above. + */ + getAISDKTools(): Record<string, Tool> { + const result: Record<string, Tool> = {}; for (const [name, def] of toolMap) { - const schema = def.parameters; - // Do NOT pass execute here — agent.ts handles tool execution - // manually via executeToolWithStreaming. Passing execute would - // cause the AI SDK to auto-execute tools AND agent.ts to execute - // them again, resulting in double execution. - const t = tool({ - description: def.description, - parameters: schema instanceof z.ZodObject ? schema : z.object({}), - }); - result[name] = t as unknown as ReturnType<typeof tool>; + result[name] = toAISDKTool(def); } return result; }, |
