/** * Running Agents View * * Displays all currently running agents across all projects. * Uses React Query for data fetching with automatic polling. */ import { useState, 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, type 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'; import { useRunningAgents } from '@/hooks/queries'; import { useStopFeature } from '@/hooks/mutations'; export function RunningAgentsView() { const [selectedAgent, setSelectedAgent] = useState(null); const { setCurrentProject, projects } = useAppStore(); const navigate = useNavigate(); const logger = createLogger('RunningAgentsView'); // Use React Query for running agents with auto-refresh const { data, isLoading, isFetching, refetch } = useRunningAgents(); const runningAgents = data?.agents ?? []; // Use mutation for stopping features const stopFeature = useStopFeature(); const handleRefresh = useCallback(() => { refetch(); }, [refetch]); const handleStopAgent = useCallback( async (agent: RunningAgent) => { const api = getElectronAPI(); // Handle backlog plans separately - they use a different API const isBacklogPlan = agent.featureId.startsWith('backlog-plan:'); if (isBacklogPlan && api.backlogPlan) { logger.debug('Stopping backlog plan agent', { featureId: agent.featureId }); await api.backlogPlan.stop(); refetch(); return; } // Use mutation for regular features stopFeature.mutate({ featureId: agent.featureId, projectPath: agent.projectPath }); }, [stopFeature, refetch, logger] ); const handleNavigateToProject = useCallback( (agent: RunningAgent) => { 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 (isLoading) { 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" /> )}
); }