import { useMemo } from 'react' import type { AgentInfo } from '../types/visual' import type { AgentAnimStatus, KanbanTask } from '../types/kanban' import { AGENT_STATUS_LABEL } from '../types/kanban' interface AgentStatusBarProps { agents: AgentInfo[] tasks: KanbanTask[] } interface AgentState { agent: AgentInfo status: AgentAnimStatus currentTool?: string taskDisplayId?: string } export function AgentStatusBar({ agents, tasks }: AgentStatusBarProps) { const agentStates = useMemo(() => { const tasksById = new Map(tasks.map((task) => [task.id, task])) return agents.map(agent => { // Find the first active (non-idle) task for this agent const activeTask = tasks.find( t => t.assigneeIds.includes(agent.agent_id) && t.agentStatus && t.agentStatus !== 'idle' ) const runtimeTask = agent.current_task_id ? tasksById.get(agent.current_task_id) : undefined return { agent, status: (activeTask?.agentStatus ?? agent.runtime_status ?? 'idle') as AgentAnimStatus, currentTool: activeTask?.currentTool ?? agent.current_tool, taskDisplayId: activeTask?.displayId ?? runtimeTask?.displayId, } }) }, [agents, tasks]) if (agents.length === 0) return null const activeCount = agentStates.filter(s => s.status !== 'idle').length return (
{activeCount > 0 ? `${activeCount}/${agents.length} active` : `${agents.length} agent${agents.length !== 1 ? 's' : ''}`}
{agentStates.map(({ agent, status, currentTool, taskDisplayId }) => (
{agent.name.charAt(0).toUpperCase()} {agent.name} {status !== 'idle' && ( <> {status === 'tool_active' && currentTool ? currentTool : AGENT_STATUS_LABEL[status]} )} {taskDisplayId && ( {taskDisplayId} )}
))}
) }