claude-mpm 4.1.4__py3-none-any.whl → 4.1.6__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 (81) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/templates/research.json +39 -13
  3. claude_mpm/cli/__init__.py +2 -0
  4. claude_mpm/cli/commands/__init__.py +2 -0
  5. claude_mpm/cli/commands/configure.py +1221 -0
  6. claude_mpm/cli/commands/configure_tui.py +1921 -0
  7. claude_mpm/cli/commands/tickets.py +365 -784
  8. claude_mpm/cli/parsers/base_parser.py +7 -0
  9. claude_mpm/cli/parsers/configure_parser.py +119 -0
  10. claude_mpm/cli/startup_logging.py +39 -12
  11. claude_mpm/constants.py +1 -0
  12. claude_mpm/core/output_style_manager.py +24 -0
  13. claude_mpm/core/socketio_pool.py +35 -3
  14. claude_mpm/core/unified_agent_registry.py +46 -15
  15. claude_mpm/dashboard/static/css/connection-status.css +370 -0
  16. claude_mpm/dashboard/static/js/components/connection-debug.js +654 -0
  17. claude_mpm/dashboard/static/js/connection-manager.js +536 -0
  18. claude_mpm/dashboard/templates/index.html +11 -0
  19. claude_mpm/hooks/claude_hooks/services/__init__.py +3 -1
  20. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +190 -0
  21. claude_mpm/services/agents/deployment/agent_discovery_service.py +12 -3
  22. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +172 -233
  23. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +575 -0
  24. claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
  25. claude_mpm/services/agents/deployment/agent_record_service.py +419 -0
  26. claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
  27. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +4 -2
  28. claude_mpm/services/diagnostics/checks/__init__.py +2 -0
  29. claude_mpm/services/diagnostics/checks/instructions_check.py +418 -0
  30. claude_mpm/services/diagnostics/diagnostic_runner.py +15 -2
  31. claude_mpm/services/event_bus/direct_relay.py +173 -0
  32. claude_mpm/services/infrastructure/__init__.py +31 -5
  33. claude_mpm/services/infrastructure/monitoring/__init__.py +43 -0
  34. claude_mpm/services/infrastructure/monitoring/aggregator.py +437 -0
  35. claude_mpm/services/infrastructure/monitoring/base.py +130 -0
  36. claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
  37. claude_mpm/services/infrastructure/monitoring/network.py +218 -0
  38. claude_mpm/services/infrastructure/monitoring/process.py +342 -0
  39. claude_mpm/services/infrastructure/monitoring/resources.py +243 -0
  40. claude_mpm/services/infrastructure/monitoring/service.py +367 -0
  41. claude_mpm/services/infrastructure/monitoring.py +67 -1030
  42. claude_mpm/services/project/analyzer.py +13 -4
  43. claude_mpm/services/project/analyzer_refactored.py +450 -0
  44. claude_mpm/services/project/analyzer_v2.py +566 -0
  45. claude_mpm/services/project/architecture_analyzer.py +461 -0
  46. claude_mpm/services/project/dependency_analyzer.py +462 -0
  47. claude_mpm/services/project/language_analyzer.py +265 -0
  48. claude_mpm/services/project/metrics_collector.py +410 -0
  49. claude_mpm/services/socketio/handlers/connection_handler.py +345 -0
  50. claude_mpm/services/socketio/server/broadcaster.py +32 -1
  51. claude_mpm/services/socketio/server/connection_manager.py +516 -0
  52. claude_mpm/services/socketio/server/core.py +63 -0
  53. claude_mpm/services/socketio/server/eventbus_integration.py +20 -9
  54. claude_mpm/services/socketio/server/main.py +27 -1
  55. claude_mpm/services/ticket_manager.py +5 -1
  56. claude_mpm/services/ticket_services/__init__.py +26 -0
  57. claude_mpm/services/ticket_services/crud_service.py +328 -0
  58. claude_mpm/services/ticket_services/formatter_service.py +290 -0
  59. claude_mpm/services/ticket_services/search_service.py +324 -0
  60. claude_mpm/services/ticket_services/validation_service.py +303 -0
  61. claude_mpm/services/ticket_services/workflow_service.py +244 -0
  62. {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/METADATA +3 -1
  63. {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/RECORD +67 -46
  64. claude_mpm/agents/OUTPUT_STYLE.md +0 -73
  65. claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
  66. claude_mpm/agents/templates/OPTIMIZATION_REPORT.md +0 -156
  67. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -79
  68. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -68
  69. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -77
  70. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -78
  71. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -67
  72. claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +0 -88
  73. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -72
  74. claude_mpm/agents/templates/backup/research_memory_efficient.json +0 -88
  75. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -78
  76. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -62
  77. claude_mpm/agents/templates/vercel_ops_instructions.md +0 -582
  78. {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/WHEEL +0 -0
  79. {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/entry_points.txt +0 -0
  80. {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/licenses/LICENSE +0 -0
  81. {claude_mpm-4.1.4.dist-info → claude_mpm-4.1.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,203 @@
1
+ """Legacy compatibility wrappers for monitoring classes.
2
+
3
+ Provides backward compatibility for existing code using the old monitoring API.
4
+ """
5
+
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ from .aggregator import MonitoringAggregatorService
9
+ from .base import HealthChecker, HealthMetric
10
+ from .network import NetworkHealthService
11
+ from .process import ProcessHealthService
12
+ from .service import ServiceHealthService
13
+
14
+
15
+ class ProcessResourceChecker(HealthChecker):
16
+ """Legacy wrapper for ProcessHealthService.
17
+
18
+ Maintains backward compatibility with existing code.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ pid: int,
24
+ cpu_threshold: float = 80.0,
25
+ memory_threshold_mb: int = 500,
26
+ fd_threshold: int = 1000,
27
+ ):
28
+ """Initialize legacy process resource checker."""
29
+ self.service = ProcessHealthService(
30
+ pid=pid,
31
+ cpu_threshold=cpu_threshold,
32
+ memory_threshold_mb=memory_threshold_mb,
33
+ fd_threshold=fd_threshold,
34
+ )
35
+ self.pid = pid
36
+
37
+ def get_name(self) -> str:
38
+ """Get checker name."""
39
+ return f"process_resources_{self.pid}"
40
+
41
+ async def check_health(self) -> List[HealthMetric]:
42
+ """Perform health check."""
43
+ return await self.service.check_health()
44
+
45
+
46
+ class NetworkConnectivityChecker(HealthChecker):
47
+ """Legacy wrapper for NetworkHealthService.
48
+
49
+ Maintains backward compatibility with existing code.
50
+ """
51
+
52
+ def __init__(self, host: str, port: int, timeout: float = 1.0):
53
+ """Initialize legacy network connectivity checker."""
54
+ self.service = NetworkHealthService(default_timeout=timeout)
55
+ self.service.add_endpoint(host, port, f"{host}_{port}", timeout)
56
+ self.host = host
57
+ self.port = port
58
+ self.timeout = timeout
59
+
60
+ def get_name(self) -> str:
61
+ """Get checker name."""
62
+ return f"network_connectivity_{self.host}_{self.port}"
63
+
64
+ async def check_health(self) -> List[HealthMetric]:
65
+ """Perform health check."""
66
+ # Filter to only return metrics for the configured endpoint
67
+ all_metrics = await self.service.check_health()
68
+ relevant_metrics = []
69
+
70
+ for metric in all_metrics:
71
+ # Include socket creation and metrics for our endpoint
72
+ if (
73
+ metric.name == "socket_creation"
74
+ or f"{self.host}_{self.port}" in metric.name
75
+ or "localhost_default" not in metric.name
76
+ ):
77
+ # Rename metrics to match legacy format
78
+ if f"port_accessible_{self.host}_{self.port}" in metric.name:
79
+ metric.name = "port_accessible"
80
+ relevant_metrics.append(metric)
81
+
82
+ return relevant_metrics
83
+
84
+
85
+ class ServiceHealthChecker(HealthChecker):
86
+ """Legacy wrapper for ServiceHealthService.
87
+
88
+ Maintains backward compatibility with existing code.
89
+ """
90
+
91
+ def __init__(
92
+ self,
93
+ service_stats: Dict[str, Any],
94
+ max_clients: int = 1000,
95
+ max_error_rate: float = 0.1,
96
+ ):
97
+ """Initialize legacy service health checker."""
98
+ self.service = ServiceHealthService(
99
+ service_stats=service_stats,
100
+ max_clients=max_clients,
101
+ max_error_rate=max_error_rate,
102
+ )
103
+ self.service_stats = service_stats
104
+ self.max_clients = max_clients
105
+ self.max_error_rate = max_error_rate
106
+ self.last_check_time = self.service.last_check_time
107
+ self.last_events_processed = self.service.last_events_processed
108
+
109
+ def get_name(self) -> str:
110
+ """Get checker name."""
111
+ return "service_health"
112
+
113
+ async def check_health(self) -> List[HealthMetric]:
114
+ """Perform health check."""
115
+ metrics = await self.service.check_health()
116
+ # Update exposed state for compatibility
117
+ self.last_check_time = self.service.last_check_time
118
+ self.last_events_processed = self.service.last_events_processed
119
+ return metrics
120
+
121
+
122
+ class AdvancedHealthMonitor:
123
+ """Legacy wrapper for MonitoringAggregatorService.
124
+
125
+ Maintains backward compatibility with existing code.
126
+ """
127
+
128
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
129
+ """Initialize legacy advanced health monitor."""
130
+ self.service = MonitoringAggregatorService(config)
131
+
132
+ # Expose service properties for compatibility
133
+ self.config = self.service.config
134
+ self.check_interval = self.service.check_interval
135
+ self.history_size = self.service.history_size
136
+ self.aggregation_window = self.service.aggregation_window
137
+ self.checkers = self.service.checkers
138
+ self.health_history = self.service.health_history
139
+ self.monitoring = self.service.monitoring
140
+ self.monitor_task = self.service.monitor_task
141
+ self.last_check_result = self.service.last_check_result
142
+ self.health_callbacks = self.service.health_callbacks
143
+ self.monitoring_stats = self.service.monitoring_stats
144
+
145
+ # Legacy logger
146
+ import logging
147
+
148
+ self.logger = logging.getLogger(f"{__name__}.AdvancedHealthMonitor")
149
+
150
+ def add_checker(self, checker: HealthChecker) -> None:
151
+ """Add a health checker."""
152
+ self.service.add_checker(checker)
153
+ self.checkers = self.service.checkers
154
+
155
+ def add_health_callback(self, callback) -> None:
156
+ """Add health callback."""
157
+ self.service.add_health_callback(callback)
158
+ self.health_callbacks = self.service.health_callbacks
159
+
160
+ async def perform_health_check(self):
161
+ """Perform health check."""
162
+ result = await self.service.perform_health_check()
163
+ # Update exposed state
164
+ self.health_history = self.service.health_history
165
+ self.last_check_result = self.service.last_check_result
166
+ self.monitoring_stats = self.service.monitoring_stats
167
+ return result
168
+
169
+ def _determine_overall_status(self, metrics):
170
+ """Determine overall status."""
171
+ return self.service._determine_overall_status(metrics)
172
+
173
+ def start_monitoring(self) -> None:
174
+ """Start monitoring."""
175
+ self.service.start_monitoring()
176
+ self.monitoring = self.service.monitoring
177
+ self.monitor_task = self.service.monitor_task
178
+
179
+ async def stop_monitoring(self) -> None:
180
+ """Stop monitoring."""
181
+ await self.service.stop_monitoring()
182
+ self.monitoring = self.service.monitoring
183
+ self.monitor_task = self.service.monitor_task
184
+
185
+ async def _monitoring_loop(self) -> None:
186
+ """Monitoring loop (should not be called directly)."""
187
+ await self.service._monitoring_loop()
188
+
189
+ def get_current_status(self):
190
+ """Get current status."""
191
+ return self.service.get_current_status()
192
+
193
+ def get_health_history(self, limit=None):
194
+ """Get health history."""
195
+ return self.service.get_health_history(limit)
196
+
197
+ def get_aggregated_status(self, window_seconds=None):
198
+ """Get aggregated status."""
199
+ return self.service.get_aggregated_status(window_seconds)
200
+
201
+ def export_diagnostics(self):
202
+ """Export diagnostics."""
203
+ return self.service.export_diagnostics()
@@ -0,0 +1,218 @@
1
+ """Network health monitoring service.
2
+
3
+ Monitors network connectivity, port availability, and socket health.
4
+ """
5
+
6
+ import socket
7
+ from typing import Dict, List, Optional
8
+
9
+ from .base import BaseMonitoringService, HealthMetric, HealthStatus
10
+
11
+
12
+ class NetworkHealthService(BaseMonitoringService):
13
+ """Service for monitoring network health and connectivity.
14
+
15
+ Monitors:
16
+ - Port availability and binding
17
+ - Socket creation capability
18
+ - Network interface status
19
+ - Connection health to specified endpoints
20
+ """
21
+
22
+ def __init__(self, default_timeout: float = 1.0):
23
+ """Initialize network health service.
24
+
25
+ Args:
26
+ default_timeout: Default connection timeout in seconds
27
+ """
28
+ super().__init__("NetworkHealth")
29
+ self.default_timeout = default_timeout
30
+ self.monitored_endpoints: List[Dict[str, any]] = []
31
+
32
+ def add_endpoint(
33
+ self,
34
+ host: str,
35
+ port: int,
36
+ name: Optional[str] = None,
37
+ timeout: Optional[float] = None,
38
+ ) -> None:
39
+ """Add an endpoint to monitor.
40
+
41
+ Args:
42
+ host: Host address to monitor
43
+ port: Port number to monitor
44
+ name: Optional name for the endpoint
45
+ timeout: Optional custom timeout for this endpoint
46
+ """
47
+ endpoint = {
48
+ "host": host,
49
+ "port": port,
50
+ "name": name or f"{host}:{port}",
51
+ "timeout": timeout or self.default_timeout,
52
+ }
53
+ self.monitored_endpoints.append(endpoint)
54
+ self.logger.info(f"Added endpoint for monitoring: {endpoint['name']}")
55
+
56
+ async def check_health(self) -> List[HealthMetric]:
57
+ """Check network health for all configured endpoints."""
58
+ metrics = []
59
+
60
+ # Check socket creation capability
61
+ metrics.extend(self._check_socket_creation())
62
+
63
+ # Check all monitored endpoints
64
+ for endpoint in self.monitored_endpoints:
65
+ metrics.extend(
66
+ self._check_endpoint(
67
+ endpoint["host"],
68
+ endpoint["port"],
69
+ endpoint["name"],
70
+ endpoint["timeout"],
71
+ )
72
+ )
73
+
74
+ # Check localhost connectivity (always check)
75
+ if not any(e["host"] == "localhost" for e in self.monitored_endpoints):
76
+ metrics.extend(
77
+ self._check_endpoint("localhost", 8765, "localhost_default", 0.5)
78
+ )
79
+
80
+ return metrics
81
+
82
+ def _check_socket_creation(self) -> List[HealthMetric]:
83
+ """Check if we can create sockets (resource availability)."""
84
+ metrics = []
85
+ try:
86
+ test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
87
+ test_sock.close()
88
+ metrics.append(
89
+ HealthMetric(
90
+ name="socket_creation",
91
+ value=True,
92
+ status=HealthStatus.HEALTHY,
93
+ message="Socket creation successful",
94
+ )
95
+ )
96
+ except Exception as e:
97
+ metrics.append(
98
+ HealthMetric(
99
+ name="socket_creation",
100
+ value=False,
101
+ status=HealthStatus.CRITICAL,
102
+ message=f"Failed to create socket: {e}",
103
+ )
104
+ )
105
+ return metrics
106
+
107
+ def _check_endpoint(
108
+ self,
109
+ host: str,
110
+ port: int,
111
+ name: str,
112
+ timeout: float,
113
+ ) -> List[HealthMetric]:
114
+ """Check connectivity to a specific endpoint.
115
+
116
+ Args:
117
+ host: Host to check
118
+ port: Port to check
119
+ name: Endpoint name for metrics
120
+ timeout: Connection timeout
121
+
122
+ Returns:
123
+ List of health metrics for the endpoint
124
+ """
125
+ metrics = []
126
+ metric_name = f"port_accessible_{name}"
127
+
128
+ try:
129
+ # Try to connect to the port
130
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
131
+ sock.settimeout(timeout)
132
+ result = sock.connect_ex((host, port))
133
+ sock.close()
134
+
135
+ if result == 0:
136
+ metrics.append(
137
+ HealthMetric(
138
+ name=metric_name,
139
+ value=True,
140
+ status=HealthStatus.HEALTHY,
141
+ message=f"Port {port} is accessible on {host}",
142
+ )
143
+ )
144
+ else:
145
+ # Determine if this is critical or warning based on endpoint type
146
+ status = (
147
+ HealthStatus.WARNING
148
+ if "optional" in name.lower()
149
+ else HealthStatus.CRITICAL
150
+ )
151
+ metrics.append(
152
+ HealthMetric(
153
+ name=metric_name,
154
+ value=False,
155
+ status=status,
156
+ message=f"Port {port} is not accessible on {host} (error: {result})",
157
+ )
158
+ )
159
+ except socket.timeout:
160
+ metrics.append(
161
+ HealthMetric(
162
+ name=metric_name,
163
+ value=False,
164
+ status=HealthStatus.WARNING,
165
+ message=f"Connection to {host}:{port} timed out after {timeout}s",
166
+ )
167
+ )
168
+ except Exception as e:
169
+ metrics.append(
170
+ HealthMetric(
171
+ name=metric_name,
172
+ value=False,
173
+ status=HealthStatus.UNKNOWN,
174
+ message=f"Error checking port accessibility: {e}",
175
+ )
176
+ )
177
+
178
+ return metrics
179
+
180
+ def check_port_available(self, port: int, host: str = "0.0.0.0") -> bool:
181
+ """Check if a port is available for binding.
182
+
183
+ Args:
184
+ port: Port number to check
185
+ host: Host interface to check
186
+
187
+ Returns:
188
+ True if port is available for binding
189
+ """
190
+ try:
191
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
192
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
193
+ sock.bind((host, port))
194
+ return True
195
+ except OSError:
196
+ return False
197
+
198
+ def scan_port_range(
199
+ self,
200
+ start_port: int,
201
+ end_port: int,
202
+ host: str = "0.0.0.0",
203
+ ) -> List[int]:
204
+ """Scan a range of ports to find available ones.
205
+
206
+ Args:
207
+ start_port: Starting port number
208
+ end_port: Ending port number (inclusive)
209
+ host: Host interface to check
210
+
211
+ Returns:
212
+ List of available port numbers
213
+ """
214
+ available_ports = []
215
+ for port in range(start_port, end_port + 1):
216
+ if self.check_port_available(port, host):
217
+ available_ports.append(port)
218
+ return available_ports