import React, { useState, useEffect, useRef } from 'react'; import { Sparkles, X, MessageSquare, Play, RefreshCw, AlertCircle, HardHat, Search, Wand2, CheckCircle2 } from 'lucide-react'; import { generateGraphWithAgents, AgentStatus } from '../services/geminiService'; import { Node } from 'reactflow'; import { NodeData } from '../types'; interface AIBuilderModalProps { isOpen: boolean; onClose: () => void; onApply: (nodes: any[], edges: any[], logMsg?: string) => void; currentNodes: Node[]; } const AIBuilderModal: React.FC = ({ isOpen, onClose, onApply, currentNodes }) => { const [prompt, setPrompt] = useState(''); const [isBuilding, setIsBuilding] = useState(false); const [error, setError] = useState(null); const [agentStatus, setAgentStatus] = useState('idle'); const [agentMessage, setAgentMessage] = useState(''); // Reset state when opened useEffect(() => { if (isOpen) { setAgentStatus('idle'); setAgentMessage(''); setError(null); } }, [isOpen]); if (!isOpen) return null; const handleBuild = async () => { if (!prompt.trim()) return; setIsBuilding(true); setError(null); try { const result = await generateGraphWithAgents(prompt, currentNodes, (status, msg) => { setAgentStatus(status); setAgentMessage(msg); }); if (result && result.nodes && result.edges) { // Ensure nodes have correct style defaults if missing const processedNodes = result.nodes.map((n: any) => { const data = n.data || {}; const type = data.type || n.type || 'Identity'; // Fallback return { ...n, type: 'custom', data: { ...data, type: type, label: data.label || n.label || type, // Safe access params: data.params || {} } }; }); // Ensure edges have styling const processedEdges = result.edges.map((e: any) => ({ ...e, animated: true, style: { stroke: '#94a3b8' } })); // Small delay to let user see "Complete" state setTimeout(() => { onApply(processedNodes, processedEdges, "AI Architect generated new graph."); onClose(); setIsBuilding(false); }, 1000); } else { throw new Error("Invalid response format from AI"); } } catch (err) { setError(err instanceof Error ? err.message : "Failed to generate architecture"); setAgentStatus('error'); setIsBuilding(false); } }; const getStepStatus = (step: AgentStatus, current: AgentStatus) => { const order = ['idle', 'architect', 'critic', 'refiner', 'complete']; const stepIdx = order.indexOf(step); const currentIdx = order.indexOf(current); if (current === 'error') return 'text-slate-500'; if (currentIdx > stepIdx) return 'text-emerald-400'; if (currentIdx === stepIdx) return 'text-blue-400 animate-pulse'; return 'text-slate-600'; }; const renderAgentStep = (step: AgentStatus, icon: React.ReactNode, label: string) => { const statusColor = getStepStatus(step, agentStatus); const isCurrent = agentStatus === step; const isDone = ['architect', 'critic', 'refiner', 'complete'].indexOf(agentStatus) > ['architect', 'critic', 'refiner'].indexOf(step); return (
{isDone ? : icon}
{label}
{isCurrent && (
{agentMessage}
)}
{isCurrent &&
}
); } return (

AI Architect Team

{!isBuilding && agentStatus !== 'complete' ? ( <>

Describe your model. Our AI Agents (Architect, Critic, and Refiner) will collaborate to build the best architecture for you.