import React, { useRef, useEffect } from 'react'; const AgentTerminal = ({ agentName, model, status, accentColor, icon, messages }) => { const borderColor = accentColor === 'cyan' ? 'border-primary/20' : 'border-secondary/20'; const bgColor = accentColor === 'cyan' ? 'bg-primary/5' : 'bg-secondary/5'; const textColor = accentColor === 'cyan' ? 'text-primary' : 'text-secondary'; const shadowColor = accentColor === 'cyan' ? 'shadow-[0_0_15px_rgba(0,212,255,0.1)]' : 'shadow-[0_0_15px_rgba(221,183,255,0.1)]'; const scrollRef = useRef(null); // Scroll by modifying scrollTop directly to avoid ancestor scroll hijacking useEffect(() => { const el = scrollRef.current; if (el) { el.scrollTop = el.scrollHeight; } }, [messages?.length]); useEffect(() => { const el = scrollRef.current; if (!el) return; const observer = new MutationObserver(() => { el.scrollTop = el.scrollHeight; }); observer.observe(el, { childList: true, subtree: true, characterData: true }); return () => observer.disconnect(); }, []); return (
{icon}

{agentName}

MODEL: {model || '[UNCONFIGURED]'}

{status}
{/* Scrollable terminal body — grows to fill all available space */}
{accentColor === 'cyan' ? '// System initialized. Awaiting objective...' : '// System initialized. Awaiting investigator output...'}
{messages && messages.map((msg, i) => (
{msg.type === 'message' && (
nexus@{agentName.toLowerCase().split(':')[0]}:~$ {msg.content} {msg.partial && }
)} {msg.type === 'tool_call' && (
❯ executing: {msg.tool_name}({JSON.stringify(msg.params)})
)} {msg.type === 'tool_result' && (
❮ result: {msg.result}
)}
))}
nexus@{agentName.toLowerCase().split(':')[0]}:~$
); }; export default AgentTerminal;