fix: extract and serialize JSON Schema from AI SDK v6 tools correctly
THE BREAKTHROUGH: AI SDK v6 tools use jsonSchema() which wraps plain JSON Schema objects, NOT Zod schemas. JSON Schema is fully serializable.
Changes:
1. Railway server: Extract raw JSON Schema from toolModule.inputSchema?.schema
2. Playground loader: Wrap received JSON Schema with { type: 'json_schema', schema: ... }
3. This matches AI SDK v6 format exactly - no Zod serialization needed
How it works:
- Tools define inputSchema: jsonSchema({ type: 'object', properties: {...} })
- AI SDK stores it as { type: 'json_schema', schema: {...} }
- Railway extracts the plain JSON Schema (.schema property)
- Sends it as plain JSON (fully serializable)
- Playground wraps it back in AI SDK format
- OpenAI receives valid JSON Schema for function calling
This fixes both errors:
✅ No more "def.shape is not a function" (not using Zod)
✅ No more "Invalid schema type None" (proper JSON Schema provided)
Note: Tools using Zod instead of jsonSchema() will need to migrate.
TPMJS standard: All tools MUST use jsonSchema() with plain JSON Schema.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
287d9b97c9
commit
bb672edf15
2 changed files with 9 additions and 6 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -76,15 +76,16 @@ async function loadAndDescribe(req: Request): Promise<Response> {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue