claude-mpm 4.1.12__py3-none-any.whl → 4.1.13__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 (30) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/cli/commands/monitor.py +88 -627
  3. claude_mpm/cli/commands/mpm_init.py +7 -2
  4. claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
  5. claude_mpm/dashboard/static/built/components/code-tree.js +1 -1
  6. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  7. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  8. claude_mpm/dashboard/static/css/activity.css +1239 -267
  9. claude_mpm/dashboard/static/css/dashboard.css +511 -0
  10. claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
  11. claude_mpm/dashboard/static/dist/components/code-tree.js +2 -2593
  12. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  13. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  14. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  15. claude_mpm/dashboard/static/js/components/activity-tree.js +1193 -892
  16. claude_mpm/dashboard/static/js/components/code-tree.js +0 -17
  17. claude_mpm/dashboard/static/js/components/module-viewer.js +21 -7
  18. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +1066 -0
  19. claude_mpm/dashboard/static/js/connection-manager.js +1 -1
  20. claude_mpm/dashboard/static/js/dashboard.js +196 -43
  21. claude_mpm/dashboard/static/js/socket-client.js +2 -2
  22. claude_mpm/dashboard/templates/index.html +95 -25
  23. claude_mpm/services/cli/socketio_manager.py +1 -1
  24. claude_mpm/services/infrastructure/monitoring.py +1 -1
  25. {claude_mpm-4.1.12.dist-info → claude_mpm-4.1.13.dist-info}/METADATA +1 -1
  26. {claude_mpm-4.1.12.dist-info → claude_mpm-4.1.13.dist-info}/RECORD +30 -29
  27. {claude_mpm-4.1.12.dist-info → claude_mpm-4.1.13.dist-info}/WHEEL +0 -0
  28. {claude_mpm-4.1.12.dist-info → claude_mpm-4.1.13.dist-info}/entry_points.txt +0 -0
  29. {claude_mpm-4.1.12.dist-info → claude_mpm-4.1.13.dist-info}/licenses/LICENSE +0 -0
  30. {claude_mpm-4.1.12.dist-info → claude_mpm-4.1.13.dist-info}/top_level.txt +0 -0
@@ -3,28 +3,29 @@ Monitor command implementation for claude-mpm.
3
3
 
4
4
  WHY: This module provides CLI commands for managing the Socket.IO monitoring server,
5
5
  allowing users to start, stop, restart, and check status of the monitoring infrastructure.
6
+ The monitor command now delegates to the unified dashboard service for consolidated operation.
6
7
 
7
8
  DESIGN DECISIONS:
9
+ - Delegate to dashboard command for unified service architecture
8
10
  - Use BaseCommand for consistent CLI patterns
9
- - Leverage shared utilities for argument parsing and output formatting
10
11
  - Maintain backward compatibility with existing Socket.IO server management
11
12
  - Support multiple output formats (json, yaml, table, text)
12
13
  """
13
14
 
14
- import subprocess
15
- import sys
16
15
  from typing import Optional
17
16
 
18
17
  from ...constants import MonitorCommands
19
- from ...core.logger import get_logger
20
18
  from ..shared import BaseCommand, CommandResult
19
+ from .dashboard import DashboardCommand
21
20
 
22
21
 
23
22
  class MonitorCommand(BaseCommand):
24
- """Monitor command using shared utilities."""
23
+ """Monitor command that delegates to the unified dashboard service."""
25
24
 
26
25
  def __init__(self):
27
26
  super().__init__("monitor")
27
+ # Create dashboard command instance for delegation
28
+ self.dashboard_command = DashboardCommand()
28
29
 
29
30
  def validate_args(self, args) -> Optional[str]:
30
31
  """Validate command arguments."""
@@ -37,41 +38,26 @@ class MonitorCommand(BaseCommand):
37
38
  return None
38
39
 
39
40
  def run(self, args) -> CommandResult:
40
- """Execute the monitor command."""
41
+ """Execute the monitor command by delegating to dashboard service."""
41
42
  try:
42
- # Import ServerManager
43
- from ...scripts.socketio_server_manager import ServerManager
43
+ self.logger.info("Monitor command delegating to unified dashboard service")
44
44
 
45
- server_manager = ServerManager()
46
-
47
- # Handle default case (no subcommand)
45
+ # Handle default case (no subcommand) - default to status
48
46
  if not hasattr(args, "monitor_command") or not args.monitor_command:
49
- # Default to status
50
- success = self._status_server(args, server_manager)
51
- if success:
52
- return CommandResult.success_result(
53
- "Monitor status retrieved successfully"
54
- )
55
- return CommandResult.error_result("Failed to retrieve monitor status")
56
-
57
- # Route to specific subcommand handlers
58
- command_map = {
59
- MonitorCommands.START.value: self._start_server,
60
- MonitorCommands.STOP.value: self._stop_server,
61
- MonitorCommands.RESTART.value: self._restart_server,
62
- MonitorCommands.STATUS.value: self._status_server,
63
- MonitorCommands.PORT.value: self._port_server,
64
- }
65
-
66
- if args.monitor_command in command_map:
67
- success = command_map[args.monitor_command](args, server_manager)
68
- if success:
69
- return CommandResult.success_result(
70
- f"Monitor {args.monitor_command} completed successfully"
71
- )
72
- return CommandResult.error_result(
73
- f"Monitor {args.monitor_command} failed"
74
- )
47
+ return self._status_dashboard(args)
48
+
49
+ # Map monitor commands to dashboard commands
50
+ if args.monitor_command == MonitorCommands.START.value:
51
+ return self._start_dashboard(args)
52
+ if args.monitor_command == MonitorCommands.STOP.value:
53
+ return self._stop_dashboard(args)
54
+ if args.monitor_command == MonitorCommands.RESTART.value:
55
+ return self._restart_dashboard(args)
56
+ if args.monitor_command == MonitorCommands.STATUS.value:
57
+ return self._status_dashboard(args)
58
+ if args.monitor_command == MonitorCommands.PORT.value:
59
+ return self._start_dashboard_on_port(args)
60
+
75
61
  return CommandResult.error_result(
76
62
  f"Unknown monitor command: {args.monitor_command}"
77
63
  )
@@ -80,616 +66,91 @@ class MonitorCommand(BaseCommand):
80
66
  self.logger.error(f"Error executing monitor command: {e}", exc_info=True)
81
67
  return CommandResult.error_result(f"Error executing monitor command: {e}")
82
68
 
83
- def _start_server(self, args, server_manager) -> bool:
84
- """Start the monitoring server."""
85
- return _start_server(args, server_manager)
86
-
87
- def _stop_server(self, args, server_manager) -> bool:
88
- """Stop the monitoring server."""
89
- return _stop_server(args, server_manager)
90
-
91
- def _restart_server(self, args, server_manager) -> bool:
92
- """Restart the monitoring server."""
93
- return _restart_server(args, server_manager)
94
-
95
- def _status_server(self, args, server_manager) -> bool:
96
- """Get monitoring server status."""
97
- return _status_server(args, server_manager)
98
-
99
- def _port_server(self, args, server_manager) -> bool:
100
- """Start/restart server on specific port."""
101
- return _port_server(args, server_manager)
102
-
103
-
104
- def manage_monitor(args):
105
- """
106
- Main entry point for monitor command.
107
-
108
- This function maintains backward compatibility while using the new BaseCommand pattern.
109
- """
110
- command = MonitorCommand()
111
- result = command.execute(args)
112
-
113
- # Print result if structured output format is requested
114
- if hasattr(args, "format") and args.format in ["json", "yaml"]:
115
- command.print_result(result, args)
116
-
117
- return result.exit_code
118
-
119
-
120
- def manage_monitor_legacy(args):
121
- """
122
- Legacy monitor command dispatcher.
123
-
124
- WHY: This contains the original manage_monitor logic, preserved during migration
125
- to BaseCommand pattern. Will be gradually refactored into the MonitorCommand class.
126
-
127
- DESIGN DECISION: When no subcommand is provided, we show the server status
128
- as the default action, giving users a quick overview of the monitoring system.
129
-
130
- Args:
131
- args: Parsed command line arguments with monitor_command attribute
132
- """
133
- logger = get_logger("cli")
134
-
135
- try:
136
- # Import ServerManager from socketio_server_manager.py
137
- from ...scripts.socketio_server_manager import ServerManager
138
-
139
- server_manager = ServerManager()
140
-
141
- if not args.monitor_command:
142
- # No subcommand - show status as default
143
- # WHY: Status is the most common operation users want when running monitor without args
144
- args.verbose = False # Set default for verbose flag
145
- success = _status_server(args, server_manager)
146
- return 0 if success else 1
147
-
148
- if args.monitor_command == MonitorCommands.START.value:
149
- success = _start_server(args, server_manager)
150
- return 0 if success else 1
69
+ def _start_dashboard(self, args) -> CommandResult:
70
+ """Start the dashboard service (unified HTTP + Socket.IO)."""
71
+ self.logger.info("Starting unified dashboard service (HTTP + Socket.IO)")
72
+ # Set default port to 8765 for unified service and background mode
73
+ if not hasattr(args, "port") or args.port is None:
74
+ args.port = 8765
75
+ # Monitor command defaults to background mode for better UX
76
+ if not hasattr(args, "background"):
77
+ args.background = True
151
78
 
152
- if args.monitor_command == MonitorCommands.STOP.value:
153
- success = _stop_server(args, server_manager)
154
- return 0 if success else 1
79
+ return self.dashboard_command._start_dashboard(args)
155
80
 
156
- if args.monitor_command == MonitorCommands.RESTART.value:
157
- success = _restart_server(args, server_manager)
158
- return 0 if success else 1
81
+ def _stop_dashboard(self, args) -> CommandResult:
82
+ """Stop the dashboard service."""
83
+ self.logger.info("Stopping unified dashboard service")
84
+ # Use default port if not specified
85
+ if not hasattr(args, "port") or args.port is None:
86
+ args.port = 8765
159
87
 
160
- if args.monitor_command == MonitorCommands.STATUS.value:
161
- success = _status_server(args, server_manager)
162
- return 0 if success else 1
88
+ return self.dashboard_command._stop_dashboard(args)
163
89
 
164
- if args.monitor_command == MonitorCommands.PORT.value:
165
- success = _port_server(args, server_manager)
166
- return 0 if success else 1
90
+ def _restart_dashboard(self, args) -> CommandResult:
91
+ """Restart the dashboard service."""
92
+ self.logger.info("Restarting unified dashboard service")
167
93
 
168
- logger.error(f"Unknown monitor command: {args.monitor_command}")
169
- print(f"Unknown monitor command: {args.monitor_command}")
170
- print("Available commands: start, stop, restart, status, port")
171
- return 1
172
-
173
- except ImportError as e:
174
- logger.error(f"Server manager not available: {e}")
175
- print("Error: Socket.IO server manager not available")
176
- print("This may indicate a missing dependency or installation issue.")
177
- return 1
178
- except Exception as e:
179
- logger.error(f"Error managing monitor: {e}")
180
- print(f"Error: {e}")
181
- return 1
182
-
183
- return 0
184
-
185
-
186
- def _port_server(args, server_manager):
187
- """
188
- Start or restart the Socket.IO monitoring server on a specific port.
94
+ # Stop first
95
+ stop_result = self._stop_dashboard(args)
96
+ if not stop_result.success:
97
+ self.logger.warning("Failed to stop service for restart, proceeding anyway")
189
98
 
190
- WHY: Users need to be able to start/restart the monitoring server on a specific
191
- port, either if no server is running (start) or if a server is already running
192
- on a different port (restart). Enhanced with smart process detection to reclaim
193
- ports from debug processes.
99
+ # Wait a moment
100
+ import time
194
101
 
195
- Args:
196
- args: Command arguments with required port and optional host, force, reclaim flags
197
- server_manager: ServerManager instance
102
+ time.sleep(1)
198
103
 
199
- Returns:
200
- bool: True if server started/restarted successfully, False otherwise
201
- """
202
- port = args.port
203
- host = getattr(args, "host", "localhost")
204
- force = getattr(args, "force", False)
205
- reclaim = getattr(args, "reclaim", True)
206
-
207
- print(f"Managing Socket.IO monitoring server on port {port}...")
208
- print(f"Target: {host}:{port}")
209
- print()
210
-
211
- try:
212
- # Import PortManager to check port status
213
- from ...services.port_manager import PortManager
214
-
215
- port_manager = PortManager()
216
-
217
- # Get detailed port status
218
- port_status = port_manager.get_port_status(port)
219
-
220
- # Check if port is in use
221
- if not port_status["available"]:
222
- process_info = port_status.get("process")
223
- if process_info:
224
- print(f"⚠️ Port {port} is in use:")
225
- print(f" Process: {process_info['name']} (PID: {process_info['pid']})")
226
-
227
- if process_info["is_ours"]:
228
- if process_info["is_debug"]:
229
- print(" Type: Debug/Test script (can be reclaimed)")
230
- if reclaim:
231
- print(" Action: Attempting to reclaim port...")
232
- if port_manager.kill_process_on_port(port, force=force):
233
- print(f" ✅ Successfully reclaimed port {port}")
234
- else:
235
- print(f" ❌ Failed to reclaim port {port}")
236
- return False
237
- elif process_info["is_daemon"]:
238
- print(" Type: Daemon process")
239
- if force:
240
- print(
241
- " Action: Force killing daemon (--force flag used)..."
242
- )
243
- if port_manager.kill_process_on_port(port, force=True):
244
- print(f" ✅ Successfully killed daemon on port {port}")
245
- else:
246
- print(f" ❌ Failed to kill daemon on port {port}")
247
- return False
248
- else:
249
- print(" ❌ Cannot start: Daemon already running")
250
- print(f" Recommendation: {port_status['recommendation']}")
251
- return False
252
- else:
253
- print(" Type: External process")
254
- print(f" ❌ Cannot start: {port_status['recommendation']}")
255
- return False
256
- print()
257
-
258
- # Check if there are any running servers
259
- running_servers = server_manager.list_running_servers()
260
-
261
- # Check if server is already running on this port after reclaim
262
- server_on_port = any(server.get("port") == port for server in running_servers)
263
-
264
- if server_on_port:
265
- print(f"Server already running on port {port}. Restarting...")
266
- success = server_manager.restart_server(port=port)
267
- action = "restarted"
268
- else:
269
- # Check if servers are running on other ports
270
- if running_servers:
271
- print("Servers running on other ports:")
272
- for server in running_servers:
273
- server_port = server.get("port")
274
- server_id = server.get("server_id", "unknown")
275
- print(f" • Server '{server_id}' on port {server_port}")
276
- print()
277
- print(f"Starting new server on port {port}...")
278
- else:
279
- print("No servers currently running. Starting new server...")
280
-
281
- success = server_manager.start_server(
282
- port=port, host=host, server_id="monitor-server"
283
- )
284
- action = "started"
285
-
286
- if success:
287
- print()
288
- print(f"Monitor server {action} successfully on port {port}")
289
- print()
290
- print("Server management commands:")
291
- print(" Status: ps aux | grep socketio")
292
- print(f" Stop: claude-mpm monitor stop --port {port}")
293
- print(f" Restart: claude-mpm monitor restart --port {port}")
294
- print()
295
- print(f"WebSocket URL: ws://{host}:{port}")
296
- else:
297
- print(f"Failed to {action.replace('ed', '')} server on port {port}")
298
- print()
299
- print("Troubleshooting:")
300
- print(f" • Check if port {port} is available: lsof -i :{port}")
301
- print(f" • Try a different port: claude-mpm monitor port {port + 1}")
302
- print(" • Check system resources: free -h && df -h")
303
-
304
- return success
305
-
306
- except Exception as e:
307
- print(f"Error managing server on port {port}: {e}")
308
- print()
309
- print("Troubleshooting:")
310
- print(f" • Verify port {port} is valid and available")
311
- print(" • Check system resources and permissions")
312
- print(" • Try manual start/stop operations")
313
- return False
314
-
315
-
316
- def _start_server(args, server_manager):
317
- """
318
- Start the Socket.IO monitoring server.
104
+ # Start again
105
+ return self._start_dashboard(args)
319
106
 
