import { useState, useEffect, useCallback } from 'react'; import { createLogger } from '@automaker/utils/logger'; import { Bot, Folder, RefreshCw, Square, Activity, FileText } from 'lucide-react'; import { Spinner } from '@/components/ui/spinner'; import { getElectronAPI, RunningAgent } from '@/lib/electron'; import { useAppStore } from '@/store/app-store'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { useNavigate } from '@tanstack/react-router'; import { AgentOutputModal } from './board-view/dialogs/agent-output-modal'; const logger = createLogger('RunningAgentsView'); export function RunningAgentsView() { const [runningAgents, setRunningAgents] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [selectedAgent, setSelectedAgent] = useState(null); const { setCurrentProject, projects } = useAppStore(); const navigate = useNavigate(); const fetchRunningAgents = useCallback(async () => { try { const api = getElectronAPI(); if (api.runningAgents) { logger.debug('Fetching running agents list'); const result = await api.runningAgents.getAll(); if (result.success && result.runningAgents) { logger.debug('Running agents list fetched', { count: result.runningAgents.length, }); setRunningAgents(result.runningAgents); } else { logger.debug('Running agents list fetch returned empty/failed', { success: result.success, }); } } else { logger.debug('Running agents API not available'); } } catch (error) { logger.error('Error fetching running agents:', error); } finally { setLoading(false); setRefreshing(false); } }, []); // Initial fetch useEffect(() => { fetchRunningAgents(); }, [fetchRunningAgents]); // Auto-refresh every 2 seconds useEffect(() => { const interval = setInterval(() => { fetchRunningAgents(); }, 2000); return () => clearInterval(interval); }, [fetchRunningAgents]); // Subscribe to auto-mode events to update in real-time useEffect(() => { const api = getElectronAPI(); if (!api.autoMode) { logger.debug('Auto mode API not available for running agents view'); return; } const unsubscribe = api.autoMode.onEvent((event) => { logger.debug('Auto mode event in running agents view', { type: event.type, }); // When a feature completes or errors, refresh the list if (event.type === 'auto_mode_feature_complete' || event.type === 'auto_mode_error') { fetchRunningAgents(); } }); return () => { unsubscribe(); }; }, [fetchRunningAgents]); const handleRefresh = useCallback(() => { logger.debug('Manual refresh requested for running agents'); setRefreshing(true); fetchRunningAgents(); }, [fetchRunningAgents]); const handleStopAgent = useCallback( async (agent: RunningAgent) => { try { const api = getElectronAPI(); const isBacklogPlan = agent.featureId.startsWith('backlog-plan:'); if (isBacklogPlan && api.backlogPlan) { logger.debug('Stopping backlog plan agent', { featureId: agent.featureId }); await api.backlogPlan.stop(); fetchRunningAgents(); return; } if (api.autoMode) { logger.debug('Stopping running agent', { featureId: agent.featureId }); await api.autoMode.stopFeature(agent.featureId); // Refresh list after stopping fetchRunningAgents(); } else { logger.debug('Auto mode API not available to stop agent', { featureId: agent.featureId }); } } catch (error) { logger.error('Error stopping agent:', error); } }, [fetchRunningAgents] ); const handleNavigateToProject = useCallback( (agent: RunningAgent) => { // Find the project by path const project = projects.find((p) => p.path === agent.projectPath); if (project) { logger.debug('Navigating to running agent project', { projectPath: agent.projectPath, featureId: agent.featureId, }); setCurrentProject(project); navigate({ to: '/board' }); } else { logger.debug('Project not found for running agent', { projectPath: agent.projectPath, featureId: agent.featureId, }); } }, [projects, setCurrentProject, navigate] ); const handleViewLogs = useCallback((agent: RunningAgent) => { logger.debug('Opening running agent logs', { featureId: agent.featureId, projectPath: agent.projectPath, }); setSelectedAgent(agent); }, []); if (loading) { return (
); } return (
{/* Header */}

Running Agents

{runningAgents.length === 0 ? 'No agents currently running' : `${runningAgents.length} agent${runningAgents.length === 1 ? '' : 's'} running across all projects`}

{/* Content */} {runningAgents.length === 0 ? (

No Running Agents

Agents will appear here when they are actively working on features. Start an agent from the Kanban board by dragging a feature to "In Progress".

) : (
{runningAgents.map((agent) => (
{/* Status indicator */}
{/* Agent info */}
{agent.title || agent.featureId} {agent.isAutoMode && ( AUTO )}
{agent.description && (

{agent.description}

)}
{/* Actions */}
))}
)} {/* Agent Output Modal */} {selectedAgent && ( setSelectedAgent(null)} projectPath={selectedAgent.projectPath} featureDescription={ selectedAgent.description || selectedAgent.title || selectedAgent.featureId } featureId={selectedAgent.featureId} featureStatus="running" /> )}
); }