diff --git a/backend/apps/agents/core/ws_manager.py b/backend/apps/agents/core/ws_manager.py index 14ddb760..302a5e03 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/agents/manager/AgentLaunchMixin.py b/backend/apps/agents/manager/AgentLaunchMixin.py index ddf3abba..8370f26b 100644 --- a/backend/apps/agents/manager/AgentLaunchMixin.py +++ b/backend/apps/agents/manager/AgentLaunchMixin.py @@ -146,6 +146,12 @@ class AgentLaunchMixin: "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 @staticmethod diff --git a/backend/apps/agents/manager/metadata.py b/backend/apps/agents/manager/metadata.py index 268fe70d..85b306ef 100644 --- a/backend/apps/agents/manager/metadata.py +++ b/backend/apps/agents/manager/metadata.py @@ -94,6 +94,11 @@ async def generate_title(session: Optional[AgentSession], session_id: str, first "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 diff --git a/backend/apps/dashboards/dashboards.py b/backend/apps/dashboards/dashboards.py index dace1da5..bbf29e91 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") p_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