Event stream

useEventStream subscribes to workspace events and invalidates queries automatically.

useEventStream opens a WebSocket to the workspace event hub and debounces cache invalidations so your queries stay fresh in near real-time. In most cases, adding it once at the top of your app is all you need.

Basic — auto-invalidate all caches

TSX
import { useEventStream } from "@aeontel/react";

function WorkspaceShell({ workspaceId, children }: Props) {
  const { connected } = useEventStream(workspaceId);
  return (
    <>
      <ConnectionPill connected={connected} />
      {children}
    </>
  );
}

Every event routes to the matching entity's key factory and calls invalidateQueriesagent.updated invalidates agentKeys.all(), run.completed invalidates runKeys.all(), and so on. Invalidations batch on a 500ms debounce to avoid thrash.

With callbacks and filters

TSX
useEventStream(workspaceId, {
  filter: ["run.completed", "agent.*"], // glob patterns
  onEvent: (event) => {
    if (event.type === "run.completed")
      toast.success(`Run ${event.subjectId} done`);
  },
});

The filter is server-side — only matching events are sent over the wire.

Disabling

Pass undefined as the workspace id to keep the hook mounted but inactive (e.g. while the user is on a workspace-less route):

TSX
const { connected } = useEventStream(currentWorkspaceId ?? undefined);

Polling fallback

When connected is true, you can drop list polling to a 60s safety net. See getRefetchInterval for the pattern.