claude-mpm 3.7.4__py3-none-any.whl → 3.8.1__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +0 -106
- claude_mpm/agents/INSTRUCTIONS.md +0 -78
- claude_mpm/agents/MEMORY.md +88 -0
- claude_mpm/agents/WORKFLOW.md +86 -0
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/templates/code_analyzer.json +26 -11
- claude_mpm/agents/templates/data_engineer.json +4 -7
- claude_mpm/agents/templates/documentation.json +2 -2
- claude_mpm/agents/templates/engineer.json +2 -2
- claude_mpm/agents/templates/ops.json +3 -8
- claude_mpm/agents/templates/qa.json +2 -3
- claude_mpm/agents/templates/research.json +2 -3
- claude_mpm/agents/templates/security.json +3 -6
- claude_mpm/agents/templates/ticketing.json +4 -9
- claude_mpm/agents/templates/version_control.json +3 -3
- claude_mpm/agents/templates/web_qa.json +4 -4
- claude_mpm/agents/templates/web_ui.json +4 -4
- claude_mpm/cli/__init__.py +2 -2
- claude_mpm/cli/commands/__init__.py +2 -1
- claude_mpm/cli/commands/agents.py +118 -1
- claude_mpm/cli/commands/tickets.py +596 -19
- claude_mpm/cli/parser.py +228 -5
- claude_mpm/config/__init__.py +30 -39
- claude_mpm/config/socketio_config.py +8 -5
- claude_mpm/constants.py +13 -0
- claude_mpm/core/__init__.py +8 -18
- claude_mpm/core/cache.py +596 -0
- claude_mpm/core/claude_runner.py +166 -622
- claude_mpm/core/config.py +5 -1
- claude_mpm/core/constants.py +339 -0
- claude_mpm/core/container.py +461 -22
- claude_mpm/core/exceptions.py +392 -0
- claude_mpm/core/framework_loader.py +208 -93
- claude_mpm/core/interactive_session.py +432 -0
- claude_mpm/core/interfaces.py +424 -0
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/logging_config.py +444 -0
- claude_mpm/core/oneshot_session.py +465 -0
- claude_mpm/core/optimized_agent_loader.py +485 -0
- claude_mpm/core/optimized_startup.py +490 -0
- claude_mpm/core/service_registry.py +52 -26
- claude_mpm/core/socketio_pool.py +162 -5
- claude_mpm/core/types.py +292 -0
- claude_mpm/core/typing_utils.py +477 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +46 -2
- claude_mpm/dashboard/templates/index.html +5 -5
- claude_mpm/hooks/claude_hooks/hook_handler.py +213 -99
- claude_mpm/init.py +2 -1
- claude_mpm/services/__init__.py +78 -14
- claude_mpm/services/agent/__init__.py +24 -0
- claude_mpm/services/agent/deployment.py +2548 -0
- claude_mpm/services/agent/management.py +598 -0
- claude_mpm/services/agent/registry.py +813 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +592 -269
- claude_mpm/services/agents/deployment/async_agent_deployment.py +5 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +21 -11
- claude_mpm/services/agents/memory/agent_memory_manager.py +156 -1
- claude_mpm/services/async_session_logger.py +8 -3
- claude_mpm/services/communication/__init__.py +21 -0
- claude_mpm/services/communication/socketio.py +1933 -0
- claude_mpm/services/communication/websocket.py +479 -0
- claude_mpm/services/core/__init__.py +123 -0
- claude_mpm/services/core/base.py +247 -0
- claude_mpm/services/core/interfaces.py +951 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +23 -23
- claude_mpm/services/framework_claude_md_generator.py +3 -2
- claude_mpm/services/health_monitor.py +4 -3
- claude_mpm/services/hook_service.py +64 -4
- claude_mpm/services/infrastructure/__init__.py +21 -0
- claude_mpm/services/infrastructure/logging.py +202 -0
- claude_mpm/services/infrastructure/monitoring.py +893 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/project/__init__.py +21 -0
- claude_mpm/services/project/analyzer.py +864 -0
- claude_mpm/services/project/registry.py +608 -0
- claude_mpm/services/project_analyzer.py +95 -2
- claude_mpm/services/recovery_manager.py +15 -9
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/base.py +121 -0
- claude_mpm/services/socketio/handlers/connection.py +198 -0
- claude_mpm/services/socketio/handlers/file.py +213 -0
- claude_mpm/services/socketio/handlers/git.py +723 -0
- claude_mpm/services/socketio/handlers/memory.py +27 -0
- claude_mpm/services/socketio/handlers/project.py +25 -0
- claude_mpm/services/socketio/handlers/registry.py +145 -0
- claude_mpm/services/socketio_client_manager.py +12 -7
- claude_mpm/services/socketio_server.py +156 -30
- claude_mpm/services/ticket_manager.py +377 -51
- claude_mpm/utils/agent_dependency_loader.py +66 -15
- claude_mpm/utils/error_handler.py +1 -1
- claude_mpm/utils/robust_installer.py +587 -0
- claude_mpm/validation/agent_validator.py +27 -14
- claude_mpm/validation/frontmatter_validator.py +231 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/METADATA +74 -41
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/RECORD +101 -76
- claude_mpm/.claude-mpm/logs/hooks_20250728.log +0 -10
- claude_mpm/agents/agent-template.yaml +0 -83
- claude_mpm/cli/README.md +0 -108
- claude_mpm/cli_module/refactoring_guide.md +0 -253
- claude_mpm/config/async_logging_config.yaml +0 -145
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
- claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/README.md +0 -121
- claude_mpm/dashboard/static/js/dashboard.js.backup +0 -1973
- claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
- claude_mpm/hooks/README.md +0 -96
- claude_mpm/schemas/agent_schema.json +0 -435
- claude_mpm/services/framework_claude_md_generator/README.md +0 -92
- claude_mpm/services/version_control/VERSION +0 -1
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/WHEEL +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/top_level.txt +0 -0
| @@ -462,10 +462,14 @@ class AsyncAgentDeploymentService: | |
| 462 462 | 
             
                    # IMPORTANT: No spaces after commas - Claude Code requires exact format
         | 
