# TASK PHASE — AGENT PRESENCE INDICATORS (MVP) Version: 1.0 Status: ACTIVE Target: DAARION.space (Next.js frontend + city-service) ## 1. Мета Реалізувати **Presence Indicators** для всіх агентів у МВП: - Online/Offline статус з Matrix presence - DAGI Router heartbeat індикатори - Візуальні бейджі у всіх місцях де відображаються агенти Правило онтології: > Агенти мають бути **"живими"** — їх статус має бути видимим завжди --- ## 2. Область робіт ### 2.1. Сторінки де потрібні Presence Indicators 1. **Agent List** (`/agents`) — кожен агент у списку 2. **Agent Cabinet** (`/agents/:agentId`) — основний статус агента 3. **Node Dashboard** (`/nodes/:nodeId`) — Node Core Agents (Guardian/Steward) 4. **MicroDAO Dashboard** (`/microdao/:slug`) — Orchestrator + team agents 5. **City Dashboard** (`/city`) — civic agents (DAARWIZZ, DARIO, DARIA) ### 2.2. Типи Presence #### Matrix Presence - `online` — користувач активний (зелений) - `unavailable` — користувач неактивний >5 хв (жовтий) - `offline` — користувач офлайн (сірий) #### DAGI Router Presence - `healthy` — DAGI router відповідає (зелений) - `degraded` — проблеми з router (жовтий) - `offline` — router недоступний (червоний) --- ## 3. Backend Implementation ### 3.1. Додати Presence API Додати до `services/city-service/routes_city.py`: ```python @api_router.get("/agents/presence") async def get_agents_presence(): """ Отримати presence статус всіх активних агентів. """ try: # Get agents from DB agents = await repo_city.list_agents_summaries(limit=1000) # Get Matrix presence from matrix-presence-aggregator matrix_presence = await get_matrix_presence_status() # Get DAGI router health dagi_health = await get_dagi_router_health() # Combine data presence_data = [] for agent in agents: matrix_status = matrix_presence.get(agent["id"], "offline") dagi_status = dagi_health.get(agent["node_id"], {}).get("router_status", "unknown") presence_data.append({ "agent_id": agent["id"], "matrix_presence": matrix_status, "dagi_router_presence": dagi_status, "last_seen": matrix_presence.get(f"{agent['id']}_last_seen"), "node_id": agent.get("node_id") }) return {"presence": presence_data} except Exception as e: logger.error(f"Failed to get agents presence: {e}") raise HTTPException(status_code=500, detail="Failed to get agents presence") ``` ### 3.2. Інтегрувати з існуючими Presence системами Використати: - `matrix-presence-aggregator` для Matrix presence - `city-service/presence_gateway.py` для forwarding - `usePresenceHeartbeat` hook для client-side heartbeats --- ## 4. Frontend Implementation ### 4.1. Presence Hook Створити `apps/web/src/hooks/useAgentPresence.ts`: ```typescript interface AgentPresence { agent_id: string; matrix_presence: 'online' | 'unavailable' | 'offline'; dagi_router_presence: 'healthy' | 'degraded' | 'offline' | 'unknown'; last_seen?: string; node_id?: string; } export function useAgentPresence(agentIds?: string[]) { const [presenceData, setPresenceData] = useState>({}); // Fetch presence data const fetchPresence = useCallback(async () => { try { const params = agentIds ? `?agent_ids=${agentIds.join(',')}` : ''; const res = await fetch(`/api/v1/agents/presence${params}`); const data = await res.json(); setPresenceData(data.presence); } catch (error) { console.error('Failed to fetch agent presence:', error); } }, [agentIds]); // Auto-refresh every 30 seconds useEffect(() => { fetchPresence(); const interval = setInterval(fetchPresence, 30000); return () => clearInterval(interval); }, [fetchPresence]); return presenceData; } ``` ### 4.2. Presence Badge Component Створити `apps/web/src/components/ui/AgentPresenceBadge.tsx`: ```typescript interface AgentPresenceBadgeProps { agentId: string; size?: 'sm' | 'md' | 'lg'; showLabel?: boolean; className?: string; } export function AgentPresenceBadge({ agentId, size = 'sm', showLabel = false, className }: AgentPresenceBadgeProps) { const presenceData = useAgentPresence([agentId]); const presence = presenceData[agentId]; if (!presence) return null; const getStatusInfo = () => { const matrixStatus = presence.matrix_presence; const dagiStatus = presence.dagi_router_presence; // Priority: Matrix status, then DAGI status if (matrixStatus === 'online') { return { color: 'bg-emerald-500', label: 'Online' }; } else if (matrixStatus === 'unavailable') { return { color: 'bg-amber-500', label: 'Away' }; } else if (dagiStatus === 'healthy') { return { color: 'bg-blue-500', label: 'Healthy' }; } else if (dagiStatus === 'degraded') { return { color: 'bg-orange-500', label: 'Degraded' }; } else if (dagiStatus === 'offline') { return { color: 'bg-red-500', label: 'Offline' }; } else { return { color: 'bg-gray-500', label: 'Unknown' }; } }; const statusInfo = getStatusInfo(); const sizeClasses = { sm: 'w-2 h-2', md: 'w-3 h-3', lg: 'w-4 h-4' }; return (
{showLabel && ( {statusInfo.label} )}
); } ``` ### 4.3. Інтеграція в Agent Cards Додати Presence Badge до `apps/web/src/components/agent/AgentCard.tsx`: ```typescript // Inside AgentCard component ``` --- ## 5. Acceptance Criteria 1. **Agent List** (`/agents`) - Кожен агент має presence indicator у правому верхньому куті аватара - Зеленый = online, Жовтий = away, Сірий = offline - Індикатор оновлюється в реальному часі 2. **Agent Cabinet** (`/agents/:agentId`) - Великий presence badge у заголовку - Показує обидва статуси: Matrix + DAGI Router - Індикатор "Last seen: 5 min ago" 3. **Node Dashboard** (`/nodes/:nodeId`) - Guardian/Steward агенти мають presence indicators - Показується DAGI router статус ноди 4. **MicroDAO Dashboard** (`/microdao/:slug`) - Orchestrator агент має presence indicator - Team agents мають presence indicators 5. **Real-time Updates** - Presence оновлюється автоматично кожні 30 секунд - Не блокує рендеринг якщо API недоступне --- ## 6. Файли до створення ### Backend - `services/city-service/routes_presence.py` — presence API endpoints - Інтеграція з `matrix-presence-aggregator` - Інтеграція з DAGI router health checks ### Frontend - `apps/web/src/hooks/useAgentPresence.ts` — presence hook - `apps/web/src/components/ui/AgentPresenceBadge.tsx` — presence badge component - Інтеграція в усі agent-related компоненти ### Конфігурація - Додати presence API до Next.js rewrites - Оновити presence gateway для forwarding agent presence --- ## 7. Тестування ```bash # Перевірити API curl https://daarion.space/api/v1/agents/presence # Перевірити UI # Відкрити /agents - подивитися на presence indicators # Відкрити /agents/daarwizz - подивитися на великий badge # Відкрити /nodes/node-1-hetzner-gex44 - presence для Guardian ``` --- ## 8. Подальше розширення (не в цьому MVP) - Agent typing indicators у кімнатах - Agent "working on task" статус - Presence history & analytics - Push notifications для presence changes - Agent availability scheduling --- **Target Date**: Today **Priority**: High (core UX improvement) **Dependencies**: Matrix presence aggregator, DAGI router health API