tpmjs/packages/db/prisma/schema.prisma
Ajax Davis ab46b6e116 feat: add interactive tool playground with AI-powered execution
Implement comprehensive tool testing environment with real package execution, AI agents, and token tracking.

**New Features:**
- Interactive playground UI with 4 tabs (Input, Output, Logs, Token Usage)
- Real npm package execution in VM2 sandbox with security constraints
- AI-powered tool execution using AI SDK v5 and GPT-4 Turbo
- Server-Sent Events (SSE) streaming for real-time progress updates
- Comprehensive 4-category token tracking (Input, Tool Description, Schema, Output)
- Visual token breakdown with colored progress bars
- IP-based rate limiting (10 executions/hour per IP)
- Database persistence of all simulations with full metadata

**Database Schema:**
- New `Simulation` model for execution records
- New `TokenUsage` model for detailed token metrics
- New `ExecutionLog` model for execution event tracking
- Added simulations relation to Tool model

**Package Executor (@tpmjs/package-executor):**
- VM2 sandbox with 5-second timeout
- Blocked dangerous modules (fs, net, http, https, child_process)
- LRU file system cache in /tmp/.tpmjs-cache
- Package installation and caching strategy

**AI Agent Service:**
- TPMJS parameter to Zod schema conversion
- AI SDK tool definition generation
- Token counting using tiktoken library
- GPT-4 Turbo pricing estimation
- Streaming text execution with callbacks

**API Endpoints:**
- POST /api/tools/[...slug]/execute - SSE streaming execution
- GET /api/tools/[...slug]/simulations - Execution history
- Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining)

**Frontend Components:**
- ToolPlayground - Main playground UI with tabs
- TokenBreakdown - Visual token metrics with colored bars
- Integrated above README section on tool detail pages

**Security:**
- VM2 sandboxing prevents filesystem/network access
- Rate limiting prevents abuse
- IP tracking for usage monitoring
- Timeout protection (60s max API duration, 5s VM timeout)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 00:36:05 +10:00

169 lines
5.6 KiB
Text

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
/// Main tools table - stores all discovered NPM packages with TPMJS metadata
model Tool {
id String @id @default(cuid())
// NPM Metadata
npmPackageName String @unique @map("npm_package_name") @db.VarChar(214)
npmVersion String @map("npm_version") @db.VarChar(50)
npmPublishedAt DateTime @map("npm_published_at")
npmDescription String? @map("npm_description") @db.Text
npmRepository Json? @map("npm_repository") @db.JsonB
npmHomepage String? @map("npm_homepage") @db.Text
npmLicense String? @map("npm_license") @db.VarChar(50)
npmKeywords String[] @default([]) @map("npm_keywords") @db.Text
npmReadme String? @map("npm_readme") @db.Text
npmAuthor Json? @map("npm_author") @db.JsonB
npmMaintainers Json? @map("npm_maintainers") @db.JsonB
// TPMJS Metadata (from package.json tpmjs field)
category String @db.VarChar(50)
description String @db.Text
example String @db.Text
parameters Json? @db.JsonB
returns Json? @db.JsonB
authentication Json? @db.JsonB
pricing Json? @db.JsonB
frameworks String[] @db.Text
links Json? @db.JsonB
tags String[] @db.Text
status String? @db.VarChar(20)
aiAgent Json? @map("ai_agent") @db.JsonB
// Discovery Metadata
discoveryMethod String @map("discovery_method") @db.VarChar(20) // 'keyword' | 'changes-feed'
isOfficial Boolean @default(false) @map("is_official")
tier String @db.VarChar(20) // 'minimal' | 'rich'
// Metrics
npmDownloadsLastMonth Int? @default(0) @map("npm_downloads_last_month")
githubStars Int? @default(0) @map("github_stars")
qualityScore Decimal? @map("quality_score") @db.Decimal(3, 2) // 0.00 to 1.00
// Timestamps
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
// Relations
simulations Simulation[]
@@index([category])
@@index([isOfficial])
@@index([qualityScore])
@@index([npmDownloadsLastMonth])
@@index([createdAt])
@@map("tools")
}
/// Sync checkpoints - tracks progress of sync workers
model SyncCheckpoint {
id String @id @default(cuid())
source String @unique @db.VarChar(50) // 'changes-feed' | 'keyword-search' | 'metrics'
checkpoint Json @db.JsonB // Stores last sequence, timestamp, etc.
updatedAt DateTime @updatedAt @map("updated_at")
@@map("sync_checkpoints")
}
/// Sync logs - audit trail of sync operations
model SyncLog {
id String @id @default(cuid())
source String @db.VarChar(50) // 'changes-feed' | 'keyword-search' | 'metrics'
status String @db.VarChar(20) // 'success' | 'error' | 'partial'
processed Int @default(0) // Number of packages processed
skipped Int @default(0) // Number of packages skipped
errors Int @default(0) // Number of errors encountered
message String? @db.Text // Error message or summary
metadata Json? @db.JsonB // Additional context
createdAt DateTime @default(now()) @map("created_at")
@@index([source])
@@index([status])
@@index([createdAt])
@@map("sync_logs")
}
/// Simulations - tracks tool playground executions
model Simulation {
id String @id @default(cuid())
// Relations
toolId String @map("tool_id")
tool Tool @relation(fields: [toolId], references: [id], onDelete: Cascade)
// Request data
userPrompt String @map("user_prompt") @db.Text
parameters Json? @db.JsonB
ipAddress String? @map("ip_address") @db.VarChar(45)
userAgent String? @map("user_agent") @db.Text
// Results
status String @db.VarChar(20) // pending|running|success|error|timeout
executionTimeMs Int? @map("execution_time_ms")
output Json? @db.JsonB
error String? @db.Text
// AI metadata
agentSteps Int @default(0) @map("agent_steps")
model String? @db.VarChar(50)
// Relations
tokenUsage TokenUsage?
logs ExecutionLog[]
createdAt DateTime @default(now()) @map("created_at")
completedAt DateTime? @map("completed_at")
@@index([toolId])
@@index([status])
@@index([ipAddress, createdAt]) // For rate limiting
@@map("simulations")
}
/// Token usage - tracks token consumption per simulation
model TokenUsage {
id String @id @default(cuid())
simulationId String @unique @map("simulation_id")
simulation Simulation @relation(fields: [simulationId], references: [id], onDelete: Cascade)
inputTokens Int @default(0) @map("input_tokens")
toolDescTokens Int @default(0) @map("tool_desc_tokens")
schemaTokens Int @default(0) @map("schema_tokens")
outputTokens Int @default(0) @map("output_tokens")
totalTokens Int @default(0) @map("total_tokens")
estimatedCost Decimal? @map("estimated_cost") @db.Decimal(10, 6)
createdAt DateTime @default(now()) @map("created_at")
@@map("token_usage")
}
/// Execution logs - detailed logs for each simulation
model ExecutionLog {
id String @id @default(cuid())
simulationId String @map("simulation_id")
simulation Simulation @relation(fields: [simulationId], references: [id], onDelete: Cascade)
timestamp DateTime @default(now())
level String @db.VarChar(20) // info|warning|error|debug
event String @db.VarChar(50)
message String @db.Text
metadata Json? @db.JsonB
@@index([simulationId])
@@map("execution_logs")
}