feat: add AI Agents feature with multi-provider support and documentation
- Add Agent, AgentCollection, AgentTool, UserApiKey, Conversation, Message models to Prisma schema - Create agent types and Zod schemas in @tpmjs/types - Implement AES-256 API key encryption utilities - Add CRUD API endpoints for agents, tools, collections, and user API keys - Create conversation streaming endpoint with SSE events - Build agent tool builder to merge collections and individual tools - Add dashboard pages: agents list, new agent form, agent detail/edit, chat interface - Add API keys settings page for managing provider keys - Add comprehensive Agents documentation section to /docs - Update navigation to include Agents link in header and mobile menu - Add new icons: terminal, puzzle, message, key, info, send Supported providers: OpenAI, Anthropic, Google, Groq, Mistral
This commit is contained in:
parent
4cbd84edb8
commit
552f319583
28 changed files with 5082 additions and 2 deletions
|
|
@ -96,6 +96,7 @@ model Tool {
|
|||
simulations Simulation[]
|
||||
healthChecks HealthCheck[]
|
||||
collections CollectionTool[]
|
||||
agents AgentTool[]
|
||||
|
||||
@@unique([packageId, name])
|
||||
@@index([qualityScore])
|
||||
|
|
@ -333,6 +334,8 @@ model User {
|
|||
sessions Session[]
|
||||
accounts Account[]
|
||||
collections Collection[]
|
||||
agents Agent[]
|
||||
apiKeys UserApiKey[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
|
|
@ -412,6 +415,7 @@ model Collection {
|
|||
|
||||
// Relations
|
||||
tools CollectionTool[]
|
||||
agents AgentCollection[]
|
||||
|
||||
// Unique constraint: user can't have duplicate collection names
|
||||
@@unique([userId, name])
|
||||
|
|
@ -446,3 +450,193 @@ model CollectionTool {
|
|||
@@index([toolId])
|
||||
@@map("collection_tools")
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Agent Models
|
||||
// ============================================================================
|
||||
|
||||
/// AI Provider enum - supported LLM providers
|
||||
enum AIProvider {
|
||||
OPENAI
|
||||
ANTHROPIC
|
||||
GOOGLE
|
||||
GROQ
|
||||
MISTRAL
|
||||
}
|
||||
|
||||
/// Message role enum - conversation message types
|
||||
enum MessageRole {
|
||||
USER
|
||||
ASSISTANT
|
||||
TOOL
|
||||
SYSTEM
|
||||
}
|
||||
|
||||
/// Agent - user-owned AI agent configurations
|
||||
model Agent {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Owner relationship
|
||||
userId String @map("user_id")
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Agent identity
|
||||
uid String @unique @db.VarChar(50) // URL-friendly identifier
|
||||
name String @db.VarChar(100)
|
||||
description String? @db.VarChar(500)
|
||||
|
||||
// Model configuration
|
||||
provider AIProvider
|
||||
modelId String @map("model_id") @db.VarChar(100)
|
||||
systemPrompt String? @map("system_prompt") @db.Text
|
||||
temperature Float @default(0.7)
|
||||
maxToolCallsPerTurn Int @default(20) @map("max_tool_calls_per_turn")
|
||||
maxMessagesInContext Int @default(10) @map("max_messages_in_context")
|
||||
|
||||
// Visibility
|
||||
isPublic Boolean @default(false) @map("is_public")
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// Relations
|
||||
collections AgentCollection[]
|
||||
tools AgentTool[]
|
||||
conversations Conversation[]
|
||||
|
||||
@@unique([userId, name])
|
||||
@@index([userId])
|
||||
@@index([uid])
|
||||
@@index([isPublic])
|
||||
@@index([createdAt])
|
||||
@@map("agents")
|
||||
}
|
||||
|
||||
/// AgentCollection - junction table for Agent -> Collection (many-to-many)
|
||||
model AgentCollection {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Relationships
|
||||
agentId String @map("agent_id")
|
||||
agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade)
|
||||
collectionId String @map("collection_id")
|
||||
collection Collection @relation(fields: [collectionId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Ordering
|
||||
position Int @default(0)
|
||||
|
||||
// Timestamps
|
||||
addedAt DateTime @default(now()) @map("added_at")
|
||||
|
||||
@@unique([agentId, collectionId])
|
||||
@@index([agentId])
|
||||
@@index([collectionId])
|
||||
@@map("agent_collections")
|
||||
}
|
||||
|
||||
/// AgentTool - junction table for Agent -> Tool (many-to-many)
|
||||
model AgentTool {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Relationships
|
||||
agentId String @map("agent_id")
|
||||
agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade)
|
||||
toolId String @map("tool_id")
|
||||
tool Tool @relation(fields: [toolId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Ordering
|
||||
position Int @default(0)
|
||||
|
||||
// Timestamps
|
||||
addedAt DateTime @default(now()) @map("added_at")
|
||||
|
||||
@@unique([agentId, toolId])
|
||||
@@index([agentId])
|
||||
@@index([toolId])
|
||||
@@map("agent_tools")
|
||||
}
|
||||
|
||||
/// UserApiKey - encrypted API keys per user per provider
|
||||
model UserApiKey {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Owner relationship
|
||||
userId String @map("user_id")
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Provider identification
|
||||
provider AIProvider
|
||||
|
||||
// Encrypted key storage
|
||||
encryptedKey String @map("encrypted_key") @db.Text
|
||||
keyIv String @map("key_iv") @db.VarChar(32)
|
||||
keyHint String? @map("key_hint") @db.VarChar(10) // Last 4 chars
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
@@unique([userId, provider])
|
||||
@@index([userId])
|
||||
@@map("user_api_keys")
|
||||
}
|
||||
|
||||
/// Conversation - chat session with an agent
|
||||
model Conversation {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Agent relationship
|
||||
agentId String @map("agent_id")
|
||||
agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Conversation identity
|
||||
slug String @db.VarChar(100) // User-chosen unique ID
|
||||
|
||||
// Metadata
|
||||
title String? @db.VarChar(200)
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
updatedAt DateTime @updatedAt @map("updated_at")
|
||||
|
||||
// Relations
|
||||
messages Message[]
|
||||
|
||||
@@unique([agentId, slug])
|
||||
@@index([agentId])
|
||||
@@index([createdAt])
|
||||
@@map("conversations")
|
||||
}
|
||||
|
||||
/// Message - individual message in a conversation
|
||||
model Message {
|
||||
id String @id @default(cuid())
|
||||
|
||||
// Conversation relationship
|
||||
conversationId String @map("conversation_id")
|
||||
conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
|
||||
|
||||
// Message content
|
||||
role MessageRole
|
||||
content String @db.Text
|
||||
|
||||
// Tool call metadata (for role=ASSISTANT with tool calls)
|
||||
toolCalls Json? @map("tool_calls") @db.JsonB
|
||||
|
||||
// Tool result metadata (for role=TOOL)
|
||||
toolCallId String? @map("tool_call_id") @db.VarChar(100)
|
||||
toolName String? @map("tool_name") @db.VarChar(200)
|
||||
toolResult Json? @map("tool_result") @db.JsonB
|
||||
|
||||
// Token tracking
|
||||
inputTokens Int? @map("input_tokens")
|
||||
outputTokens Int? @map("output_tokens")
|
||||
|
||||
// Timestamps
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
|
||||
@@index([conversationId])
|
||||
@@index([createdAt])
|
||||
@@map("messages")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue