claude-mpm 4.4.3__py3-none-any.whl → 4.4.4__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 (118) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/agent_loader.py +3 -2
  3. claude_mpm/agents/agent_loader_integration.py +2 -1
  4. claude_mpm/agents/async_agent_loader.py +2 -2
  5. claude_mpm/agents/base_agent_loader.py +2 -2
  6. claude_mpm/agents/frontmatter_validator.py +1 -0
  7. claude_mpm/agents/system_agent_config.py +2 -1
  8. claude_mpm/cli/commands/doctor.py +44 -5
  9. claude_mpm/cli/commands/mpm_init.py +116 -62
  10. claude_mpm/cli/parsers/configure_parser.py +3 -1
  11. claude_mpm/cli/startup_logging.py +1 -3
  12. claude_mpm/config/agent_config.py +1 -1
  13. claude_mpm/config/paths.py +2 -1
  14. claude_mpm/core/agent_name_normalizer.py +1 -0
  15. claude_mpm/core/config.py +2 -1
  16. claude_mpm/core/config_aliases.py +2 -1
  17. claude_mpm/core/file_utils.py +0 -1
  18. claude_mpm/core/framework/__init__.py +6 -6
  19. claude_mpm/core/framework/formatters/__init__.py +2 -2
  20. claude_mpm/core/framework/formatters/capability_generator.py +19 -8
  21. claude_mpm/core/framework/formatters/content_formatter.py +8 -3
  22. claude_mpm/core/framework/formatters/context_generator.py +7 -3
  23. claude_mpm/core/framework/loaders/__init__.py +3 -3
  24. claude_mpm/core/framework/loaders/agent_loader.py +7 -3
  25. claude_mpm/core/framework/loaders/file_loader.py +16 -6
  26. claude_mpm/core/framework/loaders/instruction_loader.py +16 -6
  27. claude_mpm/core/framework/loaders/packaged_loader.py +36 -12
  28. claude_mpm/core/framework/processors/__init__.py +2 -2
  29. claude_mpm/core/framework/processors/memory_processor.py +14 -6
  30. claude_mpm/core/framework/processors/metadata_processor.py +5 -5
  31. claude_mpm/core/framework/processors/template_processor.py +12 -6
  32. claude_mpm/core/framework_loader.py +44 -20
  33. claude_mpm/core/log_manager.py +2 -1
  34. claude_mpm/core/tool_access_control.py +1 -0
  35. claude_mpm/core/unified_agent_registry.py +2 -1
  36. claude_mpm/core/unified_paths.py +1 -0
  37. claude_mpm/experimental/cli_enhancements.py +1 -0
  38. claude_mpm/hooks/base_hook.py +1 -0
  39. claude_mpm/hooks/instruction_reinforcement.py +1 -0
  40. claude_mpm/hooks/kuzu_memory_hook.py +20 -13
  41. claude_mpm/hooks/validation_hooks.py +1 -1
  42. claude_mpm/scripts/mpm_doctor.py +1 -0
  43. claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
  44. claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
  45. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
  46. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
  47. claude_mpm/services/agents/management/agent_management_service.py +1 -1
  48. claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
  49. claude_mpm/services/agents/memory/memory_file_service.py +6 -2
  50. claude_mpm/services/agents/memory/memory_format_service.py +0 -1
  51. claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
  52. claude_mpm/services/async_session_logger.py +1 -1
  53. claude_mpm/services/claude_session_logger.py +1 -0
  54. claude_mpm/services/core/path_resolver.py +1 -0
  55. claude_mpm/services/diagnostics/checks/__init__.py +2 -0
  56. claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
  57. claude_mpm/services/diagnostics/checks/mcp_services_check.py +399 -0
  58. claude_mpm/services/diagnostics/diagnostic_runner.py +3 -0
  59. claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
  60. claude_mpm/services/event_bus/direct_relay.py +2 -1
  61. claude_mpm/services/event_bus/event_bus.py +1 -0
  62. claude_mpm/services/event_bus/relay.py +3 -2
  63. claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
  64. claude_mpm/services/infrastructure/daemon_manager.py +1 -1
  65. claude_mpm/services/mcp_config_manager.py +10 -10
  66. claude_mpm/services/mcp_gateway/core/process_pool.py +62 -23
  67. claude_mpm/services/mcp_gateway/tools/__init__.py +6 -5
  68. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +3 -1
  69. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +16 -31
  70. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  71. claude_mpm/services/project/archive_manager.py +159 -96
  72. claude_mpm/services/project/documentation_manager.py +64 -45
  73. claude_mpm/services/project/enhanced_analyzer.py +132 -89
  74. claude_mpm/services/project/project_organizer.py +225 -131
  75. claude_mpm/services/response_tracker.py +1 -1
  76. claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
  77. claude_mpm/services/unified/__init__.py +1 -1
  78. claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
  79. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
  80. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
  81. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
  82. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
  83. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
  84. claude_mpm/services/unified/config_strategies/__init__.py +111 -126
  85. claude_mpm/services/unified/config_strategies/config_schema.py +157 -111
  86. claude_mpm/services/unified/config_strategies/context_strategy.py +91 -89
  87. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +183 -173
  88. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +160 -152
  89. claude_mpm/services/unified/config_strategies/unified_config_service.py +124 -112
  90. claude_mpm/services/unified/config_strategies/validation_strategy.py +298 -259
  91. claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
  92. claude_mpm/services/unified/deployment_strategies/base.py +24 -28
  93. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
  94. claude_mpm/services/unified/deployment_strategies/local.py +49 -34
  95. claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
  96. claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
  97. claude_mpm/services/unified/interfaces.py +0 -26
  98. claude_mpm/services/unified/migration.py +17 -40
  99. claude_mpm/services/unified/strategies.py +9 -26
  100. claude_mpm/services/unified/unified_analyzer.py +48 -44
  101. claude_mpm/services/unified/unified_config.py +21 -19
  102. claude_mpm/services/unified/unified_deployment.py +21 -26
  103. claude_mpm/storage/state_storage.py +1 -0
  104. claude_mpm/utils/agent_dependency_loader.py +18 -6
  105. claude_mpm/utils/common.py +14 -12
  106. claude_mpm/utils/database_connector.py +15 -12
  107. claude_mpm/utils/error_handler.py +1 -0
  108. claude_mpm/utils/log_cleanup.py +1 -0
  109. claude_mpm/utils/path_operations.py +1 -0
  110. claude_mpm/utils/session_logging.py +1 -1
  111. claude_mpm/utils/subprocess_utils.py +1 -0
  112. claude_mpm/validation/agent_validator.py +1 -1
  113. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/METADATA +9 -3
  114. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/RECORD +118 -117
  115. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/WHEEL +0 -0
  116. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/entry_points.txt +0 -0
  117. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/licenses/LICENSE +0 -0
  118. {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.4.dist-info}/top_level.txt +0 -0
