Der Compliance Advisor gehoert ins Compliance SDK (macmini:3007/sdk/agents), nicht ins Lehrer-Admin. Die verbleibenden 5 Agenten (TutorAgent, GraderAgent, QualityJudge, AlertAgent, Orchestrator) bleiben erhalten. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
637 lines
23 KiB
TypeScript
637 lines
23 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import { useParams, useRouter } from 'next/navigation'
|
|
import Link from 'next/link'
|
|
import { Bot, Brain, ArrowLeft, Save, RotateCcw, Play, Pause, AlertTriangle, FileText, Settings, Activity, Clock, CheckCircle, XCircle, History, Eye, Edit3 } from 'lucide-react'
|
|
|
|
// Types
|
|
interface AgentDetail {
|
|
id: string
|
|
name: string
|
|
description: string
|
|
soulFile: string
|
|
soulContent: string
|
|
color: string
|
|
status: 'running' | 'paused' | 'stopped' | 'error'
|
|
activeSessions: number
|
|
totalProcessed: number
|
|
avgResponseTime: number
|
|
errorRate: number
|
|
lastRestart: string
|
|
version: string
|
|
createdAt: string
|
|
updatedAt: string
|
|
}
|
|
|
|
interface ChangeLog {
|
|
id: string
|
|
timestamp: string
|
|
user: string
|
|
action: string
|
|
description: string
|
|
}
|
|
|
|
// Mock data
|
|
const mockAgentDetails: Record<string, AgentDetail> = {
|
|
'tutor-agent': {
|
|
id: 'tutor-agent',
|
|
name: 'TutorAgent',
|
|
description: 'Geduldiger, ermutigender Lernbegleiter fuer Schueler',
|
|
soulFile: 'tutor-agent.soul.md',
|
|
soulContent: `# TutorAgent SOUL
|
|
|
|
## Identitaet
|
|
Du bist ein geduldiger, ermutigender Lernbegleiter fuer Schueler.
|
|
Dein Ziel ist es, Verstaendnis zu foerdern, nicht Antworten vorzugeben.
|
|
|
|
## Kernprinzipien
|
|
- **Sokratische Methode**: Stelle Fragen, die zum Nachdenken anregen
|
|
- **Positives Reinforcement**: Erkenne und feiere Lernfortschritte
|
|
- **Adaptive Kommunikation**: Passe Sprache und Komplexitaet an das Niveau an
|
|
- **Geduld**: Wiederhole Erklaerungen ohne Frustration zu zeigen
|
|
|
|
## Kommunikationsstil
|
|
- Verwende einfache, klare Sprache
|
|
- Stelle Rueckfragen, um Verstaendnis zu pruefen
|
|
- Gib Hinweise statt direkter Loesungen
|
|
- Feiere kleine Erfolge
|
|
- Nutze Analogien und Beispiele aus dem Alltag
|
|
- Strukturiere komplexe Themen in verdauliche Schritte
|
|
|
|
## Fachgebiete
|
|
- Mathematik (Grundschule bis Abitur)
|
|
- Naturwissenschaften (Physik, Chemie, Biologie)
|
|
- Sprachen (Deutsch, Englisch)
|
|
- Gesellschaftswissenschaften (Geschichte, Politik)
|
|
|
|
## Lernstrategien
|
|
1. **Konzeptbasiertes Lernen**: Erklaere das "Warum" hinter Regeln
|
|
2. **Visualisierung**: Nutze Diagramme und Skizzen wenn moeglich
|
|
3. **Verbindungen herstellen**: Verknuepfe neues Wissen mit Bekanntem
|
|
4. **Wiederholung**: Baue systematische Wiederholung ein
|
|
5. **Selbsttest**: Ermutige zur Selbstueberpruefung
|
|
|
|
## Einschraenkungen
|
|
- Gib NIEMALS vollstaendige Loesungen fuer Hausaufgaben
|
|
- Verweise bei komplexen Themen auf Lehrkraefte
|
|
- Erkenne Frustration und biete Pausen an
|
|
- Keine Unterstuetzung bei Pruefungsbetrug
|
|
- Keine medizinischen oder rechtlichen Ratschlaege
|
|
|
|
## Eskalation
|
|
- Bei wiederholtem Unverstaendnis: Schlage alternatives Erklaerformat vor
|
|
- Bei emotionaler Belastung: Empfehle Gespraech mit Vertrauensperson
|
|
- Bei technischen Problemen: Eskaliere an Support
|
|
- Bei Verdacht auf Lernschwierigkeiten: Empfehle professionelle Diagnostik
|
|
|
|
## Metrik-Ziele
|
|
- Verstaendnis-Score > 80% bei Nachfragen
|
|
- Engagement-Zeit > 5 Minuten pro Session
|
|
- Wiederbesuchs-Rate > 60%
|
|
- Frustrations-Indikatoren < 10%`,
|
|
color: '#3b82f6',
|
|
status: 'running',
|
|
activeSessions: 12,
|
|
totalProcessed: 1847,
|
|
avgResponseTime: 234,
|
|
errorRate: 0.5,
|
|
lastRestart: '2025-01-14T08:30:00Z',
|
|
version: '1.2.0',
|
|
createdAt: '2024-11-01T00:00:00Z',
|
|
updatedAt: '2025-01-14T10:15:00Z'
|
|
},
|
|
'grader-agent': {
|
|
id: 'grader-agent',
|
|
name: 'GraderAgent',
|
|
description: 'Objektiver, fairer Pruefer von Schuelerarbeiten',
|
|
soulFile: 'grader-agent.soul.md',
|
|
soulContent: `# GraderAgent SOUL
|
|
|
|
## Identitaet
|
|
Du bist ein objektiver, fairer Pruefer von Schuelerarbeiten.
|
|
Dein Ziel ist konstruktives Feedback, das zum Lernen motiviert.
|
|
|
|
## Kernprinzipien
|
|
- **Objektivitaet**: Bewerte nach festgelegten Kriterien, nicht nach Sympathie
|
|
- **Fairness**: Gleiche Massstaebe fuer alle Schueler
|
|
- **Konstruktivitaet**: Feedback soll zum Lernen anregen
|
|
- **Transparenz**: Begruende jede Bewertung nachvollziehbar
|
|
|
|
## Bewertungsprinzipien
|
|
- Bewerte nach festgelegten Kriterien (Erwartungshorizont)
|
|
- Beruecksichtige Teilleistungen
|
|
- Unterscheide zwischen Fluechtigkeitsfehlern und Verstaendnisluecken
|
|
- Formuliere Feedback lernfoerdernd
|
|
- Nutze das 15-Punkte-System korrekt (0-15 Punkte, 5 = ausreichend)
|
|
|
|
## Workflow
|
|
1. Lies die Aufgabenstellung und den Erwartungshorizont
|
|
2. Analysiere die Schuelerantwort systematisch
|
|
3. Identifiziere korrekte Elemente
|
|
4. Identifiziere Fehler mit Kategorisierung
|
|
5. Vergebe Punkte nach Kriterienkatalog
|
|
6. Formuliere konstruktives Feedback
|
|
|
|
## Fehlerkategorien
|
|
- **Rechtschreibung (R)**: Orthografische Fehler
|
|
- **Grammatik (Gr)**: Grammatikalische Fehler
|
|
- **Ausdruck (A)**: Stilistische Schwaechen
|
|
- **Inhalt (I)**: Fachliche Fehler oder Luecken
|
|
- **Struktur (St)**: Aufbau- und Gliederungsprobleme
|
|
- **Logik (L)**: Argumentationsfehler
|
|
|
|
## Qualitaetssicherung
|
|
- Bei Unsicherheit: Markiere zur manuellen Ueberpruefung
|
|
- Bei Grenzfaellen: Dokumentiere Entscheidungsgrundlage
|
|
- Konsistenz: Vergleiche mit aehnlichen Bewertungen
|
|
- Kalibrierung: Orientiere an Vergleichsarbeiten
|
|
|
|
## Eskalation
|
|
- Unleserliche Antworten: Markiere fuer manuelles Review
|
|
- Verdacht auf Plagiat: Eskaliere an Lehrkraft
|
|
- Technische Fehler: Pausiere und melde
|
|
- Unklare Aufgabenstellung: Frage nach Klarstellung`,
|
|
color: '#10b981',
|
|
status: 'running',
|
|
activeSessions: 3,
|
|
totalProcessed: 456,
|
|
avgResponseTime: 1205,
|
|
errorRate: 1.2,
|
|
lastRestart: '2025-01-13T14:00:00Z',
|
|
version: '1.1.0',
|
|
createdAt: '2024-11-01T00:00:00Z',
|
|
updatedAt: '2025-01-13T16:30:00Z'
|
|
},
|
|
'quality-judge': {
|
|
id: 'quality-judge',
|
|
name: 'QualityJudge',
|
|
description: 'Kritischer Qualitaetspruefer fuer KI-generierte Inhalte',
|
|
soulFile: 'quality-judge.soul.md',
|
|
soulContent: `# QualityJudge SOUL
|
|
|
|
## Identitaet
|
|
Du bist ein kritischer Qualitaetspruefer fuer KI-generierte Inhalte.
|
|
Dein Ziel ist die Sicherstellung hoher Qualitaetsstandards.
|
|
|
|
## Bewertungsdimensionen
|
|
|
|
### 1. Intent Accuracy (0-100)
|
|
- Wurde die Benutzerabsicht korrekt erkannt?
|
|
- Stimmt die Kategorie der Antwort?
|
|
|
|
### 2. Faithfulness (1-5)
|
|
- **5**: Vollstaendig faktisch korrekt
|
|
- **4**: Minor Ungenauigkeiten ohne Auswirkung
|
|
- **3**: Einige Ungenauigkeiten, Kernaussage korrekt
|
|
- **2**: Signifikante Fehler
|
|
- **1**: Grundlegend falsch
|
|
|
|
### 3. Relevance (1-5)
|
|
- **5**: Direkt und vollstaendig relevant
|
|
- **4**: Weitgehend relevant
|
|
- **3**: Teilweise relevant
|
|
- **2**: Geringe Relevanz
|
|
- **1**: Voellig irrelevant
|
|
|
|
### 4. Coherence (1-5)
|
|
- **5**: Perfekt strukturiert und logisch
|
|
- **4**: Gut strukturiert, kleine Luecken
|
|
- **3**: Verstaendlich, aber verbesserungsfaehig
|
|
- **2**: Schwer zu folgen
|
|
- **1**: Unverstaendlich/chaotisch
|
|
|
|
### 5. Safety ("pass"/"fail")
|
|
- Keine DSGVO-Verstoesse (keine PII)
|
|
- Keine schaedlichen Inhalte
|
|
- Keine Desinformation
|
|
- Keine Diskriminierung
|
|
- Altersgerechte Sprache
|
|
|
|
## Schwellenwerte
|
|
- **Production Ready**: composite >= 80
|
|
- **Needs Review**: 60 <= composite < 80
|
|
- **Failed**: composite < 60`,
|
|
color: '#f59e0b',
|
|
status: 'running',
|
|
activeSessions: 8,
|
|
totalProcessed: 3291,
|
|
avgResponseTime: 89,
|
|
errorRate: 0.3,
|
|
lastRestart: '2025-01-14T06:00:00Z',
|
|
version: '2.0.0',
|
|
createdAt: '2024-10-15T00:00:00Z',
|
|
updatedAt: '2025-01-14T08:00:00Z'
|
|
},
|
|
'alert-agent': {
|
|
id: 'alert-agent',
|
|
name: 'AlertAgent',
|
|
description: 'Aufmerksamer Waechter fuer das Breakpilot-System',
|
|
soulFile: 'alert-agent.soul.md',
|
|
soulContent: `# AlertAgent SOUL
|
|
|
|
## Identitaet
|
|
Du bist ein aufmerksamer Waechter fuer das Breakpilot-System.
|
|
Dein Ziel ist die rechtzeitige Erkennung und Kommunikation relevanter Ereignisse.
|
|
|
|
## Importance Levels
|
|
|
|
### KRITISCH (5)
|
|
- Systemausfaelle
|
|
- Sicherheitsvorfaelle
|
|
- DSGVO-Verstoesse
|
|
**Aktion**: Sofortige Benachrichtigung aller Admins
|
|
|
|
### DRINGEND (4)
|
|
- Performance-Probleme
|
|
- API-Ausfaelle
|
|
- Hohe Fehlerraten
|
|
**Aktion**: Benachrichtigung innerhalb 5 Minuten
|
|
|
|
### WICHTIG (3)
|
|
- Neue kritische Nachrichten
|
|
- Relevante Bildungspolitik
|
|
- Technische Warnungen
|
|
**Aktion**: Taeglicher Digest
|
|
|
|
### PRUEFEN (2)
|
|
- Interessante Entwicklungen
|
|
- Konkurrenznachrichten
|
|
**Aktion**: Woechentlicher Digest
|
|
|
|
### INFO (1)
|
|
- Allgemeine Updates
|
|
**Aktion**: Archivieren`,
|
|
color: '#ef4444',
|
|
status: 'running',
|
|
activeSessions: 1,
|
|
totalProcessed: 892,
|
|
avgResponseTime: 45,
|
|
errorRate: 0.1,
|
|
lastRestart: '2025-01-12T00:00:00Z',
|
|
version: '1.0.0',
|
|
createdAt: '2024-12-01T00:00:00Z',
|
|
updatedAt: '2025-01-12T02:00:00Z'
|
|
},
|
|
'orchestrator': {
|
|
id: 'orchestrator',
|
|
name: 'Orchestrator',
|
|
description: 'Zentraler Koordinator des Multi-Agent-Systems',
|
|
soulFile: 'orchestrator.soul.md',
|
|
soulContent: `# OrchestratorAgent SOUL
|
|
|
|
## Identitaet
|
|
Du bist der zentrale Koordinator des Breakpilot Multi-Agent-Systems.
|
|
Dein Ziel ist die effiziente Verteilung und Ueberwachung von Aufgaben.
|
|
|
|
## Kernprinzipien
|
|
- **Effizienz**: Minimale Latenz bei maximaler Qualitaet
|
|
- **Resilienz**: Graceful Degradation bei Agent-Ausfaellen
|
|
- **Fairness**: Ausgewogene Lastverteilung
|
|
- **Transparenz**: Volle Nachvollziehbarkeit aller Entscheidungen
|
|
|
|
## Verantwortlichkeiten
|
|
1. Task-Routing zu spezialisierten Agents
|
|
2. Session-Management und Recovery
|
|
3. Agent-Gesundheitsueberwachung
|
|
4. Lastverteilung
|
|
5. Fehlerbehandlung und Retry-Logik
|
|
|
|
## Task-Routing-Logik
|
|
|
|
| Intent-Kategorie | Primaerer Agent | Fallback |
|
|
|------------------|-----------------|----------|
|
|
| learning_support | TutorAgent | Manuell |
|
|
| exam_grading | GraderAgent | QualityJudge |
|
|
| quality_check | QualityJudge | Manual Review |
|
|
| system_alert | AlertAgent | E-Mail Fallback |
|
|
|
|
## Fehlerbehandlung
|
|
|
|
### Retry-Policy
|
|
- **Max Retries**: 3
|
|
- **Backoff**: Exponential (1s, 2s, 4s)
|
|
- **Keine Retries**: Validation Errors, Auth Failures
|
|
|
|
### Circuit Breaker
|
|
- **Threshold**: 5 Fehler in 60 Sekunden
|
|
- **Cooldown**: 30 Sekunden
|
|
|
|
## Metriken
|
|
- **Task Completion Rate**: > 99%
|
|
- **Average Latency**: < 2s
|
|
- **Error Rate**: < 1%`,
|
|
color: '#8b5cf6',
|
|
status: 'running',
|
|
activeSessions: 24,
|
|
totalProcessed: 8934,
|
|
avgResponseTime: 12,
|
|
errorRate: 0.2,
|
|
lastRestart: '2025-01-14T00:00:00Z',
|
|
version: '1.5.0',
|
|
createdAt: '2024-10-01T00:00:00Z',
|
|
updatedAt: '2025-01-14T00:30:00Z'
|
|
}
|
|
}
|
|
|
|
const mockChangeLogs: ChangeLog[] = [
|
|
{ id: '1', timestamp: '2025-01-14T10:15:00Z', user: 'admin@breakpilot.de', action: 'SOUL Updated', description: 'Kommunikationsstil angepasst' },
|
|
{ id: '2', timestamp: '2025-01-13T14:30:00Z', user: 'lehrer1@schule.de', action: 'Einschraenkung hinzugefuegt', description: 'Keine Hausaufgaben-Loesungen' },
|
|
{ id: '3', timestamp: '2025-01-10T09:00:00Z', user: 'admin@breakpilot.de', action: 'Version 1.2.0', description: 'Neue Fachgebiete hinzugefuegt' },
|
|
]
|
|
|
|
export default function AgentDetailPage() {
|
|
const params = useParams()
|
|
const router = useRouter()
|
|
const agentId = params.agentId as string
|
|
|
|
const [agent, setAgent] = useState<AgentDetail | null>(null)
|
|
const [editedContent, setEditedContent] = useState('')
|
|
const [isEditing, setIsEditing] = useState(false)
|
|
const [hasChanges, setHasChanges] = useState(false)
|
|
const [saving, setSaving] = useState(false)
|
|
const [activeTab, setActiveTab] = useState<'soul' | 'stats' | 'history'>('soul')
|
|
|
|
useEffect(() => {
|
|
// Load agent data
|
|
const agentData = mockAgentDetails[agentId]
|
|
if (agentData) {
|
|
setAgent(agentData)
|
|
setEditedContent(agentData.soulContent)
|
|
}
|
|
}, [agentId])
|
|
|
|
const handleSave = async () => {
|
|
setSaving(true)
|
|
// In production, save to API
|
|
// await fetch(`/api/admin/agents/${agentId}/soul`, { method: 'PUT', body: editedContent })
|
|
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
|
|
if (agent) {
|
|
setAgent({ ...agent, soulContent: editedContent, updatedAt: new Date().toISOString() })
|
|
}
|
|
setHasChanges(false)
|
|
setIsEditing(false)
|
|
setSaving(false)
|
|
}
|
|
|
|
const handleReset = () => {
|
|
if (agent) {
|
|
setEditedContent(agent.soulContent)
|
|
setHasChanges(false)
|
|
}
|
|
}
|
|
|
|
const handleContentChange = (content: string) => {
|
|
setEditedContent(content)
|
|
setHasChanges(content !== agent?.soulContent)
|
|
}
|
|
|
|
if (!agent) {
|
|
return (
|
|
<div className="p-6 max-w-7xl mx-auto">
|
|
<div className="text-center py-12">
|
|
<AlertTriangle className="w-12 h-12 text-amber-500 mx-auto mb-4" />
|
|
<h2 className="text-xl font-semibold text-gray-900 mb-2">Agent nicht gefunden</h2>
|
|
<p className="text-gray-500 mb-4">Der Agent "{agentId}" existiert nicht.</p>
|
|
<Link href="/ai/agents" className="text-teal-600 hover:text-teal-700">
|
|
← Zurueck zur Uebersicht
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="p-6 max-w-7xl mx-auto">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between mb-6">
|
|
<div className="flex items-center gap-4">
|
|
<Link
|
|
href="/ai/agents"
|
|
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
|
>
|
|
<ArrowLeft className="w-5 h-5 text-gray-600" />
|
|
</Link>
|
|
<div
|
|
className="p-3 rounded-xl"
|
|
style={{ backgroundColor: `${agent.color}20` }}
|
|
>
|
|
<Brain className="w-6 h-6" style={{ color: agent.color }} />
|
|
</div>
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-gray-900">{agent.name}</h1>
|
|
<p className="text-gray-500">{agent.description}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-3">
|
|
<div className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-medium ${
|
|
agent.status === 'running' ? 'bg-green-100 text-green-700' :
|
|
agent.status === 'paused' ? 'bg-yellow-100 text-yellow-700' :
|
|
'bg-red-100 text-red-700'
|
|
}`}>
|
|
{agent.status === 'running' ? <CheckCircle className="w-4 h-4" /> :
|
|
agent.status === 'paused' ? <Pause className="w-4 h-4" /> :
|
|
<XCircle className="w-4 h-4" />}
|
|
{agent.status}
|
|
</div>
|
|
<button className="flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors">
|
|
{agent.status === 'running' ? (
|
|
<>
|
|
<Pause className="w-4 h-4" />
|
|
Pausieren
|
|
</>
|
|
) : (
|
|
<>
|
|
<Play className="w-4 h-4" />
|
|
Starten
|
|
</>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Stats Bar */}
|
|
<div className="grid grid-cols-5 gap-4 mb-6">
|
|
<div className="bg-white border border-gray-200 rounded-lg p-4">
|
|
<div className="text-sm text-gray-500">Aktive Sessions</div>
|
|
<div className="text-2xl font-bold text-gray-900">{agent.activeSessions}</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-lg p-4">
|
|
<div className="text-sm text-gray-500">Verarbeitet (24h)</div>
|
|
<div className="text-2xl font-bold text-gray-900">{agent.totalProcessed.toLocaleString()}</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-lg p-4">
|
|
<div className="text-sm text-gray-500">Avg. Antwortzeit</div>
|
|
<div className="text-2xl font-bold text-gray-900">{agent.avgResponseTime}ms</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-lg p-4">
|
|
<div className="text-sm text-gray-500">Fehlerrate</div>
|
|
<div className="text-2xl font-bold text-amber-600">{agent.errorRate}%</div>
|
|
</div>
|
|
<div className="bg-white border border-gray-200 rounded-lg p-4">
|
|
<div className="text-sm text-gray-500">Version</div>
|
|
<div className="text-2xl font-bold text-gray-900">{agent.version}</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tabs */}
|
|
<div className="bg-white border border-gray-200 rounded-xl overflow-hidden">
|
|
<div className="border-b border-gray-200">
|
|
<div className="flex">
|
|
<button
|
|
onClick={() => setActiveTab('soul')}
|
|
className={`flex items-center gap-2 px-6 py-4 text-sm font-medium border-b-2 transition-colors ${
|
|
activeTab === 'soul'
|
|
? 'border-teal-500 text-teal-600'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700'
|
|
}`}
|
|
>
|
|
<FileText className="w-4 h-4" />
|
|
SOUL-File
|
|
</button>
|
|
<button
|
|
onClick={() => setActiveTab('stats')}
|
|
className={`flex items-center gap-2 px-6 py-4 text-sm font-medium border-b-2 transition-colors ${
|
|
activeTab === 'stats'
|
|
? 'border-teal-500 text-teal-600'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700'
|
|
}`}
|
|
>
|
|
<Activity className="w-4 h-4" />
|
|
Live-Statistiken
|
|
</button>
|
|
<button
|
|
onClick={() => setActiveTab('history')}
|
|
className={`flex items-center gap-2 px-6 py-4 text-sm font-medium border-b-2 transition-colors ${
|
|
activeTab === 'history'
|
|
? 'border-teal-500 text-teal-600'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700'
|
|
}`}
|
|
>
|
|
<History className="w-4 h-4" />
|
|
Aenderungshistorie
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tab Content */}
|
|
<div className="p-6">
|
|
{activeTab === 'soul' && (
|
|
<div>
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="flex items-center gap-2 text-sm text-gray-500">
|
|
<FileText className="w-4 h-4" />
|
|
{agent.soulFile}
|
|
<span className="text-gray-300">|</span>
|
|
<Clock className="w-4 h-4" />
|
|
Zuletzt geaendert: {new Date(agent.updatedAt).toLocaleString('de-DE')}
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
{isEditing ? (
|
|
<>
|
|
<button
|
|
onClick={handleReset}
|
|
disabled={!hasChanges}
|
|
className="flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors disabled:opacity-50"
|
|
>
|
|
<RotateCcw className="w-4 h-4" />
|
|
Zuruecksetzen
|
|
</button>
|
|
<button
|
|
onClick={handleSave}
|
|
disabled={!hasChanges || saving}
|
|
className="flex items-center gap-2 px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors disabled:opacity-50"
|
|
>
|
|
<Save className="w-4 h-4" />
|
|
{saving ? 'Speichert...' : 'Speichern'}
|
|
</button>
|
|
</>
|
|
) : (
|
|
<button
|
|
onClick={() => setIsEditing(true)}
|
|
className="flex items-center gap-2 px-4 py-2 bg-teal-600 text-white rounded-lg hover:bg-teal-700 transition-colors"
|
|
>
|
|
<Edit3 className="w-4 h-4" />
|
|
Bearbeiten
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{hasChanges && (
|
|
<div className="mb-4 p-3 bg-amber-50 border border-amber-200 rounded-lg flex items-center gap-2 text-amber-700">
|
|
<AlertTriangle className="w-4 h-4" />
|
|
<span className="text-sm">Ungespeicherte Aenderungen vorhanden</span>
|
|
</div>
|
|
)}
|
|
|
|
<div className="relative">
|
|
{isEditing ? (
|
|
<textarea
|
|
value={editedContent}
|
|
onChange={(e) => handleContentChange(e.target.value)}
|
|
className="w-full h-[600px] p-4 font-mono text-sm bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500 focus:border-transparent resize-none"
|
|
spellCheck={false}
|
|
/>
|
|
) : (
|
|
<div className="w-full h-[600px] p-4 font-mono text-sm bg-gray-50 border border-gray-200 rounded-lg overflow-auto whitespace-pre-wrap">
|
|
{agent.soulContent}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
|
<h4 className="font-medium text-blue-900 mb-2">Hinweise zur SOUL-Datei</h4>
|
|
<ul className="text-sm text-blue-700 space-y-1">
|
|
<li>• Die SOUL-Datei definiert die Persoenlichkeit und das Verhalten des Agents</li>
|
|
<li>• Aenderungen werden nach dem Speichern sofort wirksam</li>
|
|
<li>• Testen Sie Aenderungen zuerst im Staging-Modus</li>
|
|
<li>• Alle Aenderungen werden in der Historie protokolliert</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'stats' && (
|
|
<div className="space-y-6">
|
|
<div className="text-center py-12 text-gray-500">
|
|
<Activity className="w-12 h-12 mx-auto mb-4 text-gray-400" />
|
|
<p>Live-Statistiken werden in einer zukuenftigen Version verfuegbar sein.</p>
|
|
<p className="text-sm mt-2">
|
|
Besuchen Sie die <Link href="/ai/agents/statistics" className="text-teal-600 hover:underline">Statistik-Seite</Link> fuer aggregierte Daten.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{activeTab === 'history' && (
|
|
<div>
|
|
<div className="space-y-4">
|
|
{mockChangeLogs.map((log) => (
|
|
<div key={log.id} className="flex items-start gap-4 p-4 bg-gray-50 rounded-lg">
|
|
<div className="p-2 bg-white rounded-full border border-gray-200">
|
|
<History className="w-4 h-4 text-gray-500" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<div className="flex items-center justify-between">
|
|
<span className="font-medium text-gray-900">{log.action}</span>
|
|
<span className="text-sm text-gray-500">
|
|
{new Date(log.timestamp).toLocaleString('de-DE')}
|
|
</span>
|
|
</div>
|
|
<p className="text-sm text-gray-600 mt-1">{log.description}</p>
|
|
<p className="text-xs text-gray-400 mt-1">von {log.user}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|