feat: KI-Agent toggle in all 3 check tabs

- Impressum-Check: Toggle activates 75 Impressum MCs via agent
- Banner-Check: Toggle runs additional cookie doc-check (381 MCs)
  after the Playwright banner test completes
- Both use the same use_agent flag through doc-check endpoint

Green pill button consistent across all tabs:
'KI-Agent aus' / 'KI-Agent aktiv (X MCs)'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-11 08:00:36 +02:00
parent 6cb5da56b3
commit cc919eb608
2 changed files with 63 additions and 0 deletions
@@ -55,6 +55,8 @@ export function BannerCheckTab() {
try { const s = localStorage.getItem('banner-check-result'); return s ? JSON.parse(s) : null } catch { return null }
})
const [categories, setCategories] = useState<string[]>(['all'])
const [useAgent, setUseAgent] = useState(false)
const [mcResults, setMcResults] = useState<any>(null)
const [history, setHistory] = useState<{ url: string; date: string; provider: string; violations: number; pct: number; resultKey: string }[]>(() => {
if (typeof window === 'undefined') return []
try { return JSON.parse(localStorage.getItem('banner-check-history') || '[]') } catch { return [] }
@@ -97,6 +99,36 @@ export function BannerCheckTab() {
setResult(data)
localStorage.setItem('banner-check-result', JSON.stringify(data))
// If agent mode: also run cookie doc-check with 381 MCs
if (useAgent) {
setProgress('KI-Agent prueft Cookie-Richtlinie (381 MCs)...')
try {
const mcRes = await fetch('/api/sdk/v1/agent/doc-check', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
entries: [{ doc_type: 'cookie', label: 'Cookie-Richtlinie', url: url.trim() }],
recipient: 'dsb@breakpilot.local',
use_agent: true,
}),
})
if (mcRes.ok) {
const { check_id } = await mcRes.json()
if (check_id) {
for (let i = 0; i < 60; i++) {
await new Promise(r => setTimeout(r, 3000))
const poll = await fetch(`/api/sdk/v1/agent/doc-check?check_id=${check_id}`)
if (!poll.ok) continue
const pd = await poll.json()
if (pd.progress) setProgress(`KI-Agent: ${pd.progress}`)
if (pd.status === 'completed' && pd.result) { setMcResults(pd.result); break }
if (pd.status === 'failed') break
}
}
}
} catch { /* agent check is optional */ }
}
// Add to history with persistent result
const violations = data.structured_checks?.filter((c: CheckItem) => !c.passed && !c.skipped).length || 0
const resultKey = `banner-check-result-${Date.now()}`
@@ -162,6 +194,16 @@ export function BannerCheckTab() {
</p>
</div>
<div className="flex items-center gap-3">
<button type="button" onClick={() => setUseAgent(!useAgent)}
className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium border transition-colors ${
useAgent ? 'bg-emerald-100 border-emerald-300 text-emerald-800' : 'bg-gray-50 border-gray-200 text-gray-500 hover:bg-gray-100'
}`}>
<span className={`w-2 h-2 rounded-full ${useAgent ? 'bg-emerald-500' : 'bg-gray-300'}`} />
{useAgent ? 'KI-Agent aktiv (381 Cookie-MCs)' : 'KI-Agent aus'}
</button>
</div>
<form onSubmit={handleScan} className="space-y-3">
<div className="flex gap-3">
<input
@@ -268,6 +310,14 @@ export function BannerCheckTab() {
</div>
)}
{/* MC Agent Results (Cookie-Richtlinie) */}
{mcResults?.results && (
<div className="bg-white border border-gray-200 rounded-xl p-6 shadow-sm">
<h4 className="text-sm font-semibold text-gray-800 mb-3">KI-Agent: Cookie-Richtlinie (381 MCs)</h4>
<ChecklistView results={mcResults.results} />
</div>
)}
{!result.banner_detected && !hasStructured && (
<div className="bg-white border border-gray-200 rounded-xl p-6 shadow-sm">
<p className="text-sm text-gray-500">
@@ -25,6 +25,8 @@ export function ImpressumCheckTab() {
try { return JSON.parse(localStorage.getItem('impressum-check-history') || '[]') } catch { return [] }
})
const [useAgent, setUseAgent] = useState(false)
React.useEffect(() => { localStorage.setItem('impressum-check-url', url) }, [url])
const handleSubmit = async (e: React.FormEvent) => {
@@ -43,6 +45,7 @@ export function ImpressumCheckTab() {
body: JSON.stringify({
entries: [{ doc_type: 'impressum', label: 'Impressum', url: url.trim() }],
recipient: 'dsb@breakpilot.local',
use_agent: useAgent,
}),
})
if (!startRes.ok) throw new Error(`Fehler: ${startRes.status}`)
@@ -91,6 +94,16 @@ export function ImpressumCheckTab() {
</p>
</div>
<div className="flex items-center gap-3">
<button type="button" onClick={() => setUseAgent(!useAgent)}
className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium border transition-colors ${
useAgent ? 'bg-emerald-100 border-emerald-300 text-emerald-800' : 'bg-gray-50 border-gray-200 text-gray-500 hover:bg-gray-100'
}`}>
<span className={`w-2 h-2 rounded-full ${useAgent ? 'bg-emerald-500' : 'bg-gray-300'}`} />
{useAgent ? 'KI-Agent aktiv (75 MCs)' : 'KI-Agent aus'}
</button>
</div>
<form onSubmit={handleSubmit} className="flex gap-3">
<input type="url" value={url} onChange={e => setUrl(e.target.value)}
placeholder="https://www.example.com/impressum"