tpmjs/apps/railway-executor
Ajax Davis 89564af030 fix: sanitize invalid JSON schemas with type 'None' to valid object schemas
Add sanitizeJsonSchema() function to fix common schema issues:
- Replaces invalid type 'None' (common in Python tools) with 'object'
- Ensures all schemas have a valid type field
- Recursively sanitizes nested schemas in properties, items, anyOf/oneOf/allOf
- Prevents OpenAI API errors from malformed tool schemas

This fixes the error with @superagent-ai/ai-sdk guard tool which
returns type: 'None' instead of a valid JSON Schema type.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 18:02:10 +10:00
..
.gitignore feat: add dynamic tool loading system with Railway executor 2025-12-04 08:25:53 +10:00
Dockerfile fix: use Dockerfile instead of Nixpacks for Railway deployment 2025-12-04 08:35:50 +10:00
package-lock.json feat: add dynamic tool loading system with Railway executor 2025-12-04 08:25:53 +10:00
package.json feat: add dynamic tool loading system with Railway executor 2025-12-04 08:25:53 +10:00
README.md feat: add dynamic tool loading system with Railway executor 2025-12-04 08:25:53 +10:00
server.js feat: add dynamic tool loading system with Railway executor 2025-12-04 08:25:53 +10:00
server.ts fix: sanitize invalid JSON schemas with type 'None' to valid object schemas 2025-12-04 18:02:10 +10:00

Railway Dynamic Tool Executor

Dynamic tool executor service that runs with --experimental-network-imports to support loading npm packages from esm.sh at runtime.

Features

  • 🔥 Dynamic imports from esm.sh
  • 💾 Module caching for fast repeated loads
  • 🛡️ Validation of AI SDK tool structure
  • 🚀 Remote execution of tools with parameters

Endpoints

GET /health

Health check and cache statistics

POST /load-and-describe

Load a tool from esm.sh and return its schema

Request:

{
  "packageName": "firecrawl-aisdk",
  "exportName": "webSearchTool",
  "version": "0.7.2",
  "importUrl": "https://esm.sh/firecrawl-aisdk@0.7.2"
}

Response:

{
  "success": true,
  "tool": {
    "exportName": "webSearchTool",
    "description": "Search the web using Firecrawl",
    "inputSchema": { ... }
  }
}

POST /execute-tool

Execute a tool with parameters

Request:

{
  "packageName": "firecrawl-aisdk",
  "exportName": "webSearchTool",
  "version": "0.7.2",
  "params": {
    "query": "latest AI news"
  }
}

Response:

{
  "success": true,
  "output": { ... },
  "executionTimeMs": 1234
}

POST /cache/clear

Clear the module cache

GET /cache/stats

Get cache statistics

Local Development

# Install dependencies
npm install

# Start server
npm start

# Server runs on http://localhost:3001

Railway Deployment

This service is designed to run on Railway.

Deploy Steps

  1. Initialize Railway in this directory:
cd apps/railway-executor
railway init
  1. Link to your Railway project:
railway link
  1. Deploy:
railway up
  1. Railway will automatically:
    • Detect Node.js
    • Run npm install
    • Execute npm start (which includes --experimental-network-imports)

Environment Variables

No environment variables required for basic operation. Optional:

  • PORT - Server port (Railway sets this automatically)
  • NODE_ENV - Set to production in Railway

Testing

Test health endpoint:

curl http://localhost:3001/health

Test tool loading:

curl -X POST http://localhost:3001/load-and-describe \
  -H "Content-Type: application/json" \
  -d '{
    "packageName": "@tpmjs/hello",
    "exportName": "helloWorldTool",
    "version": "0.1.0"
  }'

Test tool execution:

curl -X POST http://localhost:3001/execute-tool \
  -H "Content-Type: application/json" \
  -d '{
    "packageName": "@tpmjs/hello",
    "exportName": "helloWorldTool",
    "version": "0.1.0",
    "params": {}
  }'

Integration with Playground

The playground app calls this service to load and execute tools dynamically.

Set in playground environment:

RAILWAY_SERVICE_URL=https://your-service.up.railway.app

Or use existing:

SANDBOX_EXECUTOR_URL=https://your-service.up.railway.app