claude-mpm 4.7.4__py3-none-any.whl → 4.18.2__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/BASE_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +106 -1
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/agent-manager.json +4 -1
- claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
- claude_mpm/agents/templates/api_qa.json +11 -2
- claude_mpm/agents/templates/circuit_breakers.md +638 -0
- claude_mpm/agents/templates/clerk-ops.json +12 -2
- claude_mpm/agents/templates/code_analyzer.json +8 -2
- claude_mpm/agents/templates/content-agent.json +358 -0
- claude_mpm/agents/templates/dart_engineer.json +15 -2
- claude_mpm/agents/templates/data_engineer.json +15 -2
- claude_mpm/agents/templates/documentation.json +10 -2
- claude_mpm/agents/templates/engineer.json +21 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
- claude_mpm/agents/templates/git_file_tracking.md +584 -0
- claude_mpm/agents/templates/golang_engineer.json +270 -0
- claude_mpm/agents/templates/imagemagick.json +4 -1
- claude_mpm/agents/templates/java_engineer.json +346 -0
- claude_mpm/agents/templates/local_ops_agent.json +1227 -6
- claude_mpm/agents/templates/memory_manager.json +4 -1
- claude_mpm/agents/templates/nextjs_engineer.json +141 -133
- claude_mpm/agents/templates/ops.json +12 -2
- claude_mpm/agents/templates/php-engineer.json +270 -174
- claude_mpm/agents/templates/pm_examples.md +474 -0
- claude_mpm/agents/templates/pm_red_flags.md +240 -0
- claude_mpm/agents/templates/product_owner.json +338 -0
- claude_mpm/agents/templates/project_organizer.json +14 -4
- claude_mpm/agents/templates/prompt-engineer.json +13 -2
- claude_mpm/agents/templates/python_engineer.json +174 -81
- claude_mpm/agents/templates/qa.json +11 -2
- claude_mpm/agents/templates/react_engineer.json +16 -3
- claude_mpm/agents/templates/refactoring_engineer.json +12 -2
- claude_mpm/agents/templates/research.json +34 -21
- claude_mpm/agents/templates/response_format.md +583 -0
- claude_mpm/agents/templates/ruby-engineer.json +129 -192
- claude_mpm/agents/templates/rust_engineer.json +270 -0
- claude_mpm/agents/templates/security.json +10 -2
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +10 -2
- claude_mpm/agents/templates/typescript_engineer.json +116 -125
- claude_mpm/agents/templates/validation_templates.md +312 -0
- claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
- claude_mpm/agents/templates/version_control.json +12 -2
- claude_mpm/agents/templates/web_qa.json +11 -2
- claude_mpm/agents/templates/web_ui.json +15 -2
- claude_mpm/cli/__init__.py +34 -614
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +235 -148
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +570 -0
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +419 -1571
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +585 -196
- claude_mpm/cli/commands/mpm_init_handler.py +37 -3
- claude_mpm/cli/commands/search.py +170 -4
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agents_parser.py +9 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +110 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +481 -0
- claude_mpm/cli/utils.py +52 -1
- claude_mpm/commands/mpm-agents-detect.md +168 -0
- claude_mpm/commands/mpm-agents-recommend.md +214 -0
- claude_mpm/commands/mpm-agents.md +75 -1
- claude_mpm/commands/mpm-auto-configure.md +217 -0
- claude_mpm/commands/mpm-help.md +163 -0
- claude_mpm/commands/mpm-init.md +148 -3
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +9 -3
- claude_mpm/core/log_manager.py +2 -0
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/__init__.py +20 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
- claude_mpm/hooks/failure_learning/__init__.py +60 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +37 -12
- claude_mpm/hooks/kuzu_response_hook.py +183 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +568 -0
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/interfaces/__init__.py +90 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +172 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/memory_manager.py +11 -24
- claude_mpm/services/core/models/__init__.py +79 -0
- claude_mpm/services/core/models/agent_config.py +381 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +235 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +23 -7
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +19 -24
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +163 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +430 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +9 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/main.py +30 -0
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory/failure_tracker.py +563 -0
- claude_mpm/services/memory_hook_service.py +165 -4
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/toolchain_analyzer.py +581 -0
- claude_mpm/services/self_upgrade_service.py +342 -0
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/storage/state_storage.py +15 -15
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +40 -20
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/robust_installer.py +73 -19
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +129 -12
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +295 -193
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/index-hub-backup.html +0 -713
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent Recommender Service for Claude MPM Framework
|
|
3
|
+
===================================================
|
|
4
|
+
|
|
5
|
+
WHY: Automated agent recommendation is critical for the auto-configuration feature.
|
|
6
|
+
This service analyzes project toolchains and recommends appropriate specialized agents
|
|
7
|
+
using configuration-driven mappings and intelligent scoring algorithms.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISION: Configuration-driven approach using YAML for flexibility and
|
|
10
|
+
maintainability. Scoring algorithm weighs language, framework, and deployment matches
|
|
11
|
+
with configurable weights. Returns ranked recommendations with detailed reasoning.
|
|
12
|
+
|
|
13
|
+
Part of TSK-0054: Auto-Configuration Feature - Phase 3
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Any, Dict, List, Optional
|
|
18
|
+
|
|
19
|
+
import yaml
|
|
20
|
+
|
|
21
|
+
from claude_mpm.core.base_service import BaseService
|
|
22
|
+
from claude_mpm.services.core.interfaces.agent import IAgentRecommender
|
|
23
|
+
from claude_mpm.services.core.models.agent_config import (
|
|
24
|
+
AgentCapabilities,
|
|
25
|
+
AgentRecommendation,
|
|
26
|
+
AgentSpecialization,
|
|
27
|
+
)
|
|
28
|
+
from claude_mpm.services.core.models.toolchain import ToolchainAnalysis
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AgentRecommenderService(BaseService, IAgentRecommender):
|
|
32
|
+
"""
|
|
33
|
+
Service for recommending agents based on toolchain analysis.
|
|
34
|
+
|
|
35
|
+
This service:
|
|
36
|
+
- Loads agent capabilities from YAML configuration
|
|
37
|
+
- Calculates match scores between toolchains and agents
|
|
38
|
+
- Returns ranked recommendations with confidence scores
|
|
39
|
+
- Provides detailed reasoning for each recommendation
|
|
40
|
+
|
|
41
|
+
Matching Algorithm:
|
|
42
|
+
- Primary language match (50% weight)
|
|
43
|
+
- Framework match (30% weight)
|
|
44
|
+
- Deployment target match (20% weight)
|
|
45
|
+
- Apply agent-specific confidence weights
|
|
46
|
+
- Framework-specific agents override language agents
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
config_path: Optional[Path] = None,
|
|
52
|
+
config: Optional[Dict[str, Any]] = None,
|
|
53
|
+
container: Optional[Any] = None,
|
|
54
|
+
):
|
|
55
|
+
"""
|
|
56
|
+
Initialize the Agent Recommender Service.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
config_path: Optional path to agent_capabilities.yaml
|
|
60
|
+
config: Optional configuration dictionary
|
|
61
|
+
container: Optional service container for dependency injection
|
|
62
|
+
"""
|
|
63
|
+
super().__init__(
|
|
64
|
+
name="AgentRecommenderService",
|
|
65
|
+
config=config,
|
|
66
|
+
enable_enhanced_features=False,
|
|
67
|
+
container=container,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Determine config file path
|
|
71
|
+
if config_path is None:
|
|
72
|
+
# Default to config directory in the package
|
|
73
|
+
package_config_dir = Path(__file__).parent.parent.parent / "config"
|
|
74
|
+
config_path = package_config_dir / "agent_capabilities.yaml"
|
|
75
|
+
|
|
76
|
+
self.config_path = config_path
|
|
77
|
+
self._capabilities_config: Dict[str, Any] = {}
|
|
78
|
+
self._agent_capabilities_cache: Dict[str, AgentCapabilities] = {}
|
|
79
|
+
self._load_configuration()
|
|
80
|
+
|
|
81
|
+
self.logger.info(
|
|
82
|
+
f"AgentRecommenderService initialized with config: {self.config_path}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
async def _initialize(self) -> None:
|
|
86
|
+
"""Initialize the service (required by BaseService)."""
|
|
87
|
+
# Configuration is loaded in __init__, no additional initialization needed
|
|
88
|
+
|
|
89
|
+
async def _cleanup(self) -> None:
|
|
90
|
+
"""Cleanup service resources (required by BaseService)."""
|
|
91
|
+
# Clear caches
|
|
92
|
+
self._agent_capabilities_cache.clear()
|
|
93
|
+
self._capabilities_config.clear()
|
|
94
|
+
|
|
95
|
+
def _load_configuration(self) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Load agent capabilities configuration from YAML file.
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
FileNotFoundError: If configuration file does not exist
|
|
101
|
+
yaml.YAMLError: If configuration file is invalid YAML
|
|
102
|
+
"""
|
|
103
|
+
if not self.config_path.exists():
|
|
104
|
+
raise FileNotFoundError(
|
|
105
|
+
f"Agent capabilities config not found: {self.config_path}"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
with self.config_path.open(encoding="utf-8") as f:
|
|
110
|
+
self._capabilities_config = yaml.safe_load(f)
|
|
111
|
+
|
|
112
|
+
if (
|
|
113
|
+
not self._capabilities_config
|
|
114
|
+
or "agent_capabilities" not in self._capabilities_config
|
|
115
|
+
):
|
|
116
|
+
raise ValueError(
|
|
117
|
+
"Invalid configuration: missing 'agent_capabilities' section"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
self.logger.info(
|
|
121
|
+
f"Loaded {len(self._capabilities_config['agent_capabilities'])} "
|
|
122
|
+
f"agent capability definitions"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
except yaml.YAMLError as e:
|
|
126
|
+
self.logger.error(f"Failed to parse YAML configuration: {e}")
|
|
127
|
+
raise
|
|
128
|
+
|
|
129
|
+
def recommend_agents(
|
|
130
|
+
self,
|
|
131
|
+
toolchain: ToolchainAnalysis,
|
|
132
|
+
constraints: Optional[Dict[str, Any]] = None,
|
|
133
|
+
) -> List[AgentRecommendation]:
|
|
134
|
+
"""
|
|
135
|
+
Recommend agents based on toolchain analysis.
|
|
136
|
+
|
|
137
|
+
Analyzes the toolchain and recommends agents that best match the
|
|
138
|
+
project's technical requirements. Considers:
|
|
139
|
+
- Language compatibility
|
|
140
|
+
- Framework expertise
|
|
141
|
+
- Deployment environment requirements
|
|
142
|
+
- Optional user-defined constraints
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
toolchain: Complete toolchain analysis results
|
|
146
|
+
constraints: Optional constraints for recommendations:
|
|
147
|
+
- max_agents: Maximum number of agents to recommend
|
|
148
|
+
- required_capabilities: List of required agent capabilities
|
|
149
|
+
- excluded_agents: List of agent IDs to exclude
|
|
150
|
+
- min_confidence: Minimum confidence score threshold
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
List[AgentRecommendation]: Ordered list of recommended agents
|
|
154
|
+
with confidence scores and reasoning
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
ValueError: If constraints are invalid or contradictory
|
|
158
|
+
"""
|
|
159
|
+
constraints = constraints or {}
|
|
160
|
+
min_confidence = constraints.get(
|
|
161
|
+
"min_confidence",
|
|
162
|
+
self._capabilities_config.get("recommendation_rules", {}).get(
|
|
163
|
+
"min_confidence_threshold", 0.5
|
|
164
|
+
),
|
|
165
|
+
)
|
|
166
|
+
excluded_agents = set(constraints.get("excluded_agents", []))
|
|
167
|
+
max_agents = constraints.get("max_agents")
|
|
168
|
+
|
|
169
|
+
recommendations: List[AgentRecommendation] = []
|
|
170
|
+
agent_configs = self._capabilities_config.get("agent_capabilities", {})
|
|
171
|
+
|
|
172
|
+
# Calculate scores for all agents
|
|
173
|
+
for agent_id, agent_config in agent_configs.items():
|
|
174
|
+
# Skip excluded agents
|
|
175
|
+
if agent_id in excluded_agents:
|
|
176
|
+
continue
|
|
177
|
+
|
|
178
|
+
# Skip agents that shouldn't auto-deploy unless explicitly allowed
|
|
179
|
+
if not agent_config.get("auto_deploy", True) and not constraints.get(
|
|
180
|
+
"include_non_auto_deploy", False
|
|
181
|
+
):
|
|
182
|
+
continue
|
|
183
|
+
|
|
184
|
+
# Calculate match score
|
|
185
|
+
score = self.match_score(agent_id, toolchain)
|
|
186
|
+
|
|
187
|
+
# Filter by minimum confidence
|
|
188
|
+
if score < min_confidence:
|
|
189
|
+
continue
|
|
190
|
+
|
|
191
|
+
# Get agent capabilities
|
|
192
|
+
capabilities = self.get_agent_capabilities(agent_id)
|
|
193
|
+
|
|
194
|
+
# Generate match reasons and concerns
|
|
195
|
+
match_reasons, concerns = self._generate_reasoning(
|
|
196
|
+
agent_id, agent_config, toolchain, score
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
# Determine deployment priority
|
|
200
|
+
deployment_priority = self._calculate_deployment_priority(
|
|
201
|
+
agent_config, toolchain
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
recommendation = AgentRecommendation(
|
|
205
|
+
agent_id=agent_id,
|
|
206
|
+
agent_name=agent_config.get("name", agent_id),
|
|
207
|
+
confidence_score=score,
|
|
208
|
+
match_reasons=match_reasons,
|
|
209
|
+
concerns=concerns,
|
|
210
|
+
capabilities=capabilities,
|
|
211
|
+
deployment_priority=deployment_priority,
|
|
212
|
+
configuration_hints=self._generate_config_hints(
|
|
213
|
+
agent_config, toolchain
|
|
214
|
+
),
|
|
215
|
+
metadata={
|
|
216
|
+
"specialization": agent_config.get("specialization"),
|
|
217
|
+
"auto_deploy": agent_config.get("auto_deploy", True),
|
|
218
|
+
},
|
|
219
|
+
)
|
|
220
|
+
recommendations.append(recommendation)
|
|
221
|
+
|
|
222
|
+
# Sort by confidence score (descending), then by deployment priority (ascending)
|
|
223
|
+
recommendations.sort(key=lambda r: (-r.confidence_score, r.deployment_priority))
|
|
224
|
+
|
|
225
|
+
# Apply max agents limit if specified
|
|
226
|
+
if max_agents is not None:
|
|
227
|
+
recommendations = recommendations[:max_agents]
|
|
228
|
+
|
|
229
|
+
self.logger.info(
|
|
230
|
+
f"Generated {len(recommendations)} agent recommendations "
|
|
231
|
+
f"for project: {toolchain.project_path}"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
return recommendations
|
|
235
|
+
|
|
236
|
+
def get_agent_capabilities(self, agent_id: str) -> AgentCapabilities:
|
|
237
|
+
"""
|
|
238
|
+
Get detailed capabilities for an agent.
|
|
239
|
+
|
|
240
|
+
Retrieves comprehensive capability information for a specific agent:
|
|
241
|
+
- Supported languages and frameworks
|
|
242
|
+
- Specialization areas
|
|
243
|
+
- Required toolchain components
|
|
244
|
+
- Performance characteristics
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
agent_id: Unique identifier of the agent
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
AgentCapabilities: Complete capability information
|
|
251
|
+
|
|
252
|
+
Raises:
|
|
253
|
+
KeyError: If agent_id does not exist
|
|
254
|
+
"""
|
|
255
|
+
# Check cache first
|
|
256
|
+
if agent_id in self._agent_capabilities_cache:
|
|
257
|
+
return self._agent_capabilities_cache[agent_id]
|
|
258
|
+
|
|
259
|
+
# Get from config
|
|
260
|
+
agent_configs = self._capabilities_config.get("agent_capabilities", {})
|
|
261
|
+
if agent_id not in agent_configs:
|
|
262
|
+
raise KeyError(f"Agent not found: {agent_id}")
|
|
263
|
+
|
|
264
|
+
agent_config = agent_configs[agent_id]
|
|
265
|
+
supports = agent_config.get("supports", {})
|
|
266
|
+
|
|
267
|
+
# Determine specializations
|
|
268
|
+
specializations = []
|
|
269
|
+
spec_type = agent_config.get("specialization", "general")
|
|
270
|
+
if spec_type == "engineering":
|
|
271
|
+
specializations.append(AgentSpecialization.LANGUAGE_SPECIFIC)
|
|
272
|
+
elif spec_type == "devops":
|
|
273
|
+
specializations.append(AgentSpecialization.DEVOPS)
|
|
274
|
+
|
|
275
|
+
# Create capabilities object
|
|
276
|
+
capabilities = AgentCapabilities(
|
|
277
|
+
agent_id=agent_id,
|
|
278
|
+
agent_name=agent_config.get("name", agent_id),
|
|
279
|
+
specializations=specializations,
|
|
280
|
+
supported_languages=supports.get("languages", []),
|
|
281
|
+
supported_frameworks=supports.get("frameworks", []),
|
|
282
|
+
required_tools=supports.get("build_tools", []),
|
|
283
|
+
deployment_targets=supports.get("deployment", []),
|
|
284
|
+
description=agent_config.get("description", ""),
|
|
285
|
+
metadata=agent_config.get("metadata", {}),
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Cache for future use
|
|
289
|
+
self._agent_capabilities_cache[agent_id] = capabilities
|
|
290
|
+
|
|
291
|
+
return capabilities
|
|
292
|
+
|
|
293
|
+
def match_score(self, agent_id: str, toolchain: ToolchainAnalysis) -> float:
|
|
294
|
+
"""
|
|
295
|
+
Calculate match score between agent and toolchain.
|
|
296
|
+
|
|
297
|
+
Computes a numerical score (0.0 to 1.0) indicating how well an agent
|
|
298
|
+
matches the project's toolchain. Higher scores indicate better matches.
|
|
299
|
+
Considers:
|
|
300
|
+
- Language compatibility (50% weight)
|
|
301
|
+
- Framework experience (30% weight)
|
|
302
|
+
- Deployment target alignment (20% weight)
|
|
303
|
+
- Toolchain component coverage
|
|
304
|
+
|
|
305
|
+
Args:
|
|
306
|
+
agent_id: Unique identifier of the agent
|
|
307
|
+
toolchain: Complete toolchain analysis
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
float: Match score between 0.0 (no match) and 1.0 (perfect match)
|
|
311
|
+
|
|
312
|
+
Raises:
|
|
313
|
+
KeyError: If agent_id does not exist
|
|
314
|
+
"""
|
|
315
|
+
agent_configs = self._capabilities_config.get("agent_capabilities", {})
|
|
316
|
+
if agent_id not in agent_configs:
|
|
317
|
+
raise KeyError(f"Agent not found: {agent_id}")
|
|
318
|
+
|
|
319
|
+
agent_config = agent_configs[agent_id]
|
|
320
|
+
supports = agent_config.get("supports", {})
|
|
321
|
+
|
|
322
|
+
# Get scoring weights
|
|
323
|
+
scoring_weights = self._capabilities_config.get("recommendation_rules", {}).get(
|
|
324
|
+
"scoring_weights", {}
|
|
325
|
+
)
|
|
326
|
+
language_weight = scoring_weights.get("language_match", 0.5)
|
|
327
|
+
framework_weight = scoring_weights.get("framework_match", 0.3)
|
|
328
|
+
deployment_weight = scoring_weights.get("deployment_match", 0.2)
|
|
329
|
+
|
|
330
|
+
# Calculate language match score
|
|
331
|
+
language_score = self._calculate_language_score(
|
|
332
|
+
supports.get("languages", []), toolchain
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Calculate framework match score
|
|
336
|
+
framework_score = self._calculate_framework_score(
|
|
337
|
+
supports.get("frameworks", []), toolchain
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
# Calculate deployment match score
|
|
341
|
+
deployment_score = self._calculate_deployment_score(
|
|
342
|
+
supports.get("deployment", []), toolchain
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# Calculate base score
|
|
346
|
+
base_score = (
|
|
347
|
+
language_score * language_weight
|
|
348
|
+
+ framework_score * framework_weight
|
|
349
|
+
+ deployment_score * deployment_weight
|
|
350
|
+
)
|
|
351
|
+
|
|
352
|
+
# Apply agent confidence weight
|
|
353
|
+
agent_confidence_weight = agent_config.get("confidence_weight", 1.0)
|
|
354
|
+
final_score = base_score * agent_confidence_weight
|
|
355
|
+
|
|
356
|
+
# Apply framework priority boost if applicable
|
|
357
|
+
if framework_score > 0.5: # Strong framework match
|
|
358
|
+
framework_boost = self._capabilities_config.get(
|
|
359
|
+
"recommendation_rules", {}
|
|
360
|
+
).get("framework_priority_boost", 0.15)
|
|
361
|
+
final_score = min(1.0, final_score + framework_boost)
|
|
362
|
+
|
|
363
|
+
# Apply deployment match boost if applicable
|
|
364
|
+
if deployment_score > 0.5: # Strong deployment match
|
|
365
|
+
deployment_boost = self._capabilities_config.get(
|
|
366
|
+
"recommendation_rules", {}
|
|
367
|
+
).get("deployment_match_boost", 0.1)
|
|
368
|
+
final_score = min(1.0, final_score + deployment_boost)
|
|
369
|
+
|
|
370
|
+
# Ensure score is in valid range and return
|
|
371
|
+
return max(0.0, min(1.0, final_score))
|
|
372
|
+
|
|
373
|
+
def _calculate_language_score(
|
|
374
|
+
self, supported_languages: List[str], toolchain: ToolchainAnalysis
|
|
375
|
+
) -> float:
|
|
376
|
+
"""Calculate language match score."""
|
|
377
|
+
if not supported_languages:
|
|
378
|
+
return 0.0
|
|
379
|
+
|
|
380
|
+
primary_language = toolchain.primary_language.lower()
|
|
381
|
+
all_languages = [lang.lower() for lang in toolchain.all_languages]
|
|
382
|
+
|
|
383
|
+
# Check for primary language match
|
|
384
|
+
for lang in supported_languages:
|
|
385
|
+
if lang.lower() == primary_language:
|
|
386
|
+
return 1.0 # Perfect match on primary language
|
|
387
|
+
|
|
388
|
+
# Check for secondary language match
|
|
389
|
+
for lang in supported_languages:
|
|
390
|
+
if lang.lower() in all_languages:
|
|
391
|
+
return 0.6 # Partial match on secondary language
|
|
392
|
+
|
|
393
|
+
return 0.0
|
|
394
|
+
|
|
395
|
+
def _calculate_framework_score(
|
|
396
|
+
self, supported_frameworks: List[str], toolchain: ToolchainAnalysis
|
|
397
|
+
) -> float:
|
|
398
|
+
"""Calculate framework match score."""
|
|
399
|
+
if not supported_frameworks:
|
|
400
|
+
return 0.0
|
|
401
|
+
|
|
402
|
+
detected_frameworks = [fw.name.lower() for fw in toolchain.frameworks]
|
|
403
|
+
if not detected_frameworks:
|
|
404
|
+
return 0.0
|
|
405
|
+
|
|
406
|
+
# Check for exact framework matches
|
|
407
|
+
matches = 0
|
|
408
|
+
for fw in supported_frameworks:
|
|
409
|
+
fw_lower = fw.lower()
|
|
410
|
+
# Normalize common variants (next.js vs nextjs, etc.)
|
|
411
|
+
fw_normalized = fw_lower.replace(".", "").replace("-", "")
|
|
412
|
+
for detected_fw in detected_frameworks:
|
|
413
|
+
detected_normalized = detected_fw.replace(".", "").replace("-", "")
|
|
414
|
+
if fw_normalized == detected_normalized:
|
|
415
|
+
matches += 1
|
|
416
|
+
break
|
|
417
|
+
|
|
418
|
+
if matches == 0:
|
|
419
|
+
return 0.0
|
|
420
|
+
|
|
421
|
+
# Calculate score based on match proportion
|
|
422
|
+
match_ratio = matches / len(detected_frameworks)
|
|
423
|
+
return min(1.0, match_ratio * 1.2) # Boost for framework matches
|
|
424
|
+
|
|
425
|
+
def _calculate_deployment_score(
|
|
426
|
+
self, supported_deployments: List[str], toolchain: ToolchainAnalysis
|
|
427
|
+
) -> float:
|
|
428
|
+
"""Calculate deployment target match score."""
|
|
429
|
+
if not supported_deployments or not toolchain.deployment_target:
|
|
430
|
+
return 0.0
|
|
431
|
+
|
|
432
|
+
target_platform = toolchain.deployment_target.platform
|
|
433
|
+
target_type = toolchain.deployment_target.target_type
|
|
434
|
+
|
|
435
|
+
# Check for exact platform match
|
|
436
|
+
for deployment in supported_deployments:
|
|
437
|
+
deployment_lower = deployment.lower()
|
|
438
|
+
if target_platform and deployment_lower == target_platform.lower():
|
|
439
|
+
return 1.0 # Perfect match on platform
|
|
440
|
+
if deployment_lower == target_type.lower():
|
|
441
|
+
return 0.8 # Good match on target type
|
|
442
|
+
|
|
443
|
+
# Check for container/cloud general matches
|
|
444
|
+
if any(d.lower() in ["docker", "kubernetes"] for d in supported_deployments):
|
|
445
|
+
if target_type in ["container", "cloud"]:
|
|
446
|
+
return 0.5 # General container/cloud match
|
|
447
|
+
|
|
448
|
+
return 0.0
|
|
449
|
+
|
|
450
|
+
def _generate_reasoning(
|
|
451
|
+
self,
|
|
452
|
+
agent_id: str,
|
|
453
|
+
agent_config: Dict[str, Any],
|
|
454
|
+
toolchain: ToolchainAnalysis,
|
|
455
|
+
score: float,
|
|
456
|
+
) -> tuple[List[str], List[str]]:
|
|
457
|
+
"""
|
|
458
|
+
Generate match reasons and concerns for recommendation.
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
Tuple of (match_reasons, concerns)
|
|
462
|
+
"""
|
|
463
|
+
match_reasons = []
|
|
464
|
+
concerns = []
|
|
465
|
+
supports = agent_config.get("supports", {})
|
|
466
|
+
|
|
467
|
+
# Check language match
|
|
468
|
+
primary_language = toolchain.primary_language.lower()
|
|
469
|
+
supported_languages = [lang.lower() for lang in supports.get("languages", [])]
|
|
470
|
+
if primary_language in supported_languages:
|
|
471
|
+
match_reasons.append(
|
|
472
|
+
f"Primary language match: {toolchain.primary_language}"
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
# Check framework matches
|
|
476
|
+
detected_frameworks = [fw.name for fw in toolchain.frameworks]
|
|
477
|
+
supported_frameworks = supports.get("frameworks", [])
|
|
478
|
+
framework_matches = []
|
|
479
|
+
for fw in detected_frameworks:
|
|
480
|
+
for supported_fw in supported_frameworks:
|
|
481
|
+
if fw.lower().replace("-", "").replace(
|
|
482
|
+
".", ""
|
|
483
|
+
) == supported_fw.lower().replace("-", "").replace(".", ""):
|
|
484
|
+
framework_matches.append(fw)
|
|
485
|
+
break
|
|
486
|
+
|
|
487
|
+
if framework_matches:
|
|
488
|
+
match_reasons.append(f"Framework expertise: {', '.join(framework_matches)}")
|
|
489
|
+
|
|
490
|
+
# Check deployment target match
|
|
491
|
+
if toolchain.deployment_target:
|
|
492
|
+
supported_deployments = supports.get("deployment", [])
|
|
493
|
+
platform = toolchain.deployment_target.platform
|
|
494
|
+
if platform and any(
|
|
495
|
+
d.lower() == platform.lower() for d in supported_deployments
|
|
496
|
+
):
|
|
497
|
+
match_reasons.append(f"Deployment platform match: {platform}")
|
|
498
|
+
|
|
499
|
+
# Add concerns for low/medium confidence
|
|
500
|
+
if score < 0.6:
|
|
501
|
+
concerns.append(
|
|
502
|
+
"Moderate confidence - consider reviewing agent capabilities"
|
|
503
|
+
)
|
|
504
|
+
elif score < 0.8:
|
|
505
|
+
concerns.append("Good match but may benefit from additional configuration")
|
|
506
|
+
|
|
507
|
+
# If no specific matches found but score > 0, add general reason
|
|
508
|
+
if not match_reasons and score > 0:
|
|
509
|
+
match_reasons.append(
|
|
510
|
+
f"General {agent_config.get('specialization', 'agent')} capabilities"
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
return match_reasons, concerns
|
|
514
|
+
|
|
515
|
+
def _calculate_deployment_priority(
|
|
516
|
+
self, agent_config: Dict[str, Any], toolchain: ToolchainAnalysis
|
|
517
|
+
) -> int:
|
|
518
|
+
"""
|
|
519
|
+
Calculate deployment priority (lower = higher priority).
|
|
520
|
+
|
|
521
|
+
Priority rules:
|
|
522
|
+
- Framework-specific agents: Priority 1
|
|
523
|
+
- Language-specific engineers: Priority 2
|
|
524
|
+
- DevOps agents: Priority 3
|
|
525
|
+
- General agents: Priority 4
|
|
526
|
+
"""
|
|
527
|
+
specialization = agent_config.get("specialization", "general")
|
|
528
|
+
supports = agent_config.get("supports", {})
|
|
529
|
+
|
|
530
|
+
# Check if this is a framework-specific agent
|
|
531
|
+
framework_matches = False
|
|
532
|
+
if toolchain.frameworks:
|
|
533
|
+
detected_frameworks = [fw.name.lower() for fw in toolchain.frameworks]
|
|
534
|
+
supported_frameworks = [fw.lower() for fw in supports.get("frameworks", [])]
|
|
535
|
+
framework_matches = any(
|
|
536
|
+
fw in supported_frameworks for fw in detected_frameworks
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
if framework_matches and specialization == "engineering":
|
|
540
|
+
return 1 # Highest priority for framework-specific engineers
|
|
541
|
+
|
|
542
|
+
if specialization == "engineering":
|
|
543
|
+
return 2 # Language-specific engineers
|
|
544
|
+
|
|
545
|
+
if specialization == "devops":
|
|
546
|
+
return 3 # DevOps agents
|
|
547
|
+
|
|
548
|
+
return 4 # General agents (lowest priority)
|
|
549
|
+
|
|
550
|
+
def _generate_config_hints(
|
|
551
|
+
self, agent_config: Dict[str, Any], toolchain: ToolchainAnalysis
|
|
552
|
+
) -> Dict[str, Any]:
|
|
553
|
+
"""Generate configuration hints for the agent."""
|
|
554
|
+
hints = {}
|
|
555
|
+
|
|
556
|
+
# Add framework-specific hints
|
|
557
|
+
if toolchain.frameworks:
|
|
558
|
+
hints["detected_frameworks"] = [fw.name for fw in toolchain.frameworks]
|
|
559
|
+
|
|
560
|
+
# Add deployment hints
|
|
561
|
+
if toolchain.deployment_target:
|
|
562
|
+
hints["deployment_target"] = toolchain.deployment_target.platform
|
|
563
|
+
|
|
564
|
+
# Add build tool hints
|
|
565
|
+
if toolchain.build_tools:
|
|
566
|
+
hints["build_tools"] = [tool.name for tool in toolchain.build_tools]
|
|
567
|
+
|
|
568
|
+
return hints
|
|
@@ -36,6 +36,7 @@ from watchdog.events import FileSystemEvent, FileSystemEventHandler
|
|
|
36
36
|
from watchdog.observers import Observer
|
|
37
37
|
|
|
38
38
|
from claude_mpm.core.base_service import BaseService
|
|
39
|
+
from claude_mpm.core.enums import OperationResult
|
|
39
40
|
from claude_mpm.core.logging_utils import get_logger
|
|
40
41
|
from claude_mpm.core.unified_agent_registry import UnifiedAgentRegistry as AgentRegistry
|
|
41
42
|
from claude_mpm.core.unified_paths import get_path_manager
|
|
@@ -551,12 +552,14 @@ class AgentModificationTracker(BaseService):
|
|
|
551
552
|
errors.append(f"File does not exist: {modification.file_path}")
|
|
552
553
|
|
|
553
554
|
# Update validation status
|
|
554
|
-
modification.validation_status =
|
|
555
|
+
modification.validation_status = (
|
|
556
|
+
OperationResult.FAILED if errors else OperationResult.SUCCESS
|
|
557
|
+
)
|
|
555
558
|
modification.validation_errors = errors
|
|
556
559
|
|
|
557
560
|
except Exception as e:
|
|
558
561
|
self.logger.error(f"Validation error: {e}")
|
|
559
|
-
modification.validation_status =
|
|
562
|
+
modification.validation_status = OperationResult.ERROR
|
|
560
563
|
modification.validation_errors.append(str(e))
|
|
561
564
|
|
|
562
565
|
async def _invalidate_agent_cache(self, agent_name: str) -> None:
|
|
@@ -12,6 +12,7 @@ Extracted from ClaudeRunner to follow Single Responsibility Principle.
|
|
|
12
12
|
from typing import Any, Dict, List
|
|
13
13
|
|
|
14
14
|
from claude_mpm.core.base_service import BaseService
|
|
15
|
+
from claude_mpm.core.enums import OperationResult
|
|
15
16
|
from claude_mpm.services.core.interfaces import CommandHandlerInterface
|
|
16
17
|
|
|
17
18
|
|
|
@@ -169,7 +170,7 @@ class CommandHandlerService(BaseService, CommandHandlerInterface):
|
|
|
169
170
|
if command == "test":
|
|
170
171
|
success = self._handle_test_command(args)
|
|
171
172
|
return {
|
|
172
|
-
|
|
173
|
+
OperationResult.SUCCESS.value: success,
|
|
173
174
|
"command": command,
|
|
174
175
|
"args": args,
|
|
175
176
|
"message": (
|
|
@@ -179,7 +180,7 @@ class CommandHandlerService(BaseService, CommandHandlerInterface):
|
|
|
179
180
|
if command == "agents":
|
|
180
181
|
success = self._handle_agents_command(args)
|
|
181
182
|
return {
|
|
182
|
-
|
|
183
|
+
OperationResult.SUCCESS.value: success,
|
|
183
184
|
"command": command,
|
|
184
185
|
"args": args,
|
|
185
186
|
"message": (
|
|
@@ -189,14 +190,19 @@ class CommandHandlerService(BaseService, CommandHandlerInterface):
|
|
|
189
190
|
),
|
|
190
191
|
}
|
|
191
192
|
return {
|
|
192
|
-
|
|
193
|
+
OperationResult.SUCCESS.value: False,
|
|
193
194
|
"command": command,
|
|
194
195
|
"args": args,
|
|
195
|
-
|
|
196
|
+
OperationResult.ERROR.value: f"Unknown command: {command}",
|
|
196
197
|
"available_commands": self.get_available_commands(),
|
|
197
198
|
}
|
|
198
199
|
except Exception as e:
|
|
199
|
-
return {
|
|
200
|
+
return {
|
|
201
|
+
OperationResult.SUCCESS.value: False,
|
|
202
|
+
"command": command,
|
|
203
|
+
"args": args,
|
|
204
|
+
OperationResult.ERROR.value: str(e),
|
|
205
|
+
}
|
|
200
206
|
|
|
201
207
|
def get_command_help(self, command: str) -> str:
|
|
202
208
|
"""Get help text for a specific command.
|