@@ -4,26 +4,29 @@ Consolidates 15+ configuration services into a single unified service
4
4
  Achieves 65-75% code reduction through strategic patterns
5
5
  """
6
6
 
7
- from abc import ABC, abstractmethod
8
- from typing import Any, Dict, Optional, Type, Union, List, Callable, TypeVar, Generic
9
- from pathlib import Path
7
+ import hashlib
10
8
  import json
11
- import yaml
12
9
  import os
13
- from enum import Enum
14
- from dataclasses import dataclass, field
10
+ import pickle
15
11
  import threading
16
- from datetime import datetime, timedelta
12
+ from abc import ABC, abstractmethod
17
13
  from collections import defaultdict
18
- import hashlib
19
- import pickle
14
+ from dataclasses import dataclass, field
15
+ from datetime import datetime, timedelta
16
+ from enum import Enum
17
+ from pathlib import Path
18
+ from typing import Any, Callable, Dict, List, Optional, TypeVar, Union
19
+
20
+ import yaml
20
21
 
21
22
  from claude_mpm.core.logging_utils import get_logger
22
23
 
23
- T = TypeVar('T')
24
+ T = TypeVar("T")
25
+
24
26
 
25
27
  class ConfigFormat(Enum):
26
28
  """Supported configuration formats"""
29
+
27
30
  JSON = "json"
28
31
  YAML = "yaml"
29
32
  ENV = "env"
@@ -31,8 +34,10 @@ class ConfigFormat(Enum):
31
34
  TOML = "toml"
32
35
  INI = "ini"
33
36
 
37
+
34
38
  class ConfigContext(Enum):
35
39
  """Configuration contexts for lifecycle management"""
40
+
36
41
  GLOBAL = "global"
37
42
  PROJECT = "project"
38
43
  USER = "user"
@@ -41,9 +46,11 @@ class ConfigContext(Enum):
41
46
  RUNTIME = "runtime"
42
47
  TEST = "test"
43
48
 
49
+
44
50
  @dataclass
45
51
  class ConfigMetadata:
46
52
  """Metadata for configuration tracking"""
53
+
47
54
  source: str
48
55
  format: ConfigFormat
49
56
  context: ConfigContext
@@ -54,28 +61,26 @@ class ConfigMetadata:
54
61
  hot_reload: bool = False
55
62
  ttl: Optional[timedelta] = None
56
63
 
64
+
57
65
  class IConfigStrategy(ABC):
58
66
  """Base strategy interface for configuration operations"""
59
67
 
60
68
  @abstractmethod
61
69
  def can_handle(self, source: Union[str, Path, Dict]) -> bool:
62
70
  """Check if this strategy can handle the given source"""
63
- pass
64
71
 
65
72
  @abstractmethod
66
73
  def load(self, source: Any, **kwargs) -> Dict[str, Any]:
67
74
  """Load configuration from source"""
68
- pass
69
75
 
70
76
  @abstractmethod
71
77
  def validate(self, config: Dict[str, Any], schema: Optional[Dict] = None) -> bool:
72
78
  """Validate configuration against schema"""
73
- pass
74
79
 
75
80
  @abstractmethod
76
81
  def transform(self, config: Dict[str, Any]) -> Dict[str, Any]:
77
82
  """Transform configuration to standard format"""
78
- pass
83
+
79
84
 
80
85
  class UnifiedConfigService:
81
86
  """
