claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__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/BUILD_NUMBER +1 -0
- claude_mpm/VERSION +1 -0
- claude_mpm/__init__.py +50 -12
- claude_mpm/__main__.py +7 -2
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
- claude_mpm/agents/WORKFLOW.md +111 -0
- claude_mpm/agents/__init__.py +92 -80
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +560 -745
- claude_mpm/agents/agent_loader_integration.py +53 -55
- claude_mpm/agents/agents_metadata.py +186 -27
- claude_mpm/agents/async_agent_loader.py +436 -0
- claude_mpm/agents/base_agent.json +8 -4
- claude_mpm/agents/frontmatter_validator.py +754 -0
- claude_mpm/agents/system_agent_config.py +222 -155
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/__init__.py +17 -13
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +90 -128
- claude_mpm/cli/__main__.py +33 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +36 -12
- claude_mpm/cli/commands/agent_manager.py +1403 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +335 -0
- claude_mpm/cli/commands/agents.py +2503 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +540 -0
- claude_mpm/cli/commands/analyze.py +553 -0
- claude_mpm/cli/commands/analyze_code.py +528 -0
- claude_mpm/cli/commands/auto_configure.py +1053 -0
- claude_mpm/cli/commands/cleanup.py +588 -0
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
- claude_mpm/cli/commands/config.py +586 -0
- claude_mpm/cli/commands/configure.py +2654 -0
- claude_mpm/cli/commands/configure_agent_display.py +282 -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 +184 -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/dashboard.py +286 -0
- claude_mpm/cli/commands/debug.py +1386 -0
- claude_mpm/cli/commands/doctor.py +243 -0
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +195 -74
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +205 -0
- claude_mpm/cli/commands/mcp_command_router.py +161 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +346 -0
- claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
- claude_mpm/cli/commands/mcp_server_commands.py +155 -0
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +585 -846
- claude_mpm/cli/commands/monitor.py +228 -310
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +759 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +195 -0
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +910 -488
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1246 -0
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/commands/tickets.py +536 -53
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +297 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +1947 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +87 -563
- claude_mpm/cli/parsers/__init__.py +35 -0
- claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +575 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
- claude_mpm/cli/parsers/base_parser.py +644 -0
- claude_mpm/cli/parsers/config_parser.py +208 -0
- claude_mpm/cli/parsers/configure_parser.py +138 -0
- claude_mpm/cli/parsers/dashboard_parser.py +113 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +195 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +142 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +157 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +277 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/shared/__init__.py +40 -0
- claude_mpm/cli/shared/argument_patterns.py +205 -0
- claude_mpm/cli/shared/base_command.py +242 -0
- claude_mpm/cli/shared/error_handling.py +242 -0
- claude_mpm/cli/shared/output_formatters.py +241 -0
- claude_mpm/cli/startup.py +1743 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +839 -0
- claude_mpm/cli/utils.py +136 -47
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +42 -64
- claude_mpm/commands/__init__.py +14 -0
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +20 -0
- claude_mpm/commands/mpm-help.md +20 -0
- claude_mpm/commands/mpm-init.md +120 -0
- claude_mpm/commands/mpm-monitor.md +31 -0
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +20 -0
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +20 -0
- claude_mpm/commands/mpm.md +31 -0
- claude_mpm/config/__init__.py +42 -2
- claude_mpm/config/agent_config.py +402 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +258 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +125 -83
- claude_mpm/constants.py +132 -22
- claude_mpm/core/__init__.py +62 -36
- claude_mpm/core/agent_name_normalizer.py +71 -73
- claude_mpm/core/agent_registry.py +385 -492
- claude_mpm/core/agent_session_manager.py +81 -70
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +159 -122
- claude_mpm/core/cache.py +560 -0
- claude_mpm/core/claude_runner.py +696 -916
- claude_mpm/core/config.py +613 -122
- claude_mpm/core/config_aliases.py +74 -73
- claude_mpm/core/config_constants.py +314 -0
- claude_mpm/core/constants.py +361 -0
- claude_mpm/core/container.py +646 -104
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/exceptions.py +536 -0
- claude_mpm/core/factories.py +105 -109
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +278 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +213 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +485 -414
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +246 -86
- claude_mpm/core/hook_performance_config.py +147 -0
- claude_mpm/core/injectable_service.py +72 -63
- claude_mpm/core/instruction_reinforcement_hook.py +267 -0
- claude_mpm/core/interactive_session.py +670 -0
- claude_mpm/core/interfaces.py +570 -164
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/log_manager.py +707 -0
- claude_mpm/core/logger.py +295 -134
- claude_mpm/core/logging_config.py +474 -0
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/minimal_framework_loader.py +24 -22
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +594 -0
- claude_mpm/core/optimized_agent_loader.py +479 -0
- claude_mpm/core/optimized_startup.py +554 -0
- claude_mpm/core/output_style_manager.py +483 -0
- claude_mpm/core/pm_hook_interceptor.py +197 -82
- 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/service_registry.py +153 -116
- claude_mpm/core/session_manager.py +179 -64
- claude_mpm/core/shared/__init__.py +17 -0
- claude_mpm/core/shared/config_loader.py +326 -0
- claude_mpm/core/shared/path_resolver.py +281 -0
- claude_mpm/core/shared/singleton_manager.py +221 -0
- claude_mpm/core/socketio_pool.py +400 -137
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +64 -57
- claude_mpm/core/types.py +307 -0
- claude_mpm/core/typing_utils.py +553 -0
- claude_mpm/core/unified_agent_registry.py +969 -0
- claude_mpm/core/unified_config.py +570 -0
- claude_mpm/core/unified_paths.py +941 -0
- claude_mpm/dashboard/__init__.py +12 -0
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/__init__.py +10 -0
- claude_mpm/experimental/cli_enhancements.py +104 -89
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +76 -66
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +37 -32
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
- claude_mpm/hooks/claude_hooks/installer.py +806 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +201 -107
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +92 -76
- claude_mpm/hooks/validation_hooks.py +62 -54
- claude_mpm/init.py +518 -83
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +40 -23
- claude_mpm/models/agent_session.py +538 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/__init__.py +12 -0
- claude_mpm/scripts/__init__.py +15 -0
- claude_mpm/scripts/claude-hook-handler.sh +227 -0
- claude_mpm/scripts/launch_monitor.py +165 -0
- claude_mpm/scripts/mpm_doctor.py +322 -0
- claude_mpm/scripts/socketio_daemon.py +189 -200
- claude_mpm/scripts/start_activity_logging.py +91 -0
- claude_mpm/services/__init__.py +208 -39
- claude_mpm/services/agent_capabilities_service.py +266 -0
- claude_mpm/services/agents/__init__.py +89 -0
- claude_mpm/services/agents/agent_builder.py +514 -0
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
- claude_mpm/services/agents/deployment/agent_validator.py +376 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
- claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
- claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
- claude_mpm/services/agents/git_source_manager.py +682 -0
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
- claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
- claude_mpm/services/agents/memory/__init__.py +22 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
- claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
- claude_mpm/services/agents/memory/content_manager.py +470 -0
- claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
- claude_mpm/services/agents/memory/memory_file_service.py +129 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
- claude_mpm/services/agents/memory/template_generator.py +83 -0
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +617 -0
- claude_mpm/services/agents/registry/__init__.py +30 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +665 -0
- claude_mpm/services/claude_session_logger.py +321 -0
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +408 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +590 -0
- claude_mpm/services/cli/memory_crud_service.py +622 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +604 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +362 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +446 -0
- claude_mpm/services/command_handler_service.py +221 -0
- claude_mpm/services/communication/__init__.py +22 -0
- claude_mpm/services/core/__init__.py +108 -0
- claude_mpm/services/core/base.py +269 -0
- claude_mpm/services/core/cache_manager.py +309 -0
- claude_mpm/services/core/interfaces/__init__.py +273 -0
- claude_mpm/services/core/interfaces/agent.py +514 -0
- claude_mpm/services/core/interfaces/communication.py +316 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/infrastructure.py +357 -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/service.py +405 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +81 -0
- claude_mpm/services/core/memory_manager.py +682 -0
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -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 +517 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +38 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/base_check.py +60 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
- claude_mpm/services/diagnostics/models.py +138 -0
- claude_mpm/services/event_aggregator.py +582 -0
- claude_mpm/services/event_bus/__init__.py +18 -0
- claude_mpm/services/event_bus/config.py +186 -0
- claude_mpm/services/event_bus/direct_relay.py +312 -0
- claude_mpm/services/event_bus/event_bus.py +396 -0
- claude_mpm/services/event_bus/relay.py +326 -0
- claude_mpm/services/events/__init__.py +44 -0
- claude_mpm/services/events/consumers/__init__.py +18 -0
- claude_mpm/services/events/consumers/dead_letter.py +306 -0
- claude_mpm/services/events/consumers/logging.py +184 -0
- claude_mpm/services/events/consumers/metrics.py +241 -0
- claude_mpm/services/events/consumers/socketio.py +377 -0
- claude_mpm/services/events/core.py +480 -0
- claude_mpm/services/events/interfaces.py +214 -0
- claude_mpm/services/events/producers/__init__.py +14 -0
- claude_mpm/services/events/producers/hook.py +269 -0
- claude_mpm/services/events/producers/system.py +329 -0
- claude_mpm/services/exceptions.py +433 -353
- claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
- claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +159 -111
- claude_mpm/services/infrastructure/__init__.py +52 -0
- claude_mpm/services/infrastructure/context_preservation.py +569 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +209 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
- claude_mpm/services/infrastructure/monitoring/base.py +122 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +219 -0
- claude_mpm/services/infrastructure/monitoring/process.py +343 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
- claude_mpm/services/infrastructure/monitoring/service.py +368 -0
- claude_mpm/services/infrastructure/monitoring.py +71 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -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 +427 -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 +1542 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/__init__.py +19 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
- claude_mpm/services/memory/cache/simple_cache.py +331 -0
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
- claude_mpm/services/memory/router.py +951 -0
- claude_mpm/services/memory_hook_service.py +470 -0
- 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 +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +698 -0
- claude_mpm/services/monitor/daemon_manager.py +1076 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +730 -0
- claude_mpm/services/monitor/server.py +1493 -0
- claude_mpm/services/monitor_build_service.py +349 -0
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/pm_skills_deployer.py +707 -0
- claude_mpm/services/port_manager.py +597 -0
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/__init__.py +44 -0
- claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +407 -0
- claude_mpm/services/project/project_organizer.py +1009 -0
- claude_mpm/services/project/registry.py +636 -0
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/recovery_manager.py +293 -240
- claude_mpm/services/response_tracker.py +267 -0
- claude_mpm/services/runner_configuration_service.py +605 -0
- claude_mpm/services/self_upgrade_service.py +608 -0
- claude_mpm/services/session_management_service.py +314 -0
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +21 -0
- claude_mpm/services/shared/async_service_base.py +216 -0
- claude_mpm/services/shared/config_service_base.py +301 -0
- claude_mpm/services/shared/lifecycle_service_base.py +308 -0
- claude_mpm/services/shared/manager_base.py +315 -0
- claude_mpm/services/shared/service_factory.py +309 -0
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
- claude_mpm/services/skills/selective_skill_deployer.py +744 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1168 -0
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/client_proxy.py +229 -0
- claude_mpm/services/socketio/dashboard_server.py +362 -0
- claude_mpm/services/socketio/event_normalizer.py +798 -0
- claude_mpm/services/socketio/handlers/__init__.py +30 -0
- claude_mpm/services/socketio/handlers/base.py +136 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
- claude_mpm/services/socketio/handlers/connection.py +643 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
- claude_mpm/services/socketio/handlers/file.py +263 -0
- claude_mpm/services/socketio/handlers/git.py +962 -0
- claude_mpm/services/socketio/handlers/hook.py +211 -0
- claude_mpm/services/socketio/handlers/memory.py +26 -0
- claude_mpm/services/socketio/handlers/project.py +24 -0
- claude_mpm/services/socketio/handlers/registry.py +214 -0
- claude_mpm/services/socketio/migration_utils.py +343 -0
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +569 -0
- claude_mpm/services/socketio/server/connection_manager.py +579 -0
- claude_mpm/services/socketio/server/core.py +1079 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
- claude_mpm/services/socketio/server/main.py +501 -0
- claude_mpm/services/socketio_client_manager.py +173 -143
- claude_mpm/services/socketio_server.py +38 -1657
- claude_mpm/services/subprocess_launcher_service.py +322 -0
- claude_mpm/services/system_instructions_service.py +270 -0
- claude_mpm/services/ticket_manager.py +25 -209
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +280 -0
- claude_mpm/services/version_control/__init__.py +34 -37
- claude_mpm/services/version_control/branch_strategy.py +26 -17
- claude_mpm/services/version_control/conflict_resolution.py +52 -36
- claude_mpm/services/version_control/git_operations.py +183 -49
- claude_mpm/services/version_control/semantic_versioning.py +172 -61
- claude_mpm/services/version_control/version_parser.py +546 -0
- claude_mpm/services/version_service.py +379 -0
- claude_mpm/services/visualization/__init__.py +15 -0
- claude_mpm/services/visualization/mermaid_generator.py +937 -0
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -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/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -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 +573 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -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 +405 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +546 -0
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/tools/__init__.py +10 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +631 -0
- claude_mpm/tools/code_tree_events.py +420 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- claude_mpm/utils/__init__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +1090 -0
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +168 -126
- claude_mpm/utils/console.py +11 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +373 -0
- claude_mpm/utils/dependency_manager.py +60 -59
- claude_mpm/utils/dependency_strategies.py +381 -0
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +313 -0
- claude_mpm/utils/error_handler.py +78 -66
- claude_mpm/utils/file_utils.py +305 -0
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +110 -104
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +823 -0
- claude_mpm/utils/session_logging.py +121 -0
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +343 -0
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +214 -108
- claude_mpm/validation/frontmatter_validator.py +252 -0
- claude_mpm-5.4.55.dist-info/METADATA +999 -0
- claude_mpm-5.4.55.dist-info/RECORD +868 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
- claude_mpm/agents/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/base_agent_loader.py +0 -529
- claude_mpm/agents/schema/agent_schema.json +0 -314
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/data_engineer.json +0 -110
- claude_mpm/agents/templates/documentation.json +0 -109
- claude_mpm/agents/templates/engineer.json +0 -113
- claude_mpm/agents/templates/ops.json +0 -109
- claude_mpm/agents/templates/pm.json +0 -25
- claude_mpm/agents/templates/qa.json +0 -111
- claude_mpm/agents/templates/research.json +0 -65
- claude_mpm/agents/templates/security.json +0 -113
- claude_mpm/agents/templates/test_integration.json +0 -112
- claude_mpm/agents/templates/version_control.json +0 -107
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/dashboard/open_dashboard.py +0 -34
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/agent_deployment.py +0 -1534
- claude_mpm/services/agent_lifecycle_manager.py +0 -1169
- claude_mpm/services/agent_memory_manager.py +0 -1415
- claude_mpm/services/agent_registry.py +0 -676
- claude_mpm/services/deployed_agent_discovery.py +0 -226
- claude_mpm/services/framework_agent_loader.py +0 -337
- claude_mpm/services/framework_claude_md_generator.py +0 -621
- claude_mpm/services/health_monitor.py +0 -892
- claude_mpm/services/memory_router.py +0 -538
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -508
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- claude_mpm/utils/paths.py +0 -289
- claude_mpm-3.4.10.dist-info/METADATA +0 -183
- claude_mpm-3.4.10.dist-info/RECORD +0 -201
- claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1246 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skills command implementation for claude-mpm.
|
|
3
|
+
|
|
4
|
+
WHY: This module provides CLI commands for managing Claude Code skills,
|
|
5
|
+
exposing SkillsService functionality for skill discovery, deployment, validation,
|
|
6
|
+
updates, and configuration. Also provides GitHub skills deployment via SkillsDeployer.
|
|
7
|
+
|
|
8
|
+
DESIGN DECISIONS:
|
|
9
|
+
- Use BaseCommand pattern for consistency with other CLI commands
|
|
10
|
+
- Rich output formatting for user-friendly display
|
|
11
|
+
- Graceful error handling with informative messages
|
|
12
|
+
- Support for verbose output and structured formats
|
|
13
|
+
- Dual service approach: SkillsService for bundled, SkillsDeployer for GitHub
|
|
14
|
+
|
|
15
|
+
ARCHITECTURE:
|
|
16
|
+
- SkillsService: Manages bundled skills (in project .claude/skills/)
|
|
17
|
+
- SkillsDeployer: Downloads from GitHub to ~/.claude/skills/ for Claude Code
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import os
|
|
21
|
+
import subprocess
|
|
22
|
+
from typing import Optional
|
|
23
|
+
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
from rich.markdown import Markdown
|
|
26
|
+
from rich.panel import Panel
|
|
27
|
+
from rich.table import Table
|
|
28
|
+
|
|
29
|
+
from ...constants import SkillsCommands
|
|
30
|
+
from ...services.skills_deployer import SkillsDeployerService
|
|
31
|
+
from ...skills.skills_service import SkillsService
|
|
32
|
+
from ..shared import BaseCommand, CommandResult
|
|
33
|
+
|
|
34
|
+
console = Console()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SkillsManagementCommand(BaseCommand):
|
|
38
|
+
"""Skills management command for Claude Code skills."""
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
super().__init__("skills")
|
|
42
|
+
self._skills_service = None
|
|
43
|
+
self._skills_deployer = None
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def skills_service(self) -> SkillsService:
|
|
47
|
+
"""Get skills service instance (lazy loaded)."""
|
|
48
|
+
if self._skills_service is None:
|
|
49
|
+
self._skills_service = SkillsService()
|
|
50
|
+
return self._skills_service
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def skills_deployer(self) -> SkillsDeployerService:
|
|
54
|
+
"""Get skills deployer instance (lazy loaded)."""
|
|
55
|
+
if self._skills_deployer is None:
|
|
56
|
+
self._skills_deployer = SkillsDeployerService()
|
|
57
|
+
return self._skills_deployer
|
|
58
|
+
|
|
59
|
+
def validate_args(self, args) -> Optional[str]:
|
|
60
|
+
"""Validate command arguments."""
|
|
61
|
+
# Most skills commands are optional, basic validation
|
|
62
|
+
if hasattr(args, "skills_command") and args.skills_command:
|
|
63
|
+
if args.skills_command == SkillsCommands.VALIDATE.value:
|
|
64
|
+
if not hasattr(args, "skill_name") or not args.skill_name:
|
|
65
|
+
return "Validate command requires a skill name"
|
|
66
|
+
elif args.skills_command == SkillsCommands.INFO.value:
|
|
67
|
+
if not hasattr(args, "skill_name") or not args.skill_name:
|
|
68
|
+
return "Info command requires a skill name"
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
def run(self, args) -> CommandResult:
|
|
72
|
+
"""Execute the skills command."""
|
|
73
|
+
try:
|
|
74
|
+
# Handle default case (no subcommand) - show list
|
|
75
|
+
if not hasattr(args, "skills_command") or not args.skills_command:
|
|
76
|
+
return self._list_skills(args)
|
|
77
|
+
|
|
78
|
+
# Route to appropriate subcommand
|
|
79
|
+
command_map = {
|
|
80
|
+
SkillsCommands.LIST.value: self._list_skills,
|
|
81
|
+
SkillsCommands.DEPLOY.value: self._deploy_skills,
|
|
82
|
+
SkillsCommands.VALIDATE.value: self._validate_skill,
|
|
83
|
+
SkillsCommands.UPDATE.value: self._update_skills,
|
|
84
|
+
SkillsCommands.INFO.value: self._show_skill_info,
|
|
85
|
+
SkillsCommands.CONFIG.value: self._manage_config,
|
|
86
|
+
SkillsCommands.CONFIGURE.value: self._configure_skills,
|
|
87
|
+
# GitHub deployment commands
|
|
88
|
+
SkillsCommands.DEPLOY_FROM_GITHUB.value: self._deploy_from_github,
|
|
89
|
+
SkillsCommands.LIST_AVAILABLE.value: self._list_available_github_skills,
|
|
90
|
+
SkillsCommands.CHECK_DEPLOYED.value: self._check_deployed_skills,
|
|
91
|
+
SkillsCommands.REMOVE.value: self._remove_skills,
|
|
92
|
+
# Collection management commands
|
|
93
|
+
SkillsCommands.COLLECTION_LIST.value: self._collection_list,
|
|
94
|
+
SkillsCommands.COLLECTION_ADD.value: self._collection_add,
|
|
95
|
+
SkillsCommands.COLLECTION_REMOVE.value: self._collection_remove,
|
|
96
|
+
SkillsCommands.COLLECTION_ENABLE.value: self._collection_enable,
|
|
97
|
+
SkillsCommands.COLLECTION_DISABLE.value: self._collection_disable,
|
|
98
|
+
SkillsCommands.COLLECTION_SET_DEFAULT.value: self._collection_set_default,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
handler = command_map.get(args.skills_command)
|
|
102
|
+
if handler:
|
|
103
|
+
return handler(args)
|
|
104
|
+
return CommandResult(
|
|
105
|
+
success=False,
|
|
106
|
+
message=f"Unknown skills command: {args.skills_command}",
|
|
107
|
+
exit_code=1,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
self.logger.error(f"Skills command failed: {e}")
|
|
112
|
+
if hasattr(args, "debug") and args.debug:
|
|
113
|
+
import traceback
|
|
114
|
+
|
|
115
|
+
traceback.print_exc()
|
|
116
|
+
return CommandResult(
|
|
117
|
+
success=False, message=f"Skills command failed: {e}", exit_code=1
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
def _list_skills(self, args) -> CommandResult:
|
|
121
|
+
"""List available skills."""
|
|
122
|
+
try:
|
|
123
|
+
# Get skills based on filter
|
|
124
|
+
if hasattr(args, "agent") and args.agent:
|
|
125
|
+
skills = self.skills_service.get_skills_for_agent(args.agent)
|
|
126
|
+
console.print(
|
|
127
|
+
f"\n[bold cyan]Skills for agent '{args.agent}':[/bold cyan]\n"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if not skills:
|
|
131
|
+
console.print(
|
|
132
|
+
f"[yellow]No skills found for agent '{args.agent}'[/yellow]"
|
|
133
|
+
)
|
|
134
|
+
return CommandResult(success=True, exit_code=0)
|
|
135
|
+
|
|
136
|
+
for skill_name in skills:
|
|
137
|
+
# Get skill metadata
|
|
138
|
+
skill_info = self._get_skill_metadata(skill_name)
|
|
139
|
+
if skill_info:
|
|
140
|
+
console.print(f" [green]•[/green] {skill_name}")
|
|
141
|
+
if (
|
|
142
|
+
hasattr(args, "verbose")
|
|
143
|
+
and args.verbose
|
|
144
|
+
and skill_info.get("description")
|
|
145
|
+
):
|
|
146
|
+
console.print(f" {skill_info['description']}")
|
|
147
|
+
else:
|
|
148
|
+
console.print(f" [green]•[/green] {skill_name}")
|
|
149
|
+
|
|
150
|
+
else:
|
|
151
|
+
# Discover all bundled skills
|
|
152
|
+
skills = self.skills_service.discover_bundled_skills()
|
|
153
|
+
|
|
154
|
+
# Filter by category if specified
|
|
155
|
+
if hasattr(args, "category") and args.category:
|
|
156
|
+
skills = [s for s in skills if s.get("category") == args.category]
|
|
157
|
+
console.print(
|
|
158
|
+
f"\n[bold cyan]Skills in category '{args.category}':[/bold cyan]\n"
|
|
159
|
+
)
|
|
160
|
+
else:
|
|
161
|
+
console.print("\n[bold cyan]Available Skills:[/bold cyan]\n")
|
|
162
|
+
|
|
163
|
+
if not skills:
|
|
164
|
+
console.print("[yellow]No skills found[/yellow]")
|
|
165
|
+
return CommandResult(success=True, exit_code=0)
|
|
166
|
+
|
|
167
|
+
# Group by category
|
|
168
|
+
by_category = {}
|
|
169
|
+
for skill in skills:
|
|
170
|
+
category = skill.get("category", "uncategorized")
|
|
171
|
+
if category not in by_category:
|
|
172
|
+
by_category[category] = []
|
|
173
|
+
by_category[category].append(skill)
|
|
174
|
+
|
|
175
|
+
# Display by category
|
|
176
|
+
for category, category_skills in sorted(by_category.items()):
|
|
177
|
+
console.print(f"[bold yellow]{category}[/bold yellow]")
|
|
178
|
+
for skill in sorted(
|
|
179
|
+
category_skills, key=lambda s: s.get("name", "")
|
|
180
|
+
):
|
|
181
|
+
name = skill.get("name", "unknown")
|
|
182
|
+
console.print(f" [green]•[/green] {name}")
|
|
183
|
+
|
|
184
|
+
if hasattr(args, "verbose") and args.verbose:
|
|
185
|
+
metadata = skill.get("metadata", {})
|
|
186
|
+
if desc := metadata.get("description"):
|
|
187
|
+
console.print(f" {desc}")
|
|
188
|
+
if version := metadata.get("version"):
|
|
189
|
+
console.print(f" [dim]Version: {version}[/dim]")
|
|
190
|
+
console.print()
|
|
191
|
+
|
|
192
|
+
return CommandResult(success=True, exit_code=0)
|
|
193
|
+
|
|
194
|
+
except Exception as e:
|
|
195
|
+
console.print(f"[red]Error listing skills: {e}[/red]")
|
|
196
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
197
|
+
|
|
198
|
+
def _deploy_skills(self, args) -> CommandResult:
|
|
199
|
+
"""Deploy skills using two-phase sync: cache → deploy.
|
|
200
|
+
|
|
201
|
+
Phase 3 Integration (1M-486): Uses Git skill source manager for deployment.
|
|
202
|
+
- Phase 1: Sync skills to ~/.claude-mpm/cache/skills/ (if needed)
|
|
203
|
+
- Phase 2: Deploy from cache to project .claude-mpm/skills/
|
|
204
|
+
|
|
205
|
+
This replaces bundled skill deployment with a multi-project
|
|
206
|
+
architecture where one cache serves multiple project deployments.
|
|
207
|
+
"""
|
|
208
|
+
try:
|
|
209
|
+
from pathlib import Path
|
|
210
|
+
|
|
211
|
+
from ...config.skill_sources import SkillSourceConfiguration
|
|
212
|
+
from ...services.skills.git_skill_source_manager import (
|
|
213
|
+
GitSkillSourceManager,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
force = getattr(args, "force", False)
|
|
217
|
+
specific_skills = getattr(args, "skills", None)
|
|
218
|
+
|
|
219
|
+
console.print("\n[bold cyan]Deploying skills...[/bold cyan]\n")
|
|
220
|
+
|
|
221
|
+
# Initialize git skill source manager
|
|
222
|
+
config = SkillSourceConfiguration.load()
|
|
223
|
+
git_skill_manager = GitSkillSourceManager(config)
|
|
224
|
+
project_dir = Path.cwd()
|
|
225
|
+
|
|
226
|
+
# Phase 1: Sync skills to cache
|
|
227
|
+
console.print("[dim]Phase 1: Syncing skills to cache...[/dim]")
|
|
228
|
+
sync_results = git_skill_manager.sync_all_sources(force=force)
|
|
229
|
+
|
|
230
|
+
synced_count = sum(
|
|
231
|
+
1 for result in sync_results.values() if result.get("synced")
|
|
232
|
+
)
|
|
233
|
+
console.print(f"[dim]Synced {synced_count} skill source(s)[/dim]\n")
|
|
234
|
+
|
|
235
|
+
# Phase 2: Deploy from cache to project
|
|
236
|
+
console.print("[dim]Phase 2: Deploying from cache to project...[/dim]\n")
|
|
237
|
+
deploy_result = git_skill_manager.deploy_skills_to_project(
|
|
238
|
+
project_dir=project_dir,
|
|
239
|
+
skill_list=specific_skills,
|
|
240
|
+
force=force,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Display results
|
|
244
|
+
if deploy_result["deployed"]:
|
|
245
|
+
console.print(
|
|
246
|
+
f"[green]✓ Deployed {len(deploy_result['deployed'])} skill(s):[/green]"
|
|
247
|
+
)
|
|
248
|
+
for skill in deploy_result["deployed"]:
|
|
249
|
+
console.print(f" • {skill}")
|
|
250
|
+
console.print()
|
|
251
|
+
|
|
252
|
+
if deploy_result["updated"]:
|
|
253
|
+
console.print(
|
|
254
|
+
f"[green]⟳ Updated {len(deploy_result['updated'])} skill(s):[/green]"
|
|
255
|
+
)
|
|
256
|
+
for skill in deploy_result["updated"]:
|
|
257
|
+
console.print(f" • {skill}")
|
|
258
|
+
console.print()
|
|
259
|
+
|
|
260
|
+
if deploy_result["skipped"]:
|
|
261
|
+
console.print(
|
|
262
|
+
f"[yellow]⊘ Skipped {len(deploy_result['skipped'])} skill(s) (already up-to-date):[/yellow]"
|
|
263
|
+
)
|
|
264
|
+
for skill in deploy_result["skipped"]:
|
|
265
|
+
console.print(f" • {skill}")
|
|
266
|
+
console.print("[dim]Use --force to redeploy[/dim]\n")
|
|
267
|
+
|
|
268
|
+
if deploy_result["failed"]:
|
|
269
|
+
console.print(
|
|
270
|
+
f"[red]✗ Failed to deploy {len(deploy_result['failed'])} skill(s):[/red]"
|
|
271
|
+
)
|
|
272
|
+
for skill in deploy_result["failed"]:
|
|
273
|
+
console.print(f" • {skill}")
|
|
274
|
+
console.print()
|
|
275
|
+
|
|
276
|
+
# Summary
|
|
277
|
+
success_count = len(deploy_result["deployed"]) + len(
|
|
278
|
+
deploy_result["updated"]
|
|
279
|
+
)
|
|
280
|
+
total = (
|
|
281
|
+
success_count
|
|
282
|
+
+ len(deploy_result["skipped"])
|
|
283
|
+
+ len(deploy_result["failed"])
|
|
284
|
+
)
|
|
285
|
+
console.print(
|
|
286
|
+
f"[bold]Summary:[/bold] {success_count} deployed/updated, "
|
|
287
|
+
f"{len(deploy_result['skipped'])} skipped, "
|
|
288
|
+
f"{len(deploy_result['failed'])} errors (Total: {total})\n"
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
console.print(
|
|
292
|
+
f"[dim]Deployment directory: {deploy_result['deployment_dir']}[/dim]\n"
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
# Exit with error if any deployments failed
|
|
296
|
+
exit_code = 1 if deploy_result["failed"] else 0
|
|
297
|
+
return CommandResult(
|
|
298
|
+
success=not deploy_result["failed"],
|
|
299
|
+
message=f"Deployed {success_count} skills from cache",
|
|
300
|
+
exit_code=exit_code,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
except Exception as e:
|
|
304
|
+
console.print(f"[red]Error deploying skills: {e}[/red]")
|
|
305
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
306
|
+
|
|
307
|
+
def _validate_skill(self, args) -> CommandResult:
|
|
308
|
+
"""Validate skill structure and metadata."""
|
|
309
|
+
try:
|
|
310
|
+
skill_name = args.skill_name
|
|
311
|
+
strict = getattr(args, "strict", False)
|
|
312
|
+
|
|
313
|
+
console.print(
|
|
314
|
+
f"\n[bold cyan]Validating skill '{skill_name}'...[/bold cyan]\n"
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
result = self.skills_service.validate_skill(skill_name)
|
|
318
|
+
|
|
319
|
+
if result["valid"]:
|
|
320
|
+
console.print(f"[green]✓ {skill_name} is valid[/green]\n")
|
|
321
|
+
|
|
322
|
+
if result.get("warnings"):
|
|
323
|
+
console.print(
|
|
324
|
+
f"[yellow]Warnings ({len(result['warnings'])}):[/yellow]"
|
|
325
|
+
)
|
|
326
|
+
for warning in result["warnings"]:
|
|
327
|
+
console.print(f" • {warning}")
|
|
328
|
+
console.print()
|
|
329
|
+
|
|
330
|
+
# Treat warnings as errors in strict mode
|
|
331
|
+
if strict:
|
|
332
|
+
console.print(
|
|
333
|
+
"[red]Strict mode: treating warnings as errors[/red]"
|
|
334
|
+
)
|
|
335
|
+
return CommandResult(success=False, exit_code=1)
|
|
336
|
+
|
|
337
|
+
return CommandResult(success=True, exit_code=0)
|
|
338
|
+
console.print(f"[red]✗ {skill_name} has validation errors:[/red]")
|
|
339
|
+
for error in result.get("errors", []):
|
|
340
|
+
console.print(f" • {error}")
|
|
341
|
+
console.print()
|
|
342
|
+
|
|
343
|
+
if result.get("warnings"):
|
|
344
|
+
console.print("[yellow]Warnings:[/yellow]")
|
|
345
|
+
for warning in result["warnings"]:
|
|
346
|
+
console.print(f" • {warning}")
|
|
347
|
+
console.print()
|
|
348
|
+
|
|
349
|
+
return CommandResult(success=False, exit_code=1)
|
|
350
|
+
|
|
351
|
+
except Exception as e:
|
|
352
|
+
console.print(f"[red]Error validating skill: {e}[/red]")
|
|
353
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
354
|
+
|
|
355
|
+
def _update_skills(self, args) -> CommandResult:
|
|
356
|
+
"""Check for and install skill updates."""
|
|
357
|
+
try:
|
|
358
|
+
skill_names = getattr(args, "skill_names", [])
|
|
359
|
+
check_only = getattr(args, "check_only", False)
|
|
360
|
+
force = getattr(args, "force", False)
|
|
361
|
+
|
|
362
|
+
action = "Checking" if check_only else "Updating"
|
|
363
|
+
console.print(f"\n[bold cyan]{action} skills...[/bold cyan]\n")
|
|
364
|
+
|
|
365
|
+
result = self.skills_service.check_for_updates(skill_names)
|
|
366
|
+
|
|
367
|
+
if not result.get("updates_available"):
|
|
368
|
+
console.print("[green]All skills are up to date[/green]\n")
|
|
369
|
+
return CommandResult(success=True, exit_code=0)
|
|
370
|
+
|
|
371
|
+
# Display available updates
|
|
372
|
+
console.print(
|
|
373
|
+
f"[yellow]Updates available for {len(result['updates_available'])} skill(s):[/yellow]"
|
|
374
|
+
)
|
|
375
|
+
for update_info in result["updates_available"]:
|
|
376
|
+
skill_name = update_info["skill"]
|
|
377
|
+
current = update_info["current_version"]
|
|
378
|
+
latest = update_info["latest_version"]
|
|
379
|
+
console.print(f" • {skill_name}: {current} → {latest}")
|
|
380
|
+
console.print()
|
|
381
|
+
|
|
382
|
+
if check_only:
|
|
383
|
+
console.print(
|
|
384
|
+
"[dim]Run without --check-only to install updates[/dim]\n"
|
|
385
|
+
)
|
|
386
|
+
return CommandResult(success=True, exit_code=0)
|
|
387
|
+
|
|
388
|
+
# Install updates
|
|
389
|
+
console.print("[bold cyan]Installing updates...[/bold cyan]\n")
|
|
390
|
+
install_result = self.skills_service.install_updates(
|
|
391
|
+
result["updates_available"], force=force
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
if install_result["updated"]:
|
|
395
|
+
console.print(
|
|
396
|
+
f"[green]✓ Updated {len(install_result['updated'])} skill(s)[/green]\n"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
if install_result.get("errors"):
|
|
400
|
+
console.print(
|
|
401
|
+
f"[red]✗ Failed to update {len(install_result['errors'])} skill(s)[/red]"
|
|
402
|
+
)
|
|
403
|
+
for skill, error in install_result["errors"].items():
|
|
404
|
+
console.print(f" • {skill}: {error}")
|
|
405
|
+
console.print()
|
|
406
|
+
|
|
407
|
+
exit_code = 1 if install_result.get("errors") else 0
|
|
408
|
+
return CommandResult(
|
|
409
|
+
success=not install_result.get("errors"), exit_code=exit_code
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
except Exception as e:
|
|
413
|
+
console.print(f"[red]Error updating skills: {e}[/red]")
|
|
414
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
415
|
+
|
|
416
|
+
def _show_skill_info(self, args) -> CommandResult:
|
|
417
|
+
"""Show detailed skill information."""
|
|
418
|
+
try:
|
|
419
|
+
skill_name = args.skill_name
|
|
420
|
+
show_content = getattr(args, "show_content", False)
|
|
421
|
+
|
|
422
|
+
skill_info = self._get_skill_metadata(skill_name)
|
|
423
|
+
|
|
424
|
+
if not skill_info:
|
|
425
|
+
console.print(f"[red]Skill '{skill_name}' not found[/red]")
|
|
426
|
+
return CommandResult(success=False, exit_code=1)
|
|
427
|
+
|
|
428
|
+
# Display skill info in a panel
|
|
429
|
+
info_text = f"[bold cyan]{skill_name}[/bold cyan]\n\n"
|
|
430
|
+
|
|
431
|
+
if desc := skill_info.get("description"):
|
|
432
|
+
info_text += f"{desc}\n\n"
|
|
433
|
+
|
|
434
|
+
if category := skill_info.get("category"):
|
|
435
|
+
info_text += f"[bold]Category:[/bold] {category}\n"
|
|
436
|
+
|
|
437
|
+
if version := skill_info.get("version"):
|
|
438
|
+
info_text += f"[bold]Version:[/bold] {version}\n"
|
|
439
|
+
|
|
440
|
+
if source := skill_info.get("source"):
|
|
441
|
+
info_text += f"[bold]Source:[/bold] {source}\n"
|
|
442
|
+
|
|
443
|
+
# Show agents using this skill
|
|
444
|
+
agents_using = self.skills_service.get_agents_for_skill(skill_name)
|
|
445
|
+
if agents_using:
|
|
446
|
+
info_text += (
|
|
447
|
+
f"\n[bold]Used by agents:[/bold] {', '.join(agents_using)}\n"
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
console.print(
|
|
451
|
+
Panel(info_text, title="Skill Information", border_style="cyan")
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
# Show content if requested
|
|
455
|
+
if show_content:
|
|
456
|
+
skill_path = self.skills_service.get_skill_path(skill_name)
|
|
457
|
+
skill_md = skill_path / "SKILL.md"
|
|
458
|
+
|
|
459
|
+
if skill_md.exists():
|
|
460
|
+
console.print("\n[bold cyan]Skill Content:[/bold cyan]\n")
|
|
461
|
+
content = skill_md.read_text()
|
|
462
|
+
console.print(Markdown(content))
|
|
463
|
+
else:
|
|
464
|
+
console.print(
|
|
465
|
+
f"\n[yellow]SKILL.md not found at {skill_md}[/yellow]"
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
return CommandResult(success=True, exit_code=0)
|
|
469
|
+
|
|
470
|
+
except Exception as e:
|
|
471
|
+
console.print(f"[red]Error showing skill info: {e}[/red]")
|
|
472
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
473
|
+
|
|
474
|
+
def _manage_config(self, args) -> CommandResult:
|
|
475
|
+
"""View or edit skills configuration."""
|
|
476
|
+
try:
|
|
477
|
+
scope = getattr(args, "scope", "project")
|
|
478
|
+
edit = getattr(args, "edit", False)
|
|
479
|
+
show_path = getattr(args, "path", False)
|
|
480
|
+
|
|
481
|
+
config_path = self.skills_service.get_config_path(scope)
|
|
482
|
+
|
|
483
|
+
if show_path:
|
|
484
|
+
console.print(
|
|
485
|
+
f"\n[cyan]Configuration path ({scope}):[/cyan] {config_path}\n"
|
|
486
|
+
)
|
|
487
|
+
return CommandResult(success=True, exit_code=0)
|
|
488
|
+
|
|
489
|
+
if not config_path.exists():
|
|
490
|
+
console.print(
|
|
491
|
+
f"\n[yellow]Configuration file does not exist: {config_path}[/yellow]"
|
|
492
|
+
)
|
|
493
|
+
console.print("[dim]Would you like to create it? (y/n):[/dim] ", end="")
|
|
494
|
+
|
|
495
|
+
if input().lower() == "y":
|
|
496
|
+
self.skills_service.create_default_config(scope)
|
|
497
|
+
console.print(
|
|
498
|
+
f"[green]Created default configuration at {config_path}[/green]\n"
|
|
499
|
+
)
|
|
500
|
+
else:
|
|
501
|
+
return CommandResult(success=False, exit_code=1)
|
|
502
|
+
|
|
503
|
+
if edit:
|
|
504
|
+
# Open in editor
|
|
505
|
+
editor = os.environ.get("EDITOR", "nano")
|
|
506
|
+
try:
|
|
507
|
+
subprocess.run([editor, str(config_path)], check=True)
|
|
508
|
+
console.print(
|
|
509
|
+
f"\n[green]Configuration saved to {config_path}[/green]\n"
|
|
510
|
+
)
|
|
511
|
+
return CommandResult(success=True, exit_code=0)
|
|
512
|
+
except subprocess.CalledProcessError as e:
|
|
513
|
+
console.print(f"[red]Error opening editor: {e}[/red]")
|
|
514
|
+
return CommandResult(success=False, exit_code=1)
|
|
515
|
+
else:
|
|
516
|
+
# Display config
|
|
517
|
+
console.print(
|
|
518
|
+
f"\n[bold cyan]Skills Configuration ({scope}):[/bold cyan]\n"
|
|
519
|
+
)
|
|
520
|
+
console.print(f"[dim]Path: {config_path}[/dim]\n")
|
|
521
|
+
|
|
522
|
+
import yaml
|
|
523
|
+
|
|
524
|
+
config = yaml.safe_load(config_path.read_text())
|
|
525
|
+
console.print(yaml.dump(config, default_flow_style=False))
|
|
526
|
+
|
|
527
|
+
return CommandResult(success=True, exit_code=0)
|
|
528
|
+
|
|
529
|
+
except Exception as e:
|
|
530
|
+
console.print(f"[red]Error managing configuration: {e}[/red]")
|
|
531
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
532
|
+
|
|
533
|
+
def _deploy_from_github(self, args) -> CommandResult:
|
|
534
|
+
"""Deploy skills from GitHub repository."""
|
|
535
|
+
try:
|
|
536
|
+
collection = getattr(args, "collection", None)
|
|
537
|
+
toolchain = getattr(args, "toolchain", None)
|
|
538
|
+
categories = getattr(args, "categories", None)
|
|
539
|
+
force = getattr(args, "force", False)
|
|
540
|
+
|
|
541
|
+
if collection:
|
|
542
|
+
console.print(
|
|
543
|
+
f"\n[bold cyan]Deploying skills from collection '{collection}'...[/bold cyan]\n"
|
|
544
|
+
)
|
|
545
|
+
else:
|
|
546
|
+
console.print(
|
|
547
|
+
"\n[bold cyan]Deploying skills from default collection...[/bold cyan]\n"
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
# Selective deployment is ALWAYS enabled (deploy only agent-referenced skills)
|
|
551
|
+
# This ensures only skills linked to deployed agents are deployed
|
|
552
|
+
result = self.skills_deployer.deploy_skills(
|
|
553
|
+
collection=collection,
|
|
554
|
+
toolchain=toolchain,
|
|
555
|
+
categories=categories,
|
|
556
|
+
force=force,
|
|
557
|
+
selective=True, # Always use selective deployment
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
# Display results
|
|
561
|
+
# Show selective mode summary
|
|
562
|
+
if result.get("selective_mode"):
|
|
563
|
+
total_available = result.get("total_available", 0)
|
|
564
|
+
deployed_count = result["deployed_count"]
|
|
565
|
+
console.print(
|
|
566
|
+
f"[cyan]📌 Selective deployment: {deployed_count} agent-referenced skills "
|
|
567
|
+
f"(out of {total_available} available)[/cyan]"
|
|
568
|
+
)
|
|
569
|
+
console.print(
|
|
570
|
+
"[dim]Use 'claude-mpm skills configure' to manually select skills[/dim]\n"
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
if result["deployed_count"] > 0:
|
|
574
|
+
console.print(
|
|
575
|
+
f"[green]✓ Deployed {result['deployed_count']} skill(s):[/green]"
|
|
576
|
+
)
|
|
577
|
+
for skill in result["deployed_skills"]:
|
|
578
|
+
console.print(f" • {skill}")
|
|
579
|
+
console.print()
|
|
580
|
+
|
|
581
|
+
if result["skipped_count"] > 0:
|
|
582
|
+
console.print(
|
|
583
|
+
f"[yellow]⊘ Skipped {result['skipped_count']} skill(s) (already deployed):[/yellow]"
|
|
584
|
+
)
|
|
585
|
+
for skill in result["skipped_skills"]:
|
|
586
|
+
console.print(f" • {skill}")
|
|
587
|
+
console.print("[dim]Use --force to redeploy[/dim]\n")
|
|
588
|
+
|
|
589
|
+
if result["errors"]:
|
|
590
|
+
console.print(f"[red]✗ {len(result['errors'])} error(s):[/red]")
|
|
591
|
+
for error in result["errors"]:
|
|
592
|
+
console.print(f" • {error}")
|
|
593
|
+
console.print()
|
|
594
|
+
|
|
595
|
+
# Show cleanup results
|
|
596
|
+
cleanup = result.get("cleanup", {})
|
|
597
|
+
if cleanup.get("removed_count", 0) > 0:
|
|
598
|
+
console.print(
|
|
599
|
+
f"[yellow]🧹 Removed {cleanup['removed_count']} orphaned skill(s):[/yellow]"
|
|
600
|
+
)
|
|
601
|
+
for skill in cleanup.get("removed_skills", []):
|
|
602
|
+
console.print(f" • {skill}")
|
|
603
|
+
console.print()
|
|
604
|
+
|
|
605
|
+
# Show restart instructions
|
|
606
|
+
if result["restart_instructions"]:
|
|
607
|
+
console.print(
|
|
608
|
+
Panel(
|
|
609
|
+
result["restart_instructions"],
|
|
610
|
+
title="⚠️ Important",
|
|
611
|
+
border_style="yellow",
|
|
612
|
+
)
|
|
613
|
+
)
|
|
614
|
+
console.print()
|
|
615
|
+
|
|
616
|
+
exit_code = 1 if result["errors"] else 0
|
|
617
|
+
return CommandResult(success=not result["errors"], exit_code=exit_code)
|
|
618
|
+
|
|
619
|
+
except Exception as e:
|
|
620
|
+
console.print(f"[red]Error deploying from GitHub: {e}[/red]")
|
|
621
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
622
|
+
|
|
623
|
+
def _list_available_github_skills(self, args) -> CommandResult:
|
|
624
|
+
"""List available skills from GitHub repository."""
|
|
625
|
+
try:
|
|
626
|
+
collection = getattr(args, "collection", None)
|
|
627
|
+
|
|
628
|
+
if collection:
|
|
629
|
+
console.print(
|
|
630
|
+
f"\n[bold cyan]Fetching skills from collection '{collection}'...[/bold cyan]\n"
|
|
631
|
+
)
|
|
632
|
+
else:
|
|
633
|
+
console.print(
|
|
634
|
+
"\n[bold cyan]Fetching skills from default collection...[/bold cyan]\n"
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
result = self.skills_deployer.list_available_skills(collection=collection)
|
|
638
|
+
|
|
639
|
+
if result.get("error"):
|
|
640
|
+
console.print(f"[red]Error: {result['error']}[/red]")
|
|
641
|
+
return CommandResult(
|
|
642
|
+
success=False, message=result["error"], exit_code=1
|
|
643
|
+
)
|
|
644
|
+
|
|
645
|
+
console.print(
|
|
646
|
+
f"[green]Found {result['total_skills']} available skills[/green]\n"
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
# Display by category
|
|
650
|
+
console.print("[bold yellow]By Category:[/bold yellow]\n")
|
|
651
|
+
for category, skills in sorted(result["by_category"].items()):
|
|
652
|
+
console.print(f" [cyan]{category}[/cyan] ({len(skills)} skills)")
|
|
653
|
+
if hasattr(args, "verbose") and args.verbose:
|
|
654
|
+
for skill in sorted(skills, key=lambda s: s.get("name", "")):
|
|
655
|
+
console.print(f" • {skill.get('name', 'unknown')}")
|
|
656
|
+
console.print()
|
|
657
|
+
|
|
658
|
+
# Display by toolchain
|
|
659
|
+
console.print("[bold yellow]By Toolchain:[/bold yellow]\n")
|
|
660
|
+
for toolchain, skills in sorted(result["by_toolchain"].items()):
|
|
661
|
+
console.print(f" [cyan]{toolchain}[/cyan] ({len(skills)} skills)")
|
|
662
|
+
if hasattr(args, "verbose") and args.verbose:
|
|
663
|
+
for skill in sorted(skills, key=lambda s: s.get("name", "")):
|
|
664
|
+
console.print(f" • {skill.get('name', 'unknown')}")
|
|
665
|
+
console.print()
|
|
666
|
+
|
|
667
|
+
return CommandResult(success=True, exit_code=0)
|
|
668
|
+
|
|
669
|
+
except Exception as e:
|
|
670
|
+
console.print(f"[red]Error listing available skills: {e}[/red]")
|
|
671
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
672
|
+
|
|
673
|
+
def _check_deployed_skills(self, args) -> CommandResult:
|
|
674
|
+
"""Check currently deployed skills in ~/.claude/skills/."""
|
|
675
|
+
try:
|
|
676
|
+
result = self.skills_deployer.check_deployed_skills()
|
|
677
|
+
|
|
678
|
+
console.print("\n[bold cyan]Claude Code Skills Status:[/bold cyan]\n")
|
|
679
|
+
console.print(f"[dim]Directory: {result['claude_skills_dir']}[/dim]\n")
|
|
680
|
+
|
|
681
|
+
if result["deployed_count"] == 0:
|
|
682
|
+
console.print("[yellow]No skills currently deployed.[/yellow]")
|
|
683
|
+
console.print(
|
|
684
|
+
"[dim]Use 'claude-mpm skills deploy-github' to deploy skills.[/dim]\n"
|
|
685
|
+
)
|
|
686
|
+
return CommandResult(success=True, exit_code=0)
|
|
687
|
+
|
|
688
|
+
console.print(
|
|
689
|
+
f"[green]{result['deployed_count']} skill(s) deployed:[/green]\n"
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
# Create table for deployed skills
|
|
693
|
+
table = Table(show_header=True, header_style="bold cyan")
|
|
694
|
+
table.add_column("Skill Name", style="green")
|
|
695
|
+
table.add_column("Path", style="dim")
|
|
696
|
+
|
|
697
|
+
for skill in sorted(result["skills"], key=lambda s: s["name"]):
|
|
698
|
+
table.add_row(skill["name"], skill["path"])
|
|
699
|
+
|
|
700
|
+
console.print(table)
|
|
701
|
+
console.print()
|
|
702
|
+
|
|
703
|
+
return CommandResult(success=True, exit_code=0)
|
|
704
|
+
|
|
705
|
+
except Exception as e:
|
|
706
|
+
console.print(f"[red]Error checking deployed skills: {e}[/red]")
|
|
707
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
708
|
+
|
|
709
|
+
def _remove_skills(self, args) -> CommandResult:
|
|
710
|
+
"""Remove deployed skills."""
|
|
711
|
+
try:
|
|
712
|
+
skill_names = getattr(args, "skill_names", None)
|
|
713
|
+
remove_all = getattr(args, "all", False)
|
|
714
|
+
|
|
715
|
+
if remove_all:
|
|
716
|
+
skill_names = None
|
|
717
|
+
console.print(
|
|
718
|
+
"\n[bold yellow]Removing ALL deployed skills...[/bold yellow]\n"
|
|
719
|
+
)
|
|
720
|
+
elif skill_names:
|
|
721
|
+
console.print(
|
|
722
|
+
f"\n[bold cyan]Removing {len(skill_names)} skill(s)...[/bold cyan]\n"
|
|
723
|
+
)
|
|
724
|
+
else:
|
|
725
|
+
console.print("[red]Error: Specify skill names or use --all[/red]")
|
|
726
|
+
return CommandResult(success=False, exit_code=1)
|
|
727
|
+
|
|
728
|
+
result = self.skills_deployer.remove_skills(skill_names)
|
|
729
|
+
|
|
730
|
+
if result["removed_count"] > 0:
|
|
731
|
+
console.print(
|
|
732
|
+
f"[green]✓ Removed {result['removed_count']} skill(s):[/green]"
|
|
733
|
+
)
|
|
734
|
+
for skill in result["removed_skills"]:
|
|
735
|
+
console.print(f" • {skill}")
|
|
736
|
+
console.print()
|
|
737
|
+
|
|
738
|
+
if result["errors"]:
|
|
739
|
+
console.print(f"[red]✗ {len(result['errors'])} error(s):[/red]")
|
|
740
|
+
for error in result["errors"]:
|
|
741
|
+
console.print(f" • {error}")
|
|
742
|
+
console.print()
|
|
743
|
+
|
|
744
|
+
exit_code = 1 if result["errors"] else 0
|
|
745
|
+
return CommandResult(success=not result["errors"], exit_code=exit_code)
|
|
746
|
+
|
|
747
|
+
except Exception as e:
|
|
748
|
+
console.print(f"[red]Error removing skills: {e}[/red]")
|
|
749
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
750
|
+
|
|
751
|
+
def _get_skill_metadata(self, skill_name: str) -> Optional[dict]:
|
|
752
|
+
"""Get skill metadata from SKILL.md file."""
|
|
753
|
+
try:
|
|
754
|
+
skill_path = self.skills_service.get_skill_path(skill_name)
|
|
755
|
+
skill_md = skill_path / "SKILL.md"
|
|
756
|
+
|
|
757
|
+
if not skill_md.exists():
|
|
758
|
+
return None
|
|
759
|
+
|
|
760
|
+
# Parse SKILL.md metadata
|
|
761
|
+
content = skill_md.read_text()
|
|
762
|
+
return self.skills_service.parse_skill_metadata(content)
|
|
763
|
+
|
|
764
|
+
except Exception:
|
|
765
|
+
return None
|
|
766
|
+
|
|
767
|
+
# === Collection Management Commands ===
|
|
768
|
+
|
|
769
|
+
def _collection_list(self, args) -> CommandResult:
|
|
770
|
+
"""List all configured skill collections."""
|
|
771
|
+
try:
|
|
772
|
+
result = self.skills_deployer.list_collections()
|
|
773
|
+
|
|
774
|
+
console.print("\n[bold cyan]Skill Collections:[/bold cyan]\n")
|
|
775
|
+
console.print(
|
|
776
|
+
f"[dim]Default collection: {result['default_collection']}[/dim]"
|
|
777
|
+
)
|
|
778
|
+
console.print(
|
|
779
|
+
f"[dim]Enabled: {result['enabled_count']} / {result['total_count']}[/dim]\n"
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
if not result["collections"]:
|
|
783
|
+
console.print("[yellow]No collections configured.[/yellow]")
|
|
784
|
+
console.print(
|
|
785
|
+
"[dim]Use 'claude-mpm skills collection-add' to add a collection.[/dim]\n"
|
|
786
|
+
)
|
|
787
|
+
return CommandResult(success=True, exit_code=0)
|
|
788
|
+
|
|
789
|
+
# Create table for collections
|
|
790
|
+
table = Table(show_header=True, header_style="bold cyan")
|
|
791
|
+
table.add_column("Name", style="green")
|
|
792
|
+
table.add_column("URL", style="white")
|
|
793
|
+
table.add_column("Priority", justify="center")
|
|
794
|
+
table.add_column("Enabled", justify="center")
|
|
795
|
+
table.add_column("Last Update", style="dim")
|
|
796
|
+
table.add_column("Default", justify="center")
|
|
797
|
+
|
|
798
|
+
# Sort by priority
|
|
799
|
+
sorted_collections = sorted(
|
|
800
|
+
result["collections"].items(), key=lambda x: x[1].get("priority", 999)
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
for name, config in sorted_collections:
|
|
804
|
+
enabled_icon = "✓" if config.get("enabled", True) else "✗"
|
|
805
|
+
default_icon = "⭐" if name == result["default_collection"] else ""
|
|
806
|
+
last_update = config.get("last_update") or "Never"
|
|
807
|
+
|
|
808
|
+
table.add_row(
|
|
809
|
+
name,
|
|
810
|
+
config["url"],
|
|
811
|
+
str(config.get("priority", "N/A")),
|
|
812
|
+
enabled_icon,
|
|
813
|
+
last_update,
|
|
814
|
+
default_icon,
|
|
815
|
+
)
|
|
816
|
+
|
|
817
|
+
console.print(table)
|
|
818
|
+
console.print()
|
|
819
|
+
|
|
820
|
+
return CommandResult(success=True, exit_code=0)
|
|
821
|
+
|
|
822
|
+
except Exception as e:
|
|
823
|
+
console.print(f"[red]Error listing collections: {e}[/red]")
|
|
824
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
825
|
+
|
|
826
|
+
def _collection_add(self, args) -> CommandResult:
|
|
827
|
+
"""Add a new skill collection."""
|
|
828
|
+
try:
|
|
829
|
+
name = getattr(args, "collection_name", None)
|
|
830
|
+
url = getattr(args, "collection_url", None)
|
|
831
|
+
priority = getattr(args, "priority", 99)
|
|
832
|
+
|
|
833
|
+
if not name or not url:
|
|
834
|
+
console.print("[red]Error: Collection name and URL are required[/red]")
|
|
835
|
+
console.print(
|
|
836
|
+
"[dim]Usage: claude-mpm skills collection-add NAME URL [--priority N][/dim]"
|
|
837
|
+
)
|
|
838
|
+
return CommandResult(success=False, exit_code=1)
|
|
839
|
+
|
|
840
|
+
console.print(f"\n[bold cyan]Adding collection '{name}'...[/bold cyan]\n")
|
|
841
|
+
|
|
842
|
+
result = self.skills_deployer.add_collection(name, url, priority)
|
|
843
|
+
|
|
844
|
+
console.print(f"[green]✓ {result['message']}[/green]")
|
|
845
|
+
console.print(f" [dim]URL: {url}[/dim]")
|
|
846
|
+
console.print(f" [dim]Priority: {priority}[/dim]\n")
|
|
847
|
+
|
|
848
|
+
return CommandResult(success=True, exit_code=0)
|
|
849
|
+
|
|
850
|
+
except ValueError as e:
|
|
851
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
852
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
853
|
+
except Exception as e:
|
|
854
|
+
console.print(f"[red]Unexpected error: {e}[/red]")
|
|
855
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
856
|
+
|
|
857
|
+
def _collection_remove(self, args) -> CommandResult:
|
|
858
|
+
"""Remove a skill collection."""
|
|
859
|
+
try:
|
|
860
|
+
name = getattr(args, "collection_name", None)
|
|
861
|
+
|
|
862
|
+
if not name:
|
|
863
|
+
console.print("[red]Error: Collection name is required[/red]")
|
|
864
|
+
console.print(
|
|
865
|
+
"[dim]Usage: claude-mpm skills collection-remove NAME[/dim]"
|
|
866
|
+
)
|
|
867
|
+
return CommandResult(success=False, exit_code=1)
|
|
868
|
+
|
|
869
|
+
console.print(
|
|
870
|
+
f"\n[bold yellow]Removing collection '{name}'...[/bold yellow]\n"
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
result = self.skills_deployer.remove_collection(name)
|
|
874
|
+
|
|
875
|
+
console.print(f"[green]✓ {result['message']}[/green]")
|
|
876
|
+
if result.get("directory_removed"):
|
|
877
|
+
console.print(" [dim]Collection directory removed[/dim]")
|
|
878
|
+
elif result.get("directory_error"):
|
|
879
|
+
console.print(
|
|
880
|
+
f" [yellow]Warning: {result['directory_error']}[/yellow]"
|
|
881
|
+
)
|
|
882
|
+
console.print()
|
|
883
|
+
|
|
884
|
+
return CommandResult(success=True, exit_code=0)
|
|
885
|
+
|
|
886
|
+
except ValueError as e:
|
|
887
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
888
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
889
|
+
except Exception as e:
|
|
890
|
+
console.print(f"[red]Unexpected error: {e}[/red]")
|
|
891
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
892
|
+
|
|
893
|
+
def _collection_enable(self, args) -> CommandResult:
|
|
894
|
+
"""Enable a disabled collection."""
|
|
895
|
+
try:
|
|
896
|
+
name = getattr(args, "collection_name", None)
|
|
897
|
+
|
|
898
|
+
if not name:
|
|
899
|
+
console.print("[red]Error: Collection name is required[/red]")
|
|
900
|
+
console.print(
|
|
901
|
+
"[dim]Usage: claude-mpm skills collection-enable NAME[/dim]"
|
|
902
|
+
)
|
|
903
|
+
return CommandResult(success=False, exit_code=1)
|
|
904
|
+
|
|
905
|
+
result = self.skills_deployer.enable_collection(name)
|
|
906
|
+
|
|
907
|
+
console.print(f"\n[green]✓ {result['message']}[/green]\n")
|
|
908
|
+
|
|
909
|
+
return CommandResult(success=True, exit_code=0)
|
|
910
|
+
|
|
911
|
+
except ValueError as e:
|
|
912
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
913
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
914
|
+
except Exception as e:
|
|
915
|
+
console.print(f"[red]Unexpected error: {e}[/red]")
|
|
916
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
917
|
+
|
|
918
|
+
def _collection_disable(self, args) -> CommandResult:
|
|
919
|
+
"""Disable a collection."""
|
|
920
|
+
try:
|
|
921
|
+
name = getattr(args, "collection_name", None)
|
|
922
|
+
|
|
923
|
+
if not name:
|
|
924
|
+
console.print("[red]Error: Collection name is required[/red]")
|
|
925
|
+
console.print(
|
|
926
|
+
"[dim]Usage: claude-mpm skills collection-disable NAME[/dim]"
|
|
927
|
+
)
|
|
928
|
+
return CommandResult(success=False, exit_code=1)
|
|
929
|
+
|
|
930
|
+
result = self.skills_deployer.disable_collection(name)
|
|
931
|
+
|
|
932
|
+
console.print(f"\n[green]✓ {result['message']}[/green]\n")
|
|
933
|
+
|
|
934
|
+
return CommandResult(success=True, exit_code=0)
|
|
935
|
+
|
|
936
|
+
except ValueError as e:
|
|
937
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
938
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
939
|
+
except Exception as e:
|
|
940
|
+
console.print(f"[red]Unexpected error: {e}[/red]")
|
|
941
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
942
|
+
|
|
943
|
+
def _collection_set_default(self, args) -> CommandResult:
|
|
944
|
+
"""Set the default collection."""
|
|
945
|
+
try:
|
|
946
|
+
name = getattr(args, "collection_name", None)
|
|
947
|
+
|
|
948
|
+
if not name:
|
|
949
|
+
console.print("[red]Error: Collection name is required[/red]")
|
|
950
|
+
console.print(
|
|
951
|
+
"[dim]Usage: claude-mpm skills collection-set-default NAME[/dim]"
|
|
952
|
+
)
|
|
953
|
+
return CommandResult(success=False, exit_code=1)
|
|
954
|
+
|
|
955
|
+
result = self.skills_deployer.set_default_collection(name)
|
|
956
|
+
|
|
957
|
+
console.print(f"\n[green]✓ {result['message']}[/green]")
|
|
958
|
+
if result.get("previous_default"):
|
|
959
|
+
console.print(f" [dim]Previous: {result['previous_default']}[/dim]")
|
|
960
|
+
console.print()
|
|
961
|
+
|
|
962
|
+
return CommandResult(success=True, exit_code=0)
|
|
963
|
+
|
|
964
|
+
except ValueError as e:
|
|
965
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
966
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
967
|
+
except Exception as e:
|
|
968
|
+
console.print(f"[red]Unexpected error: {e}[/red]")
|
|
969
|
+
|
|
970
|
+
def _configure_skills(self, args) -> CommandResult:
|
|
971
|
+
"""Interactive skills configuration using configuration.yaml.
|
|
972
|
+
|
|
973
|
+
Provides checkbox-based selection interface matching agents configure UX:
|
|
974
|
+
- Shows current mode (user_defined vs agent_referenced)
|
|
975
|
+
- If agent mode: shows agent-scanned skills
|
|
976
|
+
- Allows switching to user_defined mode and selecting skills
|
|
977
|
+
- Can reset to agent mode (clears user_defined)
|
|
978
|
+
- Saves selections to configuration.yaml
|
|
979
|
+
|
|
980
|
+
Configuration structure:
|
|
981
|
+
```yaml
|
|
982
|
+
skills:
|
|
983
|
+
agent_referenced: # Auto-populated from agent scan (read-only)
|
|
984
|
+
- systematic-debugging
|
|
985
|
+
- typescript-core
|
|
986
|
+
user_defined: # User override - if set, ONLY these are deployed
|
|
987
|
+
[] # Empty = use agent_referenced
|
|
988
|
+
```
|
|
989
|
+
"""
|
|
990
|
+
try:
|
|
991
|
+
from pathlib import Path
|
|
992
|
+
|
|
993
|
+
import questionary
|
|
994
|
+
import yaml
|
|
995
|
+
from questionary import Choice, Style
|
|
996
|
+
from rich.prompt import Prompt
|
|
997
|
+
|
|
998
|
+
from ...services.skills.selective_skill_deployer import (
|
|
999
|
+
get_skills_to_deploy,
|
|
1000
|
+
)
|
|
1001
|
+
|
|
1002
|
+
# Questionary style (matching agents configure)
|
|
1003
|
+
QUESTIONARY_STYLE = Style(
|
|
1004
|
+
[
|
|
1005
|
+
(
|
|
1006
|
+
"selected",
|
|
1007
|
+
"fg:#e0e0e0 bold",
|
|
1008
|
+
), # Light gray - excellent readability
|
|
1009
|
+
(
|
|
1010
|
+
"pointer",
|
|
1011
|
+
"fg:#ffd700 bold",
|
|
1012
|
+
), # Gold/yellow - highly visible pointer
|
|
1013
|
+
("highlighted", "fg:#e0e0e0"), # Light gray - clear hover state
|
|
1014
|
+
(
|
|
1015
|
+
"question",
|
|
1016
|
+
"fg:#e0e0e0 bold",
|
|
1017
|
+
), # Light gray bold - prominent questions
|
|
1018
|
+
("checkbox", "fg:#00ff00"), # Green - for checked boxes
|
|
1019
|
+
(
|
|
1020
|
+
"checkbox-selected",
|
|
1021
|
+
"fg:#00ff00 bold",
|
|
1022
|
+
), # Green bold - for checked selected boxes
|
|
1023
|
+
]
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
console.print("\n[bold cyan]Skills Configuration Manager[/bold cyan]\n")
|
|
1027
|
+
|
|
1028
|
+
# Load current configuration
|
|
1029
|
+
project_config_path = Path.cwd() / ".claude-mpm" / "configuration.yaml"
|
|
1030
|
+
skills_to_deploy, current_mode = get_skills_to_deploy(project_config_path)
|
|
1031
|
+
|
|
1032
|
+
# Display current mode and skill count
|
|
1033
|
+
console.print(f"[bold]Current Mode:[/bold] [cyan]{current_mode}[/cyan]")
|
|
1034
|
+
console.print(
|
|
1035
|
+
f"[bold]Active Skills:[/bold] {len(skills_to_deploy)} skills\n"
|
|
1036
|
+
)
|
|
1037
|
+
|
|
1038
|
+
if current_mode == "agent_referenced":
|
|
1039
|
+
console.print(
|
|
1040
|
+
"[dim]Agent mode: Skills are auto-detected from deployed agents[/dim]"
|
|
1041
|
+
)
|
|
1042
|
+
console.print(
|
|
1043
|
+
"[dim]Switch to user mode to manually select skills[/dim]\n"
|
|
1044
|
+
)
|
|
1045
|
+
else:
|
|
1046
|
+
console.print(
|
|
1047
|
+
"[dim]User mode: You've manually selected which skills to deploy[/dim]"
|
|
1048
|
+
)
|
|
1049
|
+
console.print("[dim]Reset to agent mode to use auto-detection[/dim]\n")
|
|
1050
|
+
|
|
1051
|
+
# Offer mode switching
|
|
1052
|
+
action_choices = [
|
|
1053
|
+
Choice("View current skills", value="view"),
|
|
1054
|
+
Choice("Switch to user mode (manual selection)", value="switch_user"),
|
|
1055
|
+
Choice("Reset to agent mode (auto-detection)", value="reset_agent"),
|
|
1056
|
+
Choice("Cancel", value="cancel"),
|
|
1057
|
+
]
|
|
1058
|
+
|
|
1059
|
+
action = questionary.select(
|
|
1060
|
+
"What would you like to do?",
|
|
1061
|
+
choices=action_choices,
|
|
1062
|
+
style=QUESTIONARY_STYLE,
|
|
1063
|
+
).ask()
|
|
1064
|
+
|
|
1065
|
+
if action == "cancel" or action is None:
|
|
1066
|
+
console.print("[yellow]Configuration cancelled[/yellow]")
|
|
1067
|
+
return CommandResult(success=True, exit_code=0)
|
|
1068
|
+
|
|
1069
|
+
if action == "view":
|
|
1070
|
+
# Display current skills
|
|
1071
|
+
console.print("\n[bold]Current Skills:[/bold]\n")
|
|
1072
|
+
for skill in sorted(skills_to_deploy):
|
|
1073
|
+
console.print(f" • {skill}")
|
|
1074
|
+
console.print()
|
|
1075
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1076
|
+
return CommandResult(success=True, exit_code=0)
|
|
1077
|
+
|
|
1078
|
+
if action == "reset_agent":
|
|
1079
|
+
# Reset to agent mode by clearing user_defined
|
|
1080
|
+
with open(project_config_path, encoding="utf-8") as f:
|
|
1081
|
+
config = yaml.safe_load(f) or {}
|
|
1082
|
+
|
|
1083
|
+
if "skills" not in config:
|
|
1084
|
+
config["skills"] = {}
|
|
1085
|
+
|
|
1086
|
+
config["skills"]["user_defined"] = []
|
|
1087
|
+
|
|
1088
|
+
with open(project_config_path, "w", encoding="utf-8") as f:
|
|
1089
|
+
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
|
1090
|
+
|
|
1091
|
+
console.print(
|
|
1092
|
+
"\n[green]✓ Reset to agent mode - skills will be auto-detected from agents[/green]\n"
|
|
1093
|
+
)
|
|
1094
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1095
|
+
return CommandResult(success=True, exit_code=0)
|
|
1096
|
+
|
|
1097
|
+
# Switch to user mode - manual skill selection
|
|
1098
|
+
if action == "switch_user":
|
|
1099
|
+
console.print(
|
|
1100
|
+
"\n[bold cyan]Switching to User Mode - Manual Skill Selection[/bold cyan]\n"
|
|
1101
|
+
)
|
|
1102
|
+
console.print("[dim]Fetching available skills from GitHub...[/dim]\n")
|
|
1103
|
+
|
|
1104
|
+
# Get available skills
|
|
1105
|
+
available_result = self.skills_deployer.list_available_skills()
|
|
1106
|
+
|
|
1107
|
+
if available_result.get("error"):
|
|
1108
|
+
console.print(f"[red]Error: {available_result['error']}[/red]")
|
|
1109
|
+
return CommandResult(
|
|
1110
|
+
success=False, message=available_result["error"], exit_code=1
|
|
1111
|
+
)
|
|
1112
|
+
|
|
1113
|
+
# Flatten skills by category
|
|
1114
|
+
all_skills = []
|
|
1115
|
+
for category, skills in available_result.get("by_category", {}).items():
|
|
1116
|
+
for skill in skills:
|
|
1117
|
+
skill_name = skill.get("name", "unknown")
|
|
1118
|
+
is_currently_selected = skill_name in skills_to_deploy
|
|
1119
|
+
skill_info = {
|
|
1120
|
+
"name": skill_name,
|
|
1121
|
+
"category": category,
|
|
1122
|
+
"is_selected": is_currently_selected,
|
|
1123
|
+
}
|
|
1124
|
+
all_skills.append(skill_info)
|
|
1125
|
+
|
|
1126
|
+
# Sort by selection status (selected first), then by name
|
|
1127
|
+
all_skills.sort(key=lambda s: (not s["is_selected"], s["name"]))
|
|
1128
|
+
|
|
1129
|
+
# Build checkbox choices
|
|
1130
|
+
while True:
|
|
1131
|
+
skill_choices = []
|
|
1132
|
+
|
|
1133
|
+
for skill in all_skills:
|
|
1134
|
+
skill_name = skill["name"]
|
|
1135
|
+
category = skill["category"]
|
|
1136
|
+
is_selected = skill["is_selected"]
|
|
1137
|
+
|
|
1138
|
+
# Format: "skill-name (category)"
|
|
1139
|
+
choice_text = f"{skill_name} ({category})"
|
|
1140
|
+
|
|
1141
|
+
# Pre-select if currently in skills_to_deploy
|
|
1142
|
+
choice = Choice(
|
|
1143
|
+
title=choice_text, value=skill_name, checked=is_selected
|
|
1144
|
+
)
|
|
1145
|
+
|
|
1146
|
+
skill_choices.append(choice)
|
|
1147
|
+
|
|
1148
|
+
# Display checkbox selection
|
|
1149
|
+
selected_skills = questionary.checkbox(
|
|
1150
|
+
"Select skills (Space to toggle, Enter to confirm):",
|
|
1151
|
+
choices=skill_choices,
|
|
1152
|
+
style=QUESTIONARY_STYLE,
|
|
1153
|
+
).ask()
|
|
1154
|
+
|
|
1155
|
+
if selected_skills is None:
|
|
1156
|
+
# User cancelled (Ctrl+C)
|
|
1157
|
+
console.print("[yellow]Skills configuration cancelled[/yellow]")
|
|
1158
|
+
return CommandResult(success=True, exit_code=0)
|
|
1159
|
+
|
|
1160
|
+
# Show summary
|
|
1161
|
+
console.print("\n[bold]Selected Skills:[/bold]")
|
|
1162
|
+
console.print(f" {len(selected_skills)} skills selected\n")
|
|
1163
|
+
|
|
1164
|
+
if selected_skills:
|
|
1165
|
+
for skill in sorted(selected_skills):
|
|
1166
|
+
console.print(f" • {skill}")
|
|
1167
|
+
console.print()
|
|
1168
|
+
|
|
1169
|
+
# Ask user to confirm, adjust, or cancel
|
|
1170
|
+
confirm_action = questionary.select(
|
|
1171
|
+
"\nWhat would you like to do?",
|
|
1172
|
+
choices=[
|
|
1173
|
+
Choice("Save to configuration", value="apply"),
|
|
1174
|
+
Choice("Adjust selection", value="adjust"),
|
|
1175
|
+
Choice("Cancel", value="cancel"),
|
|
1176
|
+
],
|
|
1177
|
+
default="apply",
|
|
1178
|
+
style=QUESTIONARY_STYLE,
|
|
1179
|
+
).ask()
|
|
1180
|
+
|
|
1181
|
+
if confirm_action == "cancel":
|
|
1182
|
+
console.print("[yellow]Configuration cancelled[/yellow]")
|
|
1183
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1184
|
+
return CommandResult(success=True, exit_code=0)
|
|
1185
|
+
|
|
1186
|
+
if confirm_action == "adjust":
|
|
1187
|
+
# Update selection state and loop back
|
|
1188
|
+
for skill in all_skills:
|
|
1189
|
+
skill["is_selected"] = skill["name"] in selected_skills
|
|
1190
|
+
console.print("\n[dim]Adjusting selection...[/dim]\n")
|
|
1191
|
+
continue
|
|
1192
|
+
|
|
1193
|
+
# Save to configuration.yaml
|
|
1194
|
+
with open(project_config_path, encoding="utf-8") as f:
|
|
1195
|
+
config = yaml.safe_load(f) or {}
|
|
1196
|
+
|
|
1197
|
+
if "skills" not in config:
|
|
1198
|
+
config["skills"] = {}
|
|
1199
|
+
|
|
1200
|
+
config["skills"]["user_defined"] = sorted(selected_skills)
|
|
1201
|
+
|
|
1202
|
+
with open(project_config_path, "w", encoding="utf-8") as f:
|
|
1203
|
+
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
|
1204
|
+
|
|
1205
|
+
console.print(
|
|
1206
|
+
f"\n[green]✓ Saved {len(selected_skills)} skills to user_defined mode[/green]"
|
|
1207
|
+
)
|
|
1208
|
+
console.print(
|
|
1209
|
+
"[yellow]⚠️ Important:[/yellow] Run [cyan]claude-mpm init[/cyan] to deploy these skills\n"
|
|
1210
|
+
)
|
|
1211
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1212
|
+
|
|
1213
|
+
# Exit the loop after successful save
|
|
1214
|
+
break
|
|
1215
|
+
|
|
1216
|
+
return CommandResult(success=True, exit_code=0)
|
|
1217
|
+
|
|
1218
|
+
except Exception as e:
|
|
1219
|
+
console.print(f"[red]Error in skills configuration: {e}[/red]")
|
|
1220
|
+
import traceback
|
|
1221
|
+
|
|
1222
|
+
console.print(f"[dim]{traceback.format_exc()}[/dim]")
|
|
1223
|
+
return CommandResult(success=False, message=str(e), exit_code=1)
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
def manage_skills(args) -> int:
|
|
1227
|
+
"""
|
|
1228
|
+
Main entry point for skills command.
|
|
1229
|
+
|
|
1230
|
+
Args:
|
|
1231
|
+
args: Parsed command-line arguments
|
|
1232
|
+
|
|
1233
|
+
Returns:
|
|
1234
|
+
Exit code (0 for success, non-zero for failure)
|
|
1235
|
+
"""
|
|
1236
|
+
command = SkillsManagementCommand()
|
|
1237
|
+
|
|
1238
|
+
# Validate arguments
|
|
1239
|
+
error = command.validate_args(args)
|
|
1240
|
+
if error:
|
|
1241
|
+
console.print(f"[red]Error: {error}[/red]")
|
|
1242
|
+
return 1
|
|
1243
|
+
|
|
1244
|
+
# Run command
|
|
1245
|
+
result = command.run(args)
|
|
1246
|
+
return result.exit_code
|