claude-mpm 0.3.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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (159) hide show
  1. claude_mpm/__init__.py +17 -0
  2. claude_mpm/__main__.py +14 -0
  3. claude_mpm/_version.py +32 -0
  4. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +88 -0
  5. claude_mpm/agents/INSTRUCTIONS.md +375 -0
  6. claude_mpm/agents/__init__.py +118 -0
  7. claude_mpm/agents/agent_loader.py +621 -0
  8. claude_mpm/agents/agent_loader_integration.py +229 -0
  9. claude_mpm/agents/agents_metadata.py +204 -0
  10. claude_mpm/agents/base_agent.json +27 -0
  11. claude_mpm/agents/base_agent_loader.py +519 -0
  12. claude_mpm/agents/schema/agent_schema.json +160 -0
  13. claude_mpm/agents/system_agent_config.py +587 -0
  14. claude_mpm/agents/templates/__init__.py +101 -0
  15. claude_mpm/agents/templates/data_engineer_agent.json +46 -0
  16. claude_mpm/agents/templates/documentation_agent.json +45 -0
  17. claude_mpm/agents/templates/engineer_agent.json +49 -0
  18. claude_mpm/agents/templates/ops_agent.json +46 -0
  19. claude_mpm/agents/templates/qa_agent.json +45 -0
  20. claude_mpm/agents/templates/research_agent.json +49 -0
  21. claude_mpm/agents/templates/security_agent.json +46 -0
  22. claude_mpm/agents/templates/update-optimized-specialized-agents.json +374 -0
  23. claude_mpm/agents/templates/version_control_agent.json +46 -0
  24. claude_mpm/agents/test_fix_deployment/.claude-pm/config/project.json +6 -0
  25. claude_mpm/cli.py +655 -0
  26. claude_mpm/cli_main.py +13 -0
  27. claude_mpm/cli_module/__init__.py +15 -0
  28. claude_mpm/cli_module/args.py +222 -0
  29. claude_mpm/cli_module/commands.py +203 -0
  30. claude_mpm/cli_module/migration_example.py +183 -0
  31. claude_mpm/cli_module/refactoring_guide.md +253 -0
  32. claude_mpm/cli_old/__init__.py +1 -0
  33. claude_mpm/cli_old/ticket_cli.py +102 -0
  34. claude_mpm/config/__init__.py +5 -0
  35. claude_mpm/config/hook_config.py +42 -0
  36. claude_mpm/constants.py +150 -0
  37. claude_mpm/core/__init__.py +45 -0
  38. claude_mpm/core/agent_name_normalizer.py +248 -0
  39. claude_mpm/core/agent_registry.py +627 -0
  40. claude_mpm/core/agent_registry.py.bak +312 -0
  41. claude_mpm/core/agent_session_manager.py +273 -0
  42. claude_mpm/core/base_service.py +747 -0
  43. claude_mpm/core/base_service.py.bak +406 -0
  44. claude_mpm/core/config.py +334 -0
  45. claude_mpm/core/config_aliases.py +292 -0
  46. claude_mpm/core/container.py +347 -0
  47. claude_mpm/core/factories.py +281 -0
  48. claude_mpm/core/framework_loader.py +472 -0
  49. claude_mpm/core/injectable_service.py +206 -0
  50. claude_mpm/core/interfaces.py +539 -0
  51. claude_mpm/core/logger.py +468 -0
  52. claude_mpm/core/minimal_framework_loader.py +107 -0
  53. claude_mpm/core/mixins.py +150 -0
  54. claude_mpm/core/service_registry.py +299 -0
  55. claude_mpm/core/session_manager.py +190 -0
  56. claude_mpm/core/simple_runner.py +511 -0
  57. claude_mpm/core/tool_access_control.py +173 -0
  58. claude_mpm/hooks/README.md +243 -0
  59. claude_mpm/hooks/__init__.py +5 -0
  60. claude_mpm/hooks/base_hook.py +154 -0
  61. claude_mpm/hooks/builtin/__init__.py +1 -0
  62. claude_mpm/hooks/builtin/logging_hook_example.py +165 -0
  63. claude_mpm/hooks/builtin/post_delegation_hook_example.py +124 -0
  64. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +125 -0
  65. claude_mpm/hooks/builtin/submit_hook_example.py +100 -0
  66. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +237 -0
  67. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +239 -0
  68. claude_mpm/hooks/builtin/workflow_start_hook.py +181 -0
  69. claude_mpm/hooks/hook_client.py +264 -0
  70. claude_mpm/hooks/hook_runner.py +370 -0
  71. claude_mpm/hooks/json_rpc_executor.py +259 -0
  72. claude_mpm/hooks/json_rpc_hook_client.py +319 -0
  73. claude_mpm/hooks/tool_call_interceptor.py +204 -0
  74. claude_mpm/init.py +246 -0
  75. claude_mpm/orchestration/SUBPROCESS_DESIGN.md +66 -0
  76. claude_mpm/orchestration/__init__.py +6 -0
  77. claude_mpm/orchestration/archive/direct_orchestrator.py +195 -0
  78. claude_mpm/orchestration/archive/factory.py +215 -0
  79. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +188 -0
  80. claude_mpm/orchestration/archive/hook_integration_example.py +178 -0
  81. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +826 -0
  82. claude_mpm/orchestration/archive/orchestrator.py +501 -0
  83. claude_mpm/orchestration/archive/pexpect_orchestrator.py +252 -0
  84. claude_mpm/orchestration/archive/pty_orchestrator.py +270 -0
  85. claude_mpm/orchestration/archive/simple_orchestrator.py +82 -0
  86. claude_mpm/orchestration/archive/subprocess_orchestrator.py +801 -0
  87. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +278 -0
  88. claude_mpm/orchestration/archive/wrapper_orchestrator.py +187 -0
  89. claude_mpm/scripts/__init__.py +1 -0
  90. claude_mpm/scripts/ticket.py +269 -0
  91. claude_mpm/services/__init__.py +10 -0
  92. claude_mpm/services/agent_deployment.py +955 -0
  93. claude_mpm/services/agent_lifecycle_manager.py +948 -0
  94. claude_mpm/services/agent_management_service.py +596 -0
  95. claude_mpm/services/agent_modification_tracker.py +841 -0
  96. claude_mpm/services/agent_profile_loader.py +606 -0
  97. claude_mpm/services/agent_registry.py +677 -0
  98. claude_mpm/services/base_agent_manager.py +380 -0
  99. claude_mpm/services/framework_agent_loader.py +337 -0
  100. claude_mpm/services/framework_claude_md_generator/README.md +92 -0
  101. claude_mpm/services/framework_claude_md_generator/__init__.py +206 -0
  102. claude_mpm/services/framework_claude_md_generator/content_assembler.py +151 -0
  103. claude_mpm/services/framework_claude_md_generator/content_validator.py +126 -0
  104. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +137 -0
  105. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +106 -0
  106. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +582 -0
  107. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +97 -0
  108. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +27 -0
  109. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +23 -0
  110. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +23 -0
  111. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +20 -0
  112. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +26 -0
  113. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +30 -0
  114. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +37 -0
  115. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +111 -0
  116. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +89 -0
  117. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +39 -0
  118. claude_mpm/services/framework_claude_md_generator/section_manager.py +106 -0
  119. claude_mpm/services/framework_claude_md_generator/version_manager.py +121 -0
  120. claude_mpm/services/framework_claude_md_generator.py +621 -0
  121. claude_mpm/services/hook_service.py +388 -0
  122. claude_mpm/services/hook_service_manager.py +223 -0
  123. claude_mpm/services/json_rpc_hook_manager.py +92 -0
  124. claude_mpm/services/parent_directory_manager/README.md +83 -0
  125. claude_mpm/services/parent_directory_manager/__init__.py +577 -0
  126. claude_mpm/services/parent_directory_manager/backup_manager.py +258 -0
  127. claude_mpm/services/parent_directory_manager/config_manager.py +210 -0
  128. claude_mpm/services/parent_directory_manager/deduplication_manager.py +279 -0
  129. claude_mpm/services/parent_directory_manager/framework_protector.py +143 -0
  130. claude_mpm/services/parent_directory_manager/operations.py +186 -0
  131. claude_mpm/services/parent_directory_manager/state_manager.py +624 -0
  132. claude_mpm/services/parent_directory_manager/template_deployer.py +579 -0
  133. claude_mpm/services/parent_directory_manager/validation_manager.py +378 -0
  134. claude_mpm/services/parent_directory_manager/version_control_helper.py +339 -0
  135. claude_mpm/services/parent_directory_manager/version_manager.py +222 -0
  136. claude_mpm/services/shared_prompt_cache.py +819 -0
  137. claude_mpm/services/ticket_manager.py +213 -0
  138. claude_mpm/services/ticket_manager_di.py +318 -0
  139. claude_mpm/services/ticketing_service_original.py +508 -0
  140. claude_mpm/services/version_control/VERSION +1 -0
  141. claude_mpm/services/version_control/__init__.py +70 -0
  142. claude_mpm/services/version_control/branch_strategy.py +670 -0
  143. claude_mpm/services/version_control/conflict_resolution.py +744 -0
  144. claude_mpm/services/version_control/git_operations.py +784 -0
  145. claude_mpm/services/version_control/semantic_versioning.py +703 -0
  146. claude_mpm/ui/__init__.py +1 -0
  147. claude_mpm/ui/rich_terminal_ui.py +295 -0
  148. claude_mpm/ui/terminal_ui.py +328 -0
  149. claude_mpm/utils/__init__.py +16 -0
  150. claude_mpm/utils/config_manager.py +468 -0
  151. claude_mpm/utils/import_migration_example.py +80 -0
  152. claude_mpm/utils/imports.py +182 -0
  153. claude_mpm/utils/path_operations.py +357 -0
  154. claude_mpm/utils/paths.py +289 -0
  155. claude_mpm-0.3.0.dist-info/METADATA +290 -0
  156. claude_mpm-0.3.0.dist-info/RECORD +159 -0
  157. claude_mpm-0.3.0.dist-info/WHEEL +5 -0
  158. claude_mpm-0.3.0.dist-info/entry_points.txt +4 -0
  159. claude_mpm-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,347 @@