@@ -97,7 +102,7 @@ class UnifiedConfigService:
97
102
 
98
103
  def __init__(self):
99
104
  """Initialize the unified configuration service"""
100
- if not hasattr(self, '_initialized'):
105
+ if not hasattr(self, "_initialized"):
101
106
  self.logger = get_logger(self.__class__.__name__)
102
107
  self._strategies: Dict[str, IConfigStrategy] = {}
103
108
  self._loaders: Dict[ConfigFormat, Callable] = {}
@@ -134,21 +139,21 @@ class UnifiedConfigService:
134
139
  def _initialize_core_validators(self):
135
140
  """Initialize the 15 composable validators (reduced from 236)"""
136
141
  # Core validators that can be composed for complex validation
137
- self._validators['required'] = self._validate_required
138
- self._validators['type'] = self._validate_type
139
- self._validators['range'] = self._validate_range
140
- self._validators['pattern'] = self._validate_pattern
141
- self._validators['enum'] = self._validate_enum
142
- self._validators['schema'] = self._validate_schema
143
- self._validators['dependency'] = self._validate_dependency
144
- self._validators['unique'] = self._validate_unique
145
- self._validators['format'] = self._validate_format
146
- self._validators['length'] = self._validate_length
147
- self._validators['custom'] = self._validate_custom
148
- self._validators['conditional'] = self._validate_conditional
149
- self._validators['recursive'] = self._validate_recursive
150
- self._validators['cross_field'] = self._validate_cross_field
151
- self._validators['composite'] = self._validate_composite
142
+ self._validators["required"] = self._validate_required
143
+ self._validators["type"] = self._validate_type
144
+ self._validators["range"] = self._validate_range
145
+ self._validators["pattern"] = self._validate_pattern
146
+ self._validators["enum"] = self._validate_enum
147
+ self._validators["schema"] = self._validate_schema
148
+ self._validators["dependency"] = self._validate_dependency
149
+ self._validators["unique"] = self._validate_unique
150
+ self._validators["format"] = self._validate_format
151
+ self._validators["length"] = self._validate_length
152
+ self._validators["custom"] = self._validate_custom
153
+ self._validators["conditional"] = self._validate_conditional
154
+ self._validators["recursive"] = self._validate_recursive
155
+ self._validators["cross_field"] = self._validate_cross_field
156
+ self._validators["composite"] = self._validate_composite
152
157
 
