claude-mpm 4.1.2__py3-none-any.whl → 4.1.3__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 (53) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/templates/engineer.json +33 -11
  3. claude_mpm/cli/commands/agents.py +556 -1009
  4. claude_mpm/cli/commands/memory.py +248 -927
  5. claude_mpm/cli/commands/run.py +139 -484
  6. claude_mpm/cli/startup_logging.py +76 -0
  7. claude_mpm/core/agent_registry.py +6 -10
  8. claude_mpm/core/framework_loader.py +114 -595
  9. claude_mpm/core/logging_config.py +2 -4
  10. claude_mpm/hooks/claude_hooks/event_handlers.py +7 -117
  11. claude_mpm/hooks/claude_hooks/hook_handler.py +91 -755
  12. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  13. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  14. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  15. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  16. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  17. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  18. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  19. claude_mpm/services/agents/deployment/agent_deployment.py +42 -454
  20. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  21. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  22. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  23. claude_mpm/services/agents/memory/agent_memory_manager.py +42 -508
  24. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  25. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  26. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  27. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  28. claude_mpm/services/agents/registry/__init__.py +1 -1
  29. claude_mpm/services/cli/__init__.py +18 -0
  30. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  31. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  32. claude_mpm/services/cli/agent_listing_service.py +463 -0
  33. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  34. claude_mpm/services/cli/agent_validation_service.py +589 -0
  35. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  36. claude_mpm/services/cli/memory_crud_service.py +617 -0
  37. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  38. claude_mpm/services/cli/session_manager.py +513 -0
  39. claude_mpm/services/cli/socketio_manager.py +498 -0
  40. claude_mpm/services/cli/startup_checker.py +370 -0
  41. claude_mpm/services/core/cache_manager.py +311 -0
  42. claude_mpm/services/core/memory_manager.py +637 -0
  43. claude_mpm/services/core/path_resolver.py +498 -0
  44. claude_mpm/services/core/service_container.py +520 -0
  45. claude_mpm/services/core/service_interfaces.py +436 -0
  46. claude_mpm/services/diagnostics/checks/agent_check.py +65 -19
  47. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  48. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.3.dist-info}/RECORD +52 -22
  49. claude_mpm/cli/commands/run_config_checker.py +0 -159
  50. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  51. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  52. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  53. {claude_mpm-4.1.2.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,395 @@
1
+ """
2
+ Agent Dependency Service
3
+ ========================
4
+
5
+ WHY: This service manages all agent dependency operations including checking,
6
+ installing, listing, and fixing dependencies with robust retry logic. It provides
7
+ a clean interface for the CLI to manage agent dependencies without embedding
8
+ complex logic in the command module.
9
+
10
+ DESIGN DECISIONS:
11
+ - Uses AgentDependencyLoader for dependency discovery and analysis
12
+ - Integrates RobustPackageInstaller for reliable package installation
13
+ - Provides retry logic for network operations to handle transient failures
14
+ - Generates detailed dependency reports for user feedback
15
+ - Maintains separation between dependency logic and CLI presentation
16
+ """
17
+
18
+ from abc import ABC, abstractmethod
19
+ from typing import Any, Dict, List, Optional, Tuple
20
+
21
+ from ...core.logger import get_logger
22
+ from ...utils.agent_dependency_loader import AgentDependencyLoader
23
+ from ...utils.robust_installer import RobustPackageInstaller
24
+
25
+
26
+ class IAgentDependencyService(ABC):
27
+ """Interface for agent dependency management operations."""
28
+
29
+ @abstractmethod
30
+ def check_dependencies(self, agent_name: Optional[str] = None) -> Dict[str, Any]:
31
+ """Check dependencies for deployed agents."""
32
+
33
+ @abstractmethod
34
+ def install_dependencies(
35
+ self, agent_name: Optional[str] = None, dry_run: bool = False
36
+ ) -> Dict[str, Any]:
37
+ """Install missing dependencies for agents."""
38
+
39
+ @abstractmethod
40
+ def list_dependencies(self, format_type: str = "text") -> Dict[str, Any]:
41
+ """List all dependencies from deployed agents."""
42
+
43
+ @abstractmethod
44
+ def fix_dependencies(
45
+ self, max_retries: int = 3, agent_name: Optional[str] = None
46
+ ) -> Dict[str, Any]:
47
+ """Auto-fix dependency issues with retry logic."""
48
+
49
+ @abstractmethod
50
+ def validate_compatibility(
51
+ self, packages: List[str]
52
+ ) -> Tuple[List[str], List[str]]:
53
+ """Check version compatibility for packages."""
54
+
55
+ @abstractmethod
56
+ def get_dependency_report(self) -> str:
57
+ """Generate a formatted dependency report."""
58
+
59
+
60
+ class AgentDependencyService(IAgentDependencyService):
61
+ """Service for managing agent dependencies with robust error handling."""
62
+
63
+ def __init__(self):
64
+ """Initialize the dependency service."""
65
+ self.logger = get_logger(__name__)
66
+ self.loader = None # Lazy initialization
67
+
68
+ def _get_loader(self, auto_install: bool = False) -> AgentDependencyLoader:
69
+ """Get or create dependency loader instance."""
70
+ if self.loader is None or self.loader.auto_install != auto_install:
71
+ self.loader = AgentDependencyLoader(auto_install=auto_install)
72
+ return self.loader
73
+
74
+ def check_dependencies(self, agent_name: Optional[str] = None) -> Dict[str, Any]:
75
+ """
76
+ Check dependencies for deployed agents.
77
+
78
+ Args:
79
+ agent_name: Optional specific agent to check
80
+
81
+ Returns:
82
+ Dictionary containing check results
83
+ """
84
+ try:
85
+ loader = self._get_loader(auto_install=False)
86
+
87
+ # Discover deployed agents
88
+ loader.discover_deployed_agents()
89
+
90
+ # Filter to specific agent if requested
91
+ if agent_name:
92
+ if agent_name not in loader.deployed_agents:
93
+ available = list(loader.deployed_agents.keys())
94
+ return {
95
+ "success": False,
96
+ "error": f"Agent '{agent_name}' is not deployed",
97
+ "available_agents": available,
98
+ }
99
+ # Keep only the specified agent
100
+ loader.deployed_agents = {
101
+ agent_name: loader.deployed_agents[agent_name]
102
+ }
103
+
104
+ # Load dependencies and check
105
+ loader.load_agent_dependencies()
106
+ results = loader.analyze_dependencies()
107
+
108
+ # Generate report
109
+ report = loader.format_report(results)
110
+
111
+ return {
112
+ "success": True,
113
+ "report": report,
114
+ "results": results,
115
+ "agent": agent_name,
116
+ }
117
+
118
+ except Exception as e:
119
+ self.logger.error(f"Dependency check failed: {e}")
120
+ return {
121
+ "success": False,
122
+ "error": str(e),
123
+ "agent": agent_name,
124
+ }
125
+
126
+ def install_dependencies(
127
+ self, agent_name: Optional[str] = None, dry_run: bool = False
128
+ ) -> Dict[str, Any]:
129
+ """
130
+ Install missing dependencies for agents.
131
+
132
+ Args:
133
+ agent_name: Optional specific agent to install for
134
+ dry_run: Whether to simulate installation
135
+
136
+ Returns:
137
+ Dictionary containing installation results
138
+ """
139
+ try:
140
+ loader = self._get_loader(auto_install=not dry_run)
141
+
142
+ # Discover deployed agents
143
+ loader.discover_deployed_agents()
144
+
145
+ # Filter to specific agent if requested
146
+ if agent_name:
147
+ if agent_name not in loader.deployed_agents:
148
+ available = list(loader.deployed_agents.keys())
149
+ return {
150
+ "success": False,
151
+ "error": f"Agent '{agent_name}' is not deployed",
152
+ "available_agents": available,
153
+ }
154
+ loader.deployed_agents = {
155
+ agent_name: loader.deployed_agents[agent_name]
156
+ }
157
+
158
+ # Load dependencies
159
+ loader.load_agent_dependencies()
160
+ results = loader.analyze_dependencies()
161
+
162
+ missing_deps = results["summary"]["missing_python"]
163
+
164
+ if not missing_deps:
165
+ return {
166
+ "success": True,
167
+ "message": "All Python dependencies are already installed",
168
+ "missing_count": 0,
169
+ }
170
+
171
+ if dry_run:
172
+ return {
173
+ "success": True,
174
+ "dry_run": True,
175
+ "missing_dependencies": missing_deps,
176
+ "install_command": f"pip install {' '.join(missing_deps)}",
177
+ }
178
+
179
+ # Install missing dependencies
180
+ success, error = loader.install_missing_dependencies(missing_deps)
181
+
182
+ if success:
183
+ # Re-check after installation
184
+ loader.checked_packages.clear()
185
+ final_results = loader.analyze_dependencies()
186
+ still_missing = final_results["summary"]["missing_python"]
187
+
188
+ return {
189
+ "success": True,
190
+ "installed": missing_deps,
191
+ "still_missing": still_missing,
192
+ "fully_resolved": len(still_missing) == 0,
193
+ }
194
+ return {
195
+ "success": False,
196
+ "error": error,
197
+ "failed_dependencies": missing_deps,
198
+ }
199
+
200
+ except Exception as e:
201
+ self.logger.error(f"Dependency installation failed: {e}")
202
+ return {
203
+ "success": False,
204
+ "error": str(e),
205
+ }
206
+
207
+ def list_dependencies(self, format_type: str = "text") -> Dict[str, Any]:
208
+ """
209
+ List all dependencies from deployed agents.
210
+
211
+ Args:
212
+ format_type: Output format (text, json, or pip)
213
+
214
+ Returns:
215
+ Dictionary containing dependency listing
216
+ """
217
+ try:
218
+ loader = self._get_loader(auto_install=False)
219
+
220
+ # Discover and load
221
+ loader.discover_deployed_agents()
222
+ loader.load_agent_dependencies()
223
+
224
+ # Collect all unique dependencies
225
+ all_python_deps = set()
226
+ all_system_deps = set()
227
+
228
+ for agent_id, deps in loader.agent_dependencies.items():
229
+ if "python" in deps:
230
+ all_python_deps.update(deps["python"])
231
+ if "system" in deps:
232
+ all_system_deps.update(deps["system"])
233
+
234
+ # Format result based on requested format
235
+ if format_type == "pip":
236
+ return {
237
+ "success": True,
238
+ "format": "pip",
239
+ "dependencies": sorted(all_python_deps),
240
+ }
241
+ if format_type == "json":
242
+ return {
243
+ "success": True,
244
+ "format": "json",
245
+ "data": {
246
+ "python": sorted(all_python_deps),
247
+ "system": sorted(all_system_deps),
248
+ "agents": loader.agent_dependencies,
249
+ },
250
+ }
251
+ # text format
252
+ return {
253
+ "success": True,
254
+ "format": "text",
255
+ "python_dependencies": sorted(all_python_deps),
256
+ "system_dependencies": sorted(all_system_deps),
257
+ "per_agent": loader.agent_dependencies,
258
+ }
259
+
260
+ except Exception as e:
261
+ self.logger.error(f"Dependency listing failed: {e}")
262
+ return {
263
+ "success": False,
264
+ "error": str(e),
265
+ }
266
+
267
+ def fix_dependencies(
268
+ self, max_retries: int = 3, agent_name: Optional[str] = None
269
+ ) -> Dict[str, Any]:
270
+ """
271
+ Auto-fix dependency issues with retry logic.
272
+
273
+ Args:
274
+ max_retries: Maximum retry attempts per package
275
+ agent_name: Optional specific agent to fix
276
+
277
+ Returns:
278
+ Dictionary containing fix results
279
+ """
280
+ try:
281
+ loader = self._get_loader(auto_install=False)
282
+
283
+ # Discover and analyze
284
+ loader.discover_deployed_agents()
285
+
286
+ if not loader.deployed_agents:
287
+ return {
288
+ "success": True,
289
+ "message": "No deployed agents found",
290
+ }
291
+
292
+ # Filter to specific agent if requested
293
+ if agent_name:
294
+ if agent_name not in loader.deployed_agents:
295
+ return {
296
+ "success": False,
297
+ "error": f"Agent '{agent_name}' is not deployed",
298
+ }
299
+ loader.deployed_agents = {
300
+ agent_name: loader.deployed_agents[agent_name]
301
+ }
302
+
303
+ loader.load_agent_dependencies()
304
+ results = loader.analyze_dependencies()
305
+
306
+ missing_python = results["summary"]["missing_python"]
307
+ missing_system = results["summary"]["missing_system"]
308
+
309
+ if not missing_python and not missing_system:
310
+ return {
311
+ "success": True,
312
+ "message": "All dependencies are already satisfied",
313
+ }
314
+
315
+ fix_results = {
316
+ "success": True,
317
+ "missing_python": missing_python,
318
+ "missing_system": missing_system,
319
+ "fixed_python": [],
320
+ "failed_python": [],
321
+ "incompatible": [],
322
+ }
323
+
324
+ # Fix Python dependencies with robust installer
325
+ if missing_python:
326
+ # Check compatibility
327
+ compatible, incompatible = loader.check_python_compatibility(
328
+ missing_python
329
+ )
330
+ fix_results["incompatible"] = incompatible
331
+
332
+ if compatible:
333
+ installer = RobustPackageInstaller(
334
+ max_retries=max_retries,
335
+ retry_delay=2.0,
336
+ timeout=300,
337
+ )
338
+
339
+ successful, failed, errors = installer.install_packages(compatible)
340
+
341
+ fix_results["fixed_python"] = successful
342
+ fix_results["failed_python"] = failed
343
+ fix_results["errors"] = errors
344
+
345
+ # Re-check after fixes
346
+ loader.checked_packages.clear()
347
+ final_results = loader.analyze_dependencies()
348
+ fix_results["still_missing"] = final_results["summary"][
349
+ "missing_python"
350
+ ]
351
+
352
+ return fix_results
353
+
354
+ except Exception as e:
355
+ self.logger.error(f"Dependency fix failed: {e}")
356
+ return {
357
+ "success": False,
358
+ "error": str(e),
359
+ }
360
+
361
+ def validate_compatibility(
362
+ self, packages: List[str]
363
+ ) -> Tuple[List[str], List[str]]:
364
+ """
365
+ Check version compatibility for packages.
366
+
367
+ Args:
368
+ packages: List of package names to check
369
+
370
+ Returns:
371
+ Tuple of (compatible_packages, incompatible_packages)
372
+ """
373
+ try:
374
+ loader = self._get_loader(auto_install=False)
375
+ return loader.check_python_compatibility(packages)
376
+ except Exception as e:
377
+ self.logger.error(f"Compatibility check failed: {e}")
378
+ return [], packages # Assume all incompatible on error
379
+
380
+ def get_dependency_report(self) -> str:
381
+ """
382
+ Generate a formatted dependency report.
383
+
384
+ Returns:
385
+ Formatted report string
386
+ """
387
+ try:
388
+ loader = self._get_loader(auto_install=False)
389
+ loader.discover_deployed_agents()
390
+ loader.load_agent_dependencies()
391
+ results = loader.analyze_dependencies()
392
+ return loader.format_report(results)
393
+ except Exception as e:
394
+ self.logger.error(f"Report generation failed: {e}")
395
+ return f"Failed to generate dependency report: {e}"