Spaces:
Running
Running
| import React, { useState, useEffect } from 'react'; | |
| import { Wrench, X, Bug, HardHat, CheckCircle2, Play, AlertTriangle } from 'lucide-react'; | |
| import { fixArchitectureErrors, AgentStatus } from '../services/geminiService'; | |
| import { Node, Edge } from 'reactflow'; | |
| import { NodeData } from '../types'; | |
| interface FixerModalProps { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| onApply: (nodes: any[], edges: any[], logMsg?: string) => void; | |
| errorMsg: string; | |
| nodes: Node<NodeData>[]; | |
| edges: Edge[]; | |
| } | |
| const FixerModal: React.FC<FixerModalProps> = ({ isOpen, onClose, onApply, errorMsg, nodes, edges }) => { | |
| const [isFixing, setIsFixing] = useState(false); | |
| const [agentStatus, setAgentStatus] = useState<AgentStatus>('idle'); | |
| const [agentMessage, setAgentMessage] = useState(''); | |
| const [error, setError] = useState<string | null>(null); | |
| useEffect(() => { | |
| if (isOpen) { | |
| setAgentStatus('idle'); | |
| setAgentMessage(''); | |
| setError(null); | |
| setIsFixing(false); | |
| } | |
| }, [isOpen]); | |
| const handleStartFix = async () => { | |
| setIsFixing(true); | |
| setAgentStatus('debugger'); | |
| setAgentMessage('Initializing debugging protocols...'); | |
| try { | |
| const result = await fixArchitectureErrors(nodes, edges, errorMsg, (status, msg) => { | |
| setAgentStatus(status); | |
| setAgentMessage(msg); | |
| }); | |
| if (result && result.nodes && result.edges) { | |
| // Post-process to ensure compatibility and safe access | |
| 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 || {} | |
| } | |
| }; | |
| }); | |
| const processedEdges = result.edges.map((e: any) => ({ | |
| ...e, animated: true, style: { stroke: '#94a3b8' } | |
| })); | |
| setTimeout(() => { | |
| onApply(processedNodes, processedEdges, "Auto-Fixer agents applied corrections."); | |
| onClose(); | |
| }, 1000); | |
| } | |
| } catch (err) { | |
| setError(err instanceof Error ? err.message : "Failed to fix architecture"); | |
| setAgentStatus('error'); | |
| setIsFixing(false); | |
| } | |
| }; | |
| const renderAgentStep = (step: AgentStatus, icon: React.ReactNode, label: string) => { | |
| const order = ['idle', 'debugger', 'architect', 'patcher', 'complete']; | |
| const stepIdx = order.indexOf(step); | |
| const currentIdx = order.indexOf(agentStatus); | |
| const isCurrent = agentStatus === step; | |
| const isDone = currentIdx > stepIdx && agentStatus !== 'error'; | |
| const isPending = currentIdx < stepIdx; | |
| let statusColor = 'text-slate-600'; | |
| if (isDone) statusColor = 'text-emerald-400'; | |
| if (isCurrent) statusColor = 'text-amber-400 animate-pulse'; | |
| if (agentStatus === 'error') statusColor = 'text-red-400'; | |
| return ( | |
| <div className={`flex items-center gap-3 p-3 rounded-lg border transition-all duration-300 ${isCurrent ? 'bg-slate-800 border-amber-500/30' : 'bg-slate-900 border-slate-800'}`}> | |
| <div className={`${statusColor}`}> | |
| {isDone ? <CheckCircle2 size={24} /> : icon} | |
| </div> | |
| <div className="flex-1"> | |
| <div className={`font-semibold text-sm ${isCurrent ? 'text-amber-200' : isDone ? 'text-emerald-200' : 'text-slate-400'}`}> | |
| {label} | |
| </div> | |
| {isCurrent && ( | |
| <div className="text-xs text-slate-500 mt-1">{agentMessage}</div> | |
| )} | |
| </div> | |
| {isCurrent && <div className="w-2 h-2 rounded-full bg-amber-400 animate-ping" />} | |
| </div> | |
| ); | |
| } | |
| if (!isOpen) return null; | |
| return ( | |
| <div className="absolute inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4"> | |
| <div className="bg-slate-950 w-full max-w-lg rounded-xl border border-red-500/30 shadow-2xl flex flex-col overflow-hidden animate-in fade-in zoom-in duration-200"> | |
| <div className="flex items-center justify-between px-6 py-4 border-b border-slate-800 bg-gradient-to-r from-slate-900 to-slate-800"> | |
| <h2 className="text-lg font-bold text-white flex items-center gap-2"> | |
| <Wrench className="text-red-400" size={20} /> | |
| Auto-Fixer | |
| </h2> | |
| <button onClick={onClose} className="text-slate-400 hover:text-white transition-colors"> | |
| <X size={20} /> | |
| </button> | |
| </div> | |
| <div className="p-6 space-y-6"> | |
| {!isFixing && agentStatus !== 'complete' ? ( | |
| <> | |
| <div className="bg-red-500/10 border border-red-500/20 rounded-lg p-4 flex gap-3 items-start"> | |
| <AlertTriangle className="text-red-400 shrink-0 mt-0.5" size={18} /> | |
| <div> | |
| <h3 className="text-sm font-bold text-red-200 mb-1">Detected Issues</h3> | |
| <p className="text-xs text-red-300/80 font-mono leading-relaxed max-h-32 overflow-y-auto"> | |
| {errorMsg} | |
| </p> | |
| </div> | |
| </div> | |
| <div className="text-sm text-slate-400"> | |
| Deploy AI debugging agents to analyze the graph structure and apply corrections automatically. | |
| </div> | |
| <div className="flex justify-end pt-2"> | |
| <button | |
| onClick={handleStartFix} | |
| className="flex items-center gap-2 px-6 py-2.5 rounded-lg font-medium text-white bg-red-600 hover:bg-red-500 transition-all shadow-lg shadow-red-900/20" | |
| > | |
| <Play size={18} fill="currentColor" /> | |
| Run Diagnostics & Fix | |
| </button> | |
| </div> | |
| </> | |
| ) : ( | |
| <div className="space-y-3"> | |
| {renderAgentStep('debugger', <Bug size={24} />, "Debugger: Identifying Root Cause")} | |
| {renderAgentStep('architect', <HardHat size={24} />, "Architect: Planning Structural Fix")} | |
| {renderAgentStep('patcher', <Wrench size={24} />, "Patcher: Applying Fixes to Graph")} | |
| {agentStatus === 'complete' && ( | |
| <div className="text-center text-emerald-400 font-bold mt-6 animate-pulse"> | |
| Fixes Applied Successfully! | |
| </div> | |
| )} | |
| {agentStatus === 'error' && ( | |
| <div className="text-center text-red-400 font-bold mt-6"> | |
| {error || "An error occurred during fixing."} | |
| </div> | |
| )} | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default FixerModal; | |