153
158
  def register_strategy(self, name: str, strategy: IConfigStrategy):
154
159
  """Register a configuration strategy"""
@@ -164,7 +169,7 @@ class UnifiedConfigService:
164
169
  schema: Optional[Dict] = None,
165
170
  hot_reload: bool = False,
166
171
  ttl: Optional[timedelta] = None,
167
- **kwargs
172
+ **kwargs,
168
173
  ) -> Dict[str, Any]:
169
174
  """
170
175
  Universal configuration loading method
@@ -214,7 +219,7 @@ class UnifiedConfigService:
214
219
  loaded_at=datetime.now(),
215
220
  checksum=self._calculate_checksum(config),
216
221
  hot_reload=hot_reload,
217
- ttl=ttl
222
+ ttl=ttl,
218
223
  )
219
224
 
220
225
  # Cache configuration
@@ -235,7 +240,7 @@ class UnifiedConfigService:
235
240
  self,
236
241
  config: Dict[str, Any],
237
242
  schema: Union[Dict, str],
238
- validators: Optional[List[str]] = None
243
+ validators: Optional[List[str]] = None,
239
244
  ) -> bool:
240
245
  """
241
246
  Universal validation method using composable validators
@@ -263,10 +268,7 @@ class UnifiedConfigService:
263
268
  return False
264
269
 
265
270
  def get(
266
- self,
267
- key: str,
268
- context: Optional[ConfigContext] = None,
269
- default: Any = None
271
+ self, key: str, context: Optional[ConfigContext] = None, default: Any = None
270
272
  ) -> Any:
271
273
  """Get configuration value by key with context awareness"""
272
274
  # Check specific context first
@@ -287,7 +289,7 @@ class UnifiedConfigService:
287
289
  key: str,
288
290
  value: Any,
289
291
  context: ConfigContext = ConfigContext.RUNTIME,
290
- persist: bool = False
292
+ persist: bool = False,
291
293
  ):
292
294
  """Set configuration value with optional persistence"""
293
295
  with self._lock:
@@ -320,7 +322,9 @@ class UnifiedConfigService:
320
322
  self._watchers[key].append(callback)
321
323
  self.logger.debug(f"Added watcher for key: {key}")
322
324
 
323
- def reload(self, cache_key: Optional[str] = None, context: Optional[ConfigContext] = None):
325
+ def reload(
326
+ self, cache_key: Optional[str] = None, context: Optional[ConfigContext] = None
327
+ ):
324
328
  """Reload configuration(s)"""
325
329
  with self._lock:
326
330
  if cache_key:
@@ -332,7 +336,7 @@ class UnifiedConfigService:
332
336
  metadata.context,
333
337
  metadata.format,
334
338
  hot_reload=metadata.hot_reload,
335
- ttl=metadata.ttl
339
+ ttl=metadata.ttl,
336
340
  )
337
341
  elif context:
338
342
  # Reload all configurations in context
@@ -344,7 +348,7 @@ class UnifiedConfigService:
344
348
  metadata.context,
345
349
  metadata.format,
346
350
  hot_reload=metadata.hot_reload,
347
- ttl=metadata.ttl
351
+ ttl=metadata.ttl,
348
352
  )
349
353
  else:
350
354
  # Reload all configurations
@@ -354,14 +358,14 @@ class UnifiedConfigService:
354
358
  metadata.context,
