claude-mpm 4.5.6__py3-none-any.whl → 4.5.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +20 -5
- claude_mpm/agents/BASE_OPS.md +10 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +28 -4
- claude_mpm/agents/agent_loader.py +19 -2
- claude_mpm/agents/base_agent_loader.py +5 -5
- claude_mpm/agents/templates/agent-manager.json +3 -3
- claude_mpm/agents/templates/agentic-coder-optimizer.json +3 -3
- claude_mpm/agents/templates/api_qa.json +1 -1
- claude_mpm/agents/templates/clerk-ops.json +3 -3
- claude_mpm/agents/templates/code_analyzer.json +3 -3
- claude_mpm/agents/templates/dart_engineer.json +294 -0
- claude_mpm/agents/templates/data_engineer.json +3 -3
- claude_mpm/agents/templates/documentation.json +2 -2
- claude_mpm/agents/templates/engineer.json +2 -2
- claude_mpm/agents/templates/gcp_ops_agent.json +2 -2
- claude_mpm/agents/templates/imagemagick.json +1 -1
- claude_mpm/agents/templates/local_ops_agent.json +363 -49
- claude_mpm/agents/templates/memory_manager.json +2 -2
- claude_mpm/agents/templates/nextjs_engineer.json +2 -2
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/php-engineer.json +1 -1
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/prompt-engineer.json +6 -4
- claude_mpm/agents/templates/python_engineer.json +2 -2
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/react_engineer.json +3 -3
- claude_mpm/agents/templates/refactoring_engineer.json +3 -3
- claude_mpm/agents/templates/research.json +2 -2
- claude_mpm/agents/templates/security.json +2 -2
- claude_mpm/agents/templates/ticketing.json +2 -2
- claude_mpm/agents/templates/typescript_engineer.json +2 -2
- claude_mpm/agents/templates/vercel_ops_agent.json +2 -2
- claude_mpm/agents/templates/version_control.json +2 -2
- claude_mpm/agents/templates/web_qa.json +6 -6
- claude_mpm/agents/templates/web_ui.json +3 -3
- claude_mpm/cli/__init__.py +49 -19
- claude_mpm/cli/commands/configure.py +591 -7
- claude_mpm/cli/parsers/configure_parser.py +5 -0
- claude_mpm/core/__init__.py +53 -17
- claude_mpm/core/config.py +1 -1
- claude_mpm/core/log_manager.py +7 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +16 -11
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +9 -11
- claude_mpm/services/__init__.py +140 -156
- claude_mpm/services/agents/deployment/deployment_config_loader.py +21 -0
- claude_mpm/services/agents/loading/base_agent_manager.py +12 -2
- claude_mpm/services/async_session_logger.py +112 -96
- claude_mpm/services/claude_session_logger.py +63 -61
- claude_mpm/services/mcp_config_manager.py +328 -38
- claude_mpm/services/mcp_gateway/__init__.py +98 -94
- claude_mpm/services/monitor/event_emitter.py +1 -1
- claude_mpm/services/orphan_detection.py +791 -0
- claude_mpm/services/project_port_allocator.py +601 -0
- claude_mpm/services/response_tracker.py +17 -6
- claude_mpm/services/session_manager.py +176 -0
- {claude_mpm-4.5.6.dist-info → claude_mpm-4.5.11.dist-info}/METADATA +1 -1
- {claude_mpm-4.5.6.dist-info → claude_mpm-4.5.11.dist-info}/RECORD +62 -58
- {claude_mpm-4.5.6.dist-info → claude_mpm-4.5.11.dist-info}/WHEEL +0 -0
- {claude_mpm-4.5.6.dist-info → claude_mpm-4.5.11.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.5.6.dist-info → claude_mpm-4.5.11.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.5.6.dist-info → claude_mpm-4.5.11.dist-info}/top_level.txt +0 -0
@@ -58,6 +58,11 @@ def add_configure_subparser(subparsers) -> argparse.ArgumentParser:
|
|
58
58
|
action="store_true",
|
59
59
|
help="Jump directly to behavior file management",
|
60
60
|
)
|
61
|
+
nav_group.add_argument(
|
62
|
+
"--startup",
|
63
|
+
action="store_true",
|
64
|
+
help="Configure startup services and agents",
|
65
|
+
)
|
61
66
|
nav_group.add_argument(
|
62
67
|
"--version-info",
|
63
68
|
action="store_true",
|
claude_mpm/core/__init__.py
CHANGED
@@ -1,20 +1,56 @@
|
|
1
|
-
"""Core components for Claude MPM.
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
)
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
"""Core components for Claude MPM.
|
2
|
+
|
3
|
+
Lazy imports for all components to avoid loading heavy dependencies
|
4
|
+
when only importing lightweight utilities (constants, logging_utils, etc).
|
5
|
+
"""
|
6
|
+
|
7
|
+
|
8
|
+
# Lazy imports via __getattr__ to prevent loading heavy dependencies
|
9
|
+
# when hooks only need lightweight utilities
|
10
|
+
def __getattr__(name):
|
11
|
+
"""Lazy load core components only when accessed using dictionary-based mapping."""
|
12
|
+
from importlib import import_module
|
13
|
+
|
14
|
+
# Dictionary mapping: name -> (module_path, attribute_name)
|
15
|
+
_LAZY_IMPORTS = {
|
16
|
+
# Core components
|
17
|
+
"ClaudeRunner": ("claude_mpm.core.claude_runner", "ClaudeRunner"),
|
18
|
+
"Config": ("claude_mpm.core.config", "Config"),
|
19
|
+
# Dependency injection
|
20
|
+
"DIContainer": ("claude_mpm.core.container", "DIContainer"),
|
21
|
+
"ServiceLifetime": ("claude_mpm.core.container", "ServiceLifetime"),
|
22
|
+
"get_container": ("claude_mpm.core.container", "get_container"),
|
23
|
+
# Factories
|
24
|
+
"AgentServiceFactory": ("claude_mpm.core.factories", "AgentServiceFactory"),
|
25
|
+
"ConfigurationFactory": ("claude_mpm.core.factories", "ConfigurationFactory"),
|
26
|
+
"ServiceFactory": ("claude_mpm.core.factories", "ServiceFactory"),
|
27
|
+
"SessionManagerFactory": ("claude_mpm.core.factories", "SessionManagerFactory"),
|
28
|
+
"get_factory_registry": ("claude_mpm.core.factories", "get_factory_registry"),
|
29
|
+
# Services and utilities
|
30
|
+
"InjectableService": (
|
31
|
+
"claude_mpm.core.injectable_service",
|
32
|
+
"InjectableService",
|
33
|
+
),
|
34
|
+
"LoggerMixin": ("claude_mpm.core.mixins", "LoggerMixin"),
|
35
|
+
# Service registry
|
36
|
+
"ServiceRegistry": ("claude_mpm.core.service_registry", "ServiceRegistry"),
|
37
|
+
"get_service_registry": (
|
38
|
+
"claude_mpm.core.service_registry",
|
39
|
+
"get_service_registry",
|
40
|
+
),
|
41
|
+
"initialize_services": (
|
42
|
+
"claude_mpm.core.service_registry",
|
43
|
+
"initialize_services",
|
44
|
+
),
|
45
|
+
}
|
46
|
+
|
47
|
+
if name in _LAZY_IMPORTS:
|
48
|
+
module_path, attr_name = _LAZY_IMPORTS[name]
|
49
|
+
module = import_module(module_path)
|
50
|
+
return getattr(module, attr_name)
|
51
|
+
|
52
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
53
|
+
|
18
54
|
|
19
55
|
__all__ = [
|
20
56
|
"AgentServiceFactory",
|
claude_mpm/core/config.py
CHANGED
@@ -201,7 +201,7 @@ class Config:
|
|
201
201
|
# Set flag IMMEDIATELY before logging to prevent any possibility of duplicate
|
202
202
|
# messages. No lock needed here since we're already inside __init__ lock
|
203
203
|
Config._success_logged = True
|
204
|
-
logger.
|
204
|
+
logger.debug(
|
205
205
|
f"✓ Successfully loaded configuration from {file_path}"
|
206
206
|
)
|
207
207
|
else:
|
claude_mpm/core/log_manager.py
CHANGED
@@ -122,6 +122,13 @@ class LogManager:
|
|
122
122
|
if run_cleanup_on_startup is None:
|
123
123
|
return # Cleanup utility not available
|
124
124
|
|
125
|
+
# Check environment variable to skip cleanup (for configure command)
|
126
|
+
import os
|
127
|
+
|
128
|
+
if os.environ.get("CLAUDE_MPM_SKIP_CLEANUP", "0") == "1":
|
129
|
+
logger.debug("Startup cleanup skipped (CLAUDE_MPM_SKIP_CLEANUP=1)")
|
130
|
+
return
|
131
|
+
|
125
132
|
try:
|
126
133
|
# Get cleanup configuration
|
127
134
|
cleanup_config = self.config.get("log_cleanup", {})
|
@@ -10,28 +10,27 @@ import os
|
|
10
10
|
import re
|
11
11
|
import sys
|
12
12
|
from datetime import datetime, timezone
|
13
|
-
from typing import Optional
|
13
|
+
from typing import Any, Optional
|
14
14
|
|
15
15
|
# Debug mode
|
16
16
|
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
|
17
17
|
|
18
18
|
# Response tracking integration
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if DEBUG:
|
26
|
-
print(f"Response tracking not available: {e}", file=sys.stderr)
|
27
|
-
RESPONSE_TRACKING_AVAILABLE = False
|
19
|
+
# NOTE: ResponseTracker import moved to _initialize_response_tracking() for lazy loading
|
20
|
+
# This prevents unnecessary import of base_agent_loader and other heavy dependencies
|
21
|
+
# when hooks don't need response tracking
|
22
|
+
RESPONSE_TRACKING_AVAILABLE = (
|
23
|
+
True # Assume available, will check on actual initialization
|
24
|
+
)
|
28
25
|
|
29
26
|
|
30
27
|
class ResponseTrackingManager:
|
31
28
|
"""Manager for response tracking functionality."""
|
32
29
|
|
33
30
|
def __init__(self):
|
34
|
-
self.response_tracker: Optional[
|
31
|
+
self.response_tracker: Optional[Any] = (
|
32
|
+
None # Type hint changed to Any for lazy import
|
33
|
+
)
|
35
34
|
self.response_tracking_enabled = False
|
36
35
|
self.track_all_interactions = (
|
37
36
|
False # Track all Claude interactions, not just delegations
|
@@ -49,8 +48,14 @@ class ResponseTrackingManager:
|
|
49
48
|
|
50
49
|
DESIGN DECISION: Check configuration to allow enabling/disabling
|
51
50
|
response tracking without code changes.
|
51
|
+
|
52
|
+
NOTE: ResponseTracker is imported lazily here to avoid loading
|
53
|
+
base_agent_loader and other heavy dependencies unless actually needed.
|
52
54
|
"""
|
53
55
|
try:
|
56
|
+
# Lazy import of ResponseTracker to avoid unnecessary dependency loading
|
57
|
+
from claude_mpm.services.response_tracker import ResponseTracker
|
58
|
+
|
54
59
|
# Create configuration with optional config file using ConfigLoader
|
55
60
|
config_file = os.environ.get("CLAUDE_PM_CONFIG_FILE")
|
56
61
|
from claude_mpm.core.shared.config_loader import ConfigLoader, ConfigPattern
|
@@ -26,14 +26,8 @@ except ImportError:
|
|
26
26
|
REQUESTS_AVAILABLE = False
|
27
27
|
requests = None
|
28
28
|
|
29
|
-
# Import high-performance event emitter
|
30
|
-
|
31
|
-
from claude_mpm.services.monitor.event_emitter import get_event_emitter
|
32
|
-
|
33
|
-
EVENT_EMITTER_AVAILABLE = True
|
34
|
-
except ImportError:
|
35
|
-
EVENT_EMITTER_AVAILABLE = False
|
36
|
-
get_event_emitter = None
|
29
|
+
# Import high-performance event emitter - lazy loaded in _async_emit()
|
30
|
+
# to reduce hook handler initialization time by ~85% (792ms -> minimal)
|
37
31
|
|
38
32
|
# Import EventNormalizer for consistent event formatting
|
39
33
|
try:
|
@@ -137,9 +131,6 @@ class ConnectionManagerService:
|
|
137
131
|
|
138
132
|
def _try_async_emit(self, namespace: str, event: str, data: dict) -> bool:
|
139
133
|
"""Try to emit event using high-performance async emitter."""
|
140
|
-
if not EVENT_EMITTER_AVAILABLE:
|
141
|
-
return False
|
142
|
-
|
143
134
|
try:
|
144
135
|
# Run async emission in the current event loop or create one
|
145
136
|
loop = None
|
@@ -170,8 +161,15 @@ class ConnectionManagerService:
|
|
170
161
|
async def _async_emit(self, namespace: str, event: str, data: dict) -> bool:
|
171
162
|
"""Async helper for event emission."""
|
172
163
|
try:
|
164
|
+
# Lazy load event emitter to reduce initialization overhead
|
165
|
+
from claude_mpm.services.monitor.event_emitter import get_event_emitter
|
166
|
+
|
173
167
|
emitter = await get_event_emitter()
|
174
168
|
return await emitter.emit_event(namespace, "claude_event", data)
|
169
|
+
except ImportError:
|
170
|
+
if DEBUG:
|
171
|
+
print("⚠️ Event emitter not available", file=sys.stderr)
|
172
|
+
return False
|
175
173
|
except Exception as e:
|
176
174
|
if DEBUG:
|
177
175
|
print(f"⚠️ Async emitter error: {e}", file=sys.stderr)
|
claude_mpm/services/__init__.py
CHANGED
@@ -13,169 +13,152 @@ New structure:
|
|
13
13
|
|
14
14
|
|
15
15
|
# Use lazy imports to prevent circular dependency issues
|
16
|
-
def __getattr__(name):
|
17
|
-
"""Lazy import to prevent circular dependencies."""
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
16
|
+
def __getattr__(name):
|
17
|
+
"""Lazy import to prevent circular dependencies using dictionary-based mapping."""
|
18
|
+
from importlib import import_module
|
19
|
+
|
20
|
+
# Dictionary mapping: name -> (module_path, attribute_name)
|
21
|
+
# For agent services, we import from the __init__.py modules to respect their import structure
|
22
|
+
_LAZY_IMPORTS = {
|
23
|
+
# Agent services - use __init__.py modules (not direct file paths) to respect import structure
|
24
|
+
"AgentDeploymentService": (
|
25
|
+
"claude_mpm.services.agents.deployment",
|
26
|
+
"AgentDeploymentService",
|
27
|
+
),
|
28
|
+
"AgentMemoryManager": (
|
29
|
+
"claude_mpm.services.agents.memory",
|
30
|
+
"AgentMemoryManager",
|
31
|
+
),
|
32
|
+
"get_memory_manager": (
|
33
|
+
"claude_mpm.services.agents.memory",
|
34
|
+
"get_memory_manager",
|
35
|
+
),
|
36
|
+
"AgentRegistry": ("claude_mpm.services.agents.registry", "AgentRegistry"),
|
37
|
+
"AgentLifecycleManager": (
|
38
|
+
"claude_mpm.services.agents.deployment",
|
39
|
+
"AgentLifecycleManager",
|
40
|
+
),
|
41
|
+
"AgentManager": ("claude_mpm.services.agents.management", "AgentManager"),
|
42
|
+
"AgentCapabilitiesGenerator": (
|
43
|
+
"claude_mpm.services.agents.management",
|
44
|
+
"AgentCapabilitiesGenerator",
|
45
|
+
),
|
46
|
+
"AgentModificationTracker": (
|
47
|
+
"claude_mpm.services.agents.registry",
|
48
|
+
"AgentModificationTracker",
|
49
|
+
),
|
50
|
+
"AgentPersistenceService": (
|
51
|
+
"claude_mpm.services.agents.memory",
|
52
|
+
"AgentPersistenceService",
|
53
|
+
),
|
54
|
+
"AgentProfileLoader": (
|
55
|
+
"claude_mpm.services.agents.loading",
|
56
|
+
"AgentProfileLoader",
|
57
|
+
),
|
58
|
+
"AgentVersionManager": (
|
59
|
+
"claude_mpm.services.agents.deployment",
|
60
|
+
"AgentVersionManager",
|
61
|
+
),
|
62
|
+
"BaseAgentManager": ("claude_mpm.services.agents.loading", "BaseAgentManager"),
|
63
|
+
"DeployedAgentDiscovery": (
|
64
|
+
"claude_mpm.services.agents.registry",
|
65
|
+
"DeployedAgentDiscovery",
|
66
|
+
),
|
67
|
+
"FrameworkAgentLoader": (
|
68
|
+
"claude_mpm.services.agents.loading",
|
69
|
+
"FrameworkAgentLoader",
|
70
|
+
),
|
71
|
+
"AgentManagementService": (
|
72
|
+
"claude_mpm.services.agents.management",
|
73
|
+
"AgentManager",
|
74
|
+
),
|
75
|
+
# Infrastructure services
|
76
|
+
"HookService": ("claude_mpm.services.hook_service", "HookService"),
|
77
|
+
"ProjectAnalyzer": ("claude_mpm.services.project.analyzer", "ProjectAnalyzer"),
|
78
|
+
"AdvancedHealthMonitor": (
|
79
|
+
"claude_mpm.services.infrastructure.monitoring",
|
80
|
+
"AdvancedHealthMonitor",
|
81
|
+
),
|
82
|
+
"HealthMonitor": (
|
83
|
+
"claude_mpm.services.infrastructure.monitoring",
|
84
|
+
"AdvancedHealthMonitor",
|
85
|
+
),
|
86
|
+
"LoggingService": (
|
87
|
+
"claude_mpm.services.infrastructure.logging",
|
88
|
+
"LoggingService",
|
89
|
+
),
|
90
|
+
# Communication services
|
91
|
+
"StandaloneSocketIOServer": (
|
92
|
+
"claude_mpm.services.socketio_server",
|
93
|
+
"SocketIOServer",
|
94
|
+
),
|
95
|
+
"SocketIOServer": ("claude_mpm.services.socketio_server", "SocketIOServer"),
|
96
|
+
"SocketIOClientManager": (
|
97
|
+
"claude_mpm.services.socketio_client_manager",
|
98
|
+
"SocketIOClientManager",
|
99
|
+
),
|
100
|
+
# Memory services
|
101
|
+
"MemoryBuilder": ("claude_mpm.services.memory.builder", "MemoryBuilder"),
|
102
|
+
"MemoryRouter": ("claude_mpm.services.memory.router", "MemoryRouter"),
|
103
|
+
"MemoryOptimizer": ("claude_mpm.services.memory.optimizer", "MemoryOptimizer"),
|
104
|
+
"SimpleCacheService": (
|
105
|
+
"claude_mpm.services.memory.cache.simple_cache",
|
106
|
+
"SimpleCacheService",
|
107
|
+
),
|
108
|
+
"SharedPromptCache": (
|
109
|
+
"claude_mpm.services.memory.cache.shared_prompt_cache",
|
110
|
+
"SharedPromptCache",
|
111
|
+
),
|
112
|
+
# Project services
|
113
|
+
"ProjectRegistry": ("claude_mpm.services.project.registry", "ProjectRegistry"),
|
114
|
+
# MCP Gateway services
|
115
|
+
"MCPConfiguration": (
|
116
|
+
"claude_mpm.services.mcp_gateway.config.configuration",
|
117
|
+
"MCPConfiguration",
|
118
|
+
),
|
119
|
+
"MCPConfigLoader": (
|
120
|
+
"claude_mpm.services.mcp_gateway.config.config_loader",
|
121
|
+
"MCPConfigLoader",
|
122
|
+
),
|
123
|
+
"MCPServer": ("claude_mpm.services.mcp_gateway.server.mcp_server", "MCPServer"),
|
124
|
+
"MCPToolRegistry": (
|
125
|
+
"claude_mpm.services.mcp_gateway.tools.tool_registry",
|
126
|
+
"MCPToolRegistry",
|
127
|
+
),
|
128
|
+
"BaseMCPService": (
|
129
|
+
"claude_mpm.services.mcp_gateway.core.base",
|
130
|
+
"BaseMCPService",
|
131
|
+
),
|
132
|
+
# Other services
|
133
|
+
"TicketManager": ("claude_mpm.services.ticket_manager", "TicketManager"),
|
134
|
+
}
|
135
|
+
|
136
|
+
# Handle direct mappings
|
137
|
+
if name in _LAZY_IMPORTS:
|
138
|
+
module_path, attr_name = _LAZY_IMPORTS[name]
|
139
|
+
module = import_module(module_path)
|
140
|
+
return getattr(module, attr_name)
|
141
|
+
|
142
|
+
# Handle RecoveryManager with special error handling
|
99
143
|
if name == "RecoveryManager":
|
100
144
|
try:
|
101
|
-
|
102
|
-
|
103
|
-
return RecoveryManager
|
145
|
+
module = import_module("claude_mpm.services.recovery_manager")
|
146
|
+
return module.RecoveryManager
|
104
147
|
except ImportError:
|
105
148
|
raise AttributeError(f"Recovery management not available: {name}")
|
106
|
-
elif name in {"StandaloneSocketIOServer", "SocketIOServer"}:
|
107
|
-
from .socketio_server import SocketIOServer
|
108
|
-
|
109
|
-
return SocketIOServer
|
110
|
-
# Backward compatibility for memory services
|
111
|
-
elif name == "MemoryBuilder":
|
112
|
-
from .memory.builder import MemoryBuilder
|
113
|
-
|
114
|
-
return MemoryBuilder
|
115
|
-
elif name == "MemoryRouter":
|
116
|
-
from .memory.router import MemoryRouter
|
117
|
-
|
118
|
-
return MemoryRouter
|
119
|
-
elif name == "MemoryOptimizer":
|
120
|
-
from .memory.optimizer import MemoryOptimizer
|
121
|
-
|
122
|
-
return MemoryOptimizer
|
123
|
-
elif name == "SimpleCacheService":
|
124
|
-
from .memory.cache.simple_cache import SimpleCacheService
|
125
|
-
|
126
|
-
return SimpleCacheService
|
127
|
-
elif name == "SharedPromptCache":
|
128
|
-
from .memory.cache.shared_prompt_cache import SharedPromptCache
|
129
|
-
|
130
|
-
return SharedPromptCache
|
131
|
-
# New service organization imports
|
132
|
-
elif name == "AgentManagementService":
|
133
|
-
from .agents.management import AgentManager
|
134
|
-
|
135
|
-
return AgentManager
|
136
|
-
elif name == "ProjectRegistry":
|
137
|
-
from .project.registry import ProjectRegistry
|
138
149
|
|
139
|
-
|
140
|
-
|
141
|
-
|
150
|
+
# Handle MCP interfaces (names starting with "IMCP")
|
151
|
+
if name.startswith("IMCP"):
|
152
|
+
module = import_module("claude_mpm.services.mcp_gateway.core.interfaces")
|
153
|
+
return getattr(module, name)
|
142
154
|
|
143
|
-
|
144
|
-
|
145
|
-
|
155
|
+
# Handle MCP exceptions (names starting with "MCP" and containing "Error")
|
156
|
+
if name.startswith("MCP") and "Error" in name:
|
157
|
+
module = import_module("claude_mpm.services.mcp_gateway.core.exceptions")
|
158
|
+
return getattr(module, name)
|
146
159
|
|
147
|
-
|
148
|
-
|
149
|
-
elif name == "MCPConfiguration":
|
150
|
-
from .mcp_gateway.config.configuration import MCPConfiguration
|
151
|
-
|
152
|
-
return MCPConfiguration
|
153
|
-
elif name == "MCPConfigLoader":
|
154
|
-
from .mcp_gateway.config.config_loader import MCPConfigLoader
|
155
|
-
|
156
|
-
return MCPConfigLoader
|
157
|
-
elif name == "MCPServer":
|
158
|
-
from .mcp_gateway.server.mcp_server import MCPServer
|
159
|
-
|
160
|
-
return MCPServer
|
161
|
-
elif name == "MCPToolRegistry":
|
162
|
-
from .mcp_gateway.tools.tool_registry import MCPToolRegistry
|
163
|
-
|
164
|
-
return MCPToolRegistry
|
165
|
-
elif name == "BaseMCPService":
|
166
|
-
from .mcp_gateway.core.base import BaseMCPService
|
167
|
-
|
168
|
-
return BaseMCPService
|
169
|
-
elif name.startswith("IMCP"):
|
170
|
-
from .mcp_gateway.core import interfaces
|
171
|
-
|
172
|
-
return getattr(interfaces, name)
|
173
|
-
elif name.startswith("MCP") and "Error" in name:
|
174
|
-
from .mcp_gateway.core import exceptions
|
175
|
-
|
176
|
-
return getattr(exceptions, name)
|
177
|
-
# Core interfaces and base classes
|
178
|
-
elif name.startswith("I") or name in [
|
160
|
+
# Handle core interfaces and base classes
|
161
|
+
if name.startswith("I") or name in [
|
179
162
|
"BaseService",
|
180
163
|
"SyncBaseService",
|
181
164
|
"SingletonService",
|
@@ -183,6 +166,7 @@ def __getattr__(name): # noqa: PLR0911
|
|
183
166
|
from . import core
|
184
167
|
|
185
168
|
return getattr(core, name)
|
169
|
+
|
186
170
|
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
187
171
|
|
188
172
|
|
@@ -112,8 +112,29 @@ class DeploymentConfigLoader:
|
|
112
112
|
Returns:
|
113
113
|
True if the agent should be deployed, False otherwise
|
114
114
|
"""
|
115
|
+
if config is None:
|
116
|
+
config = Config()
|
117
|
+
|
115
118
|
settings = self.get_deployment_settings(config)
|
116
119
|
|
120
|
+
# Check startup configuration for system agents
|
121
|
+
if agent_source == "system":
|
122
|
+
# Check startup configuration first
|
123
|
+
startup_enabled = config.get("startup.enabled_agents", [])
|
124
|
+
if startup_enabled:
|
125
|
+
# Normalize for comparison
|
126
|
+
check_id = agent_id if settings["case_sensitive"] else agent_id.lower()
|
127
|
+
startup_list = (
|
128
|
+
startup_enabled
|
129
|
+
if settings["case_sensitive"]
|
130
|
+
else [a.lower() for a in startup_enabled]
|
131
|
+
)
|
132
|
+
if check_id not in startup_list:
|
133
|
+
self.logger.debug(
|
134
|
+
f"Skipping system agent {agent_id} - not in startup enabled list"
|
135
|
+
)
|
136
|
+
return False
|
137
|
+
|
117
138
|
# Check if the source type is enabled
|
118
139
|
if agent_source == "system" and not settings["deploy_system_agents"]:
|
119
140
|
self.logger.debug(
|
@@ -13,7 +13,9 @@ from enum import Enum
|
|
13
13
|
from pathlib import Path
|
14
14
|
from typing import Any, Dict, List, Optional
|
15
15
|
|
16
|
-
|
16
|
+
# Lazy import for base_agent_loader to reduce initialization overhead
|
17
|
+
# base_agent_loader adds ~500ms to import time
|
18
|
+
# from claude_mpm.agents.base_agent_loader import clear_base_agent_cache
|
17
19
|
from claude_mpm.core.logging_utils import get_logger
|
18
20
|
from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
|
19
21
|
from claude_mpm.services.shared import ConfigServiceBase
|
@@ -21,6 +23,13 @@ from claude_mpm.services.shared import ConfigServiceBase
|
|
21
23
|
logger = get_logger(__name__)
|
22
24
|
|
23
25
|
|
26
|
+
def _get_clear_base_agent_cache():
|
27
|
+
"""Lazy loader for clear_base_agent_cache function."""
|
28
|
+
from claude_mpm.agents.base_agent_loader import clear_base_agent_cache
|
29
|
+
|
30
|
+
return clear_base_agent_cache
|
31
|
+
|
32
|
+
|
24
33
|
class BaseAgentSection(str, Enum):
|
25
34
|
"""Base agent markdown sections."""
|
26
35
|
|
@@ -134,7 +143,8 @@ class BaseAgentManager(ConfigServiceBase):
|
|
134
143
|
content = self._structure_to_markdown(current)
|
135
144
|
self.base_agent_path.write_text(content, encoding="utf-8")
|
136
145
|
|
137
|
-
# Clear caches
|
146
|
+
# Clear caches (lazy load to avoid import overhead)
|
147
|
+
clear_base_agent_cache = _get_clear_base_agent_cache()
|
138
148
|
clear_base_agent_cache()
|
139
149
|
self.cache.invalidate("base_agent:instructions")
|
140
150
|
|