- Make tooltips more verbose with detailed explanations for each node
- Add tooltip for 'Your Tools' node
- Change GitHub button labels from 'GitHub' to 'Source'
- Fix missing </p> closing tags
- Create SDKFlowDiagram component with animated D3 graphics
- Add flowing particle animations along connection paths
- Add hover interactions with tooltips for each node
- Add entrance animations with staggered timing
- Add subtle glow effects and shadows
- Responsive design that adapts to screen width
- Sleek minimal black and white aesthetic with depth effects
- Replace deprecated Agent class with streamText function
- Add @ai-sdk/anthropic import for model provider
- Change instructions to system parameter
- Add example prompt showing tool usage
- Create @tpmjs/registrySearch package for searching tool registry
- Create @tpmjs/registryExecute package for executing tools via sandbox
- Support self-hosted registries via TPMJS_API_URL and TPMJS_EXECUTOR_URL env vars
- Add /sdk documentation page with usage examples and architecture
- Add SDK link to navigation menu
- Include design doc for registry SDK architecture
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Same issue as startTime - these variables were destructured inside the
try block but referenced in the catch block for health reporting. If
JSON parsing or any early error occurred, the catch block would crash
with 'packageName is not defined'.
Now declares them with 'unknown' defaults before try, then assigns
the actual values inside.
The startTime variable was declared inside the try block but referenced
in the catch block, causing 'startTime is not defined' errors when
exceptions occurred before line 404 (e.g., during req.json() parsing).
Moving the declaration before the try ensures it's in scope for the
catch block's executionTimeMs calculation.
Health status is now reported from the executor - the single point where
all tools run. This ensures consistent health tracking regardless of
client (playground, direct API, etc).
- Add reportToolHealth() to Railway executor
- Report success/failure after every tool execution
- Remove health reporting from playground (executor handles it)
- Executor calls /api/tools/report-health which has all the logic
- Remove direct DB updates from playground
- Add /api/tools/report-health endpoint with all health logic
- Playground now reports results to web app API
- All env var / validation error detection is in one place
- Health status updates based on execution success and error type
- Fix type errors with proper null checks
The executor returns HTTP 500 for all tool errors, including missing env vars.
Before: 500 response = BROKEN
After: Check error message for env/validation patterns before marking BROKEN
This ensures tools that require API keys (like @parallel-web/ai-sdk-tools)
show importHealth: HEALTHY since the tool loads correctly - it just needs config.
Some AI SDK tools (like @parallel-web/ai-sdk-tools) expect execute(params, context)
where context contains { abortSignal, messages, toolCallId }. Previously we only
passed params which caused 'Cannot destructure abortSignal' errors.
Also:
- Improved playground system prompt for better tool execution
- Playground /api/tools now proxies to web app with response transformation
- Added broken-tools.md documenting tool failure categories
Co-Authored-By: Claude <noreply@anthropic.com>
Removes importHealth, executionHealth, healthCheckError, and lastHealthCheck
fields from tool search results. Models were refusing to call tools marked
as BROKEN, even when the issue was just a missing env var.
Co-Authored-By: Claude <noreply@anthropic.com>
Simplify execution health check logic:
- If executor responds (2xx or 4xx), tool is HEALTHY
- Only mark BROKEN for 5xx errors or network/timeout failures
- Validation errors (URL format, missing fields) mean tool IS working
- Remove brittle pattern matching for specific error messages
The previous approach tried to match specific error patterns to determine
if an error was "acceptable". This was fragile. The new approach:
- Import check: can we load and describe the tool?
- Execution check: did the tool execute at all?
If a tool throws a validation error, it executed successfully - it's
correctly rejecting invalid test input. Only infrastructure failures
(executor down, network timeout) indicate a truly broken tool.
Tools that reject invalid test inputs (like invalid URLs) are actually
working correctly - they're validating input as expected. Previously
the health check marked these as BROKEN because the test used dummy
values like 'test' which failed Zod validation.
Now input validation errors (invalid URL, invalid format, type mismatch,
etc.) are treated as HEALTHY, similar to how we already treat missing
environment variables.
When a tool is marked as BROKEN but executes successfully in the
playground, update its health status to HEALTHY. This ensures
stale health check data doesn't persist when tools are working.
Also fixes noImplicitAnyLet lint error by refactoring to const.
- Add formatTimeAgo utility function for relative time display
- Show "Published X ago" at bottom of each tool card using npmPublishedAt
- Center CodeBlock copy button vertically for better alignment
- Update Tool interface to include npmPublishedAt from API
- Add eslint-disable and biome-ignore for a11y rules in tool-search page
- Escape quotes in how-it-works page for react/no-unescaped-entities
- Exclude Deno-based railway-executor from dependency cruiser
- Extract sortTools helper to reduce cognitive complexity
- Add sortBy state with 'downloads' as default (most downloaded)
- Add 'recent' sort option to sort by createdAt
- Sorting keeps broken tools at bottom regardless of sort order
- Add createdAt field to Tool interface
- Update interface to match actual API response (Tool has package relation)
- Fix package name display in installation section (was showing undefined)
- Add step-by-step usage instructions:
1. Install package
2. Import the tool
3. Use with AI SDK (generateText example)
- Update all sidebar sections to use pkg.* for package-level data
- Remove deprecated tpmjsMetadata references
- Clean up unused Tags section
- Replace orbital spinner with 3x3 grid of blocks
- Diagonal wave animation matches dithering aesthetic
- Sharp squares, no rounded corners (brutalist)
- Inline horizontal layout with monospace text
- Consistent styling across all loading states
The new loader evokes "tools being constructed" - fitting
for a tool registry. Uses staggered opacity/scale animation
creating a wave pattern across the grid.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create new Spinner component with three orbiting dots
- Use inline CSS keyframes for reliable animation
- Support multiple size variants (xs, sm, md, lg, xl)
- Increase spinner sizes in loading states across the app
- Add biome-ignore directives for pre-existing lint issues
- Fix accessibility: change span onClick to button element
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove Tabs component and activeTab state
- Show all tools in a single grid view
- Simplify API calls by removing unnecessary count fetches
- Add missing Script import in layout.tsx
Shows duration for text generation and tool execution in chat messages.
Tracks when each part starts and completes, displays timing in the UI.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Ensures fresh data is always fetched from database on homepage load.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Simplified Docker configuration to use manually mounted volume at /data
instead of complex pre-caching strategy. This approach:
- Uses ENV DENO_DIR=/data to point to manually created Railway volume
- Keeps Dockerfile simple and maintainable
- Adds --allow-read/--allow-write permissions for cache access
- Removes railway.toml volume configuration (manual setup instead)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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>
- 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>
- 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>