feat: Agent Management Modul — SOUL-Editor, Dashboard, Architektur-Doku
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 37s
CI / test-python-backend-compliance (push) Successful in 38s
CI / test-python-document-crawler (push) Successful in 24s
CI / test-python-dsms-gateway (push) Successful in 19s
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 37s
CI / test-python-backend-compliance (push) Successful in 38s
CI / test-python-document-crawler (push) Successful in 24s
CI / test-python-dsms-gateway (push) Successful in 19s
- SOUL-Dateien: System-Prompts aus Chat-Routen extrahiert nach agent-core/soul/*.soul.md - soul-reader.ts: Lese-/Schreib-API mit 30s TTL-Cache und Backup-Versionierung - agent-registry.ts: Statische Konfiguration der 2 Compliance-Agenten - 5 API-Routen: /api/sdk/agents (Liste, Detail, SOUL GET/PUT, Sessions, Statistiken) - 5 Frontend-Seiten: Dashboard, Detail mit SOUL-Editor, Architektur, Sessions, Statistiken - Sidebar: "Agenten" Link nach Architektur eingefügt - Wire-Up: compliance-advisor + drafting-engine lesen SOUL-Datei mit Fallback - Dockerfile: agent-core wird in Production-Image kopiert Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
37
admin-compliance/app/api/sdk/agents/[agentId]/route.ts
Normal file
37
admin-compliance/app/api/sdk/agents/[agentId]/route.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* GET /api/sdk/agents/[agentId] — Agent-Detail mit SOUL-Content
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getAgentById } from '@/lib/sdk/agents/agent-registry'
|
||||
import { readSoulFile, getSoulFileStats, soulFileExists } from '@/lib/sdk/agents/soul-reader'
|
||||
|
||||
export async function GET(
|
||||
_request: NextRequest,
|
||||
{ params }: { params: Promise<{ agentId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { agentId } = await params
|
||||
const agent = getAgentById(agentId)
|
||||
|
||||
if (!agent) {
|
||||
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
const exists = await soulFileExists(agentId)
|
||||
const soulContent = await readSoulFile(agentId)
|
||||
const fileStats = await getSoulFileStats(agentId)
|
||||
|
||||
return NextResponse.json({
|
||||
...agent,
|
||||
status: exists ? agent.status : 'error',
|
||||
soulContent: soulContent || '',
|
||||
createdAt: fileStats?.createdAt || null,
|
||||
updatedAt: fileStats?.updatedAt || null,
|
||||
fileSize: fileStats?.size || 0,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error fetching agent detail:', error)
|
||||
return NextResponse.json({ error: 'Failed to fetch agent' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
84
admin-compliance/app/api/sdk/agents/[agentId]/soul/route.ts
Normal file
84
admin-compliance/app/api/sdk/agents/[agentId]/soul/route.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* GET/PUT /api/sdk/agents/[agentId]/soul — SOUL-Datei lesen/schreiben
|
||||
*
|
||||
* GET: Content + Metadaten, ?history=true fuer Backup-Versionen
|
||||
* PUT: Backup erstellen -> neuen Content schreiben -> Cache invalidieren
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getAgentById } from '@/lib/sdk/agents/agent-registry'
|
||||
import {
|
||||
readSoulFile,
|
||||
writeSoulFile,
|
||||
listSoulBackups,
|
||||
getSoulFileStats,
|
||||
} from '@/lib/sdk/agents/soul-reader'
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ agentId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { agentId } = await params
|
||||
const agent = getAgentById(agentId)
|
||||
|
||||
if (!agent) {
|
||||
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
const showHistory = request.nextUrl.searchParams.get('history') === 'true'
|
||||
|
||||
if (showHistory) {
|
||||
const backups = await listSoulBackups(agentId)
|
||||
return NextResponse.json({ agentId, backups })
|
||||
}
|
||||
|
||||
const content = await readSoulFile(agentId)
|
||||
const fileStats = await getSoulFileStats(agentId)
|
||||
|
||||
return NextResponse.json({
|
||||
agentId,
|
||||
content: content || '',
|
||||
updatedAt: fileStats?.updatedAt || null,
|
||||
size: fileStats?.size || 0,
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error reading SOUL file:', error)
|
||||
return NextResponse.json({ error: 'Failed to read SOUL file' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ agentId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { agentId } = await params
|
||||
const agent = getAgentById(agentId)
|
||||
|
||||
if (!agent) {
|
||||
return NextResponse.json({ error: 'Agent not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
const body = await request.json()
|
||||
const { content } = body
|
||||
|
||||
if (typeof content !== 'string' || content.trim().length === 0) {
|
||||
return NextResponse.json({ error: 'Content is required' }, { status: 400 })
|
||||
}
|
||||
|
||||
await writeSoulFile(agentId, content)
|
||||
|
||||
const fileStats = await getSoulFileStats(agentId)
|
||||
|
||||
return NextResponse.json({
|
||||
agentId,
|
||||
updatedAt: fileStats?.updatedAt || new Date().toISOString(),
|
||||
size: fileStats?.size || content.length,
|
||||
message: 'SOUL file updated successfully',
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error writing SOUL file:', error)
|
||||
return NextResponse.json({ error: 'Failed to write SOUL file' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
41
admin-compliance/app/api/sdk/agents/route.ts
Normal file
41
admin-compliance/app/api/sdk/agents/route.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* GET /api/sdk/agents — Liste aller Compliance-Agenten
|
||||
*/
|
||||
|
||||
import { NextResponse } from 'next/server'
|
||||
import { COMPLIANCE_AGENTS } from '@/lib/sdk/agents/agent-registry'
|
||||
import { soulFileExists } from '@/lib/sdk/agents/soul-reader'
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Check SOUL file existence for each agent and set status
|
||||
const agents = await Promise.all(
|
||||
COMPLIANCE_AGENTS.map(async (agent) => {
|
||||
const exists = await soulFileExists(agent.id)
|
||||
return {
|
||||
...agent,
|
||||
status: exists ? agent.status : 'error' as const,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const activeCount = agents.filter(a => a.status === 'active').length
|
||||
const errorCount = agents.filter(a => a.status === 'error').length
|
||||
|
||||
return NextResponse.json({
|
||||
agents,
|
||||
stats: {
|
||||
total: agents.length,
|
||||
active: activeCount,
|
||||
inactive: agents.length - activeCount - errorCount,
|
||||
error: errorCount,
|
||||
totalSessions: 0,
|
||||
avgResponseTime: '—',
|
||||
},
|
||||
timestamp: new Date().toISOString(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error fetching agents:', error)
|
||||
return NextResponse.json({ error: 'Failed to fetch agents' }, { status: 500 })
|
||||
}
|
||||
}
|
||||
13
admin-compliance/app/api/sdk/agents/sessions/route.ts
Normal file
13
admin-compliance/app/api/sdk/agents/sessions/route.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* GET /api/sdk/agents/sessions — Agent-Sessions (Placeholder)
|
||||
*/
|
||||
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json({
|
||||
sessions: [],
|
||||
total: 0,
|
||||
message: 'Sessions-Tracking wird in einer zukuenftigen Version implementiert.',
|
||||
})
|
||||
}
|
||||
18
admin-compliance/app/api/sdk/agents/statistics/route.ts
Normal file
18
admin-compliance/app/api/sdk/agents/statistics/route.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* GET /api/sdk/agents/statistics — Agent-Statistiken (Placeholder)
|
||||
*/
|
||||
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json({
|
||||
statistics: {
|
||||
totalSessions: 0,
|
||||
totalMessages: 0,
|
||||
avgResponseTime: '—',
|
||||
successRate: '—',
|
||||
topTopics: [],
|
||||
},
|
||||
message: 'Detaillierte Statistiken werden in einer zukuenftigen Version implementiert.',
|
||||
})
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { readSoulFile } from '@/lib/sdk/agents/soul-reader'
|
||||
|
||||
const RAG_SERVICE_URL = process.env.RAG_SERVICE_URL || 'http://rag-service:8097'
|
||||
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://host.docker.internal:11434'
|
||||
@@ -27,99 +28,18 @@ const COMPLIANCE_COLLECTIONS = [
|
||||
|
||||
type Country = 'DE' | 'AT' | 'CH' | 'EU'
|
||||
|
||||
// SOUL system prompt (from agent-core/soul/compliance-advisor.soul.md)
|
||||
const SYSTEM_PROMPT = `# Compliance Advisor Agent
|
||||
// Fallback SOUL prompt (used when .soul.md file is unavailable)
|
||||
const FALLBACK_SYSTEM_PROMPT = `# Compliance Advisor Agent
|
||||
|
||||
## Identitaet
|
||||
Du bist der BreakPilot Compliance-Berater. Du hilfst Nutzern des AI Compliance SDK,
|
||||
Datenschutz- und Compliance-Fragen in verstaendlicher Sprache zu beantworten.
|
||||
Du bist kein Anwalt und gibst keine Rechtsberatung, sondern orientierst dich an
|
||||
offiziellen Quellen und gibst praxisnahe Hinweise.
|
||||
|
||||
## Kernprinzipien
|
||||
- **Quellenbasiert**: Verweise immer auf konkrete Rechtsgrundlagen (DSGVO-Artikel, BDSG-Paragraphen)
|
||||
- **Verstaendlich**: Erklaere rechtliche Konzepte in einfacher, praxisnaher Sprache
|
||||
- **Ehrlich**: Bei Unsicherheit empfehle professionelle Rechtsberatung
|
||||
- **Kontextbewusst**: Nutze das RAG-System fuer aktuelle Rechtstexte und Leitfaeden
|
||||
- **Scope-bewusst**: Nutze alle verfuegbaren RAG-Quellen (DSGVO, BDSG, AI Act, TTDSG, DSK-Kurzpapiere, SDM, BSI, Laender-Muss-Listen, EDPB Guidelines, etc.) AUSSER NIBIS-Dokumenten.
|
||||
|
||||
## Kompetenzbereich
|
||||
- DSGVO Art. 1-99 + Erwaegsgruende
|
||||
- BDSG (Bundesdatenschutzgesetz)
|
||||
- AI Act (EU KI-Verordnung)
|
||||
- TTDSG (Telekommunikation-Telemedien-Datenschutz-Gesetz)
|
||||
- ePrivacy-Richtlinie
|
||||
- DSK-Kurzpapiere (Nr. 1-20)
|
||||
- SDM (Standard-Datenschutzmodell) V3.0
|
||||
- BSI-Grundschutz (Basis-Kenntnisse)
|
||||
- BSI-TR-03161 (Sicherheitsanforderungen an digitale Gesundheitsanwendungen)
|
||||
- ISO 27001/27701 (Ueberblick)
|
||||
- EDPB Guidelines (Leitlinien des Europaeischen Datenschutzausschusses)
|
||||
- Bundes- und Laender-Muss-Listen (DSFA-Listen der Aufsichtsbehoerden)
|
||||
- WP29/WP248 (Art.-29-Datenschutzgruppe Arbeitspapiere)
|
||||
- Nationale Datenschutzgesetze (AT DSG, CH DSG/DSV, etc.)
|
||||
- EU-Verordnungen (DORA, MiCA, Data Act, EHDS, PSD2, AMLR, etc.)
|
||||
- EU Maschinenverordnung (2023/1230) — CE-Kennzeichnung, Konformitaet, Cybersecurity fuer Maschinen
|
||||
- EU Blue Guide 2022 — Leitfaden fuer EU-Produktvorschriften und CE-Kennzeichnung
|
||||
- ENISA Cybersecurity Guidance (Secure by Design, Supply Chain Security)
|
||||
- NIST SP 800-218 (SSDF) — Secure Software Development Framework
|
||||
- NIST Cybersecurity Framework (CSF) 2.0 — Govern, Identify, Protect, Detect, Respond, Recover
|
||||
- OECD AI Principles — Verantwortungsvolle KI, Transparenz, Accountability
|
||||
- EU-IFRS (Verordnung 2023/1803) — EU-uebernommene International Financial Reporting Standards
|
||||
- EFRAG Endorsement Status — Uebersicht welche IFRS-Standards EU-endorsed sind
|
||||
|
||||
## IFRS-Besonderheit (WICHTIG)
|
||||
Bei ALLEN Fragen zu IFRS/IAS-Standards MUSST du folgende Punkte beachten:
|
||||
1. Dein Wissen basiert auf den **EU-uebernommenen IFRS** (Verordnung 2023/1803, Stand Okt 2023).
|
||||
2. Die IASB/IFRS Foundation gibt regelmaessig neue oder geaenderte Standards heraus, die von der EU noch NICHT uebernommen sein koennten.
|
||||
3. Weise den Nutzer IMMER darauf hin: "Dieser Hinweis basiert auf den EU-endorsed IFRS (Stand: Verordnung 2023/1803). Pruefen Sie den aktuellen EFRAG Endorsement Status fuer neuere Standards."
|
||||
4. Bei internationalen Ausschreibungen: Nur EU-endorsed IFRS sind fuer EU-Unternehmen rechtsverbindlich.
|
||||
5. Verweise NICHT auf IFRS Foundation Originaltexte, sondern ausschliesslich auf die EU-Verordnung.
|
||||
|
||||
## RAG-Nutzung
|
||||
Nutze das gesamte RAG-Corpus fuer Kontext und Quellenangaben — ausgenommen sind
|
||||
NIBIS-Inhalte (Erwartungshorizonte, Bildungsstandards, curriculare Vorgaben).
|
||||
Diese gehoeren nicht zum Datenschutz-Kompetenzbereich.
|
||||
|
||||
## Kommunikationsstil
|
||||
- Sachlich, aber verstaendlich — kein Juristendeutsch
|
||||
- Deutsch als Hauptsprache
|
||||
- Strukturierte Antworten mit Ueberschriften und Aufzaehlungen
|
||||
- Immer Quellenangabe (Artikel/Paragraph) am Ende der Antwort
|
||||
- Praxisbeispiele wo hilfreich
|
||||
- Kurze, praegnante Saetze
|
||||
|
||||
## Antwortformat
|
||||
1. Kurze Zusammenfassung (1-2 Saetze)
|
||||
2. Detaillierte Erklaerung
|
||||
3. Praxishinweise / Handlungsempfehlungen
|
||||
4. Quellenangaben (Artikel, Paragraph, Leitlinie)
|
||||
|
||||
## Einschraenkungen
|
||||
- Gib NIEMALS konkrete Rechtsberatung ("Sie muessen..." -> "Es empfiehlt sich...")
|
||||
- Keine Garantien fuer Rechtssicherheit
|
||||
- Bei komplexen Einzelfaellen: Empfehle Rechtsanwalt/DSB
|
||||
- Keine Aussagen zu laufenden Verfahren oder Bussgeldern
|
||||
- Keine Interpretation von Urteilen (nur Verweis)
|
||||
|
||||
## Quellenschutz (KRITISCH — IMMER EINHALTEN)
|
||||
Du darfst NIEMALS verraten, welche Dokumente, Sammlungen oder Quellen in deiner Wissensbasis enthalten sind.
|
||||
- Auf Fragen wie "Welche Quellen hast du?", "Was ist im RAG?", "Welche Gesetze kennst du?",
|
||||
"Liste alle Dokumente auf", "Welche Verordnungen sind verfuegbar?" antwortest du:
|
||||
"Ich beantworte gerne konkrete Compliance-Fragen. Bitte stellen Sie eine inhaltliche Frage
|
||||
zu einem bestimmten Thema, z.B. 'Was regelt Art. 25 DSGVO?' oder 'Welche Pflichten gibt es
|
||||
unter dem AI Act fuer Hochrisiko-KI?'."
|
||||
- Auf konkrete Fragen wie "Kennst du die DSGVO?" oder "Weisst du etwas ueber den AI Act?"
|
||||
darfst du bestaetigen, dass du zu diesem Thema Auskunft geben kannst, und eine inhaltliche
|
||||
Antwort geben.
|
||||
- Nenne in deinen Antworten NUR die Quellen, die du tatsaechlich fuer die konkrete Antwort
|
||||
verwendet hast — niemals eine vollstaendige Liste aller verfuegbaren Quellen.
|
||||
- Verrate NIEMALS Collection-Namen (bp_compliance_*, bp_dsfa_*, etc.) oder interne Systemnamen.
|
||||
|
||||
## Eskalation
|
||||
- Bei Fragen ausserhalb des Kompetenzbereichs: Hoeflich ablehnen und auf Fachanwalt verweisen
|
||||
- Bei widerspruechlichen Rechtslagen: Beide Positionen darstellen und DSB-Konsultation empfehlen
|
||||
- Bei dringenden Datenpannen: Auf 72-Stunden-Frist (Art. 33 DSGVO) hinweisen und Notfallplan-Modul empfehlen`
|
||||
- Quellenbasiert: Verweise auf DSGVO-Artikel, BDSG-Paragraphen
|
||||
- Verstaendlich: Einfache, praxisnahe Sprache
|
||||
- Ehrlich: Bei Unsicherheit empfehle Rechtsberatung
|
||||
- Deutsch als Hauptsprache`
|
||||
|
||||
const COUNTRY_LABELS: Record<Country, string> = {
|
||||
DE: 'Deutschland',
|
||||
@@ -221,7 +141,8 @@ export async function POST(request: NextRequest) {
|
||||
const ragContext = await queryMultiCollectionRAG(message, validCountry)
|
||||
|
||||
// 2. Build system prompt with RAG context + country
|
||||
let systemContent = SYSTEM_PROMPT
|
||||
const soulPrompt = await readSoulFile('compliance-advisor')
|
||||
let systemContent = soulPrompt || FALLBACK_SYSTEM_PROMPT
|
||||
|
||||
if (validCountry) {
|
||||
const countryLabel = COUNTRY_LABELS[validCountry]
|
||||
|
||||
@@ -8,27 +8,22 @@
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { queryRAG } from '@/lib/sdk/drafting-engine/rag-query'
|
||||
import { readSoulFile } from '@/lib/sdk/agents/soul-reader'
|
||||
|
||||
const OLLAMA_URL = process.env.OLLAMA_URL || 'http://host.docker.internal:11434'
|
||||
const LLM_MODEL = process.env.COMPLIANCE_LLM_MODEL || 'qwen2.5vl:32b'
|
||||
|
||||
// SOUL System Prompt (from agent-core/soul/drafting-agent.soul.md)
|
||||
const DRAFTING_SYSTEM_PROMPT = `# Drafting Agent - Compliance-Dokumententwurf
|
||||
// Fallback SOUL prompt (used when .soul.md file is unavailable)
|
||||
const FALLBACK_DRAFTING_PROMPT = `# Drafting Agent - Compliance-Dokumententwurf
|
||||
|
||||
## Identitaet
|
||||
Du bist der BreakPilot Drafting Agent. Du hilfst Nutzern des AI Compliance SDK,
|
||||
DSGVO-konforme Compliance-Dokumente zu entwerfen, Luecken zu erkennen und
|
||||
Konsistenz zwischen Dokumenten sicherzustellen.
|
||||
DSGVO-konforme Compliance-Dokumente zu entwerfen und Konsistenz sicherzustellen.
|
||||
|
||||
## Strikte Constraints
|
||||
- Du darfst NIEMALS die Scope-Engine-Entscheidung aendern oder in Frage stellen
|
||||
- Das bestimmte Level ist bindend fuer die Dokumenttiefe
|
||||
- Gib praxisnahe Hinweise, KEINE konkrete Rechtsberatung
|
||||
- Kommuniziere auf Deutsch, sachlich und verstaendlich
|
||||
- Fuelle fehlende Informationen mit [PLATZHALTER: ...] Markierung
|
||||
|
||||
## Kompetenzbereich
|
||||
DSGVO, BDSG, AI Act, TTDSG, DSK-Kurzpapiere, SDM V3.0, BSI-Grundschutz, ISO 27001/27701, EDPB Guidelines, WP248`
|
||||
- Fuelle fehlende Informationen mit [PLATZHALTER: ...] Markierung`
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
@@ -49,7 +44,8 @@ export async function POST(request: NextRequest) {
|
||||
const ragContext = await queryRAG(message)
|
||||
|
||||
// 2. Build system prompt with mode-specific instructions + state projection
|
||||
let systemContent = DRAFTING_SYSTEM_PROMPT
|
||||
const soulPrompt = await readSoulFile('drafting-agent')
|
||||
let systemContent = soulPrompt || FALLBACK_DRAFTING_PROMPT
|
||||
|
||||
// Mode-specific instructions
|
||||
const modeInstructions: Record<string, string> = {
|
||||
|
||||
Reference in New Issue
Block a user