/** * DevUI App - Minimal orchestrator for agent/workflow interactions * Features: Entity selection, layout management, debug coordination */ import { useState, useEffect, useCallback } from "react"; import { Button } from "@/components/ui/button"; import { AppHeader } from "@/components/shared/app-header"; import { DebugPanel } from "@/components/shared/debug-panel"; import { AboutModal } from "@/components/shared/about-modal"; import { AgentView } from "@/components/agent/agent-view"; import { WorkflowView } from "@/components/workflow/workflow-view"; import { LoadingState } from "@/components/ui/loading-state"; import { apiClient } from "@/services/api"; import { ChevronLeft } from "lucide-react"; import type { AgentInfo, WorkflowInfo, AppState, ExtendedResponseStreamEvent, } from "@/types"; export default function App() { const [appState, setAppState] = useState({ agents: [], workflows: [], isLoading: true, }); const [debugEvents, setDebugEvents] = useState( [] ); const [debugPanelOpen, setDebugPanelOpen] = useState(true); const [debugPanelWidth, setDebugPanelWidth] = useState(() => { // Initialize from localStorage or default to 320 const savedWidth = localStorage.getItem("debugPanelWidth"); return savedWidth ? parseInt(savedWidth, 10) : 320; }); const [isResizing, setIsResizing] = useState(false); const [showAboutModal, setShowAboutModal] = useState(false); // Initialize app - load agents and workflows useEffect(() => { const loadData = async () => { try { // Load agents and workflows in parallel const [agents, workflows] = await Promise.all([ apiClient.getAgents(), apiClient.getWorkflows(), ]); setAppState((prev) => ({ ...prev, agents, workflows, selectedAgent: agents.length > 0 ? agents[0] : workflows.length > 0 ? workflows[0] : undefined, isLoading: false, })); } catch (error) { console.error("Failed to load agents/workflows:", error); setAppState((prev) => ({ ...prev, error: error instanceof Error ? error.message : "Failed to load data", isLoading: false, })); } }; loadData(); }, []); // Save debug panel width to localStorage useEffect(() => { localStorage.setItem("debugPanelWidth", debugPanelWidth.toString()); }, [debugPanelWidth]); // Handle resize drag const handleMouseDown = useCallback( (e: React.MouseEvent) => { e.preventDefault(); setIsResizing(true); const startX = e.clientX; const startWidth = debugPanelWidth; const handleMouseMove = (e: MouseEvent) => { const deltaX = startX - e.clientX; // Subtract because we're dragging from right const newWidth = Math.max( 200, Math.min(window.innerWidth * 0.5, startWidth + deltaX) ); setDebugPanelWidth(newWidth); }; const handleMouseUp = () => { setIsResizing(false); document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); }, [debugPanelWidth] ); // Handle double-click to collapse const handleDoubleClick = useCallback(() => { setDebugPanelOpen(false); }, []); // Handle entity selection const handleEntitySelect = useCallback((item: AgentInfo | WorkflowInfo) => { setAppState((prev) => ({ ...prev, selectedAgent: item, currentThread: undefined, })); // Clear debug events when switching entities setDebugEvents([]); }, []); // Handle debug events from active view const handleDebugEvent = useCallback((event: ExtendedResponseStreamEvent | 'clear') => { if (event === 'clear') { setDebugEvents([]); } else { setDebugEvents((prev) => [...prev, event]); } }, []); // Show loading state while initializing if (appState.isLoading) { return (
{/* Top Bar - Skeleton */}
{/* Loading Content */}
); } // Show error state if loading failed if (appState.error) { return (
{}} isLoading={false} /> {/* Error Content */}
Failed to load entities

{appState.error}

); } // Show empty state if no agents or workflows are available if ( !appState.isLoading && appState.agents.length === 0 && appState.workflows.length === 0 ) { return (
{}} isLoading={false} /> {/* Empty State Content */}
No entities configured

No agents or workflows were found in your configuration. Please check your setup and ensure entities are properly configured.

); } return (
setShowAboutModal(true)} /> {/* Main Content - Split Panel */}
{/* Left Panel - Main View */}
{appState.selectedAgent ? ( appState.selectedAgent.type === "agent" ? ( ) : ( ) ) : (
Select an agent or workflow to get started.
)}
{/* Resize Handle */} {debugPanelOpen && (
)} {/* Button to reopen when closed */} {!debugPanelOpen && (
)} {/* Right Panel - Debug */} {debugPanelOpen && (
)}
{/* About Modal */}
); }