- Add prominent callout box on homepage in 'Publish Your Tool' section
- Add featured generator section on /publish page with full documentation link
- Include command example and links to GitHub README and NPM
- Highlight key features: 2-3 tools, complete setup, production-ready
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add comprehensive section explaining BM25 search with context awareness
- Show comparison of traditional vs dynamic tool loading approaches
- Document Deno sandboxed execution environment on Railway
- Preview future collections feature for tool organization
- Include call-to-action to try the playground
- Create comprehensive /how-it-works page explaining TPMJS architecture
- Add detailed sections on developer workflow, AI agent integration, and system internals
- Include quality scoring formula, health checks, and data flow diagrams
- Add navigation link to AppHeader between Tools and Playground
- Style consistently with existing pages (Publish, Playground)
- Fix: remove debug console.log from ToolsSidebar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Tools that fail due to missing environment variables (API keys, etc.)
are not actually broken - they just need configuration. Added detection
for common env var error patterns and mark these tools as HEALTHY
instead of BROKEN.
Error patterns detected:
- 'is required'
- 'is not set'
- 'missing environment'
- 'API key required/not provided'
- etc.
This fixes false positives where tools like @superagent-ai/ai-sdk
were marked as broken when they just need SUPERAGENT_API_KEY configured.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The search endpoint was missing importHealth, executionHealth,
healthCheckError, and lastHealthCheck fields in the response. This caused
the playground (which uses search-registry tool) to not receive health
data for displaying broken tool badges.
Added all four health fields to the tool mapping in the search response.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create ToolHealthBadge component in @tpmjs/ui for broken tool indicator
- Create ToolHealthBanner component in @tpmjs/ui for detailed health warnings
- Integrate both components into playground ToolsSidebar:
- Badge shows in tool cards in left sidebar
- Banner shows in tool detail modal
- Update search-registry to include health fields in API responses
- Add package.json exports for new health components
These components provide consistent UI for displaying broken tool status
across the application (tool search, tool detail pages, playground).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add null check before accessing npmKeywords.length to prevent
runtime TypeError when npmKeywords is undefined.
Fixes: Cannot read properties of undefined (reading 'length')
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Use loose equality (!=) instead of strict equality (!==) to check for
both null and undefined values. This prevents runtime TypeError when
githubStars is undefined.
Fixes: Cannot read properties of undefined (reading 'toLocaleString')
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive health status visibility across tool browsing:
Search Page (/tool/tool-search):
- Add health filter dropdown (All/Healthy Only/Broken Only)
- Show "Broken" badges on tool cards when import or execution fails
- Include health filter in Clear Filters button logic
- Update Tool interface with health fields
Detail Page (/tool/[...slug]):
- Add prominent warning banner for broken tools
- Display specific failure types (Import Failed / Execution Failed)
- Show health check error messages in code blocks
- Add manual "Recheck health" button with loading state
- Display last health check timestamp
Phase 3 of health check system implementation complete.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Create dedicated page to display all tools with failed health checks.
Features:
- Lists all tools with importHealth='BROKEN' OR executionHealth='BROKEN'
- Displays health status badges for both import and execution
- Shows error messages in code blocks for debugging
- Includes last checked timestamp
- Links to tool detail pages for manual recheck
- Shows empty state with checkmark when all tools are healthy
- Warning banner showing total broken tool count
UI Components:
- Card layout with red borders for broken tools
- Health status icons (check/x) for visual status
- Category badges and version info
- Direct links to tool detail pages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add non-blocking health check calls to both sync endpoints:
- /api/sync/changes: Triggers health checks after tool upsert from changes feed
- /api/sync/keyword: Triggers health checks after tool upsert from keyword search
Health checks run asynchronously with 'sync' trigger source, ensuring:
- New/updated tools are validated immediately after sync
- Sync operations don't wait for health check completion
- Errors are logged but don't fail the sync
This completes Phase 2 of the health check system implementation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive health monitoring for TPMJS tools that tracks both
import and execution health via Railway executor service.
## Database Schema
- Add HealthStatus enum (UNKNOWN, HEALTHY, BROKEN)
- Add HealthCheckType enum (IMPORT, EXECUTION, FULL)
- Add health fields to Tool model:
- importHealth: tracks if tool can be loaded
- executionHealth: tracks if tool can execute
- lastHealthCheck: timestamp of last check
- healthCheckError: stores error message
- Add HealthCheck audit table for full history
## Core Service
Create health-check-service.ts with 5 functions:
1. checkImportHealth() - Tests tool loading via /load-and-describe
2. checkExecutionHealth() - Tests execution via /execute-tool
3. generateTestParameters() - Creates minimal test params by type
4. performHealthCheck() - Full check with database updates
5. performBatchHealthCheck() - Processes tools in batches
Features:
- 30-second timeout per check
- Skips execution if import fails
- Batch processing (5 concurrent, 1s delays)
- Full audit trail in HealthCheck table
## API Endpoints
/api/sync/health-check (POST):
- Daily cron job at 2am UTC
- Checks all tools in database
- Requires CRON_SECRET auth
- Logs results to SyncLog table
- Max duration: 5 minutes
/api/tools/broken (GET):
- Lists all tools with broken health status
- Filters by importHealth='BROKEN' OR executionHealth='BROKEN'
- Includes package metadata
- Orders by lastHealthCheck DESC
## Configuration
- Add RAILWAY_EXECUTOR_URL to env.ts
- Add daily cron job to vercel.json
- Use db:push for schema changes (existing production data)
Next: Manual trigger endpoint + health filtering + UI components
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement proper BM25 scoring algorithm in /api/tools/search
- Term frequency with saturation (k1 = 1.5)
- Length normalization (b = 0.75)
- Inverse document frequency (IDF)
- Accept recent messages via 'messages' query param for better context
- Update search-registry tool to:
- Use /api/tools/search endpoint (not /api/tools)
- Pass last 3 user messages for contextual search
- Include recentMessages in tool input schema
- Update chat API to extract and pass last 3 user messages to search
BM25 formula: Σ IDF(qi) * (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * |D| / avgdl))
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Left Sidebar:
- Create /api/tools endpoint to fetch tools from registry
- Update ToolsSidebar to fetch and display tools dynamically
- Add filter input for searching tools by name/description/category
- Fix interface to use packageName/exportName from search registry
Right Sidebar:
- Create SettingsSidebar with environment variable management
- Add localStorage persistence for env vars
- Implement password masking for values
- Export useEnvVars() hook for accessing env vars
Environment Variable Forwarding:
- Update useChat hook to read and forward env vars to API
- Update chat route to extract env vars from request body
- Update dynamic-tool-loader to accept and forward env vars
- Update Railway executor to inject env vars into Deno environment
- Complete chain: localStorage → client → chat → Railway → Deno.env
Bug Fixes:
- Fix undefined property errors in tool detail page
- Add optional chaining for npmDownloadsLastMonth and qualityScore
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a complete dynamic tool loading system that allows the playground to discover and load tools from the TPMJS registry at runtime.
**Architecture:**
- Search tool package (@tpmjs/search-registry) - Searches registry for tools
- Search API endpoint (/api/tools/search) - Text-based search with scoring
- Pre-flight tool loading - Automatically searches and loads tools on every message
- Railway executor service (Deno) - Loads tools from esm.sh via HTTP imports
- Dynamic tool loader - Calls Railway to load and execute tools remotely
**Key Components:**
1. Railway Executor (apps/railway-executor/)
- Deno-based service that natively supports HTTP imports
- Endpoints: /load-and-describe, /execute-tool, /cache/stats, /cache/clear
- Deploys to Railway with deno run --allow-net --allow-env server.ts
2. Search Tool Package (packages/tools/search-registry/)
- AI SDK v6 tool for searching TPMJS registry
- Uses jsonSchema + inputSchema pattern
- Searches /api/tools/search endpoint
3. Search API (apps/web/src/app/api/tools/search/)
- Text-based search with composite scoring
- Scores: text relevance + quality boost + download boost
- Returns tool metadata with importUrl for dynamic loading
4. Dynamic Tool Loader (apps/playground/src/lib/dynamic-tool-loader.ts)
- Calls Railway service to load tools from esm.sh
- Creates tool wrappers that execute remotely
- Process-level module cache + per-conversation tracking
5. Pre-flight Loading (apps/playground/src/app/api/chat/route.ts)
- Automatically searches for tools on every user message
- Loads top 5 matching tools before agent processes request
- Merges with static tools for seamless experience
**Technical Decisions:**
- Deno over Node.js: Native HTTP import support without flags
- Remote execution: Tools run in Railway sandbox, not Vercel
- Pre-flight loading: Better UX than two-turn search pattern
- Text search: BM25 had dependency issues, simple scoring works well
**Environment Variables:**
- RAILWAY_SERVICE_URL: https://endearing-commitment-production.up.railway.app🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
BREAKING CHANGE: Complete refactoring from single-tool to multi-tool package support
Database Schema:
- Split Tool model into Package (1) and Tool (many) with one-to-many relationship
- Package stores npm metadata and package-level tpmjs fields (category, env, frameworks, tier)
- Tool stores individual tool exports with tool-level metadata (exportName, description, parameters, returns, aiAgent)
- Unique constraint on (packageId, exportName) to prevent duplicate tools
- Cascade deletes when packages are removed
Type System:
- Updated tpmjs field schema to support tools array
- Each tool has exportName, description, parameters, returns, aiAgent
- Package-level fields: category, env, frameworks shared across all tools
- Backward compatible with legacy single-tool format (auto-migrates to exportName: "default")
API Updates:
- Updated all /api/tools routes to query Tool model with Package relations
- Updated /api/tools/[slug] to accept package/export path segments
- Updated tool-executor-agent to use actual exportName instead of hardcoded "default"
- Updated metrics sync to calculate quality scores per Tool
Frontend Updates:
- Updated tool search page to display exportName as primary heading
- Updated tool detail pages to show package name as secondary info
- Removed tag-based filtering (tags moved to package level)
Manual Tool Registry:
- Added manual-tools.ts with 23 curated tools from major providers
- Created sync-manual-tools.ts script to sync manual tools to database
- Added MANUAL_TOOLS.md documentation for manual tool system
- Added GitHub workflow for automated daily sync
- Includes tools from: Vercel, Exa, Firecrawl, AWS Bedrock, Perplexity, Tavily, Superagent, Valyu
Playground Updates:
- Updated tool loader to load multiple tools per package
- Added sanitizeToolName for OpenAI API compatibility
Sync System Updates:
- Updated changes feed sync to handle multi-tool packages
- Updated keyword sync to upsert multiple tools per package
- Added orphaned tool deletion when tools removed from package.json
Migration Strategy:
- Database uses same Neon instance for dev and prod
- Schema updated via prisma db push (no migration files yet)
- All data repopulates from npm via sync system
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
API Changes:
- Track author name along with package name and reason
- Extract author from pkg.author (string or object with name field)
- Default to "unknown" if author info not available
Workflow Changes:
- Display author in format: "package-name (by author) - reason"
Example Discord output:
📋 Skipped Packages
tpmjs-threejs-tool (by john-doe) - invalid tpmjs field
@scope/package-1 (by jane-smith) - missing tpmjs field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
API Changes:
- Track skip reason along with package name
- Changed skippedPackages from string[] to Array<{name, reason}>
- Reasons: "package not found", "missing tpmjs field", "invalid tpmjs field"
Workflow Changes:
- Format skipped packages as "package-name - reason"
- Display one package per line in Discord notification
Example Discord output:
📋 Skipped Packages
@scope/package-1 - missing tpmjs field
package-2 - invalid tpmjs field
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
API Changes:
- Track skipped package names in keyword sync endpoint
- Include skippedPackages array in API response
Workflow Changes:
- Extract skipped package names from sync response
- Display skipped packages in Discord notification as comma-separated list
- Only show "📋 Skipped Packages" field when packages are skipped
- Dynamic field construction using jq
Example Discord output:
📋 Skipped Packages
package-name-1, package-name-2, package-name-3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
API Changes:
- Return errorMessages array in sync response (first 5 errors)
Workflow Changes:
- Display error messages in GitHub Actions logs with formatting
- Include error details in Discord notifications (first 3 errors)
- Shows errors in both console output and Discord embed
Example output:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ SYNC ERRORS (4 total):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Failed to process pkg1: Invalid tpmjs field
• Failed to process pkg2: Network timeout
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
These fields are redundant as they already exist in package.json:
- links: Use package.json repository/homepage fields
- tags: Use package.json keywords field
- status: Not needed in tool metadata
Changes:
- Remove TpmjsLinksSchema type definition
- Remove links, tags, and status from TpmjsRichSchema
- Update validation logic to not check these fields
- Update all documentation (spec page, publish page, HOW_TO_PUBLISH_A_TOOL.md)
- Update example tool package.json
- Simplify field reference tables
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename TpmjsEnvVarSchema to TpmjsEnvSchema
- Rename envVars field to env throughout codebase
- Remove example field from TpmjsMinimalSchema (no longer required)
- Update all documentation (spec page, publish page, HOW_TO_PUBLISH_A_TOOL.md)
- Update example tool package.json
- Simplify minimal tier requirements to only category and description
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace the authentication field with a more general envVars array that allows tools to specify required environment variables:
Changes to type definitions:
- Remove TpmjsAuthenticationSchema and TpmjsAuthentication type
- Add TpmjsEnvVarSchema with fields: name, description, required, default
- Replace authentication field with envVars array in TpmjsRichSchema
- Update validateTpmjsField to check envVars instead of authentication
Changes to documentation:
- Update /spec page to document envVars instead of authentication
- Update /publish page examples to use envVars
- Update HOW_TO_PUBLISH_A_TOOL.md with envVars examples
- Update validation errors section
- Remove authentication from @tpmjs/createblogpost example
The envVars field is more flexible and clearer - it lists all environment variables a tool needs (API keys, endpoints, config values) rather than trying to categorize authentication types.
Example:
```json
"envVars": [
{
"name": "OPENAI_API_KEY",
"description": "API key for OpenAI services",
"required": true
}
]
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove pricing field from the entire project as it doesn't make sense for tool metadata:
- Remove TpmjsPricingSchema and TpmjsPricing type from types package
- Remove pricing from TpmjsRichSchema validation
- Remove pricing from validateTpmjsField check
- Remove pricing documentation from /spec page
- Remove pricing examples from /publish page
- Remove pricing from HOW_TO_PUBLISH_A_TOOL.md
- Remove pricing from @tpmjs/createblogpost example package.json
The pricing field was removed from Tier 3 (Rich) metadata as it's not relevant for tool discovery and integration. Tools can document pricing in their README or documentation links instead.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create /spec page with complete technical reference for TPMJS metadata
- Document all three tiers (Minimal, Basic, Rich) with field explanations
- Include field reference table with types and requirements
- Explain quality scoring algorithm and discovery mechanisms
- Add cross-links to /publish page for complementary content
- Update AppHeader to include Spec link in navigation (Tools > Playground > Spec > GitHub > Publish)
The spec page provides a balanced technical reference while the publish page remains the practical how-to guide.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
- Each page had different header implementations with varying navigation links
- Inconsistent user experience across homepage, tools, playground, and publish pages
- Duplicate header code throughout the application
**Solution:**
- Created `AppHeader` component (apps/web/src/components/AppHeader.tsx) with consistent navigation:
- TPMJS logo linking to homepage
- Tools, Playground, and Publish Tool links
- GitHub icon link
- Sticky header with medium size
- Updated all pages to use the shared component:
- apps/web/src/app/page.tsx (homepage)
- apps/web/src/app/tool/tool-search/page.tsx (tools search)
- apps/web/src/app/playground/page.tsx (component playground)
- apps/web/src/app/publish/page.tsx (publish guide)
- apps/web/src/app/tool/[...slug]/page.tsx (tool detail pages)
**Benefits:**
- Consistent header across all pages
- Single source of truth for navigation
- Easier to maintain and update navigation links
- Improved user experience with predictable navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major changes:
- Fixed package executor URL protocol handling (add https:// if missing)
- Switched from streamText to generateText for proper tool execution
- AI now calls tool AND generates natural language response
- Tool results no longer show raw JSON metadata
Tool executor (tool-executor-agent.ts):
- Use generateText() instead of streamText() for tool execution
- Add system prompt to guide AI to summarize tool results
- Return result.text for natural language output
- Tool definition uses inputSchema (AI SDK v6 format)
Package executor:
- Add getSandboxUrl() to ensure URL has https:// protocol
- Fixes "Failed to parse URL" error in production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- In AI SDK v6, tool results are in fullResponse.messages with role 'tool'
- Updated result extraction to iterate through messages array
- Added detailed logging to debug response structure
- Handle both text output and tool-only responses
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
- Tool playground was only showing partial output
- When 'complete' event arrived, it replaced streamed text with final output
- Output was displayed as plain text instead of formatted markdown
**Changes:**
- Fixed streaming bug in ToolPlayground component
- Removed line that overwrote accumulated text on 'complete' event
- Now preserves all streamed chunks for full output display
- Added react-markdown with GitHub Flavored Markdown support
- Install react-markdown and remark-gfm packages
- Added @tailwindcss/typography plugin for prose styling
- Replaced plain <pre> with <ReactMarkdown> component
- Applied prose classes for proper markdown formatting
- Added type="button" to button elements for accessibility
**Files changed:**
- apps/web/src/components/ToolPlayground.tsx
- Comment out setOutput(data.output) on complete event
- Import ReactMarkdown and remarkGfm
- Replace pre element with ReactMarkdown component
- Add prose styling classes
- Add type="button" to buttons
- apps/web/tailwind.config.ts
- Add @tailwindcss/typography plugin
**Result:**
- Full streamed output now displays correctly
- Markdown is rendered with proper formatting (headings, lists, code blocks, etc.)
- Better UX for AI-generated tool responses
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
OpenAI was rejecting tool definitions with error "schema must be a JSON Schema of 'type: "object"'". This was caused by AI SDK v5 not properly converting Zod schemas to JSON Schema format.
**Changes:**
- Upgrade AI SDK from v5.0.104 to v6.0.0-beta.124
- Upgrade @ai-sdk/openai from v2.0.74 to v3.0.0-beta.22
- Upgrade Zod from v3.25.76 to v4.1.13 across all packages
**AI SDK v6 breaking changes:**
- Tool definition API: `parameters` renamed to `inputSchema`
- Removed `aiTool()` wrapper - use plain object with description, inputSchema, execute
- Streaming API: Use `textStream` async iterator instead of onChunk callback
- Zod schemas now properly converted to JSON Schema for OpenAI
**Zod v4 breaking changes:**
- `z.record()` now requires two arguments: `z.record(keySchema, valueSchema)`
- `z.enum()` params changed: `errorMap` removed, use `message` instead
- Type system improvements require explicit type parameters
- Fixed type errors in @tpmjs/env, @tpmjs/npm-client, @tpmjs/types
**Files changed:**
- apps/web/src/lib/ai-agent/tool-executor-agent.ts
- Updated tool definition to use `inputSchema` instead of `parameters`
- Removed `aiTool()` wrapper
- Fixed streaming to use `textStream` iterator
- packages/env/src/index.ts
- Updated type constraint from `z.ZodRawShape` to `Record<string, z.ZodTypeAny>`
- packages/npm-client/src/package.ts
- Fixed `z.record()` calls to include both key and value schemas
- Added type assertions for record indexing
- packages/types/src/tpmjs.ts
- Changed `errorMap` to `message` in z.enum() calls
**Testing:**
- ✅ Type-check passes
- ✅ Production build succeeds
- ✅ All routes compile correctly
This fixes the tool execution error where OpenAI rejected tool schemas with invalid format.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add server component to fetch live stats from database
- Tool count from Tool table
- Invocations from successful Simulation records
- Average latency from recent executions
- Category distribution stats
- Add featured tools section
- Display top 6 tools by quality score
- Show tool cards with name, description, category, tags
- Include quality score and download metrics
- Official badge for verified tools
- Click-through to tool detail pages
- Update HeroSection component
- Accept stats prop with real database metrics
- Format large numbers (e.g., "1.2K", "5.3M")
- Add functional search navigation
- Enter key and button click navigate to tool-search
- Empty search browses all tools
- Optimize database queries
- Use Promise.all() for parallel execution
- Calculate avg latency from last 100 simulations
- Graceful error handling with fallback values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add console.log statements to track:
- Tool parameters array and length
- Generated Zod schema details
- Tool definition structure
- Sanitized tool name
- Complete tools config sent to OpenAI
This will help diagnose why OpenAI is still receiving 'type: "None"'
for empty parameter schemas despite the fix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: OpenAI API error 'got type: None' when tool has no/invalid parameters
Solution: Add guard to explicitly create empty object schema with description when no parameters exist
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem: OpenAI tool names must match ^[a-zA-Z0-9_-]+ but npm package names like @tpmjs/createblogpost contain @ and /
Solution: Add sanitizeToolName() function and update pnpm-lock.yaml
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
The Interactive Playground was failing with "Missing tiktoken_bg.wasm" error in production. Tiktoken requires WASM files which don't work in Vercel's serverless environment.
**Solution:**
- Remove tiktoken import from tool-executor-agent
- Replace tiktoken-based token counting with character estimation (~4 chars/token)
- Remove tiktoken from package.json dependencies
- Remove unused biome-ignore comment
**Impact:**
- Token counting is now approximate but consistent
- No more WASM-related runtime errors
- Serverless deployment works properly
- Tool execution now functional in production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
The Interactive Playground was failing with "Missing tiktoken_bg.wasm" error in production. Tiktoken requires WASM files which don't work in Vercel's serverless environment.
**Solution:**
- Remove tiktoken import from tool-executor-agent
- Replace tiktoken-based token counting with character estimation (~4 chars/token)
- Remove tiktoken from package.json dependencies
- Remove experimental webpack WASM config (no longer needed)
**Impact:**
- Token counting is now approximate but consistent
- No more WASM-related runtime errors
- Serverless deployment works properly
- Tool execution now functional in production
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Convert static import of executeToolWithAgent to dynamic import inside the
POST handler. This prevents the AI SDK (and its tiktoken dependency) from
being loaded at build time, which was causing WASM loading errors.
**Why this fix works:**
- Next.js 16 + Turbopack tries to analyze routes at build time
- tiktoken requires tiktoken_bg.wasm which can't load during static analysis
- Dynamic imports defer loading until runtime, avoiding build-time WASM issues
**Changes:**
- Remove: `import { executeToolWithAgent } from '@/lib/ai-agent/tool-executor-agent'`
- Add: `const { executeToolWithAgent } = await import('@/lib/ai-agent/tool-executor-agent')`
inside the stream start() handler
Build now completes successfully. Route is properly marked as dynamic (ƒ).
Resolves: "Error: Missing tiktoken_bg.wasm" during Next.js build
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add `export const dynamic = 'force-dynamic'` to `/api/tools/execute/[...slug]`
to prevent Next.js from attempting static generation at build time.
The AI SDK (used via executeToolWithAgent) requires tiktoken_bg.wasm which
cannot be loaded during static generation. Marking as dynamic ensures the
route is only executed at runtime.
Note: This partially addresses the build error but further investigation needed
for complete resolution of tiktoken WASM loading in Next.js 16 + Turbopack.
Relates to: "Error: Missing tiktoken_bg.wasm"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**API Route Restructuring:**
- Move execute endpoint from /api/tools/[...slug]/execute to /api/tools/execute/[...slug]
- Move simulations endpoint from /api/tools/[...slug]/simulations to /api/tools/simulations/[...slug]
- Fix Next.js App Router constraint: catch-all segments must be terminal
- Update ToolPlayground component to use new endpoint paths
**Package Executor Export Fix:**
- Remove .js extensions from exports in @tpmjs/package-executor
- Change from './types.js' to './types' for proper TypeScript resolution
- Change from './executor.js' to './executor' for proper TypeScript resolution
- Fixes "Export executePackage doesn't exist in target module" build error
**Next.js Configuration:**
- Add vm2 and @tpmjs/package-executor to serverExternalPackages
- Prevents bundling VM2 which requires filesystem access to internal files
**Code Quality:**
- Add biome-ignore for excessive complexity in SSE stream handling
- Add biome-ignore for decorative loading spinner SVGs (2 instances)
Note: VM2 sandboxing still has compatibility issues with Next.js Turbopack.
This may need to be replaced with a different sandboxing approach or disabled.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Syntax Highlighting:**
- Add react-syntax-highlighter with Solarized Light theme
- Proper language detection from markdown code blocks
- Beautiful syntax highlighting for all code examples
- Improved inline code styling with subtle borders
**Enhanced Readability:**
- Larger base typography with prose-lg
- Better contrast for text colors (zinc-700/zinc-300)
- Improved heading spacing and hierarchy
- Enhanced table styling with hover effects and better spacing
- Table headers with uppercase, bold styling
- Table cells with generous padding (px-6 py-4/py-3)
- Row hover effects for better interaction
- Better blockquote styling with blue accents
- Improved list spacing with leading-relaxed
- Enhanced image borders and shadows
**Table Improvements:**
- Professional header styling with background colors
- Better cell padding and spacing
- Hover effects on rows
- Improved borders and shadows
- Responsive overflow handling
All code blocks now have beautiful Solarized Light syntax highlighting, and the overall typography is more readable and professional.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Enhanced Markdown Rendering:**
- Use prose-slate for better default typography
- Add proper heading hierarchy with bottom borders on h1/h2
- Improve code block styling with better backgrounds and shadows
- Style inline code with pink/red accent colors like npm
- Better table styling with proper borders and rounded corners
- Improve link colors (blue) with hover effects
- Add better spacing throughout (margins, padding, line-height)
- Enhance blockquote styling with background colors
- Better list spacing with space-y-2
- Add proper light/dark mode support with zinc color palette
**Component Updates:**
- Custom pre component with better background and border
- Custom table wrapper with overflow handling
- Improved link component with external link detection
- Better inline code styling
The README now renders beautifully like npm.com instead of looking plain.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename API route from [slug] to [...slug] for catch-all routing
- Update API handler to join slug segments for scoped packages
- Remove encodeURIComponent from frontend API call
This fixes the 404 error when accessing tool pages with scoped package names.
The sync workers will need to run to populate README data for existing tools.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename [slug] to [...slug] for catch-all routing
- Update tool detail page to join slug segments (e.g., ['@tpmjs', 'text-transformer'] -> '@tpmjs/text-transformer')
- Remove encodeURIComponent from tool search links
- URLs now display as /tool/@tpmjs/text-transformer instead of /tool/%40tpmjs%2Ftext-transformer
This makes URLs cleaner and more readable while maintaining full compatibility with scoped npm package names.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Database Schema:**
- Add npmReadme, npmKeywords, npmAuthor, npmMaintainers fields to Tool model
**NPM Client:**
- Add fetchLatestPackageWithMetadata() function to fetch README and top-level metadata
- Export new PackageVersionWithReadme type
**Sync Workers:**
- Update keyword and changes sync to fetch and store README content
- Store author, maintainers, and keywords from package.json
**UI Components:**
- Create Markdown component using react-markdown with GitHub Flavored Markdown
- Add rehype-sanitize for security and remark-gfm for tables/strikethrough support
**Tool Detail Page:**
- Convert from createElement to JSX for better maintainability
- Display README in a dedicated card with proper markdown rendering
- Show NPM keywords, author, and maintainers in sidebar
- Add ThemeToggle to header
- Improve layout with better spacing and organization
This brings the tool detail pages much closer to NPM's package pages,
providing users with comprehensive information about each tool including
the full README documentation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>