// ===================================================================== // MAESTRO — Chat panel (glassmorphism, agent reply, confirmations) // ===================================================================== const { useState: useState_chat, useEffect: useEffect_chat, useRef: useRef_chat } = React; const D_chat = window.MAESTRO_DATA; const I_chat = window.MAESTRO_ICONS; function MsgBlock({ block }) { if (!block) return null; return (
{block.title}
{block.items.map(([k, v], i) => ( {k} {v} ))}
); } function RiskList({ risks, onOpenProject }) { return (
{risks.map((r, i) => (
{r.severity === "danger" ? I_chat.blocked(13) : I_chat.alert(13)} onOpenProject(r.id)} >{r.name}
{r.reason}
))}
); } function ChatMessage({ msg, onConfirm, onOpenProject }) { const isUser = msg.role === "user"; return (
{isUser ? "A" : "M"}
{msg.thinking ? (
) : ( <>
{msg.text} {msg.inlineProj && ( onOpenProject(msg.inlineProj.id)} >{msg.inlineProj.name} )} {msg.textAfter}
{msg.block && } {msg.risks && } {msg.followup &&
{msg.followup}
} {msg.confirm && !msg.resolved && (
)} {msg.confirm && msg.resolved && (
)} {!msg.thinking && msg.time && (
{msg.time}
)} )}
); } function ChatPanel({ messages, onSend, onConfirm, onOpenProject }) { const [input, setInput] = useState_chat(""); const scrollRef = useRef_chat(null); const taRef = useRef_chat(null); useEffect_chat(() => { if (scrollRef.current) { scrollRef.current.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" }); } }, [messages.length, messages[messages.length - 1]?.thinking]); const submit = () => { if (!input.trim()) return; onSend(input); setInput(""); if (taRef.current) taRef.current.style.height = "20px"; }; const onKey = e => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); submit(); } }; const onInputChange = e => { setInput(e.target.value); if (taRef.current) { taRef.current.style.height = "20px"; taRef.current.style.height = Math.min(taRef.current.scrollHeight, 120) + "px"; } }; return (