320
- WHY: Users need to start the monitoring server to enable real-time monitoring
321
- of Claude MPM sessions and websocket connections. Enhanced with smart process
322
- detection to automatically reclaim ports from debug scripts.
107
+ def _status_dashboard(self, args) -> CommandResult:
108
+ """Get dashboard service status."""
109
+ return self.dashboard_command._status_dashboard(args)
323
110
 
324
- Args:
325
- args: Command arguments with optional port, host, force, and reclaim flags
326
- server_manager: ServerManager instance
327
-
328
- Returns:
329
- bool: True if server started successfully, False otherwise
330
- """
331
- port = getattr(args, "port", None)
332
- host = getattr(args, "host", "localhost")
333
- force = getattr(args, "force", False)
334
- reclaim = getattr(args, "reclaim", True)
335
-
336
- print("Starting Socket.IO monitoring server...")
337
-
338
- try:
339
- # Import PortManager for smart port selection
340
- from ...services.port_manager import PortManager
341
-
342
- port_manager = PortManager()
343
-
344
- # If no port specified, find an available one with smart reclaim
345
- if port is None:
346
- port = port_manager.find_available_port(reclaim=reclaim)
347
- if port is None:
348
- print("❌ No available ports found")
349
- print(
350
- "Try specifying a port with --port or use --force to reclaim daemon ports"
351
- )
352
- return False
353
- print(f"Selected port: {port}")
354
- else:
355
- # Check if specified port needs reclaiming
356
- port_status = port_manager.get_port_status(port)
357
- if not port_status["available"]:
358
- process_info = port_status.get("process")
359
- if process_info:
360
- print(
361
- f"⚠️ Port {port} is in use by {process_info['name']} (PID: {process_info['pid']})"
362
- )
363
-
364
- if process_info["is_ours"] and (process_info["is_debug"] or force):
365
- if reclaim:
366
- print(f"Attempting to reclaim port {port}...")
367
- if not port_manager.kill_process_on_port(port, force=force):
368
- print(f"❌ Failed to reclaim port {port}")
369
- return False
370
- print(f"✅ Successfully reclaimed port {port}")
371
- else:
372
- print(
373
- f"❌ Port {port} unavailable and --no-reclaim specified"
374
- )
375
- return False
376
- else:
377
- print(
378
- f"❌ Cannot reclaim port: {port_status['recommendation']}"
379
- )
380
- return False
381
-
382
- print(f"Target: {host}:{port}")
383
- print()
384
-
385
- success = server_manager.start_server(
386
- port=port, host=host, server_id="monitor-server"
111
+ def _start_dashboard_on_port(self, args) -> CommandResult:
112
+ """Start dashboard service on specific port."""
113
+ self.logger.info(
114
+ f"Starting dashboard service on port {getattr(args, 'port', 8765)}"
387
115
  )
116
+ # Ensure background mode for port-specific starts
117
+ if not hasattr(args, "background"):
118
+ args.background = True
388
119
 
389
- if success:
390
- print()
391
- print("Monitor server management commands:")
392
- print(" Status: claude-mpm monitor status")
393
- print(" Stop: claude-mpm monitor stop")
394
- print(" Restart: claude-mpm monitor restart")
395
- print()
396
- print(f"WebSocket URL: ws://{host}:{port}")
397
-
398
- return success
120
+ return self.dashboard_command._start_dashboard(args)
399
121
 
400
- except Exception as e:
401
- print(f"Failed to start monitoring server: {e}")
402
- print()
403
- print("Troubleshooting:")
404
- print(f" • Check if port {port} is available: lsof -i :{port}")
405
- print(f" • Try a different port: claude-mpm monitor start --port {port + 1}")
406
- print(" • Check system resources: free -h && df -h")
407
- return False
408
122
 
409
-
410
- def _stop_server(args, server_manager):
123
+ def manage_monitor(args):
411
124
  """
