- Set DENO_DIR=/app/.deno_cache to persist module cache
- Pre-cache common dependencies (zod-to-json-schema, ai, zod) during build
- Add Railway volume configuration for /app/.deno_cache
- Improve logging to show cache hits vs network downloads
- Add --allow-read and --allow-write permissions for cache access
This dramatically reduces tool loading time after the first import.
Dependencies are downloaded once and reused across all subsequent requests.
Example: ctx-zip with 200+ dependencies will only download once instead
of on every chat request.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add AbortController timeout (120s) to Railway fetch requests
- Gracefully handle timeout errors and report to health check system
- Increase /api/chat maxDuration from 60s to 300s (5 minutes)
- Prevents entire chat from timing out when one tool has large dependencies
- Tools that timeout are logged and skipped, allowing others to load
Fixes issue where tools like ctx-zip with many dependencies would
cause the entire chat request to timeout after 60 seconds.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove top-level Prisma import from dynamic-tool-loader.ts
- Use dynamic import in reportToolFailure function instead
- Prevents entire module from failing if DATABASE_URL is missing
- Fixes API route timeout issue caused by module initialization failure
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed all prompts except package name
- Auto-generate description from package name
- Use sensible defaults: 2 example tools, ai-ml category, MIT license
- Generate exampleTool and anotherTool that users can customize
- Much faster UX - no more 10+ prompts for basic usage
- Updated README with simplified flow example
- Bumped version to 1.0.3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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>
- tsup banner already adds shebang, no need in source
- bump version to 1.0.2
- fixes CLI execution errors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Interactive CLI generator for scaffolding TPMJS tool packages
- Generates packages with minimum 2 tools (ideally 2-3)
- Zod 4 schemas - uses Zod directly (not jsonSchema wrapper)
- One file per tool in src/tools/<toolName>.ts
- TPMJS validated against official schemas from @tpmjs/types
- Complete package generation ready to publish to npm
- Works both standalone and in monorepo packages/ folders
🤖 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>
Added error, warning, success, and info color CSS variables to
playground globals.css so that Badge component variants display
with correct colors. The error variant will now show red as expected.
🤖 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>
Previously env vars were stored as an array but component used Object.entries(),
causing array indices (0, 1, 2...) to appear as variable names instead of actual
names like 'EXA_API_KEY'.
Updated component to:
- Reflect correct array structure in Tool interface
- Iterate directly over array with .map() instead of Object.entries()
- Access envVar.name field for display
- Added support for displaying default values if present
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change modal from bg-background to bg-white/dark:bg-gray-900
- Makes modal stand out clearly from the app background
- Provides better visual hierarchy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change modal background from bg-surface to bg-background for proper dark mode support
- Use bg-surface for nested elements (env vars, code blocks) to create subtle contrast
- Ensures modal respects the application's dark theme
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Display package name as secondary text below tool name
- Add clickable tool cards that open detailed modal
- Modal shows comprehensive tool info: description, frameworks, env vars, import URL, tool ID
- Improve modal click handling to only close on backdrop clicks
- Fix accessibility: add type="button" to close button
- Full keyboard support with Escape key and proper ARIA labels
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add two major UX improvements to the ToolsSidebar:
1. Package Name Display
- Show package name as secondary label below tool name
- Improves tool identification at a glance
2. Tool Detail Modal
- Click any tool card to open detailed modal
- Shows comprehensive information:
* Tool name, package, version, category
* Quality score (if available)
* Full description
* Supported frameworks (badges)
* Environment variables (with required flag)
* Import URL (for manual integration)
* Tool ID (for debugging)
- Modal features:
* Backdrop blur effect
* Click outside or press Escape to close
* Close button (X icon) with SVG title
* Responsive layout (max-w-2xl)
* Scrollable content (max-h-90vh)
* Full keyboard accessibility (ARIA labels, tabIndex, Escape key)
3. Enhanced Tool Interface
- Added optional fields: toolId, qualityScore, frameworks, env, importUrl
- Maintains backward compatibility with existing API
This gives users full visibility into tool metadata and helps them
understand what each tool does before using it in conversations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>
Added Strategy 2.5 to schema extraction to handle AI SDK v6's
jsonSchema() wrapper which uses `.jsonSchema` property instead
of `.schema`.
This fixes schema validation errors for @tpmjs/hello and other
packages that use jsonSchema() wrapper.
Error was: "No valid schema found" with keys ["_type", "jsonSchema", "validate"]
Fix: Check for inputSchema.jsonSchema as an object property
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The Node.js compatibility layer (npm: specifier) broke environment
variable passing because tools imported via npm: expect process.env,
not Deno.env.
Root cause: Recent commit added npm: specifier for Node compatibility,
but env injection code only set Deno.env.set(), not process.env.
Fix: Set environment variables in BOTH locations:
- Deno.env.set() for esm.sh imports
- globalThis.process.env for npm: imports
This restores functionality for tools like Firecrawl that require
API keys via environment variables.
Fixes regression from commit 8562eb5.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Use Turborepo's --filter='...[HEAD]' to only type-check packages
with staged changes instead of all 21 packages. This reduces
pre-commit hook time from ~30s to ~3s for single-package changes.
🤖 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>
Improve visibility when multiple tools fail during batch loading:
- Track success/failure status for each tool in batch
- Log consolidated summary with counts (✅ Successful: X/Y, ❌ Failed: Y/Z)
- List all failed tools together with automatic health check confirmation
- Provide guidance to check individual error logs for detailed reasons
Also fix linting issues:
- Remove non-null assertions for safer code
- Fix template literals that don't need interpolation
- Add biome-ignore comments for AI SDK any types
This addresses error collation when multiple Railway tools fail,
making it easier to see the big picture while maintaining detailed
individual error logs and health check triggers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add real-time health status updates when tools fail to load or execute:
- Add @tpmjs/db dependency to playground package
- Create reportToolFailure() function to update health status on errors
- Trigger health check updates for:
1. Import failures (Railway load-and-describe errors)
2. Execution failures (Railway execute-tool errors)
- Updates are non-blocking and run in background
- Each tool failure now logs:
- 🏥 Triggering health check for {package}/{export}
- ✅ Health status updated for {package}/{export}
This complements the proactive health checking (daily cron + manual recheck)
with reactive health updates from actual tool usage errors.
Handles multiple errors in batch loading - each error triggers its own
health check update independently and asynchronously.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create .github/workflows/health-check.yml to run daily at 2am UTC
- Add scripts/backfill-health-checks.ts to populate health data for existing tools
- Remove health-check from vercel.json crons (now using GitHub Actions)
The GitHub Action workflow follows the same pattern as other sync operations
and calls the /api/sync/health-check endpoint with proper authentication.
The backfill script:
- Fetches all tools from database
- Runs batch health checks with concurrency control (5 tools at a time)
- Shows detailed progress and summary statistics
- Lists broken tools with error details
🤖 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>
Add multi-strategy import system to support Node.js packages in Deno:
1. Primary: Use npm: specifier for Node.js compatibility mode
2. Fallback: Use esm.sh with explicit esnext target
This allows packages like ai-sdk-tool-code-execution that depend on
Node.js built-ins (node:sqlite, undici) to work in the Deno runtime.
Also added deno.json with nodeModulesDir and BYONM support.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
AI SDK streams use "errorText" field for tool errors, not "error".
Updated MessageBubble to check both errorText and error for compatibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add error message rendering to MessageBubble component so users can see
detailed error messages when tools fail (e.g., missing API keys).
Previously only showed "output-error" badge without the actual error text.
Now displays the error message in a red-tinted box below the tool call.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Detects and handles tools exported as factory functions that require
configuration before returning the actual AI SDK tool object.
Supports multiple factory patterns:
1. No-args factory: toolName()
2. Config object: toolName({ apiKey: 'xxx' })
3. Single-arg: toolName('api-key-value')
For config objects, tries multiple key name variations:
- Raw env vars: { VALYU_API_KEY: 'xxx' }
- Normalized apiKey: { apiKey: 'xxx' }
- Normalized key: { key: 'xxx' }
This enables dynamic loading of tools like @valyu/ai-sdk paperSearch
that use factory patterns instead of direct tool exports.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The previous approach using useEnvVars() hook had a closure problem:
- envVars started as [] on first render
- buildEnvObject captured this empty array
- Even with function body, the transport memoized the old buildEnvObject
Solution: Read directly from localStorage inside the body function
- Bypasses React state entirely
- Gets fresh values on each request
- No closure issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PROBLEM:
DefaultChatTransport body is cloned ONCE on mount, so env vars
were always empty {} even after localStorage loaded them.
SOLUTION:
Use a function for body instead of an object. AI SDK v6 calls
body() on each request, ensuring latest env vars are sent.
Changes:
- useChat.ts: body: { env } → body: () => ({ env: buildEnvObject() })
- buildEnvObject() is called fresh on each request
- Env vars now sent correctly to /api/chat
Credit: ChatGPT for identifying the exact AI SDK v6 pattern
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PROBLEM:
- Tool wrappers cached env vars in closure, so cached tools used stale env
- Client env vars weren't reaching Railway executor even when provided
- No visibility into env var flow through the system
SOLUTION:
1. Store env vars per conversation in conversationEnv Map
2. Tool execute functions look up latest env from Map (not closure)
3. Chat API calls setConversationEnv() on each request
4. Added logging at every step
🤖 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>