import React from 'react';
import ReactMarkdown from 'react-markdown';
const EvaluationPanel = ({
chatHistory,
selectedAuditId,
setSelectedAuditId,
feedbackContent,
rubricContent,
historyLog,
coworkerContent,
setCoworkerContent,
handleSaveGroundTruth,
savingGroundTruth,
editConfig,
fetchData,
agent
}) => {
const messagesWithAudit = chatHistory.filter(m => m.message_metadata?.evaluation && !m.isUser);
const selectedMessage = selectedAuditId ? chatHistory.find(m => m.id === selectedAuditId) : null;
const displayFeedback = selectedMessage ? selectedMessage.message_metadata.evaluation.feedback : feedbackContent;
const displayRubric = selectedMessage ? selectedMessage.message_metadata.evaluation.rubric : rubricContent;
const displayHistory = selectedMessage ? selectedMessage.message_metadata.evaluation.history : historyLog;
return (
<div className="p-6 flex flex-col gap-6 h-full overflow-y-auto scrollbar-hide">
{/* Inspection Controls */}
<div className="flex flex-col md:flex-row justify-between items-start md:items-center p-4 bg-white/5 dark:bg-gray-800/30 backdrop-blur-md border border-gray-200 dark:border-white/5 rounded-2xl shadow-sm gap-4 shrink-0 transition-all hover:border-indigo-500/30">
<div className="flex flex-col">
<span className="text-[10px] font-black uppercase tracking-widest text-indigo-500 mb-1">Audit Mode</span>
<div className="flex bg-gray-100 dark:bg-gray-900/50 p-1 rounded-xl border border-gray-200 dark:border-gray-800">
<button
onClick={() => setSelectedAuditId(null)}
className={`px-4 py-1.5 text-xs font-bold rounded-lg transition-all ${!selectedAuditId ? 'bg-white dark:bg-gray-800 text-indigo-500 shadow-md' : 'text-gray-500 hover:text-gray-400'}`}
>
Live (Latest)
</button>
<button
onClick={() => {
if (messagesWithAudit.length > 0) setSelectedAuditId(messagesWithAudit[messagesWithAudit.length - 1].id);
}}
className={`px-4 py-1.5 text-xs font-bold rounded-lg transition-all ${selectedAuditId ? 'bg-white dark:bg-gray-800 text-indigo-500 shadow-md' : 'text-gray-500 hover:text-gray-400'}`}
>
Historical Audit
</button>
</div>
</div>
{selectedAuditId && (
<div className="flex flex-col flex-1 w-full max-w-md">
<span className="text-[10px] font-black uppercase tracking-widest text-indigo-500 mb-1">Select Historical Message</span>
<select
value={selectedAuditId || ""}
onChange={(e) => setSelectedAuditId(e.target.value)}
className="w-full bg-gray-50 dark:bg-gray-900/50 border border-gray-200 dark:border-gray-800 text-xs font-bold py-2.5 px-4 rounded-xl focus:outline-none focus:ring-2 focus:ring-indigo-500/20 transition-all cursor-pointer"
>
{messagesWithAudit.map((m, i) => (
<option key={m.id} value={m.id}>
Audit {i + 1}: {(m.text || "Tool/System Message").substring(0, 50)}... ({new Date(m.timestamp).toLocaleTimeString()})
</option>
))}
</select>
</div>
)}
<div className="flex flex-col items-end shrink-0">
<span className="text-[10px] font-black uppercase tracking-widest text-gray-400 dark:text-gray-500 mb-1">Terminal Inspector</span>
<div className="flex items-center gap-2 px-3 py-1.5 bg-gray-50 dark:bg-black/40 rounded-xl text-xs font-mono font-bold text-gray-400 border border-gray-200 dark:border-white/5 italic shadow-inner">
{selectedAuditId ? `SNAPSHOT: MSID-${selectedAuditId}` : "LIVE: .CORTEX/"}
</div>
</div>
</div>
{/* Auditor Guidelines Editor (Oversight Policy) */}
<div className="flex flex-col bg-white/5 dark:bg-black/40 backdrop-blur-xl border border-gray-200 dark:border-white/10 rounded-2xl overflow-hidden shadow-2xl shadow-indigo-500/5 shrink-0 transition-all hover:border-indigo-500/20">
<div className="px-5 py-3 bg-indigo-600/5 dark:bg-indigo-600/10 border-b border-gray-200 dark:border-white/10 flex justify-between items-center">
<div className="flex flex-col">
<span className="text-[10px] uppercase tracking-[0.3em] font-black text-indigo-500 dark:text-indigo-400 flex items-center gap-2">
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor font-bold"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} 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>
Auditor Guidelines
</span>
<span className="text-[9px] text-gray-400 dark:text-indigo-400/40 font-mono mt-0.5">Ground Truth Policy Layer</span>
</div>
<div className="flex items-center gap-4">
<span className="text-[10px] font-mono text-gray-400 dark:text-indigo-400/50 bg-gray-100 dark:bg-white/5 px-2 py-0.5 rounded">.coworker.md</span>
<button
onClick={handleSaveGroundTruth}
disabled={savingGroundTruth || editConfig?.is_locked}
className={`px-5 py-2 rounded-xl text-[10px] font-black uppercase tracking-widest transition-all shadow-lg ${savingGroundTruth
? "bg-gray-100 dark:bg-white/5 text-gray-400"
: "bg-gradient-to-r from-indigo-600 to-blue-600 text-white hover:scale-105 active:scale-95 shadow-indigo-500/20"
}`}
>
{savingGroundTruth ? "Guidelines Syncing..." : "Sync Guidelines"}
</button>
</div>
</div>
<div className="p-5">
<textarea
value={coworkerContent}
onChange={(e) => setCoworkerContent(e.target.value)}
placeholder="# Auditor Guidelines... Define architectural constraints and judging rules here."
className="w-full h-52 bg-transparent text-gray-800 dark:text-emerald-400 font-mono text-sm leading-relaxed resize-none focus:outline-none scrollbar-hide border-none placeholder:text-gray-400 dark:placeholder:text-gray-800"
spellCheck="false"
disabled={editConfig?.is_locked}
></textarea>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 flex-grow min-h-0">
{/* Evaluation Strategy (Rubric) */}
<div className="flex flex-col bg-white dark:bg-gray-800/20 border border-gray-200 dark:border-white/5 rounded-2xl overflow-hidden shadow-sm transition-all hover:border-gray-300 dark:hover:border-white/10">
<div className="px-5 py-3 border-b border-gray-100 dark:border-white/5 bg-gray-50/50 dark:bg-black/20 flex justify-between items-center shrink-0">
<span className="text-[10px] uppercase tracking-widest font-black text-gray-500 flex items-center gap-2">
<svg className="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} 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>
Quality Rubric
</span>
<span className="text-[10px] font-mono text-gray-400 bg-white dark:bg-black/20 px-1.5 py-0.5 rounded">rubric.md</span>
</div>
<div className="flex-1 p-5 overflow-auto font-mono text-xs whitespace-pre-wrap leading-relaxed text-gray-700 dark:text-gray-400 scrollbar-hide">
{displayRubric || <span className="italic text-gray-400 opacity-50 text-[10px]">No rubric configuration found for this agent instance.</span>}
</div>
</div>
{/* Live feedback loop (Feedback) */}
<div className="flex flex-col bg-white dark:bg-indigo-500/5 border border-indigo-200 dark:border-indigo-500/20 rounded-2xl overflow-hidden shadow-indigo-500/5 shadow-2xl transition-all hover:border-indigo-500/40">
<div className="px-5 py-3 border-b border-indigo-100 dark:border-indigo-500/20 bg-indigo-50/50 dark:bg-indigo-500/10 flex justify-between items-center shrink-0">
<span className="text-[10px] uppercase tracking-[0.2em] font-black text-indigo-600 dark:text-indigo-400 flex items-center gap-2">
<div className="w-2 h-2 bg-indigo-500 rounded-full animate-pulse shadow-[0_0_10px_rgba(99,102,241,0.8)]"></div>
{selectedAuditId ? "Audit Snapshot" : "Audit Stream"}
</span>
<span className="text-[10px] font-mono text-indigo-400 bg-white/50 dark:bg-black/20 px-1.5 py-0.5 rounded">{selectedAuditId ? `MSID-${selectedAuditId}` : "feedback.md"}</span>
</div>
<div className="flex-1 p-5 overflow-auto font-sans text-xs leading-relaxed text-indigo-600/90 dark:text-indigo-300 markdown-content scrollbar-hide">
{displayFeedback ? (
<ReactMarkdown className="prose prose-sm dark:prose-invert max-w-none">
{displayFeedback}
</ReactMarkdown>
) : (
<div className="flex flex-col items-center justify-center h-full gap-3 opacity-50 grayscale">
<div className="w-8 h-8 border-2 border-indigo-500/30 border-t-indigo-500 rounded-full animate-spin"></div>
<span className="italic text-center max-w-[200px]">
{agent?.status === 'active' || agent?.status === 'starting'
? "Consulting Co-Worker rubric and auditing results..."
: "Waiting for next evaluation cycle to populate feedback..."}
</span>
</div>
)}
</div>
</div>
</div>
{/* Rework History Viewer */}
<div className="flex flex-col bg-white dark:bg-gray-800/20 border border-gray-200 dark:border-white/5 rounded-2xl overflow-hidden shadow-sm shrink-0 transition-all hover:border-emerald-500/20">
<div className="px-5 py-3 border-b border-gray-100 dark:border-white/5 bg-gray-50/50 dark:bg-black/20 flex justify-between items-center shrink-0">
<span className="text-[10px] uppercase tracking-widest font-black text-emerald-600 dark:text-emerald-500 flex items-center gap-2">
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
History Timeline
</span>
<div className="flex items-center gap-4">
<button
onClick={fetchData}
className="text-[10px] font-black uppercase tracking-wider px-3 py-1 rounded-lg border border-indigo-500/30 text-indigo-500 hover:bg-indigo-500/10 transition-all active:scale-95"
>
Refresh Context
</button>
<span className="text-[10px] font-mono text-gray-400 bg-white dark:bg-black/20 px-1.5 py-0.5 rounded">history.log</span>
</div>
</div>
<div className="flex-1 overflow-y-auto px-5 py-5 scrollbar-hide max-h-[400px]">
<div className="flex flex-col gap-4">
{(displayHistory && displayHistory.length > 0) ? [...displayHistory].reverse().map((entry, idx) => (
<div key={idx} className={`group relative flex flex-col gap-3 p-4 rounded-xl border transition-all ${entry.type === 'attempt' ? 'border-gray-200 dark:border-white/5 bg-gray-50/5 dark:bg-white/5 hover:bg-white/10' : 'bg-transparent border-dashed border-gray-100 dark:border-white/5'}`}>
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<div className={`w-2.5 h-2.5 rounded-full ${entry.type === 'attempt' ? (entry.score >= (editConfig?.rework_threshold || 80) ? 'bg-emerald-500 shadow-[0_0_10px_rgba(16,185,129,0.6)]' : 'bg-amber-500 shadow-[0_0_10px_rgba(245,158,11,0.6)]') : 'bg-indigo-500/50'}`}></div>
<span className="text-[11px] font-black uppercase tracking-tight text-gray-800 dark:text-gray-100">
{entry.type === 'attempt' ? `Attempt Round ${entry.round}` : entry.name || 'Event'}
{entry.duration && <span className="ml-3 font-mono text-gray-400 dark:text-gray-600 normal-case opacity-60">took {entry.duration}s</span>}
</span>
</div>
<div className="flex items-center gap-4">
<span className="text-[10px] font-mono text-gray-400 dark:text-gray-600">
{entry.timestamp ? new Date(entry.timestamp * (entry.timestamp < 2000000000 ? 1000 : 1)).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }) : 'Pending'}
</span>
{entry.score !== undefined && (
<div className={`text-[10px] font-black px-3 py-1 rounded-lg shadow-sm ${entry.score >= (editConfig?.rework_threshold || 80) ? 'bg-emerald-500/10 text-emerald-500 border border-emerald-500/20' : 'bg-amber-500/10 text-amber-500 border border-amber-500/20'}`}>
{entry.score}% PRECISION
</div>
)}
</div>
</div>
{entry.type === 'attempt' ? (
<div className="space-y-3">
<p className="text-[12px] text-gray-600 dark:text-gray-400 font-mono leading-relaxed border-l-4 border-gray-100 dark:border-white/10 pl-5 py-1 italic bg-gray-50/50 dark:bg-black/20 rounded-r-lg">
{entry.reason || entry.message || entry.text || "No details provided"}
</p>
{entry.sub_events?.length > 0 && (
<div className="flex flex-wrap gap-2.5 pl-6">
{entry.sub_events.map((sub, sidx) => (
<div key={sidx} className="px-3 py-1 bg-white dark:bg-black/40 border border-gray-100 dark:border-white/5 rounded-lg text-[9px] font-black text-gray-500 dark:text-gray-400 flex items-center gap-3 transition-all hover:border-indigo-500/30">
<div className="w-1.5 h-1.5 bg-indigo-500 rounded-full animate-pulse"></div>
<span className="uppercase tracking-widest">{sub.name}</span>
<span className="font-mono text-indigo-500/60 dark:text-indigo-400/50">{sub.duration}ₛ</span>
</div>
))}
</div>
)}
</div>
) : (
<p className="text-[11px] text-gray-400 italic ml-6 bg-gray-50/30 dark:bg-white/5 p-2 rounded-lg">
{entry.details}
</p>
)}
</div>
)) : (
<div className="flex flex-col items-center py-12 text-gray-400 gap-4 opacity-40">
<svg className="w-12 h-12" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
<span className="text-xs uppercase tracking-[0.2em] font-black">No activity recorded</span>
</div>
)}
</div>
</div>
{displayHistory && displayHistory.length > 0 && (
<div className="px-5 py-3 bg-gray-50/30 dark:bg-black/20 border-t border-gray-100 dark:border-white/5 flex justify-between items-center text-[10px] uppercase font-black tracking-widest text-gray-400">
<span>Aggregate Time Cost</span>
<span className="font-mono text-indigo-500">
{displayHistory.reduce((acc, entry) => acc + (entry.duration || 0), 0).toFixed(2)}s
</span>
</div>
)}
</div>
</div>
);
};
export default EvaluationPanel;