412
- Stop the Socket.IO monitoring server.
413
-
414
- WHY: Users need to stop the monitoring server when it's no longer needed
415
- or when troubleshooting connection issues.
416
-
417
- Args:
418
- args: Command arguments with optional port
419
- server_manager: ServerManager instance
125
+ Main entry point for monitor command.
420
126
 
421
- Returns:
422
- bool: True if server stopped successfully, False otherwise
423
- """
424
- port = getattr(args, "port", None)
425
-
426
- print("Stopping Socket.IO monitoring server...")
427
-
428
- try:
429
- # If no port specified, try to find running servers and stop them
430
- if port is None:
431
- running_servers = server_manager.list_running_servers()
432
- if not running_servers:
433
- print("No running servers found to stop")
434
- return True
435
-
436
- # Stop the first server (or all if multiple)
437
- success = True
438
- for server in running_servers:
439
- server_port = server.get("port")
440
- server_id = server.get("server_id", "unknown")
441
- print(f"Stopping server '{server_id}' on port {server_port}...")
442
-
443
- if not server_manager.stop_server(port=server_port):
444
- print(f"Failed to stop server on port {server_port}")
445
- success = False
446
-
447
- return success
448
- # Stop specific server on given port
449
- success = server_manager.stop_server(port=port)
450
-
451
- if success:
452
- print(f"Monitor server stopped on port {port}")
453
- else:
454
- print(f"Failed to stop server on port {port}")
455
- print()
456
- print("Troubleshooting:")
457
- print(" • Check if server is running: claude-mpm monitor status")
458
- print(f" • Try force kill: kill $(lsof -ti :{port})")
459
-
460
- return success
461
-
462
- except Exception as e:
463
- print(f"Error stopping server: {e}")
464
- return False
465
-
466
-
467
- def _status_server(args, server_manager):
127
+ The monitor command now delegates to the unified dashboard service for consolidated operation.
128
+ Both dashboard and monitor commands now use the same underlying service on port 8765.
468
129
  """
