All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 36s
CI / test-python-backend-compliance (push) Successful in 35s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 18s
Agents lag in app/(sdk)/sdk/agents/ (separater Route-Group) und erbte daher nicht das SDK-Layout aus app/sdk/layout.tsx. Verschoben nach app/sdk/agents/ damit SDKSidebar, ComplianceAdvisorWidget und SDKPipelineSidebar korrekt angezeigt werden. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
225 lines
9.3 KiB
TypeScript
225 lines
9.3 KiB
TypeScript
'use client'
|
|
|
|
import React, { useEffect, useState, useCallback } from 'react'
|
|
import Link from 'next/link'
|
|
|
|
interface AgentData {
|
|
id: string
|
|
name: string
|
|
description: string
|
|
color: string
|
|
icon: string
|
|
status: 'active' | 'inactive' | 'error'
|
|
version: string
|
|
stats: {
|
|
sessionsToday: number
|
|
avgResponseTime: string
|
|
successRate: string
|
|
}
|
|
}
|
|
|
|
interface AgentsResponse {
|
|
agents: AgentData[]
|
|
stats: {
|
|
total: number
|
|
active: number
|
|
inactive: number
|
|
error: number
|
|
totalSessions: number
|
|
avgResponseTime: string
|
|
}
|
|
timestamp: string
|
|
}
|
|
|
|
const ShieldIcon = () => (
|
|
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5}
|
|
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
|
|
</svg>
|
|
)
|
|
|
|
const PencilIcon = () => (
|
|
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5}
|
|
d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
|
</svg>
|
|
)
|
|
|
|
function getAgentIcon(icon: string) {
|
|
switch (icon) {
|
|
case 'shield': return <ShieldIcon />
|
|
case 'pencil': return <PencilIcon />
|
|
default: return <ShieldIcon />
|
|
}
|
|
}
|
|
|
|
function StatusBadge({ status }: { status: string }) {
|
|
const colors = {
|
|
active: 'bg-green-100 text-green-700',
|
|
inactive: 'bg-gray-100 text-gray-600',
|
|
error: 'bg-red-100 text-red-700',
|
|
}
|
|
const labels = { active: 'Aktiv', inactive: 'Inaktiv', error: 'Fehler' }
|
|
return (
|
|
<span className={`px-2 py-0.5 rounded-full text-xs font-medium ${colors[status as keyof typeof colors] || colors.inactive}`}>
|
|
{labels[status as keyof typeof labels] || status}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
export default function AgentsDashboardPage() {
|
|
const [data, setData] = useState<AgentsResponse | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
const loadAgents = useCallback(async () => {
|
|
try {
|
|
const res = await fetch('/api/sdk/agents')
|
|
if (res.ok) {
|
|
setData(await res.json())
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to load agents:', err)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
loadAgents()
|
|
const interval = setInterval(loadAgents, 30_000)
|
|
return () => clearInterval(interval)
|
|
}, [loadAgents])
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="p-8">
|
|
<div className="animate-pulse space-y-4">
|
|
<div className="h-8 bg-gray-200 rounded w-64" />
|
|
<div className="grid grid-cols-3 gap-4">
|
|
{[1, 2, 3].map(i => <div key={i} className="h-24 bg-gray-200 rounded-xl" />)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const stats = data?.stats
|
|
const agents = data?.agents || []
|
|
|
|
return (
|
|
<div className="p-8 max-w-6xl">
|
|
{/* Header */}
|
|
<div className="mb-8">
|
|
<h1 className="text-2xl font-bold text-gray-900">Compliance-Agenten</h1>
|
|
<p className="text-gray-500 mt-1">
|
|
Verwaltung und Konfiguration der KI-Agenten im Compliance SDK
|
|
</p>
|
|
</div>
|
|
|
|
{/* Quick Links */}
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-8">
|
|
<Link href="/sdk/agents/architecture" className="flex items-center gap-2 px-4 py-3 bg-white border border-gray-200 rounded-xl hover:border-purple-300 hover:bg-purple-50 transition-colors text-sm">
|
|
<svg className="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2" />
|
|
</svg>
|
|
Architektur
|
|
</Link>
|
|
<Link href="/sdk/agents/sessions" className="flex items-center gap-2 px-4 py-3 bg-white border border-gray-200 rounded-xl hover:border-purple-300 hover:bg-purple-50 transition-colors text-sm">
|
|
<svg className="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
|
</svg>
|
|
Sessions
|
|
</Link>
|
|
<Link href="/sdk/agents/statistics" className="flex items-center gap-2 px-4 py-3 bg-white border border-gray-200 rounded-xl hover:border-purple-300 hover:bg-purple-50 transition-colors text-sm">
|
|
<svg className="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
|
</svg>
|
|
Statistiken
|
|
</Link>
|
|
<Link href="/sdk/document-generator" className="flex items-center gap-2 px-4 py-3 bg-white border border-gray-200 rounded-xl hover:border-purple-300 hover:bg-purple-50 transition-colors text-sm">
|
|
<svg className="w-5 h-5 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
|
</svg>
|
|
Dokument-Generator
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Stats Bar */}
|
|
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-8">
|
|
<div className="bg-white border border-gray-200 rounded-xl px-4 py-3">
|
|
<div className="text-2xl font-bold text-gray-900">{stats?.total || 0}</div>
|
|
<div className="text-xs text-gray-500">Agenten gesamt</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-xl px-4 py-3">
|
|
<div className="text-2xl font-bold text-green-600">{stats?.active || 0}</div>
|
|
<div className="text-xs text-gray-500">Aktiv</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-xl px-4 py-3">
|
|
<div className="text-2xl font-bold text-red-600">{stats?.error || 0}</div>
|
|
<div className="text-xs text-gray-500">Fehler</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-xl px-4 py-3">
|
|
<div className="text-2xl font-bold text-gray-900">{stats?.totalSessions || 0}</div>
|
|
<div className="text-xs text-gray-500">Sessions heute</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-xl px-4 py-3">
|
|
<div className="text-2xl font-bold text-gray-900">{stats?.avgResponseTime || '—'}</div>
|
|
<div className="text-xs text-gray-500">Avg. Antwortzeit</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-xl px-4 py-3">
|
|
<div className="text-2xl font-bold text-gray-900">6</div>
|
|
<div className="text-xs text-gray-500">RAG-Sammlungen</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Agent Grid */}
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
{agents.map((agent) => (
|
|
<Link
|
|
key={agent.id}
|
|
href={`/sdk/agents/${agent.id}`}
|
|
className="bg-white border border-gray-200 rounded-2xl p-6 hover:border-purple-300 hover:shadow-lg transition-all group"
|
|
>
|
|
<div className="flex items-start justify-between mb-4">
|
|
<div className="flex items-center gap-3">
|
|
<div
|
|
className="w-12 h-12 rounded-xl flex items-center justify-center text-white"
|
|
style={{ backgroundColor: agent.color }}
|
|
>
|
|
{getAgentIcon(agent.icon)}
|
|
</div>
|
|
<div>
|
|
<h2 className="font-semibold text-gray-900 group-hover:text-purple-700 transition-colors">
|
|
{agent.name}
|
|
</h2>
|
|
<div className="text-xs text-gray-400">v{agent.version}</div>
|
|
</div>
|
|
</div>
|
|
<StatusBadge status={agent.status} />
|
|
</div>
|
|
|
|
<p className="text-sm text-gray-600 mb-4 line-clamp-2">
|
|
{agent.description}
|
|
</p>
|
|
|
|
<div className="grid grid-cols-3 gap-3 pt-3 border-t border-gray-100">
|
|
<div>
|
|
<div className="text-lg font-semibold text-gray-900">{agent.stats.sessionsToday}</div>
|
|
<div className="text-xs text-gray-500">Sessions</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-lg font-semibold text-gray-900">{agent.stats.avgResponseTime}</div>
|
|
<div className="text-xs text-gray-500">Avg. Zeit</div>
|
|
</div>
|
|
<div>
|
|
<div className="text-lg font-semibold text-gray-900">{agent.stats.successRate}</div>
|
|
<div className="text-xs text-gray-500">Erfolgsrate</div>
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|