ChatPanel.tsx
1 import React, { useEffect, useRef } from 'react'; 2 import { useApp } from '../contexts/AppContext'; 3 import type { Message } from '../types'; 4 import './ChatPanel.css'; 5 6 const KamajiAscii = () => ( 7 <pre className="kamaji-ascii"> 8 {` ╭─────────────────────────────╮ 9 │ 🎭 KAMAJI - Multi-Agent AI │ 10 ╰─────────────────────────────╯ 11 ╭─╮ ╭─╮ ╭─╮ ╭─╮ 12 ╱🔥╲╱🔥╲╱🔥╲╱🔥╲ 13 │▓▓││▓▓││▓▓││▓▓│ 14 ╲▓╱ ╲▓╱ ╲▓╱ ╲▓╱ 15 ╭─╮╭─╮ ║ ║ ║ ║ ╭─╮╭─╮ 16 ╱⚙⚙╲⚙⚙╲║ ║ ║ ║╱⚙⚙╲⚙⚙╲ 17 │▓▓││▓▓│║ ║ ║ ║│▓▓││▓▓│ 18 ╲▓▓╱╲▓▓╱╲═╩═╩═╱╲▓▓╱╲▓▓╱ 19 ║ ║ ╱ ◉ ◉ ╲ ║ ║ 20 ║ ║ │ ▼ │ ║ ║ 21 ║ ║ ╲ ╔═╗ ╱ ║ ║ 22 ║ ║ ╲║█║╱ ║ ║ 23 ╭┴╮╭┴╮ ╭┴╮╭┴╮ 24 ╱⚙⚙╲⚙⚙╲ ╭─╮ ╱⚙⚙╲⚙⚙╲ 25 │▓▓││▓▓│╱⚙⚙╲│▓▓││▓▓│ 26 ╲▓▓╱╲▓▓╱ │▓▓│ ╲▓▓╱╲▓▓╱`} 27 </pre> 28 ); 29 30 const MessageComponent: React.FC<{ message: Message }> = ({ message }) => { 31 const { selectedAgent } = useApp(); 32 33 const renderContent = () => { 34 // Apply gradient for Moe 35 if (message.agentName === 'Moe' && message.role === 'assistant') { 36 return <span className="gradient-text">{message.content}</span>; 37 } 38 return message.content; 39 }; 40 41 const getAgentIcon = () => { 42 if (message.role === 'user') return '🔥'; 43 if (message.role === 'system') return '🔧'; 44 if (selectedAgent && message.agentName === selectedAgent.name) { 45 return selectedAgent.icon; 46 } 47 return '🎭'; 48 }; 49 50 const getAgentColor = () => { 51 if (message.role === 'user') return '#00FFFF'; 52 if (message.role === 'system') return '#808080'; 53 if (selectedAgent && message.agentName === selectedAgent.name) { 54 return selectedAgent.color; 55 } 56 return '#FF6B6B'; 57 }; 58 59 const agentName = message.role === 'user' ? 'You' : 60 message.role === 'system' ? 'System' : 61 message.agentName || 'Kamaji'; 62 63 return ( 64 <div className={`message message-${message.role}`}> 65 <div className="message-header"> 66 <span className="message-icon">{getAgentIcon()}</span> 67 <span className="message-agent" style={{ color: getAgentColor() }}> 68 {agentName}: 69 </span> 70 <span className="message-timestamp"> 71 {message.timestamp.toLocaleTimeString()} 72 </span> 73 </div> 74 <div className="message-content" style={{ 75 color: message.role === 'system' ? '#888' : getAgentColor() 76 }}> 77 {renderContent()} 78 </div> 79 </div> 80 ); 81 }; 82 83 export const ChatPanel: React.FC = () => { 84 const { messages, loading } = useApp(); 85 const messagesEndRef = useRef<HTMLDivElement>(null); 86 87 const scrollToBottom = () => { 88 messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); 89 }; 90 91 useEffect(() => { 92 scrollToBottom(); 93 }, [messages]); 94 95 return ( 96 <div className="chat-panel"> 97 <div className="chat-messages"> 98 <KamajiAscii /> 99 100 {messages.length === 0 && ( 101 <div className="welcome-message"> 102 <h2>🔥 ● ● ● Welcome to the Boiler Room ● ● ● 🔥</h2> 103 <p>💬 Type your message and press Enter to ignite the conversation</p> 104 <p>🎛️ Ctrl+P: Command Palette • Ctrl+S: Toggle Sidebar • Ctrl+A: Switch Agents</p> 105 <p>📊 Check the RIGHT SIDEBAR for consciousness metrics! →→→</p> 106 <p>🔥 Ready to fuel your development with the power of fire! 🔥</p> 107 </div> 108 )} 109 110 {messages.map((msg, idx) => ( 111 <MessageComponent key={idx} message={msg} /> 112 ))} 113 114 {loading && ( 115 <div className="loading-indicator"> 116 <div className="thinking-spinner"> 117 <span className="flame-animation">🔥</span> 118 <span>Thinking...</span> 119 </div> 120 </div> 121 )} 122 123 <div ref={messagesEndRef} /> 124 </div> 125 </div> 126 ); 127 };