469
- Check the status of Socket.IO monitoring servers.
470
-
471
- WHY: Users need to check if the monitoring server is running, what port
472
- it's using, and other diagnostic information without starting/stopping it.
473
- Enhanced to show what processes are using ports.
130
+ command = MonitorCommand()
131
+ error = command.validate_args(args)
474
132
 
475
- Args:
476
- args: Command arguments with optional verbose flag
477
- server_manager: ServerManager instance
133
+ if error:
134
+ command.logger.error(error)
135
+ print(f"Error: {error}")
136
+ return 1
478
137
 
479
- Returns:
480
- bool: True if status check succeeded, False otherwise
481
- """
482
- verbose = getattr(args, "verbose", False)
483
- show_ports = getattr(args, "show_ports", False)
484
-
485
- print("Checking Socket.IO monitoring server status...")
486
- print()
487
-
488
- try:
489
- # Check for daemon server using socketio_daemon.py
490
- daemon_script = server_manager.daemon_script
491
- if daemon_script and daemon_script.exists():
492
- # Try to get status from daemon
493
- result = subprocess.run(
494
- [sys.executable, str(daemon_script), "status"],
495
- capture_output=True,
496
- text=True,
497
- check=False,
498
- )
138
+ result = command.run(args)
499
139
 
500
- if result.returncode == 0 and result.stdout:
501
- # Daemon provided status information
502
- print(result.stdout)
503
-
504
- if verbose:
505
- # Show additional information
506
- print("\nAdditional Details:")
507
- print("─" * 40)
508
-
509
- # List all running servers from ServerManager
510
- running_servers = server_manager.list_running_servers()
511
- if running_servers:
512
- print(f"Found {len(running_servers)} running server(s):")
513
- for server in running_servers:
514
- server_port = server.get("port", "unknown")
515
- server_id = server.get("server_id", "unknown")
516
- server_pid = server.get("pid", "unknown")
517
- print(f" • Server '{server_id}'")
518
- print(f" Port: {server_port}")
519
- print(f" PID: {server_pid}")
520
- else:
521
- print("No additional servers found via ServerManager")
522
-
523
- return True
524
-
525
- # Fall back to ServerManager's list_running_servers
526
- running_servers = server_manager.list_running_servers()
527
-
528
- if not running_servers:
529
- print("❌ No Socket.IO monitoring servers are currently running")
530
- print()
531
- print("To start a server:")
532
- print(" claude-mpm monitor start")
533
- print(" claude-mpm monitor start --port 8765")
534
- return True
535
-
536
- # Import PortManager for enhanced status
537
- from ...services.port_manager import PortManager
538
-
539
- port_manager = PortManager()
540
-
541
- # Display server information
542
- print(f"✅ Found {len(running_servers)} running server(s):")
543
- print()
544
-
545
- for server in running_servers:
546
- server_port = server.get("port", "unknown")
547
- server_id = server.get("server_id", "unknown")
548
- server_pid = server.get("pid", "unknown")
549
- server_host = server.get("host", "localhost")
550
-
551
- print(f"Server: {server_id}")
552
- print(f" • PID: {server_pid}")
553
- print(f" • Port: {server_port}")
554
- print(f" • Host: {server_host}")
555
- print(f" • WebSocket URL: ws://{server_host}:{server_port}")
556
-
557
- # Show port status if verbose
558
- if verbose and server_port != "unknown":
559
- port_status = port_manager.get_port_status(int(server_port))
560
- if port_status.get("process"):
561
- process = port_status["process"]
562
- print(
563
- f" • Process Type: {'Debug' if process['is_debug'] else 'Daemon' if process['is_daemon'] else 'Regular'}"
564
- )
565
-
566
- if verbose:
567
- # Check if port is actually listening
568
- try:
569
- import socket
570
-
571
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
572
- result = sock.connect_ex((server_host, server_port))
573
- sock.close()
574
- if result == 0:
575
- print(" • Status: ✅ Listening")
576
- else:
577
- print(" • Status: ⚠️ Not responding on port")
578
- except Exception as e:
579
- print(f" • Status: ❌ Error checking: {e}")
580
-
581
- print()
582
-
583
- # Show port range status if requested
584
- if show_ports or verbose:
585
- print("\nPort Range Status (8765-8785):")
586
- print("─" * 40)
587
- for check_port in range(8765, 8771): # Show first 6 ports
588
- status = port_manager.get_port_status(check_port)
589
- if status["available"]:
590
- print(f" Port {check_port}: ✅ Available")
591
- else:
592
- process = status.get("process")
593
- if process:
594
- if process["is_ours"]:
595
- if process["is_debug"]:
596
- print(
597
- f" Port {check_port}: 🔧 Debug script (PID: {process['pid']})"
598
- )
599
- elif process["is_daemon"]:
600
- print(
601
- f" Port {check_port}: 🚀 Daemon (PID: {process['pid']})"
602
- )
603
- else:
604
- print(
605
- f" Port {check_port}: 📦 Our process (PID: {process['pid']})"
606
- )
607
- else:
608
- print(
609
- f" Port {check_port}: ⛔ External ({process['name']})"
610
- )
611
- else:
612
- print(f" Port {check_port}: ❓ In use (unknown process)")
613
- print()
614
-
615
- print("Server management commands:")
616
- print(" Stop all: claude-mpm monitor stop")
617
- print(" Restart: claude-mpm monitor restart")
618
- print(" Reclaim: claude-mpm monitor start --force # Kill debug scripts")
619
- if len(running_servers) == 1:
620
- port = running_servers[0].get("port", 8765)
621
- print(f" Stop this: claude-mpm monitor stop --port {port}")
622
-
623
- return True
624
-
625
- except Exception as e:
626
- print(f"Error checking server status: {e}")
627
- print()
628
- print("Try manual checks:")
629
- print(" • Process list: ps aux | grep socketio")
630
- print(" • Port usage: lsof -i :8765")
631
- return False
632
-
633
-
634
- def _restart_server(args, server_manager):
635
- """
636
- Restart the Socket.IO monitoring server.
140
+ if result.success:
141
+ if result.message:
142
+ print(result.message)
143
+ if result.data and getattr(args, "verbose", False):
144
+ import json
637
145
 