355
359
  metadata.format,
356
360
  hot_reload=metadata.hot_reload,
357
- ttl=metadata.ttl
361
+ ttl=metadata.ttl,
358
362
  )
359
363
 
360
364
  def merge(
361
365
  self,
362
366
  *configs: Dict[str, Any],
363
367
  strategy: str = "deep",
364
- context: ConfigContext = ConfigContext.RUNTIME
368
+ context: ConfigContext = ConfigContext.RUNTIME,
365
369
  ) -> Dict[str, Any]:
366
370
  """Merge multiple configurations with specified strategy"""
367
371
  if not configs:
@@ -372,21 +376,20 @@ class UnifiedConfigService:
372
376
  for config in configs:
373
377
  self._deep_merge(result, config)
374
378
  return result
375
- elif strategy == "shallow":
379
+ if strategy == "shallow":
376
380
  result = {}
377
381
  for config in configs:
378
382
  result.update(config)
379
383
  return result
380
- elif strategy == "override":
384
+ if strategy == "override":
381
385
  return configs[-1] if configs else {}
382
- else:
383
- raise ValueError(f"Unknown merge strategy: {strategy}")
386
+ raise ValueError(f"Unknown merge strategy: {strategy}")
384
387
 
385
388
  def export(
386
389
  self,
387
390
  format: ConfigFormat,
388
391
  context: Optional[ConfigContext] = None,
389
- path: Optional[Path] = None
392
+ path: Optional[Path] = None,
390
393
  ) -> Union[str, None]:
391
394
  """Export configuration to specified format"""
392
395
  configs = []
@@ -436,7 +439,7 @@ class UnifiedConfigService:
436
439
 
437
440
  path = Path(source)
438
441
  if path.exists():
439
- with open(path, 'r') as f:
442
+ with open(path) as f:
440
443
  return json.load(f)
441
444
 
442
445
  # Try to parse as JSON string
@@ -449,7 +452,7 @@ class UnifiedConfigService:
449
452
 
450
453
  path = Path(source)
451
454
  if path.exists():
452
- with open(path, 'r') as f:
455
+ with open(path) as f:
453
456
  return yaml.safe_load(f)
454
457
 
455
458
  # Try to parse as YAML string
@@ -457,7 +460,7 @@ class UnifiedConfigService:
457
460
 
458
461
  def _load_env(self, source: Union[str, Path, Dict], **kwargs) -> Dict[str, Any]:
459
462
  """Load environment variables as configuration"""
460
- prefix = kwargs.get('prefix', '')
463
+ prefix = kwargs.get("prefix", "")
461
464
  config = {}
462
465
 
463
466
  for key, value in os.environ.items():
@@ -465,7 +468,7 @@ class UnifiedConfigService:
465
468
  continue
466
469
 
467
470
  # Remove prefix if present
468
- clean_key = key[len(prefix):] if prefix else key
471
+ clean_key = key[len(prefix) :] if prefix else key
469
472
 
470
473
  # Convert to lowercase and replace underscores
471
474
  clean_key = clean_key.lower()
@@ -490,7 +493,7 @@ class UnifiedConfigService:
490
493
  # Extract configuration from module
491
494
  config = {}
492
495
  for key in dir(module):
493
- if not key.startswith('_'):
496
+ if not key.startswith("_"):
494
497
  config[key] = getattr(module, key)
495
498
 
496
499
  return config
@@ -505,14 +508,14 @@ class UnifiedConfigService:
505
508
 
506
509
  path = Path(source)
507
510
  if path.exists():
508
- with open(path, 'r') as f:
511
+ with open(path) as f:
509
512
  return toml.load(f)
510
513
 
511
514
  return toml.loads(str(source))
512
515
 
513
516
  def _validate_required(self, config: Dict[str, Any], schema: Dict) -> bool:
514
517
  """Validate required fields"""
515
- required = schema.get('required', [])
518
+ required = schema.get("required", [])
516
519
  for field in required:
517
520
  if field not in config:
