Task for implementing real-time presence indicators for all agents. Shows Matrix presence (online/unavailable/offline) and DAGI router health. Integrates into agent lists, cabinets, node dashboards, microdao dashboards.
8.7 KiB
8.7 KiB
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
- Agent List (
/agents) — кожен агент у списку - Agent Cabinet (
/agents/:agentId) — основний статус агента - Node Dashboard (
/nodes/:nodeId) — Node Core Agents (Guardian/Steward) - MicroDAO Dashboard (
/microdao/:slug) — Orchestrator + team agents - 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:
@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 presencecity-service/presence_gateway.pyдля forwardingusePresenceHeartbeathook для client-side heartbeats
4. Frontend Implementation
4.1. Presence Hook
Створити apps/web/src/hooks/useAgentPresence.ts:
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<Record<string, AgentPresence>>({});
// 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:
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 (
<div className={cn('flex items-center gap-1.5', className)}>
<div className={cn(
'rounded-full border border-white/20',
sizeClasses[size],
statusInfo.color
)} />
{showLabel && (
<span className="text-xs text-white/70">{statusInfo.label}</span>
)}
</div>
);
}
4.3. Інтеграція в Agent Cards
Додати Presence Badge до apps/web/src/components/agent/AgentCard.tsx:
// Inside AgentCard component
<AgentPresenceBadge
agentId={agent.id}
size="sm"
showLabel={false}
className="absolute top-2 right-2"
/>
5. Acceptance Criteria
-
Agent List (
/agents)- Кожен агент має presence indicator у правому верхньому куті аватара
- Зеленый = online, Жовтий = away, Сірий = offline
- Індикатор оновлюється в реальному часі
-
Agent Cabinet (
/agents/:agentId)- Великий presence badge у заголовку
- Показує обидва статуси: Matrix + DAGI Router
- Індикатор "Last seen: 5 min ago"
-
Node Dashboard (
/nodes/:nodeId)- Guardian/Steward агенти мають presence indicators
- Показується DAGI router статус ноди
-
MicroDAO Dashboard (
/microdao/:slug)- Orchestrator агент має presence indicator
- Team agents мають presence indicators
-
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 hookapps/web/src/components/ui/AgentPresenceBadge.tsx— presence badge component- Інтеграція в усі agent-related компоненти
Конфігурація
- Додати presence API до Next.js rewrites
- Оновити presence gateway для forwarding agent presence
7. Тестування
# Перевірити 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