| 463 463 | 
             
                    tools_str = ','.join(tools) if isinstance(tools, list) else str(tools)
         | 
| 464 464 |  | 
| 465 | 
            +
                    # Convert agent_id to Claude Code compatible name (replace underscores with hyphens)
         | 
| 466 | 
            +
                    # Claude Code requires name to match pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
         | 
| 467 | 
            +
                    claude_code_name = agent_id.replace('_', '-').lower()
         | 
| 468 | 
            +
                    
         | 
| 465 469 | 
             
                    # Build frontmatter with only the fields Claude Code uses
         | 
| 466 470 | 
             
                    frontmatter_lines = [
         | 
| 467 471 | 
             
                        "---",
         | 
| 468 | 
            -
                        f"name: { | 
| 472 | 
            +
                        f"name: {claude_code_name}",
         | 
| 469 473 | 
             
                        f"description: {description}",
         | 
| 470 474 | 
             
                        f"version: {version_string}",
         | 
| 471 475 | 
             
                        f"base_version: {self._format_version_display(base_version)}",
         | 
| @@ -116,9 +116,12 @@ class AgentCapabilitiesGenerator: | |
| 116 116 | 
             
                        if len(capability_text) > 100:
         | 
| 117 117 | 
             
                            capability_text = capability_text[:97] + '...'
         | 
| 118 118 |  | 
| 119 | 
            +
                        # Clean up the agent name for TodoWrite usage
         | 
| 120 | 
            +
                        clean_name = agent['name'].replace(' Agent', '').replace('-', ' ')
         | 
| 121 | 
            +
                        
         | 
| 119 122 | 
             
                        capabilities.append({
         | 
| 120 | 
            -
                            'name':  | 
| 121 | 
            -
                            'id': agent['id'],
         | 
| 123 | 
            +
                            'name': clean_name,  # Clean name for TodoWrite
         | 
| 124 | 
            +
                            'id': agent['id'],    # Agent ID for Task tool
         | 
| 122 125 | 
             
                            'capability_text': capability_text,
         | 
| 123 126 | 
             
                            'tools': ', '.join(agent.get('tools', [])[:5])  # First 5 tools
         | 
| 124 127 | 
             
                        })
         | 
| @@ -132,26 +135,33 @@ class AgentCapabilitiesGenerator: | |
| 132 135 | 
             
                        Configured Jinja2 template
         | 
| 133 136 | 
             
                    """
         | 
| 134 137 | 
             
                    template_content = """
         | 
| 135 | 
            -
            ## Agent  | 
| 136 | 
            -
             | 
| 138 | 
            +
            ## Available Agent Capabilities
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            You have the following specialized agents available for delegation:
         | 
| 137 141 |  | 
| 138 142 | 
             
            {% if agents_by_tier.project %}
         | 
| 139 143 | 
             
            ### Project-Specific Agents
         | 
| 140 144 | 
             
            {% for agent in agents_by_tier.project %}
         | 
| 141 | 
            -
            - **{{ agent.name }}** ({{ agent.id }}): {{ agent.description }}
         | 
| 145 | 
            +
            - **{{ agent.name|replace(' Agent', '')|replace('-', ' ') }}** (`{{ agent.id }}`): {{ agent.description }}
         | 
| 142 146 | 
             
            {% endfor %}
         | 
| 143 147 |  | 
| 144 148 | 
             
            {% endif %}
         | 
| 145 | 
            -
             | 
| 149 | 
            +
            ### Engineering Agents
         | 
| 146 150 | 
             
            {% for cap in detailed_capabilities %}
         | 
| 147 | 
            -
             | 
| 151 | 
            +
            {% if cap.id in ['engineer', 'data_engineer', 'documentation', 'ops', 'security', 'ticketing', 'version_control', 'web_ui'] %}
         | 
| 152 | 
            +
            - **{{ cap.name }}** (`{{ cap.id }}`): {{ cap.capability_text }}
         | 
| 153 | 
            +
            {% endif %}
         | 
| 148 154 | 
             
            {% endfor %}
         | 
| 149 155 |  | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 156 | 
            +
            ### Research Agents
         | 
| 157 | 
            +
            {% for cap in detailed_capabilities %}
         | 
| 158 | 
            +
            {% if cap.id in ['code_analyzer', 'qa', 'research', 'web_qa'] %}
         | 
| 159 | 
            +
            - **{{ cap.name }}** (`{{ cap.id }}`): {{ cap.capability_text }}
         | 
| 160 | 
            +
            {% endif %}
         | 
| 161 | 
            +
            {% endfor %}
         | 
| 153 162 |  | 
| 154 | 
            -
             | 
| 163 | 
            +
            **Total Available Agents**: {{ total_agents }}
         | 
| 164 | 
            +
            Use the agent ID in parentheses when delegating tasks via the Task tool.
         | 
| 155 165 | 
             
            """.strip()
         | 
| 156 166 |  | 
| 157 167 | 
             
                    return Template(template_content)
         | 
| @@ -29,10 +29,11 @@ from claude_mpm.core.config import Config | |
| 29 29 | 
             
            from claude_mpm.core.mixins import LoggerMixin
         | 
| 30 30 | 
             
            from claude_mpm.utils.paths import PathResolver
         | 
| 31 31 | 
             
            from claude_mpm.services.project_analyzer import ProjectAnalyzer
         | 
| 32 | 
            +
            from claude_mpm.core.interfaces import MemoryServiceInterface
         | 
| 32 33 | 
             
            # Socket.IO notifications are optional - we'll skip them if server is not available
         | 
| 33 34 |  | 
| 34 35 |  | 
| 35 | 
            -
            class AgentMemoryManager:
         | 
| 36 | 
            +
            class AgentMemoryManager(MemoryServiceInterface):
         | 
| 36 37 | 
             
                """Manages agent memory files with size limits and validation.
         | 
| 37 38 |  | 
| 38 39 | 
             
                WHY: Agents need to accumulate project-specific knowledge over time to become
         | 
| @@ -1394,6 +1395,160 @@ Standard markdown with structured sections. Agents expect: | |
| 1394 1395 | 
             
                    except Exception as e:
         | 
| 1395 1396 | 
             
                        self.logger.error(f"Error ensuring memories directory: {e}")
         | 
| 1396 1397 | 
             
                        # Continue anyway - memory system should not block operations
         | 
| 1398 | 
            +
                
         | 
| 1399 | 
            +
                # ================================================================================
         | 
| 1400 | 
            +
                # Interface Adapter Methods
         | 
| 1401 | 
            +
                # ================================================================================
         | 
| 1402 | 
            +
                # These methods adapt the existing implementation to comply with MemoryServiceInterface
         | 
| 1403 | 
            +
                
         | 
| 1404 | 
            +
                def load_memory(self, agent_id: str) -> Optional[str]:
         | 
| 1405 | 
            +
                    """Load memory for a specific agent.
         | 
| 1406 | 
            +
                    
         | 
| 1407 | 
            +
                    WHY: This adapter method provides interface compliance by wrapping
         | 
| 1408 | 
            +
                    the existing load_agent_memory method.
         | 
| 1409 | 
            +
                    
         | 
| 1410 | 
            +
                    Args:
         | 
| 1411 | 
            +
                        agent_id: Identifier of the agent
         | 
| 1412 | 
            +
                        
         | 
| 1413 | 
            +
                    Returns:
         | 
| 1414 | 
            +
                        Memory content as string or None if not found
         | 
| 1415 | 
            +
                    """
         | 
| 1416 | 
            +
                    try:
         | 
| 1417 | 
            +
                        content = self.load_agent_memory(agent_id)
         | 
| 1418 | 
            +
                        return content if content else None
         | 
| 1419 | 
            +
                    except Exception as e:
         | 
| 1420 | 
            +
                        self.logger.error(f"Failed to load memory for {agent_id}: {e}")
         | 
| 1421 | 
            +
                        return None
         | 
| 1422 | 
            +
                
         | 
| 1423 | 
            +
                def save_memory(self, agent_id: str, content: str) -> bool:
         | 
| 1424 | 
            +
                    """Save memory for a specific agent.
         | 
| 1425 | 
            +
                    
         | 
| 1426 | 
            +
                    WHY: This adapter method provides interface compliance. The existing
         | 
| 1427 | 
            +
                    implementation uses update_agent_memory for modifications, so we
         | 
| 1428 | 
            +
                    implement a full save by writing directly to the file.
         | 
| 1429 | 
            +
                    
         | 
| 1430 | 
            +
                    Args:
         | 
| 1431 | 
            +
                        agent_id: Identifier of the agent
         | 
| 1432 | 
            +
                        content: Memory content to save
         | 
| 1433 | 
            +
                        
         | 
| 1434 | 
            +
                    Returns:
         | 
| 1435 | 
            +
                        True if save successful
         | 
| 1436 | 
            +
                    """
         | 
| 1437 | 
            +
                    try:
         | 
| 1438 | 
            +
                        memory_path = self.memories_dir / f"{agent_id}_agent.md"
         | 
| 1439 | 
            +
                        
         | 
| 1440 | 
            +
                        # Validate size before saving
         | 
| 1441 | 
            +
                        is_valid, error_msg = self.validate_memory_size(content)
         | 
| 1442 | 
            +
                        if not is_valid:
         | 
| 1443 | 
            +
                            self.logger.error(f"Memory validation failed: {error_msg}")
         | 
| 1444 | 
            +
                            return False
         | 
| 1445 | 
            +
                        
         | 
| 1446 | 
            +
                        # Write the content
         | 
| 1447 | 
            +
                        memory_path.write_text(content, encoding='utf-8')
         | 
| 1448 | 
            +
                        self.logger.info(f"Saved memory for agent {agent_id}")
         | 
| 1449 | 
            +
                        return True
         | 
| 1450 | 
            +
                        
         | 
| 1451 | 
            +
                    except Exception as e:
         | 
| 1452 | 
            +
                        self.logger.error(f"Failed to save memory for {agent_id}: {e}")
         | 
| 1453 | 
            +
                        return False
         | 
| 1454 | 
            +
                
         | 
| 1455 | 
            +
                def validate_memory_size(self, content: str) -> tuple[bool, Optional[str]]:
         | 
| 1456 | 
            +
                    """Validate memory content size and structure.
         | 
| 1457 | 
            +
                    
         | 
| 1458 | 
            +
                    WHY: This adapter method provides interface compliance by implementing
         | 
| 1459 | 
            +
                    validation based on configured limits.
         | 
| 1460 | 
            +
                    
         | 
| 1461 | 
            +
                    Args:
         | 
| 1462 | 
            +
                        content: Memory content to validate
         | 
| 1463 | 
            +
                        
         | 
| 1464 | 
            +
                    Returns:
         | 
| 1465 | 
            +
                        Tuple of (is_valid, error_message)
         | 
| 1466 | 
            +
                    """
         | 
| 1467 | 
            +
                    try:
         | 
| 1468 | 
            +
                        # Check file size
         | 
| 1469 | 
            +
                        size_kb = len(content.encode('utf-8')) / 1024
         | 
| 1470 | 
            +
                        max_size_kb = self.memory_limits.get('max_file_size_kb', 8)
         | 
| 1471 | 
            +
                        
         | 
| 1472 | 
            +
                        if size_kb > max_size_kb:
         | 
| 1473 | 
            +
                            return False, f"Memory size {size_kb:.1f}KB exceeds limit of {max_size_kb}KB"
         | 
| 1474 | 
            +
                        
         | 
| 1475 | 
            +
                        # Check section count
         | 
| 1476 | 
            +
                        sections = re.findall(r'^##\s+(.+)$', content, re.MULTILINE)
         | 
| 1477 | 
            +
                        max_sections = self.memory_limits.get('max_sections', 10)
         | 
| 1478 | 
            +
                        
         | 
| 1479 | 
            +
                        if len(sections) > max_sections:
         | 
| 1480 | 
            +
                            return False, f"Too many sections: {len(sections)} (max {max_sections})"
         | 
| 1481 | 
            +
                        
         | 
| 1482 | 
            +
                        # Check for required sections
         | 
| 1483 | 
            +
                        required = set(self.REQUIRED_SECTIONS)
         | 
| 1484 | 
            +
                        found = set(sections)
         | 
| 1485 | 
            +
                        missing = required - found
         | 
| 1486 | 
            +
                        
         | 
| 1487 | 
            +
                        if missing:
         | 
| 1488 | 
            +
                            return False, f"Missing required sections: {', '.join(missing)}"
         | 
| 1489 | 
            +
                        
         | 
| 1490 | 
            +
                        return True, None
         | 
| 1491 | 
            +
                        
         | 
| 1492 | 
            +
                    except Exception as e:
         | 
| 1493 | 
            +
                        return False, f"Validation error: {str(e)}"
         | 
| 1494 | 
            +
                
         | 
| 1495 | 
            +
                def get_memory_metrics(self, agent_id: Optional[str] = None) -> Dict[str, Any]:
         | 
| 1496 | 
            +
                    """Get memory usage metrics.
         | 
| 1497 | 
            +
                    
         | 
| 1498 | 
            +
                    WHY: This adapter method provides interface compliance by gathering
         | 
| 1499 | 
            +
                    metrics about memory usage.
         | 
| 1500 | 
            +
                    
         | 
| 1501 | 
            +
                    Args:
         | 
| 1502 | 
            +
                        agent_id: Optional specific agent ID, or None for all
         | 
| 1503 | 
            +
                        
         | 
| 1504 | 
            +
                    Returns:
         | 
| 1505 | 
            +
                        Dictionary with memory metrics
         | 
| 1506 | 
            +
                    """
         | 
| 1507 | 
            +
                    metrics = {
         | 
| 1508 | 
            +
                        "total_memories": 0,
         | 
| 1509 | 
            +
                        "total_size_kb": 0,
         | 
| 1510 | 
            +
                        "agent_metrics": {},
         | 
| 1511 | 
            +
                        "limits": self.memory_limits.copy()
         | 
| 1512 | 
            +
                    }
         | 
| 1513 | 
            +
                    
         | 
| 1514 | 
            +
                    try:
         | 
| 1515 | 
            +
                        if agent_id:
         | 
| 1516 | 
            +
                            # Get metrics for specific agent
         | 
| 1517 | 
            +
                            memory_path = self.memories_dir / f"{agent_id}_agent.md"
         | 
| 1518 | 
            +
                            if memory_path.exists():
         | 
| 1519 | 
            +
                                content = memory_path.read_text(encoding='utf-8')
         | 
| 1520 | 
            +
                                size_kb = len(content.encode('utf-8')) / 1024
         | 
| 1521 | 
            +
                                sections = re.findall(r'^##\s+(.+)$', content, re.MULTILINE)
         | 
| 1522 | 
            +
                                
         | 
| 1523 | 
            +
                                metrics["agent_metrics"][agent_id] = {
         | 
| 1524 | 
            +
                                    "size_kb": round(size_kb, 2),
         | 
| 1525 | 
            +
                                    "sections": len(sections),
         | 
| 1526 | 
            +
                                    "exists": True
         | 
| 1527 | 
            +
                                }
         | 
| 1528 | 
            +
                                metrics["total_memories"] = 1
         | 
| 1529 | 
            +
                                metrics["total_size_kb"] = round(size_kb, 2)
         | 
| 1530 | 
            +
                        else:
         | 
| 1531 | 
            +
                            # Get metrics for all agents
         | 
| 1532 | 
            +
                            for memory_file in self.memories_dir.glob("*_agent.md"):
         | 
| 1533 | 
            +
                                agent_name = memory_file.stem.replace("_agent", "")
         | 
| 1534 | 
            +
                                content = memory_file.read_text(encoding='utf-8')
         | 
| 1535 | 
            +
                                size_kb = len(content.encode('utf-8')) / 1024
         | 
| 1536 | 
            +
                                sections = re.findall(r'^##\s+(.+)$', content, re.MULTILINE)
         | 
| 1537 | 
            +
                                
         | 
| 1538 | 
            +
                                metrics["agent_metrics"][agent_name] = {
         | 
| 1539 | 
            +
                                    "size_kb": round(size_kb, 2),
         | 
| 1540 | 
            +
                                    "sections": len(sections),
         | 
| 1541 | 
            +
                                    "exists": True
         | 
| 1542 | 
            +
                                }
         | 
| 1543 | 
            +
                                metrics["total_memories"] += 1
         | 
| 1544 | 
            +
                                metrics["total_size_kb"] += size_kb
         | 
| 1545 | 
            +
                            
         | 
| 1546 | 
            +
                            metrics["total_size_kb"] = round(metrics["total_size_kb"], 2)
         | 
| 1547 | 
            +
                        
         | 
| 1548 | 
            +
                    except Exception as e:
         | 
| 1549 | 
            +
                        self.logger.error(f"Failed to get memory metrics: {e}")
         | 
| 1550 | 
            +
                    
         | 
| 1551 | 
            +
                    return metrics
         | 
| 1397 1552 |  | 
| 1398 1553 |  | 
| 1399 1554 | 
             
            # Convenience functions for external use
         | 
| @@ -27,6 +27,11 @@ import logging | |
| 27 27 | 
             
            import logging.handlers
         | 
| 28 28 | 
             
            from dataclasses import dataclass, asdict
         | 
| 29 29 | 
             
            from enum import Enum
         | 
| 30 | 
            +
            from claude_mpm.core.constants import (
         | 
| 31 | 
            +
                SystemLimits,
         | 
| 32 | 
            +
                TimeoutConfig,
         | 
| 33 | 
            +
                PerformanceConfig
         | 
| 34 | 
            +
            )
         | 
| 30 35 |  | 
| 31 36 | 
             
            # Import configuration manager
         | 
| 32 37 | 
             
            from ..core.config import Config
         | 
| @@ -108,7 +113,7 @@ class AsyncSessionLogger: | |
| 108 113 | 
             
                    else:
         | 
| 109 114 | 
             
                        self.log_format = LogFormat.JSON
         | 
| 110 115 |  | 
| 111 | 
            -
                    self.max_queue_size = max_queue_size if max_queue_size is not None else response_config.get('max_queue_size',  | 
| 116 | 
            +
                    self.max_queue_size = max_queue_size if max_queue_size is not None else response_config.get('max_queue_size', SystemLimits.MAX_QUEUE_SIZE)
         | 
| 112 117 |  | 
| 113 118 | 
             
                    # Handle async configuration with backward compatibility
         | 
| 114 119 | 
             
                    if enable_async is not None:
         | 
| @@ -223,12 +228,12 @@ class AsyncSessionLogger: | |
| 223 228 | 
             
                    while not self._shutdown:
         | 
| 224 229 | 
             
                        try:
         | 
| 225 230 | 
             
                            # Get entry with timeout to allow shutdown checks
         | 
| 226 | 
            -
                            entry = self._queue.get(timeout= | 
| 231 | 
            +
                            entry = self._queue.get(timeout=TimeoutConfig.QUEUE_GET_TIMEOUT)
         | 
| 227 232 |  | 
| 228 233 | 
             
                            # Time the write operation
         | 
| 229 234 | 
             
                            start_time = time.perf_counter()
         | 
| 230 235 | 
             
                            self._write_entry(entry)
         | 
| 231 | 
            -
                            write_time = (time.perf_counter() - start_time) *  | 
| 236 | 
            +
                            write_time = (time.perf_counter() - start_time) * PerformanceConfig.SECONDS_TO_MS
         | 
| 232 237 |  | 
| 233 238 | 
             
                            # Update statistics
         | 
| 234 239 | 
             
                            write_times.append(write_time)
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            """
         | 
| 2 | 
            +
            Communication Services Module
         | 
| 3 | 
            +
            ============================
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            This module contains all communication-related services including
         | 
| 6 | 
            +
            SocketIO server and WebSocket utilities.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Part of TSK-0046: Service Layer Architecture Reorganization
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Services:
         | 
| 11 | 
            +
            - SocketIOServer: Main SocketIO server for real-time communication
         | 
| 12 | 
            +
            - WebSocketClientManager: WebSocket client management utilities
         | 
| 13 | 
            +
            """
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            from .socketio import SocketIOServer
         | 
| 16 | 
            +
            from .websocket import SocketIOClientManager
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            __all__ = [
         | 
| 19 | 
            +
                'SocketIOServer',
         | 
| 20 | 
            +
                'SocketIOClientManager',
         | 
| 21 | 
            +
            ]
         |