518
521
  self.logger.error(f"Required field missing: {field}")
@@ -521,44 +524,47 @@ class UnifiedConfigService:
521
524
 
522
525
  def _validate_type(self, config: Dict[str, Any], schema: Dict) -> bool:
523
526
  """Validate field types"""
524
- properties = schema.get('properties', {})
527
+ properties = schema.get("properties", {})
525
528
  for key, value in config.items():
526
529
  if key in properties:
527
- expected_type = properties[key].get('type')
530
+ expected_type = properties[key].get("type")
528
531
  if expected_type and not self._check_type(value, expected_type):
529
- self.logger.error(f"Type mismatch for {key}: expected {expected_type}")
532
+ self.logger.error(
533
+ f"Type mismatch for {key}: expected {expected_type}"
534
+ )
530
535
  return False
531
536
  return True
532
537
 
533
538
  def _validate_range(self, config: Dict[str, Any], schema: Dict) -> bool:
534
539
  """Validate numeric ranges"""
535
- properties = schema.get('properties', {})
540
+ properties = schema.get("properties", {})
536
541
  for key, value in config.items():
537
542
  if key in properties:
538
543
  prop = properties[key]
539
- if 'minimum' in prop and value < prop['minimum']:
544
+ if "minimum" in prop and value < prop["minimum"]:
540
545
  return False
541
- if 'maximum' in prop and value > prop['maximum']:
546
+ if "maximum" in prop and value > prop["maximum"]:
542
547
  return False
543
548
  return True
544
549
 
545
550
  def _validate_pattern(self, config: Dict[str, Any], schema: Dict) -> bool:
546
551
  """Validate string patterns"""
547
552
  import re
548
- properties = schema.get('properties', {})
553
+
554
+ properties = schema.get("properties", {})
549
555
  for key, value in config.items():
550
- if key in properties and 'pattern' in properties[key]:
551
- pattern = properties[key]['pattern']
556
+ if key in properties and "pattern" in properties[key]:
557
+ pattern = properties[key]["pattern"]
552
558
  if not re.match(pattern, str(value)):
553
559
  return False
554
560
  return True
555
561
 
556
562
  def _validate_enum(self, config: Dict[str, Any], schema: Dict) -> bool:
557
563
  """Validate enum values"""
558
- properties = schema.get('properties', {})
564
+ properties = schema.get("properties", {})
559
565
  for key, value in config.items():
560
- if key in properties and 'enum' in properties[key]:
561
- if value not in properties[key]['enum']:
566
+ if key in properties and "enum" in properties[key]:
567
+ if value not in properties[key]["enum"]:
562
568
  return False
563
569
  return True
564
570
 
@@ -579,7 +585,7 @@ class UnifiedConfigService:
579
585
 
580
586
  def _validate_dependency(self, config: Dict[str, Any], schema: Dict) -> bool:
581
587
  """Validate field dependencies"""
582
- dependencies = schema.get('dependencies', {})
588
+ dependencies = schema.get("dependencies", {})
583
589
  for field, deps in dependencies.items():
584
590
  if field in config:
585
591
  for dep in deps:
@@ -590,9 +596,9 @@ class UnifiedConfigService:
590
596
 
591
597
  def _validate_unique(self, config: Dict[str, Any], schema: Dict) -> bool:
592
598
  """Validate unique values in arrays"""
593
- properties = schema.get('properties', {})
599
+ properties = schema.get("properties", {})
594
600
  for key, value in config.items():
595
- if key in properties and properties[key].get('uniqueItems'):
601
+ if key in properties and properties[key].get("uniqueItems"):
596
602
  if isinstance(value, list) and len(value) != len(set(map(str, value))):
597
603
  return False
598
604
  return True
@@ -604,48 +610,48 @@ class UnifiedConfigService:
604
610
 
605
611
  def _validate_length(self, config: Dict[str, Any], schema: Dict) -> bool:
606
612
  """Validate string/array lengths"""
607
- properties = schema.get('properties', {})
613
+ properties = schema.get("properties", {})
608
614
  for key, value in config.items():
