/** * Advisor Agent * ============= * Persistent AI copilot for the Darkroom Control Center. * Always visible, ready to chat, suggest actions, and execute commands. */ import { useState, useRef, useEffect } from 'react'; import { useQuery, useMutation } from '@tanstack/react-query'; import { api } from '../services/api'; import { Bot, X, Send, Sparkles, ChevronRight, Zap, AlertTriangle, CheckCircle, Clock, Terminal, Target, TrendingUp, MessageSquare, } from 'lucide-react'; interface Message { role: 'user' | 'advisor'; content: string; actions?: { label: string; action: string; target?: string }[]; suggestions?: string[]; timestamp: Date; } export default function AdvisorAgent({ adminKey }: { adminKey: string }) { const [isOpen, setIsOpen] = useState(false); const [input, setInput] = useState(''); const [messages, setMessages] = useState([ { role: 'advisor', content: "I'm your Advisor Agent. I can help you scan wallets, manage content, post to Telegram, check system health, or coordinate the AI mesh. What would you like to do?", suggestions: ['Show project status', 'Scan a wallet', 'Draft content', 'Post to Telegram'], timestamp: new Date(), }, ]); const [sessionId] = useState(`adv-${Date.now()}`); const scrollRef = useRef(null); useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [messages, isOpen]); // Proactive suggestions const { data: suggestions } = useQuery({ queryKey: ['advisor-suggest', adminKey], queryFn: () => api.advisorSuggest(adminKey), enabled: !!adminKey && isOpen, refetchInterval: 30000, }); const chatMutation = useMutation({ mutationFn: (message: string) => api.advisorChat(adminKey, message, sessionId), onSuccess: (data) => { const resp = data.response; setMessages((prev) => [ ...prev, { role: 'advisor', content: resp.content, actions: resp.actions || [], suggestions: resp.suggestions || [], timestamp: new Date(), }, ]); }, }); const actMutation = useMutation({ mutationFn: ({ action, params }: { action: string; params?: any }) => api.advisorAct(adminKey, action, params, true), onSuccess: (data) => { setMessages((prev) => [ ...prev, { role: 'advisor', content: `✅ ${data.message}`, timestamp: new Date(), }, ]); }, }); const handleSend = () => { if (!input.trim() || chatMutation.isPending) return; const msg = input.trim(); setMessages((prev) => [...prev, { role: 'user', content: msg, timestamp: new Date() }]); setInput(''); chatMutation.mutate(msg); }; const handleSuggestion = (text: string) => { setMessages((prev) => [...prev, { role: 'user', content: text, timestamp: new Date() }]); chatMutation.mutate(text); }; const handleAction = (action: { label: string; action: string; target?: string }) => { if (action.action === 'navigate') { // Emit custom event for DarkRoomControl to handle navigation window.dispatchEvent(new CustomEvent('advisor-navigate', { detail: action.target })); setMessages((prev) => [ ...prev, { role: 'advisor', content: `Navigating to ${action.label}...`, timestamp: new Date() }, ]); } else { actMutation.mutate({ action: action.action }); } }; const proactive = suggestions?.suggestions || []; return ( <> {/* Floating Button */} {!isOpen && ( )} {/* Chat Panel */} {isOpen && (
{/* Header */}

Advisor Agent

Online • AI Ready
{/* Proactive Alerts */} {proactive.length > 0 && (
{proactive.slice(0, 2).map((s: any, i: number) => (
{s.priority === 'high' ? ( ) : s.priority === 'medium' ? ( ) : ( )}

{s.title}

{s.description}

{s.action && ( )}
))}
)} {/* Messages */}
{messages.map((msg, i) => (
{msg.role === 'advisor' && (
Advisor
)}
{msg.content}
{/* Action buttons */} {msg.actions && msg.actions.length > 0 && (
{msg.actions.map((action, j) => ( ))}
)} {/* Suggestion chips */} {msg.suggestions && msg.suggestions.length > 0 && (
{msg.suggestions.map((s, j) => ( ))}
)}
))} {chatMutation.isPending && (
Advisor is thinking...
)}
{/* Input */}
setInput(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSend()} placeholder="Ask Advisor anything..." className="flex-1 bg-black/30 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-white placeholder-gray-500 focus:outline-none focus:border-purple-500/50" />
)} ); }