From 3d5aa33a203ea1afc9a41840d7a4f53e642eea75 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Tue, 23 Jun 2026 21:33:09 -0700 Subject: [PATCH] [eric] analytics: wire deeper bridges (agent message via ws_manager, agent created/title, dashboard create/delete/duplicate) --- backend/apps/agents/agent_manager.py | 11 +++++++++++ backend/apps/agents/core/ws_manager.py | 10 ++++++++++ backend/apps/dashboards/dashboards.py | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/backend/apps/agents/agent_manager.py b/backend/apps/agents/agent_manager.py index fbf0e377..30caf1d3 100644 --- a/backend/apps/agents/agent_manager.py +++ b/backend/apps/agents/agent_manager.py @@ -381,6 +381,12 @@ class AgentManager: "session": session.model_dump(mode="json"), }) + try: + from backend.apps.service.analytics import track_agent_created + track_agent_created(id=session.id, dashboard_id=session.dashboard_id) + except Exception: + pass + return session def _build_dir_tree(self, root: str, max_depth: int = 4, prefix: str = "") -> list[str]: @@ -4207,6 +4213,11 @@ class AgentManager: "session_id": session_id, "name": title, }) + try: + from backend.apps.service.analytics import track_agent_title + track_agent_title(id=session_id, title=title) + except Exception: + pass return title async def generate_turn_label( diff --git a/backend/apps/agents/core/ws_manager.py b/backend/apps/agents/core/ws_manager.py index 0a92e2dd..7ea0e913 100644 --- a/backend/apps/agents/core/ws_manager.py +++ b/backend/apps/agents/core/ws_manager.py @@ -90,6 +90,16 @@ class ConnectionManager: if event == "agent:status" and data.get("status") in TERMINAL_STATUSES: seq_log.persist_terminal(session_id, payload_str) + # Mirror every discrete agent message into swarm-analytics. Outside the + # stamp lock (fire-and-forget; must not gate the broadcast). Replays use + # ws.send_text directly, not this path, so reconnects don't double-count. + if event == "agent:message": + try: + from backend.apps.service.analytics import bridge_agent_message + bridge_agent_message(session_id, data.get("message") or {}) + except Exception: + logger.debug("agent:message analytics bridge failed", exc_info=True) + async def replay_to( self, session_id: str, websocket: WebSocket, last_seq: int ) -> dict: diff --git a/backend/apps/dashboards/dashboards.py b/backend/apps/dashboards/dashboards.py index f5fc346d..9cf4a396 100644 --- a/backend/apps/dashboards/dashboards.py +++ b/backend/apps/dashboards/dashboards.py @@ -136,6 +136,11 @@ async def list_dashboards(): async def create_dashboard(body: DashboardCreate): dashboard = Dashboard(name=body.name) _save(dashboard) + try: + from backend.apps.service.analytics import track_dashboard_event + track_dashboard_event(dashboard_id=dashboard.id, action="create") + except Exception: + pass return dashboard.model_dump(mode="json") @@ -452,6 +457,11 @@ async def delete_dashboard(dashboard_id: str): logger.warning(f"Failed to delete active session {sid} during dashboard deletion") _delete(dashboard_id) + try: + from backend.apps.service.analytics import track_dashboard_event + track_dashboard_event(dashboard_id=dashboard_id, action="delete") + except Exception: + pass return {"ok": True} @@ -554,4 +564,10 @@ async def duplicate_dashboard(dashboard_id: str): } atomic_write_json(os.path.join(DATA_DIR, f"{new_id}.json"), new_dashboard) + try: + from backend.apps.service.analytics import track_dashboard_event + track_dashboard_event(dashboard_id=new_id, action="create") + except Exception: + pass + return new_dashboard