claude-mpm 4.2.9__py3-none-any.whl → 4.2.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/cli/commands/dashboard.py +59 -126
  3. claude_mpm/cli/commands/monitor.py +71 -212
  4. claude_mpm/cli/commands/run.py +33 -33
  5. claude_mpm/dashboard/static/css/code-tree.css +8 -16
  6. claude_mpm/dashboard/static/dist/components/code-tree.js +1 -1
  7. claude_mpm/dashboard/static/dist/components/file-viewer.js +2 -0
  8. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  9. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +1 -1
  10. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  11. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  12. claude_mpm/dashboard/static/js/components/code-tree.js +692 -114
  13. claude_mpm/dashboard/static/js/components/file-viewer.js +538 -0
  14. claude_mpm/dashboard/static/js/components/module-viewer.js +26 -0
  15. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +166 -14
  16. claude_mpm/dashboard/static/js/dashboard.js +108 -91
  17. claude_mpm/dashboard/static/js/socket-client.js +9 -7
  18. claude_mpm/dashboard/templates/index.html +2 -7
  19. claude_mpm/hooks/claude_hooks/hook_handler.py +1 -11
  20. claude_mpm/hooks/claude_hooks/services/connection_manager.py +54 -59
  21. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +112 -72
  22. claude_mpm/services/agents/deployment/agent_template_builder.py +0 -1
  23. claude_mpm/services/cli/unified_dashboard_manager.py +354 -0
  24. claude_mpm/services/monitor/__init__.py +20 -0
  25. claude_mpm/services/monitor/daemon.py +256 -0
  26. claude_mpm/services/monitor/event_emitter.py +279 -0
  27. claude_mpm/services/monitor/handlers/__init__.py +20 -0
  28. claude_mpm/services/monitor/handlers/code_analysis.py +334 -0
  29. claude_mpm/services/monitor/handlers/dashboard.py +298 -0
  30. claude_mpm/services/monitor/handlers/hooks.py +491 -0
  31. claude_mpm/services/monitor/management/__init__.py +18 -0
  32. claude_mpm/services/monitor/management/health.py +124 -0
  33. claude_mpm/services/monitor/management/lifecycle.py +298 -0
  34. claude_mpm/services/monitor/server.py +442 -0
  35. claude_mpm/tools/code_tree_analyzer.py +33 -17
  36. {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/METADATA +1 -1
  37. {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/RECORD +41 -36
  38. claude_mpm/cli/commands/socketio_monitor.py +0 -233
  39. claude_mpm/scripts/socketio_daemon.py +0 -571
  40. claude_mpm/scripts/socketio_daemon_hardened.py +0 -937
  41. claude_mpm/scripts/socketio_daemon_wrapper.py +0 -78
  42. claude_mpm/scripts/socketio_server_manager.py +0 -349
  43. claude_mpm/services/cli/dashboard_launcher.py +0 -423
  44. claude_mpm/services/cli/socketio_manager.py +0 -595
  45. claude_mpm/services/dashboard/stable_server.py +0 -1020
  46. claude_mpm/services/socketio/monitor_server.py +0 -505
  47. {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/WHEEL +0 -0
  48. {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/entry_points.txt +0 -0
  49. {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/licenses/LICENSE +0 -0
  50. {claude_mpm-4.2.9.dist-info → claude_mpm-4.2.11.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,298 @@
1
+ """
2
+ Dashboard Event Handler for Unified Monitor
3
+ ===========================================
4
+
5
+ WHY: This handler manages dashboard-specific Socket.IO events for the unified
6
+ monitor daemon. It handles client connections, status updates, and dashboard
7
+ state management.
8
+
9
+ DESIGN DECISIONS:
10
+ - Manages client connections and session state
11
+ - Provides dashboard status and health information
12
+ - Handles real-time dashboard updates
13
+ - Integrates with the unified monitor architecture
14
+ """
15
+
16
+ import asyncio
17
+ from typing import Dict, Set
18
+
19
+ import socketio
20
+
21
+ from ....core.logging_config import get_logger
22
+
23
+
24
+ class DashboardHandler:
25
+ """Event handler for dashboard-specific functionality.
26
+
27
+ WHY: Manages dashboard client connections and provides real-time updates
28
+ for the unified monitor daemon.
29
+ """
30
+
31
+ def __init__(self, sio: socketio.AsyncServer):
32
+ """Initialize the dashboard handler.
33
+
34
+ Args:
35
+ sio: Socket.IO server instance
36
+ """
37
+ self.sio = sio
38
+ self.logger = get_logger(__name__)
39
+
40
+ # Client management
41
+ self.connected_clients: Set[str] = set()
42
+ self.client_info: Dict[str, Dict] = {}
43
+
44
+ def register(self):
45
+ """Register Socket.IO event handlers."""
46
+ try:
47
+ # Connection events
48
+ self.sio.on("connect", self.handle_connect)
49
+ self.sio.on("disconnect", self.handle_disconnect)
50
+
51
+ # Dashboard events
52
+ self.sio.on("dashboard:status", self.handle_get_status)
53
+ self.sio.on("dashboard:info", self.handle_get_info)
54
+ self.sio.on("dashboard:ping", self.handle_ping)
55
+
56
+ # Client management
57
+ self.sio.on("client:register", self.handle_client_register)
58
+ self.sio.on("client:list", self.handle_client_list)
59
+
60
+ self.logger.info("Dashboard event handlers registered")
61
+
62
+ except Exception as e:
63
+ self.logger.error(f"Error registering dashboard handlers: {e}")
64
+ raise
65
+
66
+ async def handle_connect(self, sid: str, environ: Dict):
67
+ """Handle client connection.
68
+
69
+ Args:
70
+ sid: Socket.IO session ID
71
+ environ: Connection environment
72
+ """
73
+ try:
74
+ self.connected_clients.add(sid)
75
+
76
+ # Extract client info
77
+ client_info = {
78
+ "connected_at": asyncio.get_event_loop().time(),
79
+ "user_agent": environ.get("HTTP_USER_AGENT", "Unknown"),
80
+ "remote_addr": environ.get("REMOTE_ADDR", "Unknown"),
81
+ }
82
+ self.client_info[sid] = client_info
83
+
84
+ self.logger.info(f"Dashboard client connected: {sid}")
85
+
86
+ # Send welcome message
87
+ await self.sio.emit(
88
+ "dashboard:welcome",
89
+ {
90
+ "message": "Connected to Claude MPM Unified Monitor",
91
+ "session_id": sid,
92
+ "server_info": {"service": "unified-monitor", "version": "1.0.0"},
93
+ },
94
+ room=sid,
95
+ )
96
+
97
+ # Broadcast client count update
98
+ await self._broadcast_client_count()
99
+
100
+ except Exception as e:
101
+ self.logger.error(f"Error handling client connection: {e}")
102
+
103
+ async def handle_disconnect(self, sid: str):
104
+ """Handle client disconnection.
105
+
106
+ Args:
107
+ sid: Socket.IO session ID
108
+ """
109
+ try:
110
+ self.connected_clients.discard(sid)
111
+ self.client_info.pop(sid, None)
112
+
113
+ self.logger.info(f"Dashboard client disconnected: {sid}")
114
+
115
+ # Broadcast client count update
116
+ await self._broadcast_client_count()
117
+
118
+ except Exception as e:
119
+ self.logger.error(f"Error handling client disconnection: {e}")
120
+
121
+ async def handle_get_status(self, sid: str, data: Dict):
122
+ """Handle dashboard status request.
123
+
124
+ Args:
125
+ sid: Socket.IO session ID
126
+ data: Request data
127
+ """
128
+ try:
129
+ status = {
130
+ "service": "unified-monitor",
131
+ "status": "running",
132
+ "clients_connected": len(self.connected_clients),
133
+ "uptime": asyncio.get_event_loop().time(),
134
+ "features": {
135
+ "code_analysis": True,
136
+ "real_ast": True,
137
+ "file_monitoring": True,
138
+ "dashboard": True,
139
+ },
140
+ }
141
+
142
+ await self.sio.emit("dashboard:status:response", status, room=sid)
143
+
144
+ except Exception as e:
145
+ self.logger.error(f"Error getting dashboard status: {e}")
146
+ await self.sio.emit(
147
+ "dashboard:error", {"error": f"Status error: {e!s}"}, room=sid
148
+ )
149
+
150
+ async def handle_get_info(self, sid: str, data: Dict):
151
+ """Handle dashboard info request.
152
+
153
+ Args:
154
+ sid: Socket.IO session ID
155
+ data: Request data
156
+ """
157
+ try:
158
+ info = {
159
+ "service_name": "Claude MPM Unified Monitor",
160
+ "description": "Single stable daemon for all monitoring functionality",
161
+ "features": [
162
+ "Real AST Analysis",
163
+ "Code Tree Visualization",
164
+ "File System Monitoring",
165
+ "Socket.IO Events",
166
+ "HTTP Dashboard",
167
+ ],
168
+ "endpoints": {"dashboard": "/", "health": "/health", "api": "/api/*"},
169
+ "events": {
170
+ "code_analysis": [
171
+ "code:analyze:file",
172
+ "code:analyze:directory",
173
+ "code:get:tree",
174
+ ],
175
+ "dashboard": [
176
+ "dashboard:status",
177
+ "dashboard:info",
178
+ "dashboard:ping",
179
+ ],
180
+ },
181
+ }
182
+
183
+ await self.sio.emit("dashboard:info:response", info, room=sid)
184
+
185
+ except Exception as e:
186
+ self.logger.error(f"Error getting dashboard info: {e}")
187
+ await self.sio.emit(
188
+ "dashboard:error", {"error": f"Info error: {e!s}"}, room=sid
189
+ )
190
+
191
+ async def handle_ping(self, sid: str, data: Dict):
192
+ """Handle ping request.
193
+
194
+ Args:
195
+ sid: Socket.IO session ID
196
+ data: Request data
197
+ """
198
+ try:
199
+ timestamp = data.get("timestamp", asyncio.get_event_loop().time())
200
+
201
+ await self.sio.emit(
202
+ "dashboard:pong",
203
+ {
204
+ "timestamp": timestamp,
205
+ "server_time": asyncio.get_event_loop().time(),
206
+ },
207
+ room=sid,
208
+ )
209
+
210
+ except Exception as e:
211
+ self.logger.error(f"Error handling ping: {e}")
212
+
213
+ async def handle_client_register(self, sid: str, data: Dict):
214
+ """Handle client registration.
215
+
216
+ Args:
217
+ sid: Socket.IO session ID
218
+ data: Client registration data
219
+ """
220
+ try:
221
+ client_name = data.get("name", f"Client-{sid[:8]}")
222
+ client_type = data.get("type", "dashboard")
223
+
224
+ # Update client info
225
+ if sid in self.client_info:
226
+ self.client_info[sid].update(
227
+ {"name": client_name, "type": client_type, "registered": True}
228
+ )
229
+
230
+ self.logger.info(f"Client registered: {client_name} ({client_type})")
231
+
232
+ await self.sio.emit(
233
+ "client:registered",
234
+ {"name": client_name, "type": client_type, "session_id": sid},
235
+ room=sid,
236
+ )
237
+
238
+ except Exception as e:
239
+ self.logger.error(f"Error registering client: {e}")
240
+ await self.sio.emit(
241
+ "dashboard:error", {"error": f"Registration error: {e!s}"}, room=sid
242
+ )
243
+
244
+ async def handle_client_list(self, sid: str, data: Dict):
245
+ """Handle client list request.
246
+
247
+ Args:
248
+ sid: Socket.IO session ID
249
+ data: Request data
250
+ """
251
+ try:
252
+ client_list = []
253
+ for client_sid, info in self.client_info.items():
254
+ client_list.append(
255
+ {
256
+ "session_id": client_sid,
257
+ "name": info.get("name", f"Client-{client_sid[:8]}"),
258
+ "type": info.get("type", "unknown"),
259
+ "connected_at": info.get("connected_at"),
260
+ "registered": info.get("registered", False),
261
+ }
262
+ )
263
+
264
+ await self.sio.emit(
265
+ "client:list:response",
266
+ {"clients": client_list, "total": len(client_list)},
267
+ room=sid,
268
+ )
269
+
270
+ except Exception as e:
271
+ self.logger.error(f"Error getting client list: {e}")
272
+ await self.sio.emit(
273
+ "dashboard:error", {"error": f"Client list error: {e!s}"}, room=sid
274
+ )
275
+
276
+ async def _broadcast_client_count(self):
277
+ """Broadcast client count update to all connected clients."""
278
+ try:
279
+ await self.sio.emit(
280
+ "dashboard:client:count", {"count": len(self.connected_clients)}
281
+ )
282
+
283
+ except Exception as e:
284
+ self.logger.error(f"Error broadcasting client count: {e}")
285
+
286
+ def get_stats(self) -> Dict:
287
+ """Get handler statistics.
288
+
289
+ Returns:
290
+ Dictionary with handler stats
291
+ """
292
+ return {
293
+ "connected_clients": len(self.connected_clients),
294
+ "registered_clients": sum(
295
+ 1 for info in self.client_info.values() if info.get("registered", False)
296
+ ),
297
+ "client_types": {},
298
+ }