/** * useRealtimeSync — mounts the SSE connection once at the app level and * wires incoming events to React Query cache invalidation. * * Event → query key mapping: * agent.status → ['agents'] * agent.task → ['tasks'], ['agents'] * agent.progress → ['tasks'], ['agents'] * fleet.update → ['agents'], ['sessions'], ['tasks'] */ import { useQueryClient } from '@tanstack/react-query' import { useCallback } from 'react' import { useSSE, type SSEMessage, type SSEStatus } from './useSSE' export function useRealtimeSync(): { sseStatus: SSEStatus } { const queryClient = useQueryClient() const handleMessage = useCallback( (msg: SSEMessage) => { switch (msg.type) { case 'agent.status': queryClient.invalidateQueries({ queryKey: ['agents'] }) break case 'agent.task': queryClient.invalidateQueries({ queryKey: ['tasks'] }) queryClient.invalidateQueries({ queryKey: ['agents'] }) break case 'agent.progress': queryClient.invalidateQueries({ queryKey: ['tasks'] }) queryClient.invalidateQueries({ queryKey: ['agents'] }) break case 'fleet.update': queryClient.invalidateQueries({ queryKey: ['agents'] }) queryClient.invalidateQueries({ queryKey: ['sessions'] }) queryClient.invalidateQueries({ queryKey: ['tasks'] }) break default: // 'connected' and unknown events — no action needed break } }, [queryClient], ) const { status: sseStatus } = useSSE({ onMessage: handleMessage }) return { sseStatus } }