claude-mpm 5.0.2__py3-none-any.whl → 5.1.9__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1176 -909
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/frontmatter_validator.py +68 -0
- claude_mpm/agents/templates/circuit-breakers.md +293 -44
- claude_mpm/cli/__init__.py +0 -1
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_state_manager.py +64 -11
- claude_mpm/cli/commands/agents.py +446 -25
- claude_mpm/cli/commands/auto_configure.py +535 -233
- claude_mpm/cli/commands/configure.py +545 -89
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +1 -39
- claude_mpm/cli/commands/skills.py +322 -19
- claude_mpm/cli/interactive/agent_wizard.py +302 -195
- claude_mpm/cli/parsers/agents_parser.py +137 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
- claude_mpm/cli/parsers/base_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +7 -0
- claude_mpm/cli/startup.py +73 -32
- claude_mpm/commands/mpm-agents-auto-configure.md +2 -2
- claude_mpm/commands/mpm-agents-list.md +2 -2
- claude_mpm/commands/mpm-config-view.md +2 -2
- claude_mpm/commands/mpm-help.md +3 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/mpm-session-resume.md +2 -2
- claude_mpm/commands/mpm-ticket-organize.md +2 -2
- claude_mpm/commands/mpm-ticket-view.md +2 -2
- claude_mpm/config/agent_presets.py +312 -82
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -25
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/interactive_session.py +19 -5
- claude_mpm/core/oneshot_session.py +16 -4
- claude_mpm/core/output_style_manager.py +173 -43
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_agent_registry.py +129 -1
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
- claude_mpm/models/agent_definition.py +7 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +110 -3
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +195 -1
- claude_mpm/services/agents/sources/git_source_sync_service.py +37 -5
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/command_deployment_service.py +108 -5
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/git/git_operations_service.py +8 -8
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/monitor/daemon.py +28 -8
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/runner_configuration_service.py +16 -3
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/gitignore.py +3 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +5 -1
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/METADATA +69 -8
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/RECORD +76 -62
- /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/WHEEL +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.0.2.dist-info → claude_mpm-5.1.9.dist-info}/top_level.txt +0 -0
|
@@ -3,13 +3,16 @@ Auto-Configuration CLI Command for Claude MPM Framework
|
|
|
3
3
|
========================================================
|
|
4
4
|
|
|
5
5
|
WHY: This module provides a user-friendly CLI interface for the auto-configuration
|
|
6
|
-
feature, allowing users to automatically configure agents based on
|
|
6
|
+
feature, allowing users to automatically configure BOTH agents AND skills based on
|
|
7
|
+
detected toolchain.
|
|
7
8
|
|
|
8
9
|
DESIGN DECISION: Uses rich for beautiful terminal output, implements interactive
|
|
9
10
|
confirmation, and provides comprehensive error handling. Supports both interactive
|
|
10
|
-
and non-interactive modes for flexibility.
|
|
11
|
+
and non-interactive modes for flexibility. Orchestrates both agent auto-config
|
|
12
|
+
(via AutoConfigManagerService) and skill recommendations (via SkillsDeployer).
|
|
11
13
|
|
|
12
14
|
Part of TSK-0054: Auto-Configuration Feature - Phase 5
|
|
15
|
+
Unified Auto-Configure: 1M-502 Phase 2
|
|
13
16
|
"""
|
|
14
17
|
|
|
15
18
|
import json
|
|
@@ -29,7 +32,6 @@ except ImportError:
|
|
|
29
32
|
from ...core.enums import OperationResult
|
|
30
33
|
from ...services.agents.auto_config_manager import AutoConfigManagerService
|
|
31
34
|
from ...services.agents.observers import NullObserver
|
|
32
|
-
from ...services.core.models.agent_config import ConfigurationResult
|
|
33
35
|
from ..shared import BaseCommand, CommandResult
|
|
34
36
|
|
|
35
37
|
|
|
@@ -100,7 +102,11 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
100
102
|
Handle auto-configuration CLI commands.
|
|
101
103
|
|
|
102
104
|
This command provides a user-friendly interface for automatically configuring
|
|
103
|
-
agents based on detected project toolchain.
|
|
105
|
+
BOTH agents AND skills based on detected project toolchain.
|
|
106
|
+
|
|
107
|
+
Orchestrates:
|
|
108
|
+
1. Agent auto-configuration (via AutoConfigManagerService)
|
|
109
|
+
2. Skills recommendations and deployment (via SkillsDeployer + agent-skill mapping)
|
|
104
110
|
"""
|
|
105
111
|
|
|
106
112
|
def __init__(self):
|
|
@@ -108,6 +114,7 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
108
114
|
super().__init__("auto-configure")
|
|
109
115
|
self.console = Console() if RICH_AVAILABLE else None
|
|
110
116
|
self._auto_config_manager = None
|
|
117
|
+
self._skills_deployer = None
|
|
111
118
|
|
|
112
119
|
@property
|
|
113
120
|
def auto_config_manager(self) -> AutoConfigManagerService:
|
|
@@ -140,6 +147,15 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
140
147
|
|
|
141
148
|
return self._auto_config_manager
|
|
142
149
|
|
|
150
|
+
@property
|
|
151
|
+
def skills_deployer(self):
|
|
152
|
+
"""Get skills deployer instance (lazy loaded)."""
|
|
153
|
+
if self._skills_deployer is None:
|
|
154
|
+
from ...services.skills_deployer import SkillsDeployerService
|
|
155
|
+
|
|
156
|
+
self._skills_deployer = SkillsDeployerService()
|
|
157
|
+
return self._skills_deployer
|
|
158
|
+
|
|
143
159
|
def validate_args(self, args) -> Optional[str]:
|
|
144
160
|
"""Validate command arguments."""
|
|
145
161
|
# Validate project path
|
|
@@ -191,11 +207,26 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
191
207
|
skip_confirmation = args.yes if hasattr(args, "yes") and args.yes else False
|
|
192
208
|
json_output = args.json if hasattr(args, "json") and args.json else False
|
|
193
209
|
|
|
210
|
+
# Determine what to configure (agents, skills, or both)
|
|
211
|
+
configure_agents = not getattr(args, "skills_only", False)
|
|
212
|
+
configure_skills = not getattr(args, "agents_only", False)
|
|
213
|
+
|
|
194
214
|
# Run preview or full configuration
|
|
195
215
|
if dry_run or args.preview if hasattr(args, "preview") else False:
|
|
196
|
-
return self._run_preview(
|
|
216
|
+
return self._run_preview(
|
|
217
|
+
project_path,
|
|
218
|
+
min_confidence,
|
|
219
|
+
json_output,
|
|
220
|
+
configure_agents,
|
|
221
|
+
configure_skills,
|
|
222
|
+
)
|
|
197
223
|
return self._run_full_configuration(
|
|
198
|
-
project_path,
|
|
224
|
+
project_path,
|
|
225
|
+
min_confidence,
|
|
226
|
+
skip_confirmation,
|
|
227
|
+
json_output,
|
|
228
|
+
configure_agents,
|
|
229
|
+
configure_skills,
|
|
199
230
|
)
|
|
200
231
|
|
|
201
232
|
except KeyboardInterrupt:
|
|
@@ -215,24 +246,47 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
215
246
|
return CommandResult.error_result(error_msg)
|
|
216
247
|
|
|
217
248
|
def _run_preview(
|
|
218
|
-
self,
|
|
249
|
+
self,
|
|
250
|
+
project_path: Path,
|
|
251
|
+
min_confidence: float,
|
|
252
|
+
json_output: bool,
|
|
253
|
+
configure_agents: bool = True,
|
|
254
|
+
configure_skills: bool = True,
|
|
219
255
|
) -> CommandResult:
|
|
220
256
|
"""Run configuration preview without deploying."""
|
|
221
|
-
#
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
257
|
+
# Get agent preview
|
|
258
|
+
agent_preview = None
|
|
259
|
+
if configure_agents:
|
|
260
|
+
if self.console and not json_output:
|
|
261
|
+
with self.console.status("[bold green]Analyzing project toolchain..."):
|
|
262
|
+
agent_preview = self.auto_config_manager.preview_configuration(
|
|
263
|
+
project_path, min_confidence
|
|
264
|
+
)
|
|
265
|
+
else:
|
|
266
|
+
agent_preview = self.auto_config_manager.preview_configuration(
|
|
225
267
|
project_path, min_confidence
|
|
226
268
|
)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
269
|
+
|
|
270
|
+
# Get skills recommendations
|
|
271
|
+
skills_recommendations = None
|
|
272
|
+
if configure_skills:
|
|
273
|
+
if self.console and not json_output:
|
|
274
|
+
with self.console.status("[bold green]Analyzing skill requirements..."):
|
|
275
|
+
skills_recommendations = self._recommend_skills(agent_preview)
|
|
276
|
+
else:
|
|
277
|
+
skills_recommendations = self._recommend_skills(agent_preview)
|
|
231
278
|
|
|
232
279
|
# Output results
|
|
233
280
|
if json_output:
|
|
234
|
-
return self._output_preview_json(
|
|
235
|
-
|
|
281
|
+
return self._output_preview_json(
|
|
282
|
+
agent_preview,
|
|
283
|
+
skills_recommendations,
|
|
284
|
+
configure_agents,
|
|
285
|
+
configure_skills,
|
|
286
|
+
)
|
|
287
|
+
return self._display_preview(
|
|
288
|
+
agent_preview, skills_recommendations, configure_agents, configure_skills
|
|
289
|
+
)
|
|
236
290
|
|
|
237
291
|
def _run_full_configuration(
|
|
238
292
|
self,
|
|
@@ -240,147 +294,251 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
240
294
|
min_confidence: float,
|
|
241
295
|
skip_confirmation: bool,
|
|
242
296
|
json_output: bool,
|
|
297
|
+
configure_agents: bool = True,
|
|
298
|
+
configure_skills: bool = True,
|
|
243
299
|
) -> CommandResult:
|
|
244
300
|
"""Run full auto-configuration with deployment."""
|
|
245
|
-
# Get preview
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
301
|
+
# Get agent preview
|
|
302
|
+
agent_preview = None
|
|
303
|
+
if configure_agents:
|
|
304
|
+
if self.console and not json_output:
|
|
305
|
+
with self.console.status("[bold green]Analyzing project toolchain..."):
|
|
306
|
+
agent_preview = self.auto_config_manager.preview_configuration(
|
|
307
|
+
project_path, min_confidence
|
|
308
|
+
)
|
|
309
|
+
else:
|
|
310
|
+
agent_preview = self.auto_config_manager.preview_configuration(
|
|
249
311
|
project_path, min_confidence
|
|
250
312
|
)
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
313
|
+
|
|
314
|
+
# Get skills recommendations
|
|
315
|
+
skills_recommendations = None
|
|
316
|
+
if configure_skills:
|
|
317
|
+
if self.console and not json_output:
|
|
318
|
+
with self.console.status("[bold green]Analyzing skill requirements..."):
|
|
319
|
+
skills_recommendations = self._recommend_skills(agent_preview)
|
|
320
|
+
else:
|
|
321
|
+
skills_recommendations = self._recommend_skills(agent_preview)
|
|
255
322
|
|
|
256
323
|
# Display preview (unless JSON output)
|
|
257
324
|
if not json_output:
|
|
258
|
-
self._display_preview(
|
|
325
|
+
self._display_preview(
|
|
326
|
+
agent_preview,
|
|
327
|
+
skills_recommendations,
|
|
328
|
+
configure_agents,
|
|
329
|
+
configure_skills,
|
|
330
|
+
)
|
|
259
331
|
|
|
260
332
|
# Ask for confirmation (unless skipped)
|
|
261
333
|
if not skip_confirmation and not json_output:
|
|
262
|
-
if not self._confirm_deployment(
|
|
334
|
+
if not self._confirm_deployment(
|
|
335
|
+
agent_preview,
|
|
336
|
+
skills_recommendations,
|
|
337
|
+
configure_agents,
|
|
338
|
+
configure_skills,
|
|
339
|
+
):
|
|
263
340
|
if self.console:
|
|
264
341
|
self.console.print("\n❌ Operation cancelled by user")
|
|
265
342
|
else:
|
|
266
343
|
print("\nOperation cancelled by user")
|
|
267
344
|
return CommandResult.error_result("Operation cancelled", exit_code=0)
|
|
268
345
|
|
|
269
|
-
# Execute configuration
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
self.
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
346
|
+
# Execute agent configuration
|
|
347
|
+
agent_result = None
|
|
348
|
+
if configure_agents and agent_preview:
|
|
349
|
+
import asyncio
|
|
350
|
+
|
|
351
|
+
observer = RichProgressObserver(self.console) if self.console else None
|
|
352
|
+
agent_result = asyncio.run(
|
|
353
|
+
self.auto_config_manager.auto_configure(
|
|
354
|
+
project_path,
|
|
355
|
+
confirmation_required=False, # Already confirmed above
|
|
356
|
+
dry_run=False,
|
|
357
|
+
min_confidence=min_confidence,
|
|
358
|
+
observer=observer,
|
|
359
|
+
)
|
|
280
360
|
)
|
|
281
|
-
|
|
361
|
+
|
|
362
|
+
# Deploy skills
|
|
363
|
+
skills_result = None
|
|
364
|
+
if configure_skills and skills_recommendations:
|
|
365
|
+
if self.console and not json_output:
|
|
366
|
+
self.console.print("\n[bold cyan]Deploying skills...[/bold cyan]\n")
|
|
367
|
+
skills_result = self._deploy_skills(skills_recommendations)
|
|
282
368
|
|
|
283
369
|
# Output results
|
|
284
370
|
if json_output:
|
|
285
|
-
return self._output_result_json(
|
|
286
|
-
return self._display_result(
|
|
371
|
+
return self._output_result_json(agent_result, skills_result)
|
|
372
|
+
return self._display_result(agent_result, skills_result)
|
|
287
373
|
|
|
288
|
-
def _display_preview(
|
|
374
|
+
def _display_preview(
|
|
375
|
+
self,
|
|
376
|
+
agent_preview,
|
|
377
|
+
skills_recommendations=None,
|
|
378
|
+
configure_agents=True,
|
|
379
|
+
configure_skills=True,
|
|
380
|
+
) -> CommandResult:
|
|
289
381
|
"""Display configuration preview with Rich formatting."""
|
|
290
382
|
if not self.console:
|
|
291
383
|
# Fallback to plain text
|
|
292
|
-
return self._display_preview_plain(
|
|
384
|
+
return self._display_preview_plain(
|
|
385
|
+
agent_preview,
|
|
386
|
+
skills_recommendations,
|
|
387
|
+
configure_agents,
|
|
388
|
+
configure_skills,
|
|
389
|
+
)
|
|
293
390
|
|
|
294
|
-
#
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
toolchain_table = Table(show_header=True, header_style="bold")
|
|
298
|
-
toolchain_table.add_column("Component", style="cyan")
|
|
299
|
-
toolchain_table.add_column("Version", style="yellow")
|
|
300
|
-
toolchain_table.add_column("Confidence", style="green")
|
|
301
|
-
|
|
302
|
-
for component in preview.detected_toolchain.components:
|
|
303
|
-
confidence_pct = int(component.confidence * 100)
|
|
304
|
-
bar = "█" * (confidence_pct // 10) + "░" * (10 - confidence_pct // 10)
|
|
305
|
-
confidence_str = f"{bar} {confidence_pct}%"
|
|
306
|
-
|
|
307
|
-
toolchain_table.add_row(
|
|
308
|
-
(
|
|
309
|
-
component.type.value
|
|
310
|
-
if hasattr(component.type, "value")
|
|
311
|
-
else str(component.type)
|
|
312
|
-
),
|
|
313
|
-
component.version or "Unknown",
|
|
314
|
-
confidence_str,
|
|
315
|
-
)
|
|
391
|
+
# Only show toolchain and agents if configuring agents
|
|
392
|
+
if not configure_agents:
|
|
393
|
+
agent_preview = None
|
|
316
394
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
self.console.print("
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
self.console.print(
|
|
395
|
+
# Display detected toolchain
|
|
396
|
+
if configure_agents and agent_preview:
|
|
397
|
+
self.console.print("\n📊 Detected Toolchain:", style="bold blue")
|
|
398
|
+
if (
|
|
399
|
+
agent_preview.detected_toolchain
|
|
400
|
+
and agent_preview.detected_toolchain.components
|
|
401
|
+
):
|
|
402
|
+
toolchain_table = Table(show_header=True, header_style="bold")
|
|
403
|
+
toolchain_table.add_column("Component", style="cyan")
|
|
404
|
+
toolchain_table.add_column("Version", style="yellow")
|
|
405
|
+
toolchain_table.add_column("Confidence", style="green")
|
|
406
|
+
|
|
407
|
+
for component in agent_preview.detected_toolchain.components:
|
|
408
|
+
confidence_pct = int(component.confidence * 100)
|
|
409
|
+
bar = "█" * (confidence_pct // 10) + "░" * (
|
|
410
|
+
10 - confidence_pct // 10
|
|
411
|
+
)
|
|
412
|
+
confidence_str = f"{bar} {confidence_pct}%"
|
|
413
|
+
|
|
414
|
+
toolchain_table.add_row(
|
|
415
|
+
(
|
|
416
|
+
component.type.value
|
|
417
|
+
if hasattr(component.type, "value")
|
|
418
|
+
else str(component.type)
|
|
419
|
+
),
|
|
420
|
+
component.version or "Unknown",
|
|
421
|
+
confidence_str,
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
self.console.print(toolchain_table)
|
|
425
|
+
else:
|
|
426
|
+
self.console.print(" No toolchain detected", style="yellow")
|
|
427
|
+
|
|
428
|
+
# Display recommended agents
|
|
429
|
+
self.console.print("\n🤖 Recommended Agents:", style="bold blue")
|
|
430
|
+
if agent_preview.recommendations:
|
|
431
|
+
for rec in agent_preview.recommendations:
|
|
432
|
+
confidence_pct = int(rec.confidence * 100)
|
|
433
|
+
icon = "✓" if rec.confidence >= 0.8 else "○"
|
|
434
|
+
self.console.print(
|
|
435
|
+
f" {icon} [bold]{rec.agent_id}[/bold] ({confidence_pct}% confidence)"
|
|
436
|
+
)
|
|
437
|
+
self.console.print(f" Reason: {rec.reasoning}", style="dim")
|
|
438
|
+
else:
|
|
439
|
+
self.console.print(" No agents recommended", style="yellow")
|
|
440
|
+
|
|
441
|
+
# Display validation issues
|
|
442
|
+
if (
|
|
443
|
+
agent_preview.validation_result
|
|
444
|
+
and agent_preview.validation_result.issues
|
|
445
|
+
):
|
|
446
|
+
self.console.print("\n⚠️ Validation Issues:", style="bold yellow")
|
|
447
|
+
for issue in agent_preview.validation_result.issues:
|
|
448
|
+
severity_icon = {"error": "❌", "warning": "⚠️", "info": "ℹ️"}.get(
|
|
449
|
+
(
|
|
450
|
+
issue.severity.value
|
|
451
|
+
if hasattr(issue.severity, "value")
|
|
452
|
+
else str(issue.severity)
|
|
453
|
+
),
|
|
454
|
+
"•",
|
|
455
|
+
)
|
|
456
|
+
self.console.print(
|
|
457
|
+
f" {severity_icon} {issue.message}", style="yellow"
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
# Display recommended skills
|
|
461
|
+
if configure_skills and skills_recommendations:
|
|
462
|
+
self.console.print("\n🎯 Recommended Skills:", style="bold blue")
|
|
463
|
+
for skill in skills_recommendations:
|
|
464
|
+
self.console.print(f" ✓ [bold]{skill}[/bold]")
|
|
347
465
|
|
|
348
466
|
return CommandResult.success_result()
|
|
349
467
|
|
|
350
|
-
def _display_preview_plain(
|
|
468
|
+
def _display_preview_plain(
|
|
469
|
+
self,
|
|
470
|
+
agent_preview,
|
|
471
|
+
skills_recommendations=None,
|
|
472
|
+
configure_agents=True,
|
|
473
|
+
configure_skills=True,
|
|
474
|
+
) -> CommandResult:
|
|
351
475
|
"""Display preview in plain text (fallback when Rich not available)."""
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
print(
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
476
|
+
if configure_agents and agent_preview:
|
|
477
|
+
print("\nDetected Toolchain:")
|
|
478
|
+
if (
|
|
479
|
+
agent_preview.detected_toolchain
|
|
480
|
+
and agent_preview.detected_toolchain.components
|
|
481
|
+
):
|
|
482
|
+
for component in agent_preview.detected_toolchain.components:
|
|
483
|
+
confidence_pct = int(component.confidence * 100)
|
|
484
|
+
print(
|
|
485
|
+
f" - {component.type}: {component.version} ({confidence_pct}%)"
|
|
486
|
+
)
|
|
487
|
+
else:
|
|
488
|
+
print(" No toolchain detected")
|
|
489
|
+
|
|
490
|
+
print("\nRecommended Agents:")
|
|
491
|
+
if agent_preview.recommendations:
|
|
492
|
+
for rec in agent_preview.recommendations:
|
|
493
|
+
confidence_pct = int(rec.confidence * 100)
|
|
494
|
+
print(f" - {rec.agent_id} ({confidence_pct}%)")
|
|
495
|
+
print(f" Reason: {rec.reasoning}")
|
|
496
|
+
else:
|
|
497
|
+
print(" No agents recommended")
|
|
368
498
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
499
|
+
if (
|
|
500
|
+
agent_preview.validation_result
|
|
501
|
+
and agent_preview.validation_result.issues
|
|
502
|
+
):
|
|
503
|
+
print("\nValidation Issues:")
|
|
504
|
+
for issue in agent_preview.validation_result.issues:
|
|
505
|
+
print(f" - {issue.severity}: {issue.message}")
|
|
506
|
+
|
|
507
|
+
if configure_skills and skills_recommendations:
|
|
508
|
+
print("\nRecommended Skills:")
|
|
509
|
+
for skill in skills_recommendations:
|
|
510
|
+
print(f" - {skill}")
|
|
373
511
|
|
|
374
512
|
return CommandResult.success_result()
|
|
375
513
|
|
|
376
|
-
def _confirm_deployment(
|
|
514
|
+
def _confirm_deployment(
|
|
515
|
+
self,
|
|
516
|
+
agent_preview,
|
|
517
|
+
skills_recommendations=None,
|
|
518
|
+
configure_agents=True,
|
|
519
|
+
configure_skills=True,
|
|
520
|
+
) -> bool:
|
|
377
521
|
"""Ask user to confirm deployment."""
|
|
378
|
-
|
|
522
|
+
has_agents = (
|
|
523
|
+
configure_agents and agent_preview and agent_preview.recommendations
|
|
524
|
+
)
|
|
525
|
+
has_skills = configure_skills and skills_recommendations
|
|
526
|
+
|
|
527
|
+
if not has_agents and not has_skills:
|
|
379
528
|
return False
|
|
380
529
|
|
|
530
|
+
# Build confirmation message
|
|
531
|
+
items = []
|
|
532
|
+
if has_agents:
|
|
533
|
+
items.append(f"{len(agent_preview.recommendations)} agent(s)")
|
|
534
|
+
if has_skills:
|
|
535
|
+
items.append(f"{len(skills_recommendations)} skill(s)")
|
|
536
|
+
|
|
537
|
+
message = f"Deploy {' and '.join(items)}?"
|
|
538
|
+
|
|
381
539
|
if self.console:
|
|
382
540
|
self.console.print("\n" + "=" * 60)
|
|
383
|
-
self.console.print(
|
|
541
|
+
self.console.print(message, style="bold yellow")
|
|
384
542
|
self.console.print("=" * 60)
|
|
385
543
|
response = (
|
|
386
544
|
self.console.input("\n[bold]Proceed? (y/n/s for select):[/bold] ")
|
|
@@ -389,7 +547,7 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
389
547
|
)
|
|
390
548
|
else:
|
|
391
549
|
print("\n" + "=" * 60)
|
|
392
|
-
print(
|
|
550
|
+
print(message)
|
|
393
551
|
print("=" * 60)
|
|
394
552
|
response = input("\nProceed? (y/n/s for select): ").strip().lower()
|
|
395
553
|
|
|
@@ -407,160 +565,304 @@ class AutoConfigureCommand(BaseCommand):
|
|
|
407
565
|
return False
|
|
408
566
|
return False
|
|
409
567
|
|
|
410
|
-
def _display_result(
|
|
568
|
+
def _display_result(
|
|
569
|
+
self, agent_result: Optional = None, skills_result: Optional[dict] = None
|
|
570
|
+
) -> CommandResult:
|
|
411
571
|
"""Display configuration result."""
|
|
412
572
|
if not self.console:
|
|
413
|
-
return self._display_result_plain(
|
|
573
|
+
return self._display_result_plain(agent_result, skills_result)
|
|
574
|
+
|
|
575
|
+
# Determine overall success
|
|
576
|
+
agent_success = (
|
|
577
|
+
(agent_result and agent_result.status == OperationResult.SUCCESS)
|
|
578
|
+
if agent_result
|
|
579
|
+
else True
|
|
580
|
+
)
|
|
581
|
+
skills_success = not skills_result or (
|
|
582
|
+
skills_result and not skills_result.get("errors")
|
|
583
|
+
)
|
|
584
|
+
overall_success = agent_success and skills_success
|
|
414
585
|
|
|
415
586
|
# Display summary
|
|
416
|
-
if
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
587
|
+
if overall_success:
|
|
588
|
+
# Build summary message
|
|
589
|
+
deployed_items = []
|
|
590
|
+
if agent_result and agent_result.deployed_agents:
|
|
591
|
+
deployed_items.append(f"{len(agent_result.deployed_agents)} agent(s)")
|
|
592
|
+
if skills_result and skills_result.get("deployed"):
|
|
593
|
+
deployed_items.append(f"{len(skills_result['deployed'])} skill(s)")
|
|
594
|
+
|
|
595
|
+
panel_text = "✅ Auto-configuration completed successfully!\n\n"
|
|
596
|
+
if deployed_items:
|
|
597
|
+
panel_text += f"Deployed {' and '.join(deployed_items)}"
|
|
598
|
+
else:
|
|
599
|
+
panel_text += "No deployments needed"
|
|
600
|
+
|
|
601
|
+
panel = Panel(panel_text, title="Success", border_style="green")
|
|
423
602
|
self.console.print(panel)
|
|
424
603
|
|
|
425
604
|
# Show deployed agents
|
|
426
|
-
if
|
|
605
|
+
if agent_result and agent_result.deployed_agents:
|
|
427
606
|
self.console.print("\n📦 Deployed Agents:", style="bold green")
|
|
428
|
-
for agent_id in
|
|
607
|
+
for agent_id in agent_result.deployed_agents:
|
|
429
608
|
self.console.print(f" ✓ {agent_id}")
|
|
430
609
|
|
|
610
|
+
# Show deployed skills
|
|
611
|
+
if skills_result and skills_result.get("deployed"):
|
|
612
|
+
self.console.print("\n🎯 Deployed Skills:", style="bold green")
|
|
613
|
+
for skill in skills_result["deployed"]:
|
|
614
|
+
self.console.print(f" ✓ {skill}")
|
|
615
|
+
|
|
431
616
|
return CommandResult.success_result()
|
|
432
617
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
)
|
|
441
|
-
self.console.print(panel)
|
|
618
|
+
# Partial or complete failure
|
|
619
|
+
has_errors = False
|
|
620
|
+
if agent_result and agent_result.status in [
|
|
621
|
+
OperationResult.WARNING,
|
|
622
|
+
OperationResult.FAILED,
|
|
623
|
+
]:
|
|
624
|
+
has_errors = True
|
|
442
625
|
|
|
443
|
-
if
|
|
626
|
+
if agent_result.status == OperationResult.WARNING:
|
|
627
|
+
self.console.print(
|
|
628
|
+
"\n⚠️ Agent configuration partially completed", style="yellow"
|
|
629
|
+
)
|
|
630
|
+
else:
|
|
631
|
+
self.console.print("\n❌ Agent configuration failed", style="red")
|
|
632
|
+
|
|
633
|
+
if agent_result.failed_agents:
|
|
444
634
|
self.console.print("\n❌ Failed Agents:", style="bold red")
|
|
445
|
-
for agent_id in
|
|
446
|
-
error =
|
|
635
|
+
for agent_id in agent_result.failed_agents:
|
|
636
|
+
error = agent_result.errors.get(agent_id, "Unknown error")
|
|
447
637
|
self.console.print(f" ✗ {agent_id}: {error}")
|
|
448
638
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
639
|
+
if skills_result and skills_result.get("errors"):
|
|
640
|
+
has_errors = True
|
|
641
|
+
self.console.print("\n❌ Skill deployment failed", style="red")
|
|
642
|
+
for error in skills_result["errors"]:
|
|
643
|
+
self.console.print(f" ✗ {error}")
|
|
644
|
+
|
|
645
|
+
return (
|
|
646
|
+
CommandResult.error_result(
|
|
647
|
+
"Configuration partially succeeded"
|
|
648
|
+
if (agent_success or skills_success)
|
|
649
|
+
else "Configuration failed",
|
|
650
|
+
exit_code=1,
|
|
651
|
+
)
|
|
652
|
+
if has_errors
|
|
653
|
+
else CommandResult.success_result()
|
|
455
654
|
)
|
|
456
|
-
self.console.print(panel)
|
|
457
|
-
|
|
458
|
-
return CommandResult.error_result("Configuration failed", exit_code=1)
|
|
459
655
|
|
|
460
|
-
def _display_result_plain(
|
|
656
|
+
def _display_result_plain(
|
|
657
|
+
self, agent_result: Optional = None, skills_result: Optional[dict] = None
|
|
658
|
+
) -> CommandResult:
|
|
461
659
|
"""Display result in plain text (fallback)."""
|
|
462
|
-
|
|
660
|
+
# Determine overall success
|
|
661
|
+
agent_success = (
|
|
662
|
+
(agent_result and agent_result.status == OperationResult.SUCCESS)
|
|
663
|
+
if agent_result
|
|
664
|
+
else True
|
|
665
|
+
)
|
|
666
|
+
skills_success = not skills_result or not skills_result.get("errors")
|
|
667
|
+
overall_success = agent_success and skills_success
|
|
668
|
+
|
|
669
|
+
if overall_success:
|
|
463
670
|
print("\n✅ Auto-configuration completed successfully!")
|
|
464
|
-
print(f"Deployed {len(result.deployed_agents)} agent(s)")
|
|
465
671
|
|
|
466
|
-
if
|
|
672
|
+
if agent_result and agent_result.deployed_agents:
|
|
673
|
+
print(f"Deployed {len(agent_result.deployed_agents)} agent(s)")
|
|
467
674
|
print("\nDeployed Agents:")
|
|
468
|
-
for agent_id in
|
|
675
|
+
for agent_id in agent_result.deployed_agents:
|
|
469
676
|
print(f" - {agent_id}")
|
|
470
677
|
|
|
678
|
+
if skills_result and skills_result.get("deployed"):
|
|
679
|
+
print(f"\nDeployed {len(skills_result['deployed'])} skill(s)")
|
|
680
|
+
print("\nDeployed Skills:")
|
|
681
|
+
for skill in skills_result["deployed"]:
|
|
682
|
+
print(f" - {skill}")
|
|
683
|
+
|
|
471
684
|
return CommandResult.success_result()
|
|
472
685
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
686
|
+
# Partial or complete failure
|
|
687
|
+
has_errors = False
|
|
688
|
+
if agent_result and agent_result.status in [
|
|
689
|
+
OperationResult.WARNING,
|
|
690
|
+
OperationResult.FAILED,
|
|
691
|
+
]:
|
|
692
|
+
has_errors = True
|
|
693
|
+
print(
|
|
694
|
+
"\n⚠️ Agent configuration partially completed"
|
|
695
|
+
if agent_result.status == OperationResult.WARNING
|
|
696
|
+
else "\n❌ Agent configuration failed"
|
|
697
|
+
)
|
|
477
698
|
|
|
478
|
-
if
|
|
699
|
+
if agent_result.failed_agents:
|
|
479
700
|
print("\nFailed Agents:")
|
|
480
|
-
for agent_id in
|
|
481
|
-
error =
|
|
701
|
+
for agent_id in agent_result.failed_agents:
|
|
702
|
+
error = agent_result.errors.get(agent_id, "Unknown error")
|
|
482
703
|
print(f" - {agent_id}: {error}")
|
|
483
704
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
705
|
+
if skills_result and skills_result.get("errors"):
|
|
706
|
+
has_errors = True
|
|
707
|
+
print("\n❌ Skill deployment failed")
|
|
708
|
+
for error in skills_result["errors"]:
|
|
709
|
+
print(f" - {error}")
|
|
710
|
+
|
|
711
|
+
return (
|
|
712
|
+
CommandResult.error_result(
|
|
713
|
+
"Configuration partially succeeded"
|
|
714
|
+
if (agent_success or skills_success)
|
|
715
|
+
else "Configuration failed",
|
|
716
|
+
exit_code=1,
|
|
717
|
+
)
|
|
718
|
+
if has_errors
|
|
719
|
+
else CommandResult.success_result()
|
|
720
|
+
)
|
|
490
721
|
|
|
491
|
-
def _output_preview_json(
|
|
722
|
+
def _output_preview_json(
|
|
723
|
+
self,
|
|
724
|
+
agent_preview,
|
|
725
|
+
skills_recommendations=None,
|
|
726
|
+
configure_agents=True,
|
|
727
|
+
configure_skills=True,
|
|
728
|
+
) -> CommandResult:
|
|
492
729
|
"""Output preview as JSON."""
|
|
493
|
-
output = {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
730
|
+
output = {}
|
|
731
|
+
|
|
732
|
+
if configure_agents and agent_preview:
|
|
733
|
+
output["agents"] = {
|
|
734
|
+
"detected_toolchain": {
|
|
735
|
+
"components": (
|
|
736
|
+
[
|
|
737
|
+
{
|
|
738
|
+
"type": (
|
|
739
|
+
c.type.value
|
|
740
|
+
if hasattr(c.type, "value")
|
|
741
|
+
else str(c.type)
|
|
742
|
+
),
|
|
743
|
+
"version": c.version,
|
|
744
|
+
"confidence": c.confidence,
|
|
745
|
+
}
|
|
746
|
+
for c in agent_preview.detected_toolchain.components
|
|
747
|
+
]
|
|
748
|
+
if agent_preview.detected_toolchain
|
|
749
|
+
else []
|
|
750
|
+
)
|
|
751
|
+
},
|
|
752
|
+
"recommendations": [
|
|
753
|
+
{
|
|
754
|
+
"agent_id": r.agent_id,
|
|
755
|
+
"confidence": r.confidence,
|
|
756
|
+
"reasoning": r.reasoning,
|
|
757
|
+
}
|
|
758
|
+
for r in agent_preview.recommendations
|
|
759
|
+
],
|
|
760
|
+
"validation": {
|
|
761
|
+
"is_valid": (
|
|
762
|
+
agent_preview.validation_result.is_valid
|
|
763
|
+
if agent_preview.validation_result
|
|
764
|
+
else True
|
|
765
|
+
),
|
|
766
|
+
"issues": (
|
|
767
|
+
[
|
|
768
|
+
{
|
|
769
|
+
"severity": (
|
|
770
|
+
i.severity.value
|
|
771
|
+
if hasattr(i.severity, "value")
|
|
772
|
+
else str(i.severity)
|
|
773
|
+
),
|
|
774
|
+
"message": i.message,
|
|
775
|
+
}
|
|
776
|
+
for i in agent_preview.validation_result.issues
|
|
777
|
+
]
|
|
778
|
+
if agent_preview.validation_result
|
|
779
|
+
else []
|
|
780
|
+
),
|
|
781
|
+
},
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
if configure_skills and skills_recommendations:
|
|
785
|
+
output["skills"] = {
|
|
786
|
+
"recommendations": skills_recommendations,
|
|
787
|
+
}
|
|
543
788
|
|
|
544
789
|
print(json.dumps(output, indent=2))
|
|
545
790
|
return CommandResult.success_result(data=output)
|
|
546
791
|
|
|
547
|
-
def _output_result_json(
|
|
792
|
+
def _output_result_json(
|
|
793
|
+
self, agent_result: Optional = None, skills_result: Optional[dict] = None
|
|
794
|
+
) -> CommandResult:
|
|
548
795
|
"""Output result as JSON."""
|
|
549
|
-
output = {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
796
|
+
output = {}
|
|
797
|
+
|
|
798
|
+
if agent_result:
|
|
799
|
+
output["agents"] = {
|
|
800
|
+
"status": (
|
|
801
|
+
agent_result.status.value
|
|
802
|
+
if hasattr(agent_result.status, "value")
|
|
803
|
+
else str(agent_result.status)
|
|
804
|
+
),
|
|
805
|
+
"deployed_agents": agent_result.deployed_agents,
|
|
806
|
+
"failed_agents": agent_result.failed_agents,
|
|
807
|
+
"errors": agent_result.errors,
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
if skills_result:
|
|
811
|
+
output["skills"] = skills_result
|
|
559
812
|
|
|
560
813
|
print(json.dumps(output, indent=2))
|
|
561
814
|
|
|
562
|
-
|
|
815
|
+
# Determine overall success
|
|
816
|
+
agent_success = (
|
|
817
|
+
agent_result.status == OperationResult.SUCCESS if agent_result else True
|
|
818
|
+
)
|
|
819
|
+
skills_success = not skills_result or not skills_result.get("errors")
|
|
820
|
+
overall_success = agent_success and skills_success
|
|
821
|
+
|
|
822
|
+
if overall_success:
|
|
563
823
|
return CommandResult.success_result(data=output)
|
|
564
824
|
return CommandResult.error_result(
|
|
565
825
|
"Configuration failed or partial", exit_code=1, data=output
|
|
566
826
|
)
|
|
827
|
+
|
|
828
|
+
def _recommend_skills(self, agent_preview):
|
|
829
|
+
"""Recommend skills based on deployed/recommended agents.
|
|
830
|
+
|
|
831
|
+
Args:
|
|
832
|
+
agent_preview: Agent preview result with recommendations
|
|
833
|
+
|
|
834
|
+
Returns:
|
|
835
|
+
List of recommended skill names, or None if no agents recommended
|
|
836
|
+
"""
|
|
837
|
+
if not agent_preview or not agent_preview.recommendations:
|
|
838
|
+
return None
|
|
839
|
+
|
|
840
|
+
# Import agent-skill mapping
|
|
841
|
+
from ...cli.interactive.skills_wizard import AGENT_SKILL_MAPPING
|
|
842
|
+
|
|
843
|
+
# Collect recommended skills based on agent types
|
|
844
|
+
recommended_skills = set()
|
|
845
|
+
for rec in agent_preview.recommendations:
|
|
846
|
+
agent_id = rec.agent_id
|
|
847
|
+
# Map agent ID to skill recommendations
|
|
848
|
+
if agent_id in AGENT_SKILL_MAPPING:
|
|
849
|
+
recommended_skills.update(AGENT_SKILL_MAPPING[agent_id])
|
|
850
|
+
|
|
851
|
+
return list(recommended_skills) if recommended_skills else None
|
|
852
|
+
|
|
853
|
+
def _deploy_skills(self, recommended_skills: list[str]) -> dict:
|
|
854
|
+
"""Deploy recommended skills.
|
|
855
|
+
|
|
856
|
+
Args:
|
|
857
|
+
recommended_skills: List of skill names to deploy
|
|
858
|
+
|
|
859
|
+
Returns:
|
|
860
|
+
Dict with deployment results: {"deployed": [...], "errors": [...]}
|
|
861
|
+
"""
|
|
862
|
+
try:
|
|
863
|
+
return self.skills_deployer.deploy_skills(
|
|
864
|
+
skill_names=recommended_skills, force=False
|
|
865
|
+
)
|
|
866
|
+
except Exception as e:
|
|
867
|
+
self.logger.error(f"Failed to deploy skills: {e}")
|
|
868
|
+
return {"deployed": [], "errors": [str(e)]}
|