import { NextRequest, NextResponse } from 'next/server' import * as fs from 'fs/promises' import * as path from 'path' /** * Individual Agent API * * GET - Get agent details including SOUL content * PUT - Update agent configuration * DELETE - Delete agent */ const AGENT_CORE_PATH = process.env.AGENT_CORE_PATH || '/app/agent-core' const SOUL_PATH = path.join(AGENT_CORE_PATH, 'soul') interface AgentDetails { id: string name: string description: string soulFile: string soulContent: string color: string icon: string status: 'running' | 'paused' | 'stopped' | 'error' activeSessions: number totalProcessed: number avgResponseTime: number errorRate: number lastActivity: string version: string createdAt: string updatedAt: string } // Agent metadata (in production, store in database) const agentMetadata: Record> = { 'tutor-agent': { name: 'TutorAgent', description: 'Lernbegleitung und Fragen beantworten', color: '#3b82f6', icon: 'brain' }, 'grader-agent': { name: 'GraderAgent', description: 'Klausur-Korrektur und Bewertung', color: '#10b981', icon: 'bot' }, 'quality-judge': { name: 'QualityJudge', description: 'BQAS Qualitaetspruefung', color: '#f59e0b', icon: 'settings' }, 'alert-agent': { name: 'AlertAgent', description: 'Monitoring und Benachrichtigungen', color: '#ef4444', icon: 'alert' }, 'orchestrator': { name: 'Orchestrator', description: 'Task-Koordination und Routing', color: '#8b5cf6', icon: 'message' } } // Read SOUL file content async function readSoulFile(agentId: string): Promise { const soulFile = `${agentId}.soul.md` const soulFilePath = path.join(SOUL_PATH, soulFile) try { const content = await fs.readFile(soulFilePath, 'utf-8') return content } catch { return null } } // Get file stats async function getFileStats(agentId: string): Promise<{ createdAt: string; updatedAt: string } | null> { const soulFile = `${agentId}.soul.md` const soulFilePath = path.join(SOUL_PATH, soulFile) try { const stats = await fs.stat(soulFilePath) return { createdAt: stats.birthtime.toISOString(), updatedAt: stats.mtime.toISOString() } } catch { return null } } // Mock agent stats (in production, query from Redis/PostgreSQL) function getMockStats(agentId: string) { const mockStats: Record = { 'tutor-agent': { activeSessions: 12, totalProcessed: 1847, avgResponseTime: 234, errorRate: 0.3 }, 'grader-agent': { activeSessions: 3, totalProcessed: 456, avgResponseTime: 1205, errorRate: 0.5 }, 'quality-judge': { activeSessions: 8, totalProcessed: 3291, avgResponseTime: 89, errorRate: 0.1 }, 'alert-agent': { activeSessions: 1, totalProcessed: 892, avgResponseTime: 45, errorRate: 0.0 }, 'orchestrator': { activeSessions: 24, totalProcessed: 8934, avgResponseTime: 12, errorRate: 0.2 } } return mockStats[agentId] || { activeSessions: 0, totalProcessed: 0, avgResponseTime: 0, errorRate: 0 } } // GET - Get agent details export async function GET( request: NextRequest, { params }: { params: Promise<{ agentId: string }> } ) { try { const { agentId } = await params const soulContent = await readSoulFile(agentId) if (!soulContent) { return NextResponse.json( { error: 'Agent not found' }, { status: 404 } ) } const fileStats = await getFileStats(agentId) const metadata = agentMetadata[agentId] || {} const stats = getMockStats(agentId) const agent: AgentDetails = { id: agentId, name: metadata.name || agentId.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(''), description: metadata.description || 'Custom agent', soulFile: `${agentId}.soul.md`, soulContent, color: metadata.color || '#6b7280', icon: metadata.icon || 'bot', status: 'running', ...stats, lastActivity: 'just now', version: '1.0.0', createdAt: fileStats?.createdAt || new Date().toISOString(), updatedAt: fileStats?.updatedAt || new Date().toISOString() } return NextResponse.json(agent) } catch (error) { console.error('Error fetching agent:', error) return NextResponse.json( { error: error instanceof Error ? error.message : 'Failed to fetch agent' }, { status: 500 } ) } } // PUT - Update agent export async function PUT( request: NextRequest, { params }: { params: Promise<{ agentId: string }> } ) { try { const { agentId } = await params const body = await request.json() const { soulContent, name, description, color, icon } = body const soulFile = `${agentId}.soul.md` const soulFilePath = path.join(SOUL_PATH, soulFile) // Check if agent exists try { await fs.access(soulFilePath) } catch { return NextResponse.json( { error: 'Agent not found' }, { status: 404 } ) } // Update SOUL file if content provided if (soulContent) { // Create backup before updating const backupPath = path.join(SOUL_PATH, '.backups', `${agentId}-${Date.now()}.soul.md`) try { await fs.mkdir(path.dirname(backupPath), { recursive: true }) const currentContent = await fs.readFile(soulFilePath, 'utf-8') await fs.writeFile(backupPath, currentContent, 'utf-8') } catch { // Backup failed, continue anyway } // Write new content await fs.writeFile(soulFilePath, soulContent, 'utf-8') } // In production, update metadata in database // For now, just return success return NextResponse.json({ success: true, message: `Agent ${agentId} updated successfully`, agent: { id: agentId, name: name || agentMetadata[agentId]?.name || agentId, description: description || agentMetadata[agentId]?.description || '', soulFile, color: color || agentMetadata[agentId]?.color || '#6b7280', icon: icon || agentMetadata[agentId]?.icon || 'bot', updatedAt: new Date().toISOString() } }) } catch (error) { console.error('Error updating agent:', error) return NextResponse.json( { error: error instanceof Error ? error.message : 'Failed to update agent' }, { status: 500 } ) } } // DELETE - Delete agent export async function DELETE( request: NextRequest, { params }: { params: Promise<{ agentId: string }> } ) { try { const { agentId } = await params // Don't allow deleting core agents const coreAgents = ['tutor-agent', 'grader-agent', 'quality-judge', 'alert-agent', 'orchestrator'] if (coreAgents.includes(agentId)) { return NextResponse.json( { error: 'Cannot delete core system agent' }, { status: 403 } ) } const soulFile = `${agentId}.soul.md` const soulFilePath = path.join(SOUL_PATH, soulFile) // Check if agent exists try { await fs.access(soulFilePath) } catch { return NextResponse.json( { error: 'Agent not found' }, { status: 404 } ) } // Create backup before deleting const backupPath = path.join(SOUL_PATH, '.deleted', `${agentId}-${Date.now()}.soul.md`) try { await fs.mkdir(path.dirname(backupPath), { recursive: true }) const content = await fs.readFile(soulFilePath, 'utf-8') await fs.writeFile(backupPath, content, 'utf-8') } catch { // Backup failed, continue anyway } // Delete the file await fs.unlink(soulFilePath) return NextResponse.json({ success: true, message: `Agent ${agentId} deleted successfully` }) } catch (error) { console.error('Error deleting agent:', error) return NextResponse.json( { error: error instanceof Error ? error.message : 'Failed to delete agent' }, { status: 500 } ) } }