609
615
  if key in properties:
610
616
  prop = properties[key]
611
- if 'minLength' in prop and len(value) < prop['minLength']:
617
+ if "minLength" in prop and len(value) < prop["minLength"]:
612
618
  return False
613
- if 'maxLength' in prop and len(value) > prop['maxLength']:
619
+ if "maxLength" in prop and len(value) > prop["maxLength"]:
614
620
  return False
615
621
  return True
616
622
 
617
623
  def _validate_custom(self, config: Dict[str, Any], schema: Dict) -> bool:
618
624
  """Apply custom validation functions"""
619
- if 'custom' in schema:
620
- validator = schema['custom']
625
+ if "custom" in schema:
626
+ validator = schema["custom"]
621
627
  if callable(validator):
622
628
  return validator(config)
623
629
  return True
624
630
 
625
631
  def _validate_conditional(self, config: Dict[str, Any], schema: Dict) -> bool:
626
632
  """Validate conditional requirements"""
627
- if 'if' in schema:
628
- condition = schema['if']
633
+ if "if" in schema:
634
+ condition = schema["if"]
629
635
  if self._evaluate_condition(config, condition):
630
- if 'then' in schema:
631
- return self._validate_schema(config, schema['then'])
632
- elif 'else' in schema:
633
- return self._validate_schema(config, schema['else'])
636
+ if "then" in schema:
637
+ return self._validate_schema(config, schema["then"])
638
+ elif "else" in schema:
639
+ return self._validate_schema(config, schema["else"])
634
640
  return True
635
641
 
636
642
  def _validate_recursive(self, config: Dict[str, Any], schema: Dict) -> bool:
637
643
  """Recursively validate nested structures"""
638
- properties = schema.get('properties', {})
644
+ properties = schema.get("properties", {})
639
645
  for key, value in config.items():
640
646
  if key in properties and isinstance(value, dict):
641
- if 'properties' in properties[key]:
647
+ if "properties" in properties[key]:
642
648
  if not self._validate_schema(value, properties[key]):
643
649
  return False
644
650
  return True
645
651
 
646
652
  def _validate_cross_field(self, config: Dict[str, Any], schema: Dict) -> bool:
647
653
  """Validate cross-field constraints"""
648
- constraints = schema.get('crossField', [])
654
+ constraints = schema.get("crossField", [])
649
655
  for constraint in constraints:
650
656
  if not self._evaluate_constraint(config, constraint):
651
657
  return False
@@ -653,7 +659,7 @@ class UnifiedConfigService:
653
659
 
654
660
  def _validate_composite(self, config: Dict[str, Any], schema: Dict) -> bool:
655
661
  """Composite validation using multiple validators"""
656
- validators = schema.get('validators', [])
662
+ validators = schema.get("validators", [])
657
663
  for validator_name in validators:
658
664
  if validator_name in self._validators:
659
665
  if not self._validators[validator_name](config, schema):
@@ -668,22 +674,22 @@ class UnifiedConfigService:
668
674
  path = Path(source)
669
675
  if path.exists():
670
676
  suffix = path.suffix.lower()
671
- if suffix == '.json':
677
+ if suffix == ".json":
672
678
  return ConfigFormat.JSON
673
- elif suffix in ['.yaml', '.yml']:
679
+ if suffix in [".yaml", ".yml"]:
674
680
  return ConfigFormat.YAML
675
- elif suffix == '.toml':
681
+ if suffix == ".toml":
676
682
  return ConfigFormat.TOML
677
- elif suffix in ['.py', '.python']:
683
+ if suffix in [".py", ".python"]:
678
684
  return ConfigFormat.PYTHON
679
- elif suffix in ['.env']:
685
+ if suffix in [".env"]:
680
686
  return ConfigFormat.ENV
681
687
 
682
688
  # Try to detect from content
683
689
  content = str(source)
684
- if content.startswith('{'):
690
+ if content.startswith("{"):
685
691
  return ConfigFormat.JSON