1
+ """
2
+ Lightweight Dependency Injection Container for Claude MPM.
3
+
4
+ This module provides a simple yet powerful dependency injection container
5
+ that supports:
6
+ - Service registration with interfaces
7
+ - Constructor injection
8
+ - Singleton and transient lifetimes
9
+ - Factory functions
10
+ - Lazy initialization
11
+ - Circular dependency detection
12
+ """
13
+
14
+ import inspect
15
+ import threading
16
+ from abc import ABC
17
+ from enum import Enum
18
+ from typing import Any, Callable, Dict, List, Optional, Set, Type, TypeVar, Union
19
+
20
+ from .logger import get_logger
21
+
22
+ logger = get_logger(__name__)
23
+
24
+ T = TypeVar('T')
25
+
26
+
27
+ class ServiceLifetime(Enum):
28
+ """Service lifetime options."""
29
+ SINGLETON = "singleton" # One instance per container
30
+ TRANSIENT = "transient" # New instance per request
31
+ SCOPED = "scoped" # One instance per scope (future enhancement)
32
+
33
+
34
+ class ServiceRegistration:
35
+ """Represents a service registration in the container."""
36
+
37
+ def __init__(
38
+ self,
39
+ service_type: Type,
40
+ implementation: Optional[Union[Type, Callable]] = None,
41
+ factory: Optional[Callable] = None,
42
+ instance: Optional[Any] = None,
43
+ lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
44
+ dependencies: Optional[Dict[str, Type]] = None
45
+ ):
46
+ """
47
+ Initialize service registration.
48
+
49
+ Args:
50
+ service_type: The interface/base type being registered
51
+ implementation: The concrete implementation class
52
+ factory: Factory function to create instances
53
+ instance: Pre-created instance (for singleton registration)
54
+ lifetime: Service lifetime management
55
+ dependencies: Explicit dependency mapping
56
+ """
57
+ self.service_type = service_type
58
+ self.implementation = implementation or service_type
59
+ self.factory = factory
60
+ self.instance = instance
61
+ self.lifetime = lifetime
62
+ self.dependencies = dependencies or {}
63
+ self._lock = threading.Lock()
64
+
65
+ def create_instance(self, container: 'DIContainer') -> Any:
66
+ """Create an instance of the service."""
67
+ if self.instance is not None:
68
+ return self.instance
69
+
70
+ if self.factory:
71
+ return self.factory(container)
72
+
73
+ # Get constructor parameters
74
+ if inspect.isclass(self.implementation):
75
+ return container.create_instance(self.implementation, self.dependencies)
76
+ else:
77
+ # It's already an instance or callable
78
+ return self.implementation
79
+
80
+
81
+ class CircularDependencyError(Exception):
82
+ """Raised when circular dependencies are detected."""
83
+ pass
84
+
85
+
86
+ class ServiceNotFoundError(Exception):
87
+ """Raised when a requested service is not registered."""
88
+ pass
89
+
90
+
91
+ class DIContainer:
92
+ """
93
+ Lightweight Dependency Injection Container.
94
+
95
+ Provides service registration, resolution, and lifecycle management.
96
+ """
97
+
98
+ def __init__(self):
99
+ """Initialize the DI container."""
100
+ self._registrations: Dict[Type, ServiceRegistration] = {}
101
+ self._singletons: Dict[Type, Any] = {}
102
+ self._lock = threading.RLock()
103
+ self._resolving: Set[Type] = set()
104
+
105
+ def register(
106
+ self,
107
+ service_type: Type[T],
108
+ implementation: Optional[Union[Type[T], Callable[..., T]]] = None,
109
+ lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
110
+ factory: Optional[Callable[['DIContainer'], T]] = None,
111
+ instance: Optional[T] = None,
112
+ dependencies: Optional[Dict[str, Type]] = None
113
+ ) -> None:
114
+ """
115
+ Register a service in the container.
116
+
117
+ Args:
118
+ service_type: The interface/base type to register
119
+ implementation: The concrete implementation (class or factory)
120
+ lifetime: Service lifetime (singleton/transient)
121
+ factory: Optional factory function
122
+ instance: Pre-created instance (for singleton)
123
+ dependencies: Explicit dependency mapping for constructor params
124
+
125
+ Examples:
126
+ # Register interface with implementation
127
+ container.register(ILogger, ConsoleLogger)
128
+
129
+ # Register with factory
130
+ container.register(IDatabase, factory=lambda c: Database(c.resolve(IConfig)))
131
+
132
+ # Register singleton instance
133
+ container.register(IConfig, instance=Config())
134
+
135
+ # Register with explicit dependencies
136
+ container.register(IService, ServiceImpl, dependencies={'logger': ILogger})
137
+ """
138
+ with self._lock:
139
+ registration = ServiceRegistration(
140
+ service_type=service_type,
141
+ implementation=implementation,
142
+ factory=factory,
143
+ instance=instance,
144
+ lifetime=lifetime,
145
+ dependencies=dependencies
146
+ )
147
+ self._registrations[service_type] = registration
148
+
149
+ # If instance provided, store as singleton
150
+ if instance is not None:
151
+ self._singletons[service_type] = instance
152
+
153
+ def register_singleton(
154
+ self,
155
+ service_type: Type[T],
156
+ implementation: Optional[Union[Type[T], T]] = None
157
+ ) -> None:
158
+ """
159
+ Register a singleton service.
160
+
161
+ Convenience method for registering singletons.
162
+ """
163
+ if implementation is not None and not inspect.isclass(implementation):
164
+ # It's an instance
165
+ self.register(service_type, instance=implementation)
166
+ else:
167
+ self.register(service_type, implementation, lifetime=ServiceLifetime.SINGLETON)
168
+
169
+ def register_transient(
170
+ self,
171
+ service_type: Type[T],
172
+ implementation: Optional[Type[T]] = None
173
+ ) -> None:
174
+ """
175
+ Register a transient service.
176
+
177
+ Convenience method for registering transient services.
178
+ """
179
+ self.register(service_type, implementation, lifetime=ServiceLifetime.TRANSIENT)
180
+
181
+ def register_factory(
182
+ self,
183
+ service_type: Type[T],
184
+ factory: Callable[['DIContainer'], T],
185
+ lifetime: ServiceLifetime = ServiceLifetime.SINGLETON
186
+ ) -> None:
187
+ """
188
+ Register a service with a factory function.
189
+
190
+ The factory receives the container as parameter for resolving dependencies.
191
+ """
192
+ self.register(service_type, factory=factory, lifetime=lifetime)
193
+
194
+ def resolve(self, service_type: Type[T]) -> T:
195
+ """
196
+ Resolve a service from the container.
197
+
198
+ Args:
199
+ service_type: The type to resolve
200
+
201
+ Returns:
202
+ Instance of the requested service
203
+
204
+ Raises:
205
+ ServiceNotFoundError: If service is not registered
206
+ CircularDependencyError: If circular dependencies detected
207
+ """
208
+ with self._lock:
209
+ # Check for circular dependencies
210
+ if service_type in self._resolving:
211
+ cycle = " -> ".join(str(t) for t in self._resolving) + f" -> {service_type}"
212
+ raise CircularDependencyError(f"Circular dependency detected: {cycle}")
213
+
214
+ # Check if registered
215
+ if service_type not in self._registrations:
216
+ raise ServiceNotFoundError(f"Service {service_type} is not registered")
217
+
218
+ registration = self._registrations[service_type]
219
+
220
+ # Return existing singleton if available
221
+ if registration.lifetime == ServiceLifetime.SINGLETON:
222
+ if service_type in self._singletons:
223
+ return self._singletons[service_type]
224
+
225
+ # Mark as resolving
226
+ self._resolving.add(service_type)
227
+
228
+ try:
229
+ # Create instance
230
+ instance = registration.create_instance(self)
231
+
232
+ # Store singleton
233
+ if registration.lifetime == ServiceLifetime.SINGLETON:
234
+ self._singletons[service_type] = instance
235
+
236
+ return instance
237
+
238
+ finally:
239
+ self._resolving.remove(service_type)
240
+
241
+ def resolve_optional(self, service_type: Type[T], default: Optional[T] = None) -> Optional[T]:
242
+ """
243
+ Resolve a service if registered, otherwise return default.
244
+
245
+ Useful for optional dependencies.
246
+ """
247
+ try:
248
+ return self.resolve(service_type)
249
+ except ServiceNotFoundError:
250
+ return default
251
+
252
+ def create_instance(self, cls: Type[T], explicit_deps: Optional[Dict[str, Type]] = None) -> T:
253
+ """
254
+ Create an instance of a class, resolving constructor dependencies.
255
+
256
+ Args:
257
+ cls: The class to instantiate
258
+ explicit_deps: Explicit dependency mapping for constructor params
259
+
260
+ Returns:
261
+ New instance with resolved dependencies
262
+ """
263
+ # Get constructor signature
264
+ sig = inspect.signature(cls.__init__)
265
+ kwargs = {}
266
+
267
+ for param_name, param in sig.parameters.items():
268
+ if param_name == 'self':
269
+ continue
270
+
271
+ # Check explicit dependencies first
272
+ if explicit_deps and param_name in explicit_deps:
273
+ dep_type = explicit_deps[param_name]
274
+ kwargs[param_name] = self.resolve(dep_type)
275
+ continue
276
+
277
+ # Try to resolve by type annotation
278
+ if param.annotation != param.empty:
279
+ param_type = param.annotation
280
+
281
+ # Handle Optional types
282
+ if hasattr(param_type, '__origin__') and param_type.__origin__ is Union:
283
+ # Get the non-None type from Optional
284
+ args = param_type.__args__
285
+ param_type = next((arg for arg in args if arg is not type(None)), None)
286
+
287
+ if param_type and param_type in self._registrations:
288
+ kwargs[param_name] = self.resolve(param_type)
289
+ elif param.default != param.empty:
290
+ # Use default value
291
+ kwargs[param_name] = param.default
292
+
293
+ return cls(**kwargs)
294
+
295
+ def is_registered(self, service_type: Type) -> bool:
296
+ """Check if a service type is registered."""
297
+ return service_type in self._registrations
298
+
299
+ def get_all_registrations(self) -> Dict[Type, ServiceRegistration]:
300
+ """Get all service registrations."""
301
+ with self._lock:
302
+ return self._registrations.copy()
303
+
304
+ def create_child_container(self) -> 'DIContainer':
305
+ """
306
+ Create a child container that inherits registrations.
307
+
308
+ Useful for scoped scenarios.
309
+ """
310
+ child = DIContainer()
311
+ with self._lock:
312
+ # Copy registrations but not singleton instances
313
+ for service_type, registration in self._registrations.items():
314
+ child._registrations[service_type] = registration
315
+ return child
316
+
317
+ def clear(self) -> None:
318
+ """Clear all registrations and instances."""
319
+ with self._lock:
320
+ self._registrations.clear()
321
+ self._singletons.clear()
322
+ self._resolving.clear()
323
+
324
+
325
+ # Global container instance (optional, for convenience)
326
+ _global_container: Optional[DIContainer] = None
327
+ _global_lock = threading.Lock()
328
+
329
+
330
+ def get_container() -> DIContainer:
331
+ """
332
+ Get the global DI container instance.
333
+
334
+ Creates one if it doesn't exist.
335
+ """
336
+ global _global_container
337
+ with _global_lock:
338
+ if _global_container is None:
339
+ _global_container = DIContainer()
340
+ return _global_container
341
+
342
+
343
+ def set_container(container: DIContainer) -> None:
344
+ """Set the global DI container instance."""
345
+ global _global_container
346
+ with _global_lock:
347
+ _global_container = container
@@ -0,0 +1,281 @@
1
+ """
2
+ Factory classes for creating complex dependencies in Claude MPM.
3
+
4
+ Provides factory patterns for services that require complex initialization
5
+ or have multiple configuration options.
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from pathlib import Path
10
+ from typing import Any, Dict, Optional, Type, TypeVar
11
+
12
+ from .container import DIContainer
13
+ from .logger import get_logger
14
+ from .config import Config
15
+ from ..services.json_rpc_hook_manager import JSONRPCHookManager
16
+ from ..services.agent_deployment import AgentDeploymentService
17
+ from ..orchestration.factory import OrchestratorFactory
18
+ from ..orchestration.base import BaseOrchestrator
19
+
20
+ logger = get_logger(__name__)
21
+
22
+ T = TypeVar('T')
23
+
24
+
25
+ class ServiceFactory(ABC):
26
+ """Base factory for creating services."""
27
+
28
+ @abstractmethod
29
+ def create(self, container: DIContainer, **kwargs) -> Any:
30
+ """Create a service instance."""
31
+ pass
32
+
33
+
34
+ class HookManagerFactory(ServiceFactory):
35
+ """Factory for creating hook manager instances."""
36
+
37
+ def create(
38
+ self,
39
+ container: DIContainer,
40
+ log_dir: Optional[Path] = None,
41
+ enabled: bool = True
42
+ ) -> Optional[JSONRPCHookManager]:
43
+ """
44
+ Create a hook manager instance.
45
+
46
+ Args:
47
+ container: DI container
48
+ log_dir: Log directory path
49
+ enabled: Whether hooks are enabled
50
+
51
+ Returns:
52
+ Hook manager instance or None if disabled
53
+ """
54
+ config = container.resolve(Config)
55
+
56
+ # Check if hooks are enabled
57
+ if not enabled or config.get('hooks.enabled', True) is False:
58
+ logger.info("Hooks are disabled")
59
+ return None
60
+
61
+ # Get log directory from config if not provided
62
+ if log_dir is None:
63
+ log_dir = Path(config.get('log_dir', '.claude-mpm/logs'))
64
+
65
+ # Create hook manager
66
+ hook_manager = JSONRPCHookManager(log_dir=log_dir)
67
+
68
+ # Start the service
69
+ if hook_manager.start_service():
70
+ logger.info("Hook manager initialized successfully")
71
+ return hook_manager
72
+ else:
73
+ logger.warning("Failed to start hook manager")
74
+ return None
75
+
76
+
77
+ class OrchestratorFactoryWrapper(ServiceFactory):
78
+ """Factory wrapper for creating orchestrator instances."""
79
+
80
+ def __init__(self):
81
+ """Initialize the factory wrapper."""
82
+ self._factory = OrchestratorFactory()
83
+
84
+ def create(
85
+ self,
86
+ container: DIContainer,
87
+ orchestrator_type: Optional[str] = None,
88
+ **kwargs
89
+ ) -> BaseOrchestrator:
90
+ """
91
+ Create an orchestrator instance.
92
+
93
+ Args:
94
+ container: DI container
95
+ orchestrator_type: Type of orchestrator to create
96
+ **kwargs: Additional arguments for orchestrator
97
+
98
+ Returns:
99
+ Orchestrator instance
100
+ """
101
+ config = container.resolve(Config)
102
+
103
+ # Get orchestrator type from config if not provided
104
+ if orchestrator_type is None:
105
+ orchestrator_type = config.get('orchestrator.type', 'subprocess')
106
+
107
+ # Get orchestrator config
108
+ orch_config = config.get(f'orchestrator.{orchestrator_type}', {})
109
+
110
+ # Merge with provided kwargs
111
+ orch_config.update(kwargs)
112
+
113
+ # Inject services into orchestrator config
114
+ if 'hook_manager' not in orch_config and container.is_registered(JSONRPCHookManager):
115
+ orch_config['hook_manager'] = container.resolve_optional(JSONRPCHookManager)
116
+
117
+ # Create orchestrator
118
+ orchestrator = self._factory.create_orchestrator(
119
+ orchestrator_type,
120
+ **orch_config
121
+ )
122
+
123
+ logger.info(f"Created {orchestrator_type} orchestrator")
124
+ return orchestrator
125
+
126
+
127
+ class AgentServiceFactory(ServiceFactory):
128
+ """Factory for creating agent-related services."""
129
+
130
+ def create(
131
+ self,
132
+ container: DIContainer,
133
+ framework_dir: Optional[Path] = None,
134
+ project_dir: Optional[Path] = None
135
+ ) -> AgentDeploymentService:
136
+ """
137
+ Create an agent deployment service.
138
+
139
+ Args:
140
+ container: DI container
141
+ framework_dir: Framework directory path
142
+ project_dir: Project directory path
143
+
144
+ Returns:
145
+ Agent deployment service instance
146
+ """
147
+ config = container.resolve(Config)
148
+
149
+ # Get directories from config if not provided
150
+ if framework_dir is None:
151
+ framework_dir = Path(config.get('framework.dir', 'framework'))
152
+
153
+ if project_dir is None:
154
+ project_dir = Path(config.get('project.dir', '.'))
155
+
156
+ # Create service with dependencies
157
+ service = AgentDeploymentService()
158
+
159
+ # Inject any required dependencies
160
+ if hasattr(service, 'set_directories'):
161
+ service.set_directories(framework_dir, project_dir)
162
+
163
+ logger.info("Created agent deployment service")
164
+ return service
165
+
166
+
167
+ class SessionManagerFactory(ServiceFactory):
168
+ """Factory for creating session managers."""
169
+
170
+ def create(
171
+ self,
172
+ container: DIContainer,
173
+ session_type: str = "standard",
174
+ **kwargs
175
+ ) -> Any:
176
+ """
177
+ Create a session manager instance.
178
+
179
+ Args:
180
+ container: DI container
181
+ session_type: Type of session manager
182
+ **kwargs: Additional configuration
183
+
184
+ Returns:
185
+ Session manager instance
186
+ """
187
+ config = container.resolve(Config)
188
+
189
+ if session_type == "agent":
190
+ from ..core.agent_session_manager import AgentSessionManager
191
+
192
+ session_dir = kwargs.get('session_dir') or Path(config.get('session.dir', '.claude-mpm/sessions'))
193
+ max_sessions = kwargs.get('max_sessions_per_agent', config.get('session.max_per_agent', 3))
194
+
195
+ return AgentSessionManager(
196
+ session_dir=session_dir,
197
+ max_sessions_per_agent=max_sessions
198
+ )
199
+ else:
200
+ from ..core.session_manager import SessionManager
201
+
202
+ session_dir = kwargs.get('session_dir') or Path(config.get('session.dir', '.claude-mpm/sessions'))
203
+
204
+ return SessionManager(session_dir=session_dir)
205
+
206
+
207
+ class ConfigurationFactory(ServiceFactory):
208
+ """Factory for creating configuration instances."""
209
+
210
+ def create(
211
+ self,
212
+ container: DIContainer,
213
+ config_data: Optional[Dict[str, Any]] = None,
214
+ config_path: Optional[Path] = None,
215
+ env_prefix: str = "CLAUDE_MPM"
216
+ ) -> Config:
217
+ """
218
+ Create a configuration instance.
219
+
220
+ Args:
221
+ container: DI container
222
+ config_data: Initial configuration data
223
+ config_path: Path to configuration file
224
+ env_prefix: Environment variable prefix
225
+
226
+ Returns:
227
+ Configuration instance
228
+ """
229
+ # Load from multiple sources
230
+ config = Config(config_data or {}, config_path)
231
+
232
+ # Load environment variables
233
+ import os
234
+ for key, value in os.environ.items():
235
+ if key.startswith(env_prefix):
236
+ # Convert CLAUDE_MPM_FOO_BAR to foo.bar
237
+ config_key = key[len(env_prefix)+1:].lower().replace('_', '.')
238
+ config.set(config_key, value)
239
+
240
+ logger.info("Created configuration instance")
241
+ return config
242
+
243
+
244
+ # Factory registry for easy access
245
+ class FactoryRegistry:
246
+ """Registry for all service factories."""
247
+
248
+ def __init__(self):
249
+ """Initialize factory registry."""
250
+ self._factories: Dict[str, ServiceFactory] = {
251
+ 'hook_manager': HookManagerFactory(),
252
+ 'orchestrator': OrchestratorFactoryWrapper(),
253
+ 'agent_service': AgentServiceFactory(),
254
+ 'session_manager': SessionManagerFactory(),
255
+ 'configuration': ConfigurationFactory(),
256
+ }
257
+
258
+ def get_factory(self, name: str) -> ServiceFactory:
259
+ """Get a factory by name."""
260
+ if name not in self._factories:
261
+ raise KeyError(f"Factory '{name}' not registered")
262
+ return self._factories[name]
263
+
264
+ def register_factory(self, name: str, factory: ServiceFactory) -> None:
265
+ """Register a new factory."""
266
+ self._factories[name] = factory
267
+ logger.debug(f"Registered factory: {name}")
268
+
269
+ def create(self, factory_name: str, container: DIContainer, **kwargs) -> Any:
270
+ """Create a service using a named factory."""
271
+ factory = self.get_factory(factory_name)
272
+ return factory.create(container, **kwargs)
273
+
274
+
275
+ # Global factory registry
276
+ _factory_registry = FactoryRegistry()
277
+
278
+
279
+ def get_factory_registry() -> FactoryRegistry:
280
+ """Get the global factory registry."""
281
+ return _factory_registry