From 536b727fc6812f714ac9a11b4470bf9b02fa17c6 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Sun, 11 Jan 2026 02:34:37 +1000 Subject: [PATCH] fix: use full inputSchema for tool definitions instead of flattened parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue was that tools with complex nested parameters (like arrays of objects) were losing their structure when converted to Zod schemas. The LLM would then pass stringified JSON instead of actual arrays. - Import jsonSchema from AI SDK - Check if tool.inputSchema exists (full JSON Schema from executor) - Use jsonSchema() wrapper to preserve nested array/object structures - Fall back to legacy tpmjsParamsToZodSchema only if inputSchema is missing This fixes the changelog tool and similar tools with complex parameter types. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../src/lib/ai-agent/tool-executor-agent.ts | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/apps/web/src/lib/ai-agent/tool-executor-agent.ts b/apps/web/src/lib/ai-agent/tool-executor-agent.ts index b6bfff1..5bb256f 100644 --- a/apps/web/src/lib/ai-agent/tool-executor-agent.ts +++ b/apps/web/src/lib/ai-agent/tool-executor-agent.ts @@ -6,7 +6,7 @@ import { openai } from '@ai-sdk/openai'; import type { Package, Tool } from '@tpmjs/db'; import type { ExecutorConfig } from '@tpmjs/types/executor'; -import { type ModelMessage, generateText } from 'ai'; +import { generateText, jsonSchema, type ModelMessage } from 'ai'; import { z } from 'zod'; import { executeWithExecutor } from '../executors'; @@ -101,21 +101,24 @@ export function createToolDefinition( tool: Tool & { package: Package }, executorConfig?: ExecutorConfig | null ) { - const parameters = Array.isArray(tool.parameters) - ? (tool.parameters as unknown as TPMJSParameter[]) - : []; - console.log('[createToolDefinition] Tool:', tool.package.npmPackageName, '/', tool.name); - console.log('[createToolDefinition] Parameters array:', JSON.stringify(parameters)); - console.log('[createToolDefinition] Parameters length:', parameters.length); - // Ensure we have a valid schema - if no parameters, use an empty object + // Prefer full inputSchema if available (has nested object/array structures) + // Fall back to legacy parameters array conversion if not const inputSchema = - parameters.length > 0 - ? tpmjsParamsToZodSchema(parameters) - : z.object({}).describe('No parameters required'); - - console.log('[createToolDefinition] Created Zod schema:', inputSchema); + tool.inputSchema && typeof tool.inputSchema === 'object' + ? // Use full JSON Schema directly - preserves nested array/object structures + jsonSchema(tool.inputSchema as Parameters[0]) + : // Legacy: convert flattened parameters array to Zod schema + (() => { + const parameters = Array.isArray(tool.parameters) + ? (tool.parameters as unknown as TPMJSParameter[]) + : []; + console.log('[createToolDefinition] Using legacy parameters:', parameters.length); + return parameters.length > 0 + ? tpmjsParamsToZodSchema(parameters) + : z.object({}).describe('No parameters required'); + })(); const sanitizedName = sanitizeToolName(`${tool.package.npmPackageName}-${tool.name}`);