claude-mpm 4.12.1__py3-none-any.whl → 4.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (38) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +110 -459
  3. claude_mpm/agents/templates/README.md +465 -0
  4. claude_mpm/agents/templates/circuit_breakers.md +638 -0
  5. claude_mpm/agents/templates/git_file_tracking.md +584 -0
  6. claude_mpm/agents/templates/pm_examples.md +474 -0
  7. claude_mpm/agents/templates/pm_red_flags.md +240 -0
  8. claude_mpm/agents/templates/response_format.md +583 -0
  9. claude_mpm/agents/templates/validation_templates.md +312 -0
  10. claude_mpm/cli/__init__.py +10 -0
  11. claude_mpm/cli/commands/agents.py +31 -0
  12. claude_mpm/cli/commands/agents_detect.py +380 -0
  13. claude_mpm/cli/commands/agents_recommend.py +309 -0
  14. claude_mpm/cli/commands/auto_configure.py +564 -0
  15. claude_mpm/cli/parsers/agents_parser.py +9 -0
  16. claude_mpm/cli/parsers/auto_configure_parser.py +253 -0
  17. claude_mpm/cli/parsers/base_parser.py +7 -0
  18. claude_mpm/core/log_manager.py +2 -0
  19. claude_mpm/services/agents/__init__.py +18 -5
  20. claude_mpm/services/agents/auto_config_manager.py +797 -0
  21. claude_mpm/services/agents/observers.py +547 -0
  22. claude_mpm/services/agents/recommender.py +568 -0
  23. claude_mpm/services/core/__init__.py +33 -1
  24. claude_mpm/services/core/interfaces/__init__.py +16 -1
  25. claude_mpm/services/core/interfaces/agent.py +184 -0
  26. claude_mpm/services/core/interfaces/project.py +121 -0
  27. claude_mpm/services/core/models/__init__.py +46 -0
  28. claude_mpm/services/core/models/agent_config.py +397 -0
  29. claude_mpm/services/core/models/toolchain.py +306 -0
  30. claude_mpm/services/project/__init__.py +23 -0
  31. claude_mpm/services/project/detection_strategies.py +719 -0
  32. claude_mpm/services/project/toolchain_analyzer.py +581 -0
  33. {claude_mpm-4.12.1.dist-info → claude_mpm-4.13.0.dist-info}/METADATA +1 -1
  34. {claude_mpm-4.12.1.dist-info → claude_mpm-4.13.0.dist-info}/RECORD +38 -18
  35. {claude_mpm-4.12.1.dist-info → claude_mpm-4.13.0.dist-info}/WHEEL +0 -0
  36. {claude_mpm-4.12.1.dist-info → claude_mpm-4.13.0.dist-info}/entry_points.txt +0 -0
  37. {claude_mpm-4.12.1.dist-info → claude_mpm-4.13.0.dist-info}/licenses/LICENSE +0 -0
  38. {claude_mpm-4.12.1.dist-info → claude_mpm-4.13.0.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
@@ -16,7 +16,9 @@ from .interfaces import ( # Core dependency injection; Configuration management
16
16
  CacheEntry,
17
17
  HealthStatus,
18
18
  HookServiceInterface,
19
+ IAgentRecommender,
19
20
  IAgentRegistry,
21
+ IAutoConfigManager,
20
22
  ICacheService,
21
23
  IConfigurationManager,
22
24
  IConfigurationService,
@@ -31,6 +33,7 @@ from .interfaces import ( # Core dependency injection; Configuration management
31
33
  IServiceLifecycle,
32
34
  IStructuredLogger,
33
35
  ITemplateManager,
36
+ IToolchainAnalyzer,
34
37
  MemoryServiceInterface,
35
38
  ProjectAnalyzerInterface,
36
39
  ServiceType,
@@ -38,8 +41,21 @@ from .interfaces import ( # Core dependency injection; Configuration management
38
41
  TemplateRenderContext,
39
42
  TicketManagerInterface,
40
43
  )
44
+ from .models import ( # Data models for services
45
+ AgentCapabilities,
46
+ AgentRecommendation,
47
+ ConfidenceLevel,
48
+ ConfigurationPreview,
49
+ ConfigurationResult,
50
+ DeploymentTarget,
51
+ Framework,
52
+ LanguageDetection,
53
+ ToolchainAnalysis,
54
+ ToolchainComponent,
55
+ ValidationResult,
56
+ )
41
57
 
42
- __all__ = [
58
+ __all__ = [ # noqa: RUF022 - Grouped by category with comments for clarity
43
59
  # Service interfaces
44
60
  "AgentDeploymentInterface",
45
61
  "AgentMetadata",
@@ -48,7 +64,9 @@ __all__ = [
48
64
  "CacheEntry",
49
65
  "HealthStatus",
50
66
  "HookServiceInterface",
67
+ "IAgentRecommender",
51
68
  "IAgentRegistry",
69
+ "IAutoConfigManager",
52
70
  "ICacheService",
53
71
  "IConfigurationManager",
54
72
  "IConfigurationService",
@@ -63,6 +81,7 @@ __all__ = [
63
81
  "IServiceLifecycle",
64
82
  "IStructuredLogger",
65
83
  "ITemplateManager",
84
+ "IToolchainAnalyzer",
66
85
  # Registry
67
86
  "InterfaceRegistry",
68
87
  "MemoryServiceInterface",
@@ -73,4 +92,17 @@ __all__ = [
73
92
  "SyncBaseService",
74
93
  "TemplateRenderContext",
75
94
  "TicketManagerInterface",
95
+ # Data models - Toolchain
96
+ "ConfidenceLevel",
97
+ "ToolchainComponent",
98
+ "LanguageDetection",
99
+ "Framework",
100
+ "DeploymentTarget",
101
+ "ToolchainAnalysis",
102
+ # Data models - Agent Configuration
103
+ "AgentCapabilities",
104
+ "AgentRecommendation",
105
+ "ConfigurationResult",
106
+ "ValidationResult",
107
+ "ConfigurationPreview",
76
108
  ]
@@ -24,11 +24,13 @@ MODULES:
24
24
  """
25
25
 
26
26
  # Agent interfaces (agent management and operations)
27
- from .agent import ( # Agent registry; Agent deployment; Agent capabilities; System instructions; Subprocess management; Runner configuration
27
+ from .agent import ( # Agent registry; Agent deployment; Agent capabilities; System instructions; Subprocess management; Runner configuration; Agent recommendation; Auto-configuration
28
28
  AgentCapabilitiesInterface,
29
29
  AgentDeploymentInterface,
30
30
  AgentMetadata,
31
+ IAgentRecommender,
31
32
  IAgentRegistry,
33
+ IAutoConfigManager,
32
34
  RunnerConfigurationInterface,
33
35
  SubprocessLauncherInterface,
34
36
  SystemInstructionsInterface,
@@ -63,6 +65,11 @@ from .infrastructure import ( # Type variables; Core dependency injection; Conf
63
65
  TemplateRenderContext,
64
66
  )
65
67
 
68
+ # Project interfaces (project analysis and toolchain detection)
69
+ from .project import ( # Toolchain analysis
70
+ IToolchainAnalyzer,
71
+ )
72
+
66
73
  # Service interfaces (business services)
67
74
  from .service import ( # Version service; Command handling; Memory management; Session management; Utilities; Hook service
68
75
  CommandHandlerInterface,
@@ -118,6 +125,10 @@ class InterfaceRegistry:
118
125
  "socketio_service": SocketIOServiceInterface,
119
126
  "project_analyzer": ProjectAnalyzerInterface,
120
127
  "ticket_manager": TicketManagerInterface,
128
+ # Project interfaces
129
+ "toolchain_analyzer": IToolchainAnalyzer,
130
+ "agent_recommender": IAgentRecommender,
131
+ "auto_config_manager": IAutoConfigManager,
121
132
  }
122
133
 
123
134
  @classmethod
@@ -151,7 +162,9 @@ __all__ = [
151
162
  "HealthStatus",
152
163
  "HookServiceInterface",
153
164
  # Agent interfaces
165
+ "IAgentRecommender",
154
166
  "IAgentRegistry",
167
+ "IAutoConfigManager",
155
168
  "ICacheService",
156
169
  "IConfigurationManager",
157
170
  "IConfigurationService",
@@ -166,6 +179,8 @@ __all__ = [
166
179
  "IServiceLifecycle",
167
180
  "IStructuredLogger",
168
181
  "ITemplateManager",
182
+ # Project interfaces
183
+ "IToolchainAnalyzer",
169
184
  # Registry
170
185
  "InterfaceRegistry",
171
186
  "MemoryHookInterface",