summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'packages/core/src/tools')
-rw-r--r--packages/core/src/tools/registry.ts48
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;
},