'use client' /** * AgentResultView — der geteilte Render-Body eines AgentOutput: * MC-Coverage + Speedometer + Eskalationslog + Findings (HIGH→LOW) + * konsolidierte Maßnahmen. KEIN Header — den setzt der Consumer * (AgentSlotCard = Agent-Test-Slot, AgentResultTab = Themen-Tab). * * Dieser View ist die "Karten"-Darstellung für Themen mit wenigen * Findings (z.B. Impressum). Dichte Themen (Cookie, bis ~1000 Zeilen) * bekommen später einen eigenen Tabellen-View im gleichen Tab-Rahmen. */ import React, { useState } from 'react' import type { Severity, SlotOutput } from './_agentTypes' import { AgentFindingCard } from './AgentFindingCard' import { AgentPflichtTable } from './AgentPflichtTable' import { AgentRecommendationCard } from './AgentRecommendationCard' import { AgentSpeedometer } from './AgentSpeedometer' const SEV_ORDER: Record = { HIGH: 0, MEDIUM: 1, LOW: 2, INFO: 3, } const INITIAL_VISIBLE = 12 export function AgentResultView({ output }: { output: SlotOutput }) { const [showAll, setShowAll] = useState(false) const sortedFindings = [...output.findings].sort( (a, b) => SEV_ORDER[a.severity] - SEV_ORDER[b.severity], ) const visible = showAll ? sortedFindings : sortedFindings.slice(0, INITIAL_VISIBLE) return (
{output.notes && (
Hinweis: {output.notes}
)} {output.escalation_log.length > 0 && (
LLM-Eskalation eingesetzt:
{output.escalation_log.map((e, i) => (
{e.stage} {e.model}{' '} · {e.duration_ms} ms{' '} {e.tokens_in ? `· ${e.tokens_in}→${e.tokens_out} tok` : ''}{' '} {e.success ? '✓' : `✗ ${e.error || ''}`}
))}
)} {sortedFindings.length > 0 && (
Findings ({sortedFindings.length}) — nach Schwere sortiert
{visible.map(f => ( ))}
{sortedFindings.length > INITIAL_VISIBLE && ( )}
)} {output.recommendations.length > 0 && (
Maßnahmen-Plan ({output.recommendations.length} konsolidiert)
{output.recommendations.map(r => ( ))}
)}
) }