claude-mpm 3.4.27__py3-none-any.whl → 3.5.0__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 (123) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +182 -299
  3. claude_mpm/agents/agent_loader.py +283 -57
  4. claude_mpm/agents/agent_loader_integration.py +6 -9
  5. claude_mpm/agents/base_agent.json +2 -1
  6. claude_mpm/agents/base_agent_loader.py +1 -1
  7. claude_mpm/cli/__init__.py +5 -7
  8. claude_mpm/cli/commands/__init__.py +0 -2
  9. claude_mpm/cli/commands/agents.py +1 -1
  10. claude_mpm/cli/commands/memory.py +1 -1
  11. claude_mpm/cli/commands/run.py +12 -0
  12. claude_mpm/cli/parser.py +0 -13
  13. claude_mpm/cli/utils.py +1 -1
  14. claude_mpm/config/__init__.py +44 -2
  15. claude_mpm/config/agent_config.py +348 -0
  16. claude_mpm/config/paths.py +322 -0
  17. claude_mpm/constants.py +0 -1
  18. claude_mpm/core/__init__.py +2 -5
  19. claude_mpm/core/agent_registry.py +63 -17
  20. claude_mpm/core/claude_runner.py +354 -43
  21. claude_mpm/core/config.py +7 -1
  22. claude_mpm/core/config_aliases.py +4 -3
  23. claude_mpm/core/config_paths.py +151 -0
  24. claude_mpm/core/factories.py +4 -50
  25. claude_mpm/core/logger.py +11 -13
  26. claude_mpm/core/service_registry.py +2 -2
  27. claude_mpm/dashboard/static/js/components/agent-inference.js +101 -25
  28. claude_mpm/dashboard/static/js/components/event-processor.js +3 -2
  29. claude_mpm/hooks/claude_hooks/hook_handler.py +343 -83
  30. claude_mpm/hooks/memory_integration_hook.py +1 -1
  31. claude_mpm/init.py +37 -6
  32. claude_mpm/scripts/socketio_daemon.py +6 -2
  33. claude_mpm/services/__init__.py +71 -3
  34. claude_mpm/services/agents/__init__.py +85 -0
  35. claude_mpm/services/agents/deployment/__init__.py +21 -0
  36. claude_mpm/services/{agent_deployment.py → agents/deployment/agent_deployment.py} +192 -41
  37. claude_mpm/services/{agent_lifecycle_manager.py → agents/deployment/agent_lifecycle_manager.py} +11 -10
  38. claude_mpm/services/agents/loading/__init__.py +11 -0
  39. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +9 -8
  40. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +2 -2
  41. claude_mpm/services/{framework_agent_loader.py → agents/loading/framework_agent_loader.py} +116 -40
  42. claude_mpm/services/agents/management/__init__.py +9 -0
  43. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +6 -5
  44. claude_mpm/services/agents/memory/__init__.py +21 -0
  45. claude_mpm/services/{agent_memory_manager.py → agents/memory/agent_memory_manager.py} +3 -3
  46. claude_mpm/services/agents/registry/__init__.py +29 -0
  47. claude_mpm/services/{agent_registry.py → agents/registry/agent_registry.py} +101 -16
  48. claude_mpm/services/{deployed_agent_discovery.py → agents/registry/deployed_agent_discovery.py} +12 -2
  49. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +6 -5
  50. claude_mpm/services/async_session_logger.py +584 -0
  51. claude_mpm/services/claude_session_logger.py +299 -0
  52. claude_mpm/services/framework_claude_md_generator/content_assembler.py +2 -2
  53. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +17 -17
  54. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +3 -3
  55. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +1 -1
  56. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +1 -1
  57. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +19 -24
  58. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +1 -1
  59. claude_mpm/services/framework_claude_md_generator.py +4 -2
  60. claude_mpm/services/memory/__init__.py +17 -0
  61. claude_mpm/services/{memory_builder.py → memory/builder.py} +3 -3
  62. claude_mpm/services/memory/cache/__init__.py +14 -0
  63. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +1 -1
  64. claude_mpm/services/memory/cache/simple_cache.py +317 -0
  65. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +1 -1
  66. claude_mpm/services/{memory_router.py → memory/router.py} +1 -1
  67. claude_mpm/services/optimized_hook_service.py +542 -0
  68. claude_mpm/services/project_registry.py +14 -8
  69. claude_mpm/services/response_tracker.py +237 -0
  70. claude_mpm/services/ticketing_service_original.py +4 -2
  71. claude_mpm/services/version_control/branch_strategy.py +3 -1
  72. claude_mpm/utils/paths.py +12 -10
  73. claude_mpm/utils/session_logging.py +114 -0
  74. claude_mpm/validation/agent_validator.py +2 -1
  75. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/METADATA +26 -20
  76. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/RECORD +83 -106
  77. claude_mpm/cli/commands/ui.py +0 -57
  78. claude_mpm/core/simple_runner.py +0 -1046
  79. claude_mpm/hooks/builtin/__init__.py +0 -1
  80. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  81. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  82. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  83. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  84. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  85. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  86. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  87. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  88. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  89. claude_mpm/orchestration/__init__.py +0 -6
  90. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  91. claude_mpm/orchestration/archive/factory.py +0 -215
  92. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  93. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  94. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  95. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  96. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  97. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  98. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  99. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  100. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  101. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  102. claude_mpm/schemas/workflow_validator.py +0 -411
  103. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  104. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  105. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  106. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  107. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  108. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  109. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  110. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  111. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  112. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  113. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  114. claude_mpm/ui/__init__.py +0 -1
  115. claude_mpm/ui/rich_terminal_ui.py +0 -295
  116. claude_mpm/ui/terminal_ui.py +0 -328
  117. /claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +0 -0
  118. /claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +0 -0
  119. /claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +0 -0
  120. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/WHEEL +0 -0
  121. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/entry_points.txt +0 -0
  122. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/licenses/LICENSE +0 -0
  123. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/top_level.txt +0 -0