686
- elif ':' in content and '\n' in content:
692
+ if ":" in content and "\n" in content:
687
693
  return ConfigFormat.YAML
688
694
 
689
695
  return ConfigFormat.JSON
@@ -712,11 +718,10 @@ class UnifiedConfigService:
712
718
  source: Any,
713
719
  format: ConfigFormat,
714
720
  schema: Optional[Dict],
715
- context: ConfigContext
721
+ context: ConfigContext,
716
722
  ):
717
723
  """Setup hot reload for configuration"""
718
724
  # Implementation for file watching and hot reload
719
- pass
720
725
 
721
726
  def _trigger_watchers(self, key: str, value: Any):
722
727
  """Trigger registered watchers for key"""
@@ -729,9 +734,10 @@ class UnifiedConfigService:
729
734
  def _persist_config(self, key: str, value: Any, context: ConfigContext):
730
735
  """Persist configuration change"""
731
736
  # Implementation for persisting configuration changes
732
- pass
733
737
 
734
- def _handle_error(self, error: Exception, source: Any, context: ConfigContext) -> Dict[str, Any]:
738
+ def _handle_error(
739
+ self, error: Exception, source: Any, context: ConfigContext
740
+ ) -> Dict[str, Any]:
735
741
  """Unified error handling"""
736
742
  for handler in self._error_handlers:
737
743
  try:
@@ -747,7 +753,11 @@ class UnifiedConfigService:
747
753
  def _deep_merge(self, target: Dict, source: Dict):
748
754
  """Deep merge source into target"""
749
755
  for key, value in source.items():
750
- if key in target and isinstance(target[key], dict) and isinstance(value, dict):
756
+ if (
757
+ key in target
758
+ and isinstance(target[key], dict)
759
+ and isinstance(value, dict)
760
+ ):
751
761
  self._deep_merge(target[key], value)
752
762
  else:
753
763
  target[key] = value
@@ -755,12 +765,12 @@ class UnifiedConfigService:
755
765
  def _check_type(self, value: Any, expected_type: str) -> bool:
756
766
  """Check if value matches expected type"""
757
767
  type_map = {
758
- 'string': str,
759
- 'number': (int, float),
760
- 'integer': int,
761
- 'boolean': bool,
762
- 'array': list,
763
- 'object': dict
768
+ "string": str,
769
+ "number": (int, float),
770
+ "integer": int,
771
+ "boolean": bool,
772
+ "array": list,
773
+ "object": dict,
764
774
  }
765
775
  expected = type_map.get(expected_type)
766
776
  if expected:
@@ -785,18 +795,20 @@ class UnifiedConfigService:
785
795
  def get_statistics(self) -> Dict[str, Any]:
786
796
  """Get service statistics for monitoring"""
787
797
  return {
788
- 'total_configs': len(self._cache),
789
- 'contexts': {ctx.value: len(configs) for ctx, configs in self._contexts.items()},
790
- 'strategies': len(self._strategies),
791
- 'loaders': len(self._loaders),
792
- 'validators': len(self._validators),
793
- 'watchers': sum(len(w) for w in self._watchers.values()),
794
- 'cache_size': sum(len(str(c)) for c in self._cache.values()),
795
- 'metadata_entries': len(self._metadata)
798
+ "total_configs": len(self._cache),
799
+ "contexts": {
800
+ ctx.value: len(configs) for ctx, configs in self._contexts.items()
801
+ },
802
+ "strategies": len(self._strategies),
803
+ "loaders": len(self._loaders),
804
+ "validators": len(self._validators),
805
+ "watchers": sum(len(w) for w in self._watchers.values()),
806
+ "cache_size": sum(len(str(c)) for c in self._cache.values()),
807
+ "metadata_entries": len(self._metadata),
796
808
  }
797
809
 
798
810
 
799
811
  # Backward compatibility aliases
800
812
  ConfigService = UnifiedConfigService
801
813
  ConfigManager = UnifiedConfigService
802
- ConfigLoader = UnifiedConfigService
814
+ ConfigLoader = UnifiedConfigService