'use client';
import { useEffect, useState } from 'react';
import type { SwarmStatusFromApi } from '../../lib/swarm-api';
import { Badge } from '@/components/ui/badge';
import { CheckCircle2, PlayCircle, Clock, AlertCircle, Loader2, Users } from 'lucide-react';
import { AgentAvatar } from '../shared/agent-avatar';
import { useAgentPool } from '../../hooks/use-agent-pool';
interface SwarmInspectorProps {
swarmId: string;
projectRoot: string;
onClose?: () => void;
}
function ProgressBar({ progress }: { progress: number }) {
const filled = Math.round(progress / 10);
const empty = 10 - filled;
return (
Progress
{progress}%
{'█'.repeat(filled)}
{'░'.repeat(empty)}
);
}
export function SwarmInspector({ swarmId, projectRoot }: SwarmInspectorProps) {
const [status, setStatus] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const { getAgentsBySwarm } = useAgentPool(projectRoot);
useEffect(() => {
async function fetchStatus() {
setIsLoading(true);
setError(null);
try {
const response = await fetch(
`/api/swarm/status?projectRoot=${encodeURIComponent(projectRoot)}&epic=${encodeURIComponent(swarmId)}`
);
const payload = await response.json();
if (payload.ok && payload.data) {
setStatus(payload.data);
} else {
setError(payload.error?.message || 'Failed to load swarm status');
}
} catch {
setError('Failed to fetch swarm status');
} finally {
setIsLoading(false);
}
}
fetchStatus();
}, [swarmId, projectRoot]);
const assignedAgents = getAgentsBySwarm(swarmId);
if (isLoading) {
return (
Loading...
);
}
if (error || !status) {
return (
{error || 'No data found'}
);
}
return (
{/* Header */}
{swarmId}
Active Operation
{status.epic_title}
{/* Agent Roster */}
Assigned Agents
{assignedAgents.length}
{assignedAgents.length === 0 ? (
No agents currently assigned.
Use "Join" on the main card.
) : (
{assignedAgents.map(agent => (
{agent.display_name}
{agent.status}
))}
)}
{/* Task Stats */}
Done
{status.completed.length}
Ready
{status.ready_count}
{/* Active Tasks List */}
{status.active.length > 0 && (
Currently Executing
{status.active.map((task) => (
{task.id}
IN PROGRESS
{task.title}
))}
)}
);
}