claude-mpm 4.4.3__py3-none-any.whl → 4.4.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/agent_loader.py +3 -2
- claude_mpm/agents/agent_loader_integration.py +2 -1
- claude_mpm/agents/async_agent_loader.py +2 -2
- claude_mpm/agents/base_agent_loader.py +2 -2
- claude_mpm/agents/frontmatter_validator.py +1 -0
- claude_mpm/agents/system_agent_config.py +2 -1
- claude_mpm/cli/commands/doctor.py +44 -5
- claude_mpm/cli/commands/mpm_init.py +116 -62
- claude_mpm/cli/parsers/configure_parser.py +3 -1
- claude_mpm/cli/startup_logging.py +1 -3
- claude_mpm/config/agent_config.py +1 -1
- claude_mpm/config/paths.py +2 -1
- claude_mpm/core/agent_name_normalizer.py +1 -0
- claude_mpm/core/config.py +2 -1
- claude_mpm/core/config_aliases.py +2 -1
- claude_mpm/core/file_utils.py +0 -1
- claude_mpm/core/framework/__init__.py +6 -6
- claude_mpm/core/framework/formatters/__init__.py +2 -2
- claude_mpm/core/framework/formatters/capability_generator.py +19 -8
- claude_mpm/core/framework/formatters/content_formatter.py +8 -3
- claude_mpm/core/framework/formatters/context_generator.py +7 -3
- claude_mpm/core/framework/loaders/__init__.py +3 -3
- claude_mpm/core/framework/loaders/agent_loader.py +7 -3
- claude_mpm/core/framework/loaders/file_loader.py +16 -6
- claude_mpm/core/framework/loaders/instruction_loader.py +16 -6
- claude_mpm/core/framework/loaders/packaged_loader.py +36 -12
- claude_mpm/core/framework/processors/__init__.py +2 -2
- claude_mpm/core/framework/processors/memory_processor.py +14 -6
- claude_mpm/core/framework/processors/metadata_processor.py +5 -5
- claude_mpm/core/framework/processors/template_processor.py +12 -6
- claude_mpm/core/framework_loader.py +44 -20
- claude_mpm/core/log_manager.py +2 -1
- claude_mpm/core/tool_access_control.py +1 -0
- claude_mpm/core/unified_agent_registry.py +2 -1
- claude_mpm/core/unified_paths.py +1 -0
- claude_mpm/experimental/cli_enhancements.py +1 -0
- claude_mpm/hooks/base_hook.py +1 -0
- claude_mpm/hooks/instruction_reinforcement.py +1 -0
- claude_mpm/hooks/kuzu_memory_hook.py +20 -13
- claude_mpm/hooks/validation_hooks.py +1 -1
- claude_mpm/scripts/mpm_doctor.py +1 -0
- claude_mpm/services/agents/loading/agent_profile_loader.py +1 -1
- claude_mpm/services/agents/loading/base_agent_manager.py +1 -1
- claude_mpm/services/agents/loading/framework_agent_loader.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -0
- claude_mpm/services/agents/management/agent_management_service.py +1 -1
- claude_mpm/services/agents/memory/memory_categorization_service.py +0 -1
- claude_mpm/services/agents/memory/memory_file_service.py +6 -2
- claude_mpm/services/agents/memory/memory_format_service.py +0 -1
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
- claude_mpm/services/async_session_logger.py +1 -1
- claude_mpm/services/claude_session_logger.py +1 -0
- claude_mpm/services/core/path_resolver.py +1 -0
- claude_mpm/services/diagnostics/checks/__init__.py +2 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +126 -25
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +451 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +3 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +259 -32
- claude_mpm/services/event_bus/direct_relay.py +2 -1
- claude_mpm/services/event_bus/event_bus.py +1 -0
- claude_mpm/services/event_bus/relay.py +3 -2
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +1 -1
- claude_mpm/services/infrastructure/daemon_manager.py +1 -1
- claude_mpm/services/mcp_config_manager.py +301 -54
- claude_mpm/services/mcp_gateway/core/process_pool.py +62 -23
- claude_mpm/services/mcp_gateway/tools/__init__.py +6 -5
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +3 -1
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +16 -31
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/project/archive_manager.py +159 -96
- claude_mpm/services/project/documentation_manager.py +64 -45
- claude_mpm/services/project/enhanced_analyzer.py +132 -89
- claude_mpm/services/project/project_organizer.py +225 -131
- claude_mpm/services/response_tracker.py +1 -1
- claude_mpm/services/socketio/server/eventbus_integration.py +1 -1
- claude_mpm/services/unified/__init__.py +1 -1
- claude_mpm/services/unified/analyzer_strategies/__init__.py +3 -3
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +97 -53
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +81 -40
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +277 -178
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +196 -112
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +83 -49
- claude_mpm/services/unified/config_strategies/__init__.py +111 -126
- claude_mpm/services/unified/config_strategies/config_schema.py +157 -111
- claude_mpm/services/unified/config_strategies/context_strategy.py +91 -89
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +183 -173
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +160 -152
- claude_mpm/services/unified/config_strategies/unified_config_service.py +124 -112
- claude_mpm/services/unified/config_strategies/validation_strategy.py +298 -259
- claude_mpm/services/unified/deployment_strategies/__init__.py +7 -7
- claude_mpm/services/unified/deployment_strategies/base.py +24 -28
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +168 -88
- claude_mpm/services/unified/deployment_strategies/local.py +49 -34
- claude_mpm/services/unified/deployment_strategies/utils.py +39 -43
- claude_mpm/services/unified/deployment_strategies/vercel.py +30 -24
- claude_mpm/services/unified/interfaces.py +0 -26
- claude_mpm/services/unified/migration.py +17 -40
- claude_mpm/services/unified/strategies.py +9 -26
- claude_mpm/services/unified/unified_analyzer.py +48 -44
- claude_mpm/services/unified/unified_config.py +21 -19
- claude_mpm/services/unified/unified_deployment.py +21 -26
- claude_mpm/storage/state_storage.py +1 -0
- claude_mpm/utils/agent_dependency_loader.py +18 -6
- claude_mpm/utils/common.py +14 -12
- claude_mpm/utils/database_connector.py +15 -12
- claude_mpm/utils/error_handler.py +1 -0
- claude_mpm/utils/log_cleanup.py +1 -0
- claude_mpm/utils/path_operations.py +1 -0
- claude_mpm/utils/session_logging.py +1 -1
- claude_mpm/utils/subprocess_utils.py +1 -0
- claude_mpm/validation/agent_validator.py +1 -1
- {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/METADATA +35 -15
- {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/RECORD +118 -117
- {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/WHEEL +0 -0
- {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.4.3.dist-info → claude_mpm-4.4.5.dist-info}/top_level.txt +0 -0
@@ -120,7 +120,6 @@ class IDeploymentService(ABC):
|
|
120
120
|
Returns:
|
121
121
|
ServiceMetadata: Complete service metadata
|
122
122
|
"""
|
123
|
-
pass
|
124
123
|
|
125
124
|
@abstractmethod
|
126
125
|
def validate_deployment(
|
@@ -136,7 +135,6 @@ class IDeploymentService(ABC):
|
|
136
135
|
Returns:
|
137
136
|
List[str]: List of validation errors (empty if valid)
|
138
137
|
"""
|
139
|
-
pass
|
140
138
|
|
141
139
|
@abstractmethod
|
142
140
|
def deploy(
|
@@ -158,7 +156,6 @@ class IDeploymentService(ABC):
|
|
158
156
|
Returns:
|
159
157
|
DeploymentResult: Result of the deployment operation
|
160
158
|
"""
|
161
|
-
pass
|
162
159
|
|
163
160
|
@abstractmethod
|
164
161
|
def rollback(
|
@@ -174,7 +171,6 @@ class IDeploymentService(ABC):
|
|
174
171
|
Returns:
|
175
172
|
DeploymentResult: Result of the rollback operation
|
176
173
|
"""
|
177
|
-
pass
|
178
174
|
|
179
175
|
@abstractmethod
|
180
176
|
def list_deployments(
|
@@ -189,7 +185,6 @@ class IDeploymentService(ABC):
|
|
189
185
|
Returns:
|
190
186
|
List[Dict[str, Any]]: List of deployment information
|
191
187
|
"""
|
192
|
-
pass
|
193
188
|
|
194
189
|
@abstractmethod
|
195
190
|
def get_deployment_status(self, deployment_id: str) -> Dict[str, Any]:
|
@@ -202,7 +197,6 @@ class IDeploymentService(ABC):
|
|
202
197
|
Returns:
|
203
198
|
Dict[str, Any]: Deployment status information
|
204
199
|
"""
|
205
|
-
pass
|
206
200
|
|
207
201
|
|
208
202
|
class IAnalyzerService(ABC):
|
@@ -222,7 +216,6 @@ class IAnalyzerService(ABC):
|
|
222
216
|
Returns:
|
223
217
|
ServiceMetadata: Complete service metadata
|
224
218
|
"""
|
225
|
-
pass
|
226
219
|
|
227
220
|
@abstractmethod
|
228
221
|
def analyze(
|
@@ -240,7 +233,6 @@ class IAnalyzerService(ABC):
|
|
240
233
|
Returns:
|
241
234
|
AnalysisResult: Result of the analysis
|
242
235
|
"""
|
243
|
-
pass
|
244
236
|
|
245
237
|
@abstractmethod
|
246
238
|
def batch_analyze(
|
@@ -258,7 +250,6 @@ class IAnalyzerService(ABC):
|
|
258
250
|
Returns:
|
259
251
|
List[AnalysisResult]: Results for each target
|
260
252
|
"""
|
261
|
-
pass
|
262
253
|
|
263
254
|
@abstractmethod
|
264
255
|
def get_metrics(self, target: Union[str, Path, Any]) -> Dict[str, Any]:
|
@@ -271,7 +262,6 @@ class IAnalyzerService(ABC):
|
|
271
262
|
Returns:
|
272
263
|
Dict[str, Any]: Analysis metrics
|
273
264
|
"""
|
274
|
-
pass
|
275
265
|
|
276
266
|
@abstractmethod
|
277
267
|
def compare(
|
@@ -291,7 +281,6 @@ class IAnalyzerService(ABC):
|
|
291
281
|
Returns:
|
292
282
|
Dict[str, Any]: Comparison results
|
293
283
|
"""
|
294
|
-
pass
|
295
284
|
|
296
285
|
@abstractmethod
|
297
286
|
def get_recommendations(
|
@@ -306,7 +295,6 @@ class IAnalyzerService(ABC):
|
|
306
295
|
Returns:
|
307
296
|
List[Dict[str, Any]]: List of recommendations
|
308
297
|
"""
|
309
|
-
pass
|
310
298
|
|
311
299
|
|
312
300
|
class IConfigurationService(ABC):
|
@@ -326,7 +314,6 @@ class IConfigurationService(ABC):
|
|
326
314
|
Returns:
|
327
315
|
ServiceMetadata: Complete service metadata
|
328
316
|
"""
|
329
|
-
pass
|
330
317
|
|
331
318
|
@abstractmethod
|
332
319
|
def load_config(
|
@@ -341,7 +328,6 @@ class IConfigurationService(ABC):
|
|
341
328
|
Returns:
|
342
329
|
ConfigurationResult: Loaded configuration result
|
343
330
|
"""
|
344
|
-
pass
|
345
331
|
|
346
332
|
@abstractmethod
|
347
333
|
def save_config(
|
@@ -357,7 +343,6 @@ class IConfigurationService(ABC):
|
|
357
343
|
Returns:
|
358
344
|
ConfigurationResult: Save operation result
|
359
345
|
"""
|
360
|
-
pass
|
361
346
|
|
362
347
|
@abstractmethod
|
363
348
|
def validate_config(self, config: Dict[str, Any]) -> List[str]:
|
@@ -370,7 +355,6 @@ class IConfigurationService(ABC):
|
|
370
355
|
Returns:
|
371
356
|
List[str]: List of validation errors (empty if valid)
|
372
357
|
"""
|
373
|
-
pass
|
374
358
|
|
375
359
|
@abstractmethod
|
376
360
|
def merge_configs(
|
@@ -386,7 +370,6 @@ class IConfigurationService(ABC):
|
|
386
370
|
Returns:
|
387
371
|
Dict[str, Any]: Merged configuration
|
388
372
|
"""
|
389
|
-
pass
|
390
373
|
|
391
374
|
@abstractmethod
|
392
375
|
def get_config_value(
|
@@ -403,7 +386,6 @@ class IConfigurationService(ABC):
|
|
403
386
|
Returns:
|
404
387
|
Any: Configuration value
|
405
388
|
"""
|
406
|
-
pass
|
407
389
|
|
408
390
|
@abstractmethod
|
409
391
|
def set_config_value(
|
@@ -420,7 +402,6 @@ class IConfigurationService(ABC):
|
|
420
402
|
Returns:
|
421
403
|
ConfigurationResult: Result of set operation
|
422
404
|
"""
|
423
|
-
pass
|
424
405
|
|
425
406
|
@abstractmethod
|
426
407
|
def get_schema(self) -> Dict[str, Any]:
|
@@ -430,7 +411,6 @@ class IConfigurationService(ABC):
|
|
430
411
|
Returns:
|
431
412
|
Dict[str, Any]: Configuration schema
|
432
413
|
"""
|
433
|
-
pass
|
434
414
|
|
435
415
|
@abstractmethod
|
436
416
|
def apply_defaults(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -443,7 +423,6 @@ class IConfigurationService(ABC):
|
|
443
423
|
Returns:
|
444
424
|
Dict[str, Any]: Configuration with defaults applied
|
445
425
|
"""
|
446
|
-
pass
|
447
426
|
|
448
427
|
|
449
428
|
class IUnifiedService(ABC):
|
@@ -462,14 +441,12 @@ class IUnifiedService(ABC):
|
|
462
441
|
Returns:
|
463
442
|
bool: True if initialization successful
|
464
443
|
"""
|
465
|
-
pass
|
466
444
|
|
467
445
|
@abstractmethod
|
468
446
|
async def shutdown(self) -> None:
|
469
447
|
"""
|
470
448
|
Gracefully shutdown the service.
|
471
449
|
"""
|
472
|
-
pass
|
473
450
|
|
474
451
|
@abstractmethod
|
475
452
|
def health_check(self) -> Dict[str, Any]:
|
@@ -479,7 +456,6 @@ class IUnifiedService(ABC):
|
|
479
456
|
Returns:
|
480
457
|
Dict[str, Any]: Health status information
|
481
458
|
"""
|
482
|
-
pass
|
483
459
|
|
484
460
|
@abstractmethod
|
485
461
|
def get_metrics(self) -> Dict[str, Any]:
|
@@ -489,11 +465,9 @@ class IUnifiedService(ABC):
|
|
489
465
|
Returns:
|
490
466
|
Dict[str, Any]: Service metrics
|
491
467
|
"""
|
492
|
-
pass
|
493
468
|
|
494
469
|
@abstractmethod
|
495
470
|
def reset(self) -> None:
|
496
471
|
"""
|
497
472
|
Reset service to initial state.
|
498
473
|
"""
|
499
|
-
pass
|
@@ -21,10 +21,9 @@ Migration Strategy:
|
|
21
21
|
"""
|
22
22
|
|
23
23
|
import inspect
|
24
|
-
from dataclasses import dataclass
|
24
|
+
from dataclasses import dataclass
|
25
25
|
from enum import Enum
|
26
|
-
from
|
27
|
-
from typing import Any, Callable, Dict, List, Optional, Set, Type, TypeVar
|
26
|
+
from typing import Any, Dict, List, Optional, Type, TypeVar
|
28
27
|
|
29
28
|
from claude_mpm.core.logging_utils import get_logger
|
30
29
|
|
@@ -131,9 +130,7 @@ class ServiceMapper:
|
|
131
130
|
def __init__(self):
|
132
131
|
"""Initialize service mapper."""
|
133
132
|
self._mappings: Dict[str, ServiceMapping] = {}
|
134
|
-
self._feature_flags: Dict[FeatureFlag, bool] =
|
135
|
-
flag: False for flag in FeatureFlag
|
136
|
-
}
|
133
|
+
self._feature_flags: Dict[FeatureFlag, bool] = dict.fromkeys(FeatureFlag, False)
|
137
134
|
self._metrics = MigrationMetrics()
|
138
135
|
self._logger = get_logger(f"{__name__}.ServiceMapper")
|
139
136
|
self._initialize_mappings()
|
@@ -199,9 +196,7 @@ class ServiceMapper:
|
|
199
196
|
"""
|
200
197
|
return self._mappings.get(legacy_service)
|
201
198
|
|
202
|
-
def get_unified_service(
|
203
|
-
self, legacy_path: str, legacy_class: str
|
204
|
-
) -> Optional[str]:
|
199
|
+
def get_unified_service(self, legacy_path: str, legacy_class: str) -> Optional[str]:
|
205
200
|
"""
|
206
201
|
Get unified service for a legacy service.
|
207
202
|
|
@@ -216,9 +211,7 @@ class ServiceMapper:
|
|
216
211
|
mapping = self._mappings.get(key)
|
217
212
|
return mapping.unified_service if mapping else None
|
218
213
|
|
219
|
-
def update_status(
|
220
|
-
self, legacy_service: str, status: MigrationStatus
|
221
|
-
) -> bool:
|
214
|
+
def update_status(self, legacy_service: str, status: MigrationStatus) -> bool:
|
222
215
|
"""
|
223
216
|
Update migration status for a service.
|
224
217
|
|
@@ -247,9 +240,7 @@ class ServiceMapper:
|
|
247
240
|
elif status == MigrationStatus.REMOVED:
|
248
241
|
self._metrics.removed_services += 1
|
249
242
|
|
250
|
-
self._logger.info(
|
251
|
-
f"Updated {legacy_service} status: {old_status} -> {status}"
|
252
|
-
)
|
243
|
+
self._logger.info(f"Updated {legacy_service} status: {old_status} -> {status}")
|
253
244
|
return True
|
254
245
|
|
255
246
|
def set_feature_flag(self, flag: FeatureFlag, enabled: bool) -> None:
|
@@ -336,9 +327,7 @@ def create_compatibility_wrapper(
|
|
336
327
|
def __init__(self, *args, **kwargs):
|
337
328
|
"""Initialize wrapper with unified service."""
|
338
329
|
self._unified_service = unified_service
|
339
|
-
self._logger = get_logger(
|
340
|
-
f"{__name__}.{legacy_class.__name__}Wrapper"
|
341
|
-
)
|
330
|
+
self._logger = get_logger(f"{__name__}.{legacy_class.__name__}Wrapper")
|
342
331
|
self._logger.debug(
|
343
332
|
f"Created compatibility wrapper for {legacy_class.__name__}"
|
344
333
|
)
|
@@ -375,9 +364,7 @@ def create_compatibility_wrapper(
|
|
375
364
|
return attr
|
376
365
|
|
377
366
|
# Fallback to legacy implementation if allowed
|
378
|
-
if ServiceMapper().is_feature_enabled(
|
379
|
-
FeatureFlag.ALLOW_LEGACY_FALLBACK
|
380
|
-
):
|
367
|
+
if ServiceMapper().is_feature_enabled(FeatureFlag.ALLOW_LEGACY_FALLBACK):
|
381
368
|
if hasattr(legacy_class, name):
|
382
369
|
self._logger.warning(
|
383
370
|
f"Falling back to legacy implementation for {name}"
|
@@ -434,26 +421,22 @@ class MigrationValidator:
|
|
434
421
|
|
435
422
|
# Get public methods from legacy class
|
436
423
|
legacy_methods = {
|
437
|
-
name
|
438
|
-
|
439
|
-
)
|
424
|
+
name
|
425
|
+
for name, _ in inspect.getmembers(legacy_class, inspect.ismethod)
|
440
426
|
if not name.startswith("_")
|
441
427
|
}
|
442
428
|
|
443
429
|
# Get public methods from unified class
|
444
430
|
unified_methods = {
|
445
|
-
name
|
446
|
-
|
447
|
-
)
|
431
|
+
name
|
432
|
+
for name, _ in inspect.getmembers(unified_class, inspect.ismethod)
|
448
433
|
if not name.startswith("_")
|
449
434
|
}
|
450
435
|
|
451
436
|
# Check for missing methods
|
452
437
|
missing = legacy_methods - unified_methods
|
453
438
|
if missing:
|
454
|
-
issues.append(
|
455
|
-
f"Missing methods in unified service: {', '.join(missing)}"
|
456
|
-
)
|
439
|
+
issues.append(f"Missing methods in unified service: {', '.join(missing)}")
|
457
440
|
|
458
441
|
# Check method signatures
|
459
442
|
for method_name in legacy_methods & unified_methods:
|
@@ -494,14 +477,10 @@ class MigrationValidator:
|
|
494
477
|
|
495
478
|
try:
|
496
479
|
# Execute on legacy service
|
497
|
-
legacy_result = getattr(legacy_instance, method_name)(
|
498
|
-
*args, **kwargs
|
499
|
-
)
|
480
|
+
legacy_result = getattr(legacy_instance, method_name)(*args, **kwargs)
|
500
481
|
|
501
482
|
# Execute on unified service
|
502
|
-
unified_result = getattr(unified_instance, method_name)(
|
503
|
-
*args, **kwargs
|
504
|
-
)
|
483
|
+
unified_result = getattr(unified_instance, method_name)(*args, **kwargs)
|
505
484
|
|
506
485
|
# Compare results
|
507
486
|
if legacy_result != unified_result:
|
@@ -511,9 +490,7 @@ class MigrationValidator:
|
|
511
490
|
)
|
512
491
|
|
513
492
|
except Exception as e:
|
514
|
-
differences.append(
|
515
|
-
f"Error testing {method_name}: {str(e)}"
|
516
|
-
)
|
493
|
+
differences.append(f"Error testing {method_name}: {e!s}")
|
517
494
|
|
518
495
|
return differences
|
519
496
|
|
@@ -529,4 +506,4 @@ def get_service_mapper() -> ServiceMapper:
|
|
529
506
|
Returns:
|
530
507
|
ServiceMapper: Global mapper instance
|
531
508
|
"""
|
532
|
-
return _global_mapper
|
509
|
+
return _global_mapper
|
@@ -24,7 +24,7 @@ from abc import ABC, abstractmethod
|
|
24
24
|
from dataclasses import dataclass, field
|
25
25
|
from enum import Enum
|
26
26
|
from pathlib import Path
|
27
|
-
from typing import Any,
|
27
|
+
from typing import Any, Dict, List, Optional, Set, Type, TypeVar, Union
|
28
28
|
|
29
29
|
from claude_mpm.core.logging_utils import get_logger
|
30
30
|
|
@@ -104,9 +104,7 @@ class BaseStrategy(ABC):
|
|
104
104
|
Args:
|
105
105
|
metadata: Strategy metadata
|
106
106
|
"""
|
107
|
-
self.metadata = metadata or StrategyMetadata(
|
108
|
-
name=self.__class__.__name__
|
109
|
-
)
|
107
|
+
self.metadata = metadata or StrategyMetadata(name=self.__class__.__name__)
|
110
108
|
self._logger = get_logger(f"{__name__}.{self.metadata.name}")
|
111
109
|
|
112
110
|
@abstractmethod
|
@@ -120,7 +118,6 @@ class BaseStrategy(ABC):
|
|
120
118
|
Returns:
|
121
119
|
bool: True if strategy can handle context
|
122
120
|
"""
|
123
|
-
pass
|
124
121
|
|
125
122
|
@abstractmethod
|
126
123
|
def validate_input(self, input_data: Any) -> List[str]:
|
@@ -133,7 +130,6 @@ class BaseStrategy(ABC):
|
|
133
130
|
Returns:
|
134
131
|
List[str]: List of validation errors (empty if valid)
|
135
132
|
"""
|
136
|
-
pass
|
137
133
|
|
138
134
|
def pre_execute(self, input_data: Any) -> Any:
|
139
135
|
"""
|
@@ -186,7 +182,6 @@ class DeploymentStrategy(BaseStrategy):
|
|
186
182
|
Returns:
|
187
183
|
Dict[str, Any]: Deployment result
|
188
184
|
"""
|
189
|
-
pass
|
190
185
|
|
191
186
|
@abstractmethod
|
192
187
|
def prepare_rollback(self, deployment_info: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -199,7 +194,6 @@ class DeploymentStrategy(BaseStrategy):
|
|
199
194
|
Returns:
|
200
195
|
Dict[str, Any]: Rollback information
|
201
196
|
"""
|
202
|
-
pass
|
203
197
|
|
204
198
|
@abstractmethod
|
205
199
|
def cleanup(self, target: Union[str, Path]) -> bool:
|
@@ -212,7 +206,6 @@ class DeploymentStrategy(BaseStrategy):
|
|
212
206
|
Returns:
|
213
207
|
bool: True if cleanup successful
|
214
208
|
"""
|
215
|
-
pass
|
216
209
|
|
217
210
|
|
218
211
|
class AnalyzerStrategy(BaseStrategy):
|
@@ -237,7 +230,6 @@ class AnalyzerStrategy(BaseStrategy):
|
|
237
230
|
Returns:
|
238
231
|
Dict[str, Any]: Analysis results
|
239
232
|
"""
|
240
|
-
pass
|
241
233
|
|
242
234
|
@abstractmethod
|
243
235
|
def extract_metrics(self, analysis_result: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -250,7 +242,6 @@ class AnalyzerStrategy(BaseStrategy):
|
|
250
242
|
Returns:
|
251
243
|
Dict[str, Any]: Extracted metrics
|
252
244
|
"""
|
253
|
-
pass
|
254
245
|
|
255
246
|
@abstractmethod
|
256
247
|
def generate_report(
|
@@ -266,7 +257,6 @@ class AnalyzerStrategy(BaseStrategy):
|
|
266
257
|
Returns:
|
267
258
|
Union[str, Dict[str, Any]]: Generated report
|
268
259
|
"""
|
269
|
-
pass
|
270
260
|
|
271
261
|
|
272
262
|
class ConfigStrategy(BaseStrategy):
|
@@ -288,7 +278,6 @@ class ConfigStrategy(BaseStrategy):
|
|
288
278
|
Returns:
|
289
279
|
Dict[str, Any]: Loaded configuration
|
290
280
|
"""
|
291
|
-
pass
|
292
281
|
|
293
282
|
@abstractmethod
|
294
283
|
def validate(self, config: Dict[str, Any]) -> List[str]:
|
@@ -301,7 +290,6 @@ class ConfigStrategy(BaseStrategy):
|
|
301
290
|
Returns:
|
302
291
|
List[str]: Validation errors (empty if valid)
|
303
292
|
"""
|
304
|
-
pass
|
305
293
|
|
306
294
|
@abstractmethod
|
307
295
|
def transform(self, config: Dict[str, Any]) -> Dict[str, Any]:
|
@@ -314,7 +302,6 @@ class ConfigStrategy(BaseStrategy):
|
|
314
302
|
Returns:
|
315
303
|
Dict[str, Any]: Transformed configuration
|
316
304
|
"""
|
317
|
-
pass
|
318
305
|
|
319
306
|
@abstractmethod
|
320
307
|
def get_schema(self) -> Dict[str, Any]:
|
@@ -324,7 +311,6 @@ class ConfigStrategy(BaseStrategy):
|
|
324
311
|
Returns:
|
325
312
|
Dict[str, Any]: Configuration schema
|
326
313
|
"""
|
327
|
-
pass
|
328
314
|
|
329
315
|
|
330
316
|
class StrategyRegistry:
|
@@ -372,7 +358,8 @@ class StrategyRegistry:
|
|
372
358
|
# Remove old strategy if overriding
|
373
359
|
if override and strategy_name in self._strategy_metadata:
|
374
360
|
self._strategies[strategy_class] = [
|
375
|
-
s
|
361
|
+
s
|
362
|
+
for s in self._strategies[strategy_class]
|
376
363
|
if s.metadata.name != strategy_name
|
377
364
|
]
|
378
365
|
|
@@ -399,7 +386,8 @@ class StrategyRegistry:
|
|
399
386
|
# Remove from all strategy lists
|
400
387
|
for strategy_class in self._strategies:
|
401
388
|
self._strategies[strategy_class] = [
|
402
|
-
s
|
389
|
+
s
|
390
|
+
for s in self._strategies[strategy_class]
|
403
391
|
if s.metadata.name != strategy_name
|
404
392
|
]
|
405
393
|
|
@@ -435,16 +423,11 @@ class StrategyRegistry:
|
|
435
423
|
candidates.append(strategy)
|
436
424
|
|
437
425
|
if not candidates:
|
438
|
-
self._logger.warning(
|
439
|
-
f"No suitable strategy found for context: {context}"
|
440
|
-
)
|
426
|
+
self._logger.warning(f"No suitable strategy found for context: {context}")
|
441
427
|
return None
|
442
428
|
|
443
429
|
# Sort by priority (highest first)
|
444
|
-
candidates.sort(
|
445
|
-
key=lambda s: s.metadata.priority.value,
|
446
|
-
reverse=True
|
447
|
-
)
|
430
|
+
candidates.sort(key=lambda s: s.metadata.priority.value, reverse=True)
|
448
431
|
|
449
432
|
selected = candidates[0]
|
450
433
|
self._logger.debug(
|
@@ -548,4 +531,4 @@ def select_strategy(
|
|
548
531
|
Returns:
|
549
532
|
Optional[BaseStrategy]: Selected strategy or None
|
550
533
|
"""
|
551
|
-
return _global_registry.select_strategy(strategy_class, context)
|
534
|
+
return _global_registry.select_strategy(strategy_class, context)
|
@@ -22,7 +22,6 @@ Features:
|
|
22
22
|
- Recommendation generation
|
23
23
|
"""
|
24
24
|
|
25
|
-
import asyncio
|
26
25
|
from pathlib import Path
|
27
26
|
from typing import Any, Dict, List, Optional, Union
|
28
27
|
|
@@ -111,7 +110,7 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
111
110
|
return True
|
112
111
|
|
113
112
|
except Exception as e:
|
114
|
-
self._logger.error(f"Failed to initialize: {
|
113
|
+
self._logger.error(f"Failed to initialize: {e!s}")
|
115
114
|
return False
|
116
115
|
|
117
116
|
async def shutdown(self) -> None:
|
@@ -228,9 +227,7 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
228
227
|
)
|
229
228
|
|
230
229
|
# Execute analysis using strategy
|
231
|
-
self._logger.info(
|
232
|
-
f"Analyzing {target} using {strategy.metadata.name}"
|
233
|
-
)
|
230
|
+
self._logger.info(f"Analyzing {target} using {strategy.metadata.name}")
|
234
231
|
|
235
232
|
# Validate input
|
236
233
|
validation_errors = strategy.validate_input(target)
|
@@ -264,11 +261,11 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
264
261
|
return result
|
265
262
|
|
266
263
|
except Exception as e:
|
267
|
-
self._logger.error(f"Analysis error: {
|
264
|
+
self._logger.error(f"Analysis error: {e!s}")
|
268
265
|
self._metrics["analysis_errors"] += 1
|
269
266
|
return AnalysisResult(
|
270
267
|
success=False,
|
271
|
-
summary=f"Analysis failed: {
|
268
|
+
summary=f"Analysis failed: {e!s}",
|
272
269
|
severity="error",
|
273
270
|
)
|
274
271
|
|
@@ -380,7 +377,7 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
380
377
|
}
|
381
378
|
|
382
379
|
except Exception as e:
|
383
|
-
self._logger.error(f"Comparison error: {
|
380
|
+
self._logger.error(f"Comparison error: {e!s}")
|
384
381
|
return {"success": False, "error": str(e)}
|
385
382
|
|
386
383
|
def get_recommendations(
|
@@ -399,31 +396,37 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
399
396
|
|
400
397
|
# Basic recommendations from result
|
401
398
|
for rec in analysis_result.recommendations:
|
402
|
-
recommendations.append(
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
399
|
+
recommendations.append(
|
400
|
+
{
|
401
|
+
"type": "general",
|
402
|
+
"description": rec,
|
403
|
+
"priority": "medium",
|
404
|
+
}
|
405
|
+
)
|
407
406
|
|
408
407
|
# Add severity-based recommendations
|
409
408
|
if analysis_result.severity == "critical":
|
410
|
-
recommendations.insert(
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
409
|
+
recommendations.insert(
|
410
|
+
0,
|
411
|
+
{
|
412
|
+
"type": "urgent",
|
413
|
+
"description": "Critical issues found - immediate attention required",
|
414
|
+
"priority": "high",
|
415
|
+
},
|
416
|
+
)
|
415
417
|
elif analysis_result.severity == "error":
|
416
|
-
recommendations.insert(
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
418
|
+
recommendations.insert(
|
419
|
+
0,
|
420
|
+
{
|
421
|
+
"type": "important",
|
422
|
+
"description": "Errors found - should be addressed soon",
|
423
|
+
"priority": "high",
|
424
|
+
},
|
425
|
+
)
|
421
426
|
|
422
427
|
# Add metric-based recommendations
|
423
428
|
if analysis_result.metrics:
|
424
|
-
metric_recs = self._generate_metric_recommendations(
|
425
|
-
analysis_result.metrics
|
426
|
-
)
|
429
|
+
metric_recs = self._generate_metric_recommendations(analysis_result.metrics)
|
427
430
|
recommendations.extend(metric_recs)
|
428
431
|
|
429
432
|
return recommendations
|
@@ -436,9 +439,7 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
436
439
|
# This would be extended with actual strategy implementations
|
437
440
|
self._logger.debug("Default strategies registered")
|
438
441
|
|
439
|
-
def _determine_analysis_type(
|
440
|
-
self, target: Any, options: Dict[str, Any]
|
441
|
-
) -> str:
|
442
|
+
def _determine_analysis_type(self, target: Any, options: Dict[str, Any]) -> str:
|
442
443
|
"""
|
443
444
|
Determine analysis type from target and options.
|
444
445
|
|
@@ -460,7 +461,7 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
460
461
|
# Determine by file extension
|
461
462
|
if path.suffix in [".py", ".js", ".ts", ".java"]:
|
462
463
|
return "code"
|
463
|
-
|
464
|
+
if path.suffix in [".json", ".yaml", ".yml"]:
|
464
465
|
return "config"
|
465
466
|
elif path.is_dir():
|
466
467
|
return "project"
|
@@ -482,7 +483,6 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
482
483
|
def _aggregate_batch_metrics(self, results: List[AnalysisResult]) -> None:
|
483
484
|
"""Aggregate metrics from batch analysis."""
|
484
485
|
# Implementation would aggregate metrics across results
|
485
|
-
pass
|
486
486
|
|
487
487
|
def _compare_metrics(
|
488
488
|
self, metrics1: Dict[str, Any], metrics2: Dict[str, Any]
|
@@ -492,8 +492,8 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
492
492
|
all_keys = set(metrics1.keys()) | set(metrics2.keys())
|
493
493
|
|
494
494
|
for key in all_keys:
|
495
|
-
val1 = metrics1.get(key
|
496
|
-
val2 = metrics2.get(key
|
495
|
+
val1 = metrics1.get(key)
|
496
|
+
val2 = metrics2.get(key)
|
497
497
|
|
498
498
|
if val1 != val2:
|
499
499
|
diff[key] = {"target1": val1, "target2": val2}
|
@@ -518,17 +518,21 @@ class UnifiedAnalyzer(IAnalyzerService, IUnifiedService):
|
|
518
518
|
|
519
519
|
# Example metric-based recommendations
|
520
520
|
if metrics.get("complexity", 0) > 10:
|
521
|
-
recommendations.append(
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
521
|
+
recommendations.append(
|
522
|
+
{
|
523
|
+
"type": "complexity",
|
524
|
+
"description": "Consider refactoring to reduce complexity",
|
525
|
+
"priority": "medium",
|
526
|
+
}
|
527
|
+
)
|
526
528
|
|
527
529
|
if metrics.get("code_duplication", 0) > 20:
|
528
|
-
recommendations.append(
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
530
|
+
recommendations.append(
|
531
|
+
{
|
532
|
+
"type": "duplication",
|
533
|
+
"description": "High code duplication detected - consider extracting common functionality",
|
534
|
+
"priority": "medium",
|
535
|
+
}
|
536
|
+
)
|
533
537
|
|
534
|
-
return recommendations
|
538
|
+
return recommendations
|