claude_mpm/cli/utils.py CHANGED
@@ -60,7 +60,7 @@ def get_agent_versions_display() -> Optional[str]:
60
60
  Formatted string containing agent version information, or None if failed
61
61
  """
62
62
  try:
63
- from ..services.agent_deployment import AgentDeploymentService
63
+ from ..services import AgentDeploymentService
64
64
  deployment_service = AgentDeploymentService()
65
65
 
66
66
  # Get deployed agents
@@ -1,5 +1,47 @@
1
1
  """Configuration module for claude-mpm."""
2
2
 
3
- from .hook_config import HookConfig
3
+ # Import only modules that exist
4
+ __all__ = []
4
5
 
5
- __all__ = ['HookConfig']
6
+ # Import centralized path management
7
+ try:
8
+ from .paths import (
9
+ paths,
10
+ ClaudeMPMPaths,
11
+ get_project_root,
12
+ get_src_dir,
13
+ get_claude_mpm_dir,
14
+ get_agents_dir,
15
+ get_services_dir,
16
+ get_config_dir,
17
+ get_version,
18
+ ensure_src_in_path
19
+ )
20
+ __all__.extend([
21
+ 'paths',
22
+ 'ClaudeMPMPaths',
23
+ 'get_project_root',
24
+ 'get_src_dir',
25
+ 'get_claude_mpm_dir',
26
+ 'get_agents_dir',
27
+ 'get_services_dir',
28
+ 'get_config_dir',
29
+ 'get_version',
30
+ 'ensure_src_in_path'
31
+ ])
32
+ except ImportError:
33
+ pass
34
+
35
+ # Try to import HookConfig if it exists
36
+ try:
37
+ from .hook_config import HookConfig
38
+ __all__.append('HookConfig')
39
+ except ImportError:
40
+ pass
41
+
42
+ # Import AgentConfig
43
+ try:
44
+ from .agent_config import AgentConfig, get_agent_config, set_agent_config, reset_agent_config
45
+ __all__.extend(['AgentConfig', 'get_agent_config', 'set_agent_config', 'reset_agent_config'])
46
+ except ImportError:
47
+ pass
@@ -0,0 +1,348 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Agent Configuration Module
4
+
5
+ Provides configuration support for agent loading across all tiers,
6
+ with special support for PROJECT-level agent directories.
7
+
8
+ This module handles:
9
+ - Agent directory discovery and configuration
10
+ - Environment variable support for agent paths
11
+ - Project-specific agent overrides
12
+ - Tier precedence configuration
13
+ """
14
+
15
+ import os
16
+ import json
17
+ import logging
18
+ from pathlib import Path
19
+ from typing import Dict, Optional, List, Any
20
+ from dataclasses import dataclass, field
21
+ from enum import Enum
22
+
23
+ from claude_mpm.core.config_paths import ConfigPaths
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class AgentPrecedenceMode(Enum):
29
+ """Agent loading precedence modes."""
30
+ STRICT = "strict" # PROJECT > USER > SYSTEM (no fallback)
31
+ OVERRIDE = "override" # PROJECT > USER > SYSTEM (with fallback)
32
+ MERGE = "merge" # Merge agents from all tiers
33
+
34
+
35
+ @dataclass
36
+ class AgentConfig:
37
+ """Configuration for agent loading and discovery."""
38
+
39
+ # Agent directory paths
40
+ project_agents_dir: Optional[Path] = None
41
+ user_agents_dir: Optional[Path] = None
42
+ system_agents_dir: Optional[Path] = None
43
+
44
+ # Additional search paths (from environment or config)
45
+ additional_paths: List[Path] = field(default_factory=list)
46
+
47
+ # Precedence configuration
48
+ precedence_mode: AgentPrecedenceMode = AgentPrecedenceMode.OVERRIDE
49
+
50
+ # Feature flags
51
+ enable_project_agents: bool = True
52
+ enable_user_agents: bool = True
53
+ enable_system_agents: bool = True
54
+ enable_hot_reload: bool = True
55
+
56
+ # Cache configuration
57
+ cache_ttl_seconds: int = 3600
58
+ enable_caching: bool = True
59
+
60
+ # Validation settings
61
+ validate_on_load: bool = True
62
+ strict_validation: bool = False
63
+
64
+ @classmethod
65
+ def from_environment(cls) -> 'AgentConfig':
66
+ """
67
+ Create configuration from environment variables.
68
+
69
+ Environment variables:
70
+ - CLAUDE_MPM_PROJECT_AGENTS_DIR: Override project agents directory
71
+ - CLAUDE_MPM_USER_AGENTS_DIR: Override user agents directory
72
+ - CLAUDE_MPM_SYSTEM_AGENTS_DIR: Override system agents directory
73
+ - CLAUDE_MPM_AGENT_SEARCH_PATH: Additional paths (colon-separated)
74
+ - CLAUDE_MPM_AGENT_PRECEDENCE: Precedence mode (strict/override/merge)
75
+ - CLAUDE_MPM_DISABLE_PROJECT_AGENTS: Disable project agents
76
+ - CLAUDE_MPM_DISABLE_USER_AGENTS: Disable user agents
77
+ - CLAUDE_MPM_DISABLE_SYSTEM_AGENTS: Disable system agents
78
+ - CLAUDE_MPM_AGENT_HOT_RELOAD: Enable/disable hot reload
79
+ - CLAUDE_MPM_AGENT_CACHE_TTL: Cache TTL in seconds
80
+ """
81
+ config = cls()
82
+
83
+ # Directory overrides
84
+ if proj_dir := os.getenv('CLAUDE_MPM_PROJECT_AGENTS_DIR'):
85
+ config.project_agents_dir = Path(proj_dir)
86
+ logger.info(f"Project agents directory override: {proj_dir}")
87
+
88
+ if user_dir := os.getenv('CLAUDE_MPM_USER_AGENTS_DIR'):
89
+ config.user_agents_dir = Path(user_dir)
90
+ logger.info(f"User agents directory override: {user_dir}")
91
+
92
+ if sys_dir := os.getenv('CLAUDE_MPM_SYSTEM_AGENTS_DIR'):
93
+ config.system_agents_dir = Path(sys_dir)
94
+ logger.info(f"System agents directory override: {sys_dir}")
95
+
96
+ # Additional search paths
97
+ if search_path := os.getenv('CLAUDE_MPM_AGENT_SEARCH_PATH'):
98
+ paths = [Path(p.strip()) for p in search_path.split(':') if p.strip()]
99
+ config.additional_paths = [p for p in paths if p.exists()]
100
+ logger.info(f"Additional agent search paths: {config.additional_paths}")
101
+
102
+ # Precedence mode
103
+ if precedence := os.getenv('CLAUDE_MPM_AGENT_PRECEDENCE'):
104
+ try:
105
+ config.precedence_mode = AgentPrecedenceMode(precedence.lower())
106
+ logger.info(f"Agent precedence mode: {config.precedence_mode.value}")
107
+ except ValueError:
108
+ logger.warning(f"Invalid precedence mode: {precedence}, using default")
109
+
110
+ # Feature flags
111
+ config.enable_project_agents = os.getenv('CLAUDE_MPM_DISABLE_PROJECT_AGENTS', '').lower() != 'true'
112
+ config.enable_user_agents = os.getenv('CLAUDE_MPM_DISABLE_USER_AGENTS', '').lower() != 'true'
113
+ config.enable_system_agents = os.getenv('CLAUDE_MPM_DISABLE_SYSTEM_AGENTS', '').lower() != 'true'
114
+ config.enable_hot_reload = os.getenv('CLAUDE_MPM_AGENT_HOT_RELOAD', 'true').lower() == 'true'
115
+
116
+ # Cache configuration
117
+ if cache_ttl := os.getenv('CLAUDE_MPM_AGENT_CACHE_TTL'):
118
+ try:
119
+ config.cache_ttl_seconds = int(cache_ttl)
120
+ except ValueError:
121
+ logger.warning(f"Invalid cache TTL: {cache_ttl}, using default")
122
+
123
+ return config
124
+
125
+ @classmethod
126
+ def from_file(cls, config_file: Path) -> 'AgentConfig':
127
+ """
128
+ Load configuration from a JSON or YAML file.
129
+
130
+ Args:
131
+ config_file: Path to configuration file
132
+
133
+ Returns:
134
+ AgentConfig instance
135
+ """
136
+ if not config_file.exists():
137
+ logger.warning(f"Config file not found: {config_file}")
138
+ return cls()
139
+
140
+ try:
141
+ if config_file.suffix in ['.yaml', '.yml']:
142
+ import yaml
143
+ with open(config_file, 'r') as f:
144
+ data = yaml.safe_load(f)
145
+ else:
146
+ with open(config_file, 'r') as f:
147
+ data = json.load(f)
148
+
149
+ config = cls()
150
+
151
+ # Parse directory paths
152
+ if 'project_agents_dir' in data:
153
+ config.project_agents_dir = Path(data['project_agents_dir'])
154
+ if 'user_agents_dir' in data:
155
+ config.user_agents_dir = Path(data['user_agents_dir'])
156
+ if 'system_agents_dir' in data:
157
+ config.system_agents_dir = Path(data['system_agents_dir'])
158
+
159
+ # Parse additional paths
160
+ if 'additional_paths' in data:
161
+ config.additional_paths = [Path(p) for p in data['additional_paths']]
162
+
163
+ # Parse precedence mode
164
+ if 'precedence_mode' in data:
165
+ config.precedence_mode = AgentPrecedenceMode(data['precedence_mode'])
166
+
167
+ # Parse feature flags
168
+ for flag in ['enable_project_agents', 'enable_user_agents',
169
+ 'enable_system_agents', 'enable_hot_reload',
170
+ 'enable_caching', 'validate_on_load', 'strict_validation']:
171
+ if flag in data:
172
+ setattr(config, flag, bool(data[flag]))
173
+
174
+ # Parse cache TTL
175
+ if 'cache_ttl_seconds' in data:
176
+ config.cache_ttl_seconds = int(data['cache_ttl_seconds'])
177
+
178
+ return config
179
+
180
+ except Exception as e:
181
+ logger.error(f"Error loading config from {config_file}: {e}")
182
+ return cls()
183
+
184
+ @classmethod
185
+ def auto_discover(cls) -> 'AgentConfig':
186
+ """
187
+ Automatically discover agent directories and create configuration.
188
+
189
+ This method:
190
+ 1. Checks environment variables first
191
+ 2. Looks for config files in standard locations
192
+ 3. Auto-discovers agent directories
193
+
194
+ Returns:
195
+ AgentConfig with discovered settings
196
+ """
197
+ # Start with environment configuration
198
+ config = cls.from_environment()
199
+
200
+ # Look for config file if not already configured
201
+ if not config.project_agents_dir and not config.user_agents_dir:
202
+ # Check for project config file
203
+ project_config = Path.cwd() / ConfigPaths.CONFIG_DIR / 'agent_config.yaml'
204
+ if project_config.exists():
205
+ logger.info(f"Loading project agent config from {project_config}")
206
+ file_config = cls.from_file(project_config)
207
+ # Merge with environment config (env takes precedence)
208
+ config = cls._merge_configs(config, file_config)
209
+
210
+ # Check for user config file
211
+ user_config_dir = ConfigPaths.get_user_config_dir()
212
+ if user_config_dir:
213
+ user_config = user_config_dir / 'agent_config.yaml'
214
+ if user_config.exists():
215
+ logger.info(f"Loading user agent config from {user_config}")
216
+ file_config = cls.from_file(user_config)
217
+ config = cls._merge_configs(config, file_config)
218
+
219
+ # Auto-discover directories if not configured
220
+ if not config.project_agents_dir:
221
+ project_agents = Path.cwd() / ConfigPaths.CONFIG_DIR / 'agents'
222
+ if project_agents.exists():
223
+ config.project_agents_dir = project_agents
224
+ logger.debug(f"Auto-discovered project agents at {project_agents}")
225
+
226
+ if not config.user_agents_dir:
227
+ user_agents = ConfigPaths.get_user_agents_dir()
228
+ if user_agents and user_agents.exists():
229
+ config.user_agents_dir = user_agents
230
+ logger.debug(f"Auto-discovered user agents at {user_agents}")
231
+
232
+ if not config.system_agents_dir:
233
+ # Default to built-in agents
234
+ system_agents = Path(__file__).parent.parent / 'agents'
235
+ if system_agents.exists():
236
+ config.system_agents_dir = system_agents
237
+ logger.debug(f"Auto-discovered system agents at {system_agents}")
238
+
239
+ return config
240
+
241
+ @staticmethod
242
+ def _merge_configs(primary: 'AgentConfig', secondary: 'AgentConfig') -> 'AgentConfig':
243
+ """
244
+ Merge two configurations, with primary taking precedence.
245
+
246
+ Args:
247
+ primary: Primary configuration (higher precedence)
248
+ secondary: Secondary configuration (lower precedence)
249
+
250
+ Returns:
251
+ Merged configuration
252
+ """
253
+ result = AgentConfig()
254
+
255
+ # Merge directory paths (primary takes precedence)
256
+ result.project_agents_dir = primary.project_agents_dir or secondary.project_agents_dir
257
+ result.user_agents_dir = primary.user_agents_dir or secondary.user_agents_dir
258
+ result.system_agents_dir = primary.system_agents_dir or secondary.system_agents_dir
259
+
260
+ # Merge additional paths
261
+ result.additional_paths = list(set(primary.additional_paths + secondary.additional_paths))
262
+
263
+ # Use primary's settings for other fields
264
+ result.precedence_mode = primary.precedence_mode
265
+ result.enable_project_agents = primary.enable_project_agents
266
+ result.enable_user_agents = primary.enable_user_agents
267
+ result.enable_system_agents = primary.enable_system_agents
268
+ result.enable_hot_reload = primary.enable_hot_reload
269
+ result.cache_ttl_seconds = primary.cache_ttl_seconds
270
+ result.enable_caching = primary.enable_caching
271
+ result.validate_on_load = primary.validate_on_load
272
+ result.strict_validation = primary.strict_validation
273
+
274
+ return result
275
+
276
+ def get_enabled_tiers(self) -> Dict[str, Optional[Path]]:
277
+ """
278
+ Get enabled agent directories by tier.
279
+
280
+ Returns:
281
+ Dictionary mapping tier names to their paths (if enabled)
282
+ """
283
+ tiers = {}
284
+
285
+ if self.enable_project_agents and self.project_agents_dir:
286
+ tiers['project'] = self.project_agents_dir
287
+
288
+ if self.enable_user_agents and self.user_agents_dir:
289
+ tiers['user'] = self.user_agents_dir
290
+
291
+ if self.enable_system_agents and self.system_agents_dir:
292
+ tiers['system'] = self.system_agents_dir
293
+
294
+ return tiers
295
+
296
+ def to_dict(self) -> Dict[str, Any]:
297
+ """Convert configuration to dictionary for serialization."""
298
+ return {
299
+ 'project_agents_dir': str(self.project_agents_dir) if self.project_agents_dir else None,
300
+ 'user_agents_dir': str(self.user_agents_dir) if self.user_agents_dir else None,
301
+ 'system_agents_dir': str(self.system_agents_dir) if self.system_agents_dir else None,
302
+ 'additional_paths': [str(p) for p in self.additional_paths],
303
+ 'precedence_mode': self.precedence_mode.value,
304
+ 'enable_project_agents': self.enable_project_agents,
305
+ 'enable_user_agents': self.enable_user_agents,
306
+ 'enable_system_agents': self.enable_system_agents,
307
+ 'enable_hot_reload': self.enable_hot_reload,
308
+ 'cache_ttl_seconds': self.cache_ttl_seconds,
309
+ 'enable_caching': self.enable_caching,
310
+ 'validate_on_load': self.validate_on_load,
311
+ 'strict_validation': self.strict_validation
312
+ }
313
+
314
+
315
+ # Global configuration instance
316
+ _global_config: Optional[AgentConfig] = None
317
+
318
+
319
+ def get_agent_config() -> AgentConfig:
320
+ """
321
+ Get the global agent configuration.
322
+
323
+ Returns:
324
+ AgentConfig instance (auto-discovered if not set)
325
+ """
326
+ global _global_config
327
+ if _global_config is None:
328
+ _global_config = AgentConfig.auto_discover()
329
+ return _global_config
330
+
331
+
332
+ def set_agent_config(config: AgentConfig) -> None:
333
+ """
334
+ Set the global agent configuration.
335
+
336
+ Args:
337
+ config: AgentConfig instance to use globally
338
+ """
339
+ global _global_config
340
+ _global_config = config
341
+ logger.info(f"Agent configuration updated: {config.get_enabled_tiers()}")
342
+
343
+
344
+ def reset_agent_config() -> None:
345
+ """Reset the global agent configuration to auto-discover on next access."""
346
+ global _global_config
347
+ _global_config = None
348
+ logger.info("Agent configuration reset")