diff --git a/apps/playground/src/lib/dynamic-tool-loader.ts b/apps/playground/src/lib/dynamic-tool-loader.ts index e0c2916..2591e59 100644 --- a/apps/playground/src/lib/dynamic-tool-loader.ts +++ b/apps/playground/src/lib/dynamic-tool-loader.ts @@ -67,10 +67,12 @@ export async function loadToolDynamically( console.log(`📋 Description: ${data.tool.description}`); // Create a tool wrapper that executes remotely - // Note: We don't include inputSchema because Zod schemas can't be serialized over HTTP - // The AI SDK will infer parameters from the description + // Railway returns plain JSON Schema - wrap it in the AI SDK jsonSchema format const tool = { description: data.tool.description, + inputSchema: data.tool.inputSchema + ? { type: 'json_schema' as const, schema: data.tool.inputSchema } + : undefined, // biome-ignore lint/suspicious/noExplicitAny: Tool params are dynamic execute: async (params: any) => { console.log(`🚀 Executing ${packageName}/${exportName} remotely with params:`, params); diff --git a/apps/railway-executor/server.ts b/apps/railway-executor/server.ts index f98776c..5f27d88 100644 --- a/apps/railway-executor/server.ts +++ b/apps/railway-executor/server.ts @@ -76,15 +76,16 @@ async function loadAndDescribe(req: Request): Promise { } // Extract tool definition - // Note: We don't send inputSchema because Zod schemas can't be serialized over JSON - // The playground will use the actual tool's inputSchema when creating the wrapper + // AI SDK v6 tools use jsonSchema() which wraps a plain JSON Schema object + // Extract the raw JSON Schema from toolModule.inputSchema.schema + const rawJsonSchema = toolModule.inputSchema?.schema ?? null; + return Response.json({ success: true, tool: { exportName, description: toolModule.description, - // Store reference that inputSchema exists (for validation) - hasInputSchema: !!toolModule.inputSchema, + inputSchema: rawJsonSchema, // Plain JSON Schema - fully serializable }, }); } catch (error) {