638
- WHY: Users need to restart the monitoring server to apply configuration
639
- changes or recover from error states.
146
+ print(json.dumps(result.data, indent=2))
147
+ return 0
148
+ if result.message:
149
+ print(f"Error: {result.message}")
150
+ return 1
640
151
 
641
- Args:
642
- args: Command arguments with optional port
643
- server_manager: ServerManager instance
644
152
 
645
- Returns:
646
- bool: True if server restarted successfully, False otherwise
647
- """
648
- port = getattr(args, "port", None)
649
-
650
- print("Restarting Socket.IO monitoring server...")
651
-
652
- try:
653
- # If no port specified, find running servers to restart
654
- if port is None:
655
- running_servers = server_manager.list_running_servers()
656
- if not running_servers:
657
- print(
658
- "No running servers found. Starting new server on default port..."
659
- )
660
- return _start_server(args, server_manager)
661
-
662
- # Restart the first server found
663
- server = running_servers[0]
664
- port = server.get("port", 8765)
665
-
666
- print(f"Using port {port} for restart...")
667
-
668
- # Use ServerManager's restart method
669
- success = server_manager.restart_server(port=port)
670
-
671
- if success:
672
- print(f"Monitor server restarted successfully on port {port}")
673
- print()
674
- print("Server management commands:")
675
- print(" Status: claude-mpm monitor status")
676
- print(f" Stop: claude-mpm monitor stop --port {port}")
677
- print(f" Start: claude-mpm monitor start --port {port}")
678
- else:
679
- print(f"Failed to restart server on port {port}")
680
- print()
681
- print("Troubleshooting:")
682
- print(" • Try stopping and starting manually:")
683
- print(f" claude-mpm monitor stop --port {port}")
684
- print(f" claude-mpm monitor start --port {port}")
685
- print(" • Check server logs for errors")
686
-
687
- return success
688
-
689
- except Exception as e:
690
- print(f"Error restarting server: {e}")
691
- print()
692
- print("Fallback options:")
693
- print(" • Manual restart: stop then start")
694
- print(" • Check system resources and try again")
695
- return False
153
+ # All legacy functions have been removed.
154
+ # The monitor command now delegates to the unified dashboard service.
155
+ # This consolidation provides a single service that handles both HTTP (port 8765)
156
+ # and Socket.IO (also on port 8765) rather than separate services on different ports.