claude-mpm 3.4.10__py3-none-any.whl → 5.4.85__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/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_FOUNDERS_OUTPUT_STYLE.md +405 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +112 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +186 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1429 -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 +94 -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 +2501 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/agents_reconcile.py +197 -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 +3253 -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 +1398 -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 +298 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +31 -0
- claude_mpm/cli/interactive/agent_wizard.py +1927 -0
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -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 +649 -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 +1578 -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 +133 -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 +491 -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 +612 -0
- claude_mpm/core/unified_paths.py +958 -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/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/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 +1377 -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_reconciler.py +577 -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/startup_reconciliation.py +138 -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 +1205 -0
- claude_mpm/services/agents/startup_sync.py +262 -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 +711 -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 +1340 -0
- claude_mpm/services/skills/selective_skill_deployer.py +743 -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/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -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/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -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/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -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/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -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/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/pm-bug-reporting/pm-bug-reporting.md +248 -0
- claude_mpm/skills/bundled/pm/pm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/pm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/pm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/pm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/pm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/pm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -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/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -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 +1189 -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 +844 -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.85.dist-info/METADATA +1023 -0
- claude_mpm-5.4.85.dist-info/RECORD +980 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.85.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.85.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.85.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.85.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1927 @@
|
|
|
1
|
+
"""Interactive Agent Creation Wizard for Claude MPM.
|
|
2
|
+
|
|
3
|
+
This module provides a step-by-step interactive wizard for creating and managing
|
|
4
|
+
local agents with user-friendly prompts, intelligent defaults, and validation.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import re
|
|
9
|
+
import shutil
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
13
|
+
|
|
14
|
+
import questionary
|
|
15
|
+
|
|
16
|
+
from claude_mpm.cli.interactive.questionary_styles import (
|
|
17
|
+
BANNER_WIDTH,
|
|
18
|
+
MPM_STYLE,
|
|
19
|
+
print_section_header,
|
|
20
|
+
)
|
|
21
|
+
from claude_mpm.core.logging_config import get_logger
|
|
22
|
+
from claude_mpm.services.agents.local_template_manager import (
|
|
23
|
+
LocalAgentTemplate,
|
|
24
|
+
LocalAgentTemplateManager,
|
|
25
|
+
)
|
|
26
|
+
from claude_mpm.utils.agent_filters import apply_all_filters
|
|
27
|
+
|
|
28
|
+
logger = get_logger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AgentWizard:
|
|
32
|
+
"""
|
|
33
|
+
Interactive wizard for agent creation and management.
|
|
34
|
+
|
|
35
|
+
DEPRECATED: This interface has been superseded by the unified
|
|
36
|
+
configuration interface. Please use 'claude-mpm config' instead.
|
|
37
|
+
|
|
38
|
+
This class is retained for backward compatibility but will be
|
|
39
|
+
removed in a future version.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self):
|
|
43
|
+
"""Initialize the agent wizard."""
|
|
44
|
+
self.manager = LocalAgentTemplateManager()
|
|
45
|
+
self.logger = logger
|
|
46
|
+
|
|
47
|
+
# Initialize remote discovery services
|
|
48
|
+
try:
|
|
49
|
+
from claude_mpm.services.agents.git_source_manager import GitSourceManager
|
|
50
|
+
|
|
51
|
+
self.source_manager = GitSourceManager()
|
|
52
|
+
self.discovery_enabled = True
|
|
53
|
+
self.logger.debug("Remote agent discovery enabled")
|
|
54
|
+
except Exception as e:
|
|
55
|
+
self.logger.warning(f"Failed to initialize remote discovery: {e}")
|
|
56
|
+
self.source_manager = None
|
|
57
|
+
self.discovery_enabled = False
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def _calculate_column_widths(
|
|
61
|
+
terminal_width: int, columns: Dict[str, int]
|
|
62
|
+
) -> Dict[str, int]:
|
|
63
|
+
"""Calculate dynamic column widths based on terminal size.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
terminal_width: Current terminal width in characters
|
|
67
|
+
columns: Dict mapping column names to minimum widths
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Dict mapping column names to calculated widths
|
|
71
|
+
|
|
72
|
+
Design:
|
|
73
|
+
- Ensures minimum widths are respected
|
|
74
|
+
- Distributes extra space proportionally
|
|
75
|
+
- Handles narrow terminals gracefully (minimum 80 chars)
|
|
76
|
+
"""
|
|
77
|
+
# Ensure minimum terminal width
|
|
78
|
+
min_terminal_width = 80
|
|
79
|
+
terminal_width = max(terminal_width, min_terminal_width)
|
|
80
|
+
|
|
81
|
+
# Calculate total minimum width needed
|
|
82
|
+
total_min_width = sum(columns.values())
|
|
83
|
+
|
|
84
|
+
# Account for spacing between columns
|
|
85
|
+
overhead = len(columns) + 1
|
|
86
|
+
available_width = terminal_width - overhead
|
|
87
|
+
|
|
88
|
+
# If we have extra space, distribute proportionally
|
|
89
|
+
if available_width > total_min_width:
|
|
90
|
+
extra_space = available_width - total_min_width
|
|
91
|
+
total_weight = sum(columns.values())
|
|
92
|
+
|
|
93
|
+
result = {}
|
|
94
|
+
for col_name, min_width in columns.items():
|
|
95
|
+
# Distribute extra space based on minimum width proportion
|
|
96
|
+
proportion = min_width / total_weight
|
|
97
|
+
extra = int(extra_space * proportion)
|
|
98
|
+
result[col_name] = min_width + extra
|
|
99
|
+
return result
|
|
100
|
+
# Terminal too narrow, use minimum widths
|
|
101
|
+
return columns.copy()
|
|
102
|
+
|
|
103
|
+
def run_interactive_create(self) -> Tuple[bool, str]:
|
|
104
|
+
"""Run interactive agent creation wizard.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Tuple of (success, message)
|
|
108
|
+
"""
|
|
109
|
+
try:
|
|
110
|
+
print_section_header("🧙♂️", "Agent Creation Wizard", width=BANNER_WIDTH)
|
|
111
|
+
print("\nI'll guide you through creating a custom local agent.")
|
|
112
|
+
print("Press Ctrl+C anytime to cancel.\n")
|
|
113
|
+
|
|
114
|
+
# Step 1: Agent ID
|
|
115
|
+
agent_id = self._get_agent_id()
|
|
116
|
+
if not agent_id:
|
|
117
|
+
return False, "Agent creation cancelled"
|
|
118
|
+
|
|
119
|
+
# Step 2: Agent Name
|
|
120
|
+
agent_name = self._get_agent_name(agent_id)
|
|
121
|
+
|
|
122
|
+
# Step 3: Agent Type/Category
|
|
123
|
+
agent_type = self._get_agent_type()
|
|
124
|
+
|
|
125
|
+
# Step 4: Model Selection
|
|
126
|
+
model = self._get_model_choice()
|
|
127
|
+
|
|
128
|
+
# Step 5: Inheritance Option
|
|
129
|
+
parent_agent, _base_template = self._get_inheritance_option()
|
|
130
|
+
|
|
131
|
+
# Step 6: Capabilities Configuration
|
|
132
|
+
capabilities = self._get_capabilities_configuration()
|
|
133
|
+
|
|
134
|
+
# Step 7: Description
|
|
135
|
+
description = self._get_agent_description(agent_type)
|
|
136
|
+
|
|
137
|
+
# Step 8: Instructions
|
|
138
|
+
instructions = self._get_agent_instructions(
|
|
139
|
+
agent_id, agent_type, parent_agent
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Step 9: Preview Configuration
|
|
143
|
+
config_preview = self._create_preview_config(
|
|
144
|
+
agent_id,
|
|
145
|
+
agent_name,
|
|
146
|
+
agent_type,
|
|
147
|
+
model,
|
|
148
|
+
parent_agent,
|
|
149
|
+
capabilities,
|
|
150
|
+
description,
|
|
151
|
+
instructions,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Step 10: Confirmation
|
|
155
|
+
if not self._confirm_creation(config_preview):
|
|
156
|
+
return False, "Agent creation cancelled"
|
|
157
|
+
|
|
158
|
+
# Step 11: Create and Save Agent
|
|
159
|
+
template = self._create_agent_template(
|
|
160
|
+
agent_id,
|
|
161
|
+
agent_name,
|
|
162
|
+
agent_type,
|
|
163
|
+
model,
|
|
164
|
+
parent_agent,
|
|
165
|
+
capabilities,
|
|
166
|
+
description,
|
|
167
|
+
instructions,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
template_file = self.manager.save_local_template(template, "project")
|
|
171
|
+
|
|
172
|
+
print(f"\n✅ Agent '{agent_id}' created successfully!")
|
|
173
|
+
print(f"📁 Saved to: {template_file}")
|
|
174
|
+
print("\n💡 Next steps:")
|
|
175
|
+
print(
|
|
176
|
+
f" • Deploy: claude-mpm agent-manager deploy-local --agent-id {agent_id}"
|
|
177
|
+
)
|
|
178
|
+
print(f" • Edit: Edit {template_file} directly")
|
|
179
|
+
print(f" • Test: claude-mpm run --agent {agent_id}")
|
|
180
|
+
|
|
181
|
+
return True, f"Agent '{agent_id}' created successfully"
|
|
182
|
+
|
|
183
|
+
except KeyboardInterrupt:
|
|
184
|
+
print("\n\n❌ Agent creation cancelled by user")
|
|
185
|
+
return False, "Agent creation cancelled"
|
|
186
|
+
except Exception as e:
|
|
187
|
+
error_msg = f"Failed to create agent: {e}"
|
|
188
|
+
self.logger.error(error_msg, exc_info=True)
|
|
189
|
+
return False, error_msg
|
|
190
|
+
|
|
191
|
+
def _merge_agent_sources(self) -> List[Dict[str, Any]]:
|
|
192
|
+
"""
|
|
193
|
+
Merge agents from all sources with precedence: local > discovered.
|
|
194
|
+
|
|
195
|
+
Returns list of agents with metadata:
|
|
196
|
+
{
|
|
197
|
+
"agent_id": "engineer/backend/python-engineer",
|
|
198
|
+
"name": "Python Engineer",
|
|
199
|
+
"description": "...",
|
|
200
|
+
"source_type": "system" | "project",
|
|
201
|
+
"source_identifier": "bobmatnyc/claude-mpm-agents",
|
|
202
|
+
"category": "engineer/backend",
|
|
203
|
+
"deployed": True | False,
|
|
204
|
+
"path": "/path/to/agent.md"
|
|
205
|
+
}
|
|
206
|
+
"""
|
|
207
|
+
agents = {}
|
|
208
|
+
|
|
209
|
+
# Get discovered agents (system/user sources)
|
|
210
|
+
if self.discovery_enabled and self.source_manager:
|
|
211
|
+
try:
|
|
212
|
+
discovered = self.source_manager.list_cached_agents()
|
|
213
|
+
self.logger.debug(f"Discovered {len(discovered)} remote agents")
|
|
214
|
+
|
|
215
|
+
for agent in discovered:
|
|
216
|
+
agent_id = agent.get("agent_id", "")
|
|
217
|
+
if not agent_id:
|
|
218
|
+
continue
|
|
219
|
+
|
|
220
|
+
# Extract metadata
|
|
221
|
+
metadata = agent.get("metadata", {})
|
|
222
|
+
agents[agent_id] = {
|
|
223
|
+
"agent_id": agent_id,
|
|
224
|
+
"name": metadata.get("name", agent_id),
|
|
225
|
+
"description": metadata.get("description", ""),
|
|
226
|
+
"source_type": "system",
|
|
227
|
+
"source_identifier": agent.get("source", "unknown"),
|
|
228
|
+
"category": agent.get("category", ""),
|
|
229
|
+
"deployed": False, # Will be updated below
|
|
230
|
+
"path": agent.get("path", agent.get("source_file", "")),
|
|
231
|
+
}
|
|
232
|
+
except Exception as e:
|
|
233
|
+
self.logger.warning(f"Failed to discover remote agents: {e}")
|
|
234
|
+
|
|
235
|
+
# Get local agents (project-level, highest precedence)
|
|
236
|
+
local_templates = self.manager.list_local_templates()
|
|
237
|
+
for template in local_templates:
|
|
238
|
+
agent_id = template.agent_id
|
|
239
|
+
agents[agent_id] = {
|
|
240
|
+
"agent_id": agent_id,
|
|
241
|
+
"name": template.metadata.get("name", agent_id),
|
|
242
|
+
"description": template.metadata.get("description", ""),
|
|
243
|
+
"source_type": "project",
|
|
244
|
+
"source_identifier": "local",
|
|
245
|
+
"category": template.metadata.get("category", ""),
|
|
246
|
+
"deployed": True, # Local templates are deployed
|
|
247
|
+
"path": str(self._get_template_path(template)),
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
# Check deployment status for discovered agents
|
|
251
|
+
deployed_dir = Path.cwd() / ".claude" / "agents"
|
|
252
|
+
if deployed_dir.exists():
|
|
253
|
+
for agent_id, agent_data in agents.items():
|
|
254
|
+
deployed_file = deployed_dir / f"{agent_id.replace('/', '-')}.md"
|
|
255
|
+
# Also check hierarchical path
|
|
256
|
+
deployed_file_alt = deployed_dir / f"{agent_id.split('/')[-1]}.md"
|
|
257
|
+
if deployed_file.exists() or deployed_file_alt.exists():
|
|
258
|
+
agent_data["deployed"] = True
|
|
259
|
+
|
|
260
|
+
# Filter BASE_AGENT from all agent lists (1M-502 Phase 1)
|
|
261
|
+
# BASE_AGENT is a build tool, not a deployable agent
|
|
262
|
+
agent_list = list(agents.values())
|
|
263
|
+
return apply_all_filters(agent_list, filter_base=True, filter_deployed=False)
|
|
264
|
+
|
|
265
|
+
def run_interactive_manage(self) -> Tuple[bool, str]:
|
|
266
|
+
"""Run interactive agent management menu.
|
|
267
|
+
|
|
268
|
+
Returns:
|
|
269
|
+
Tuple of (success, message)
|
|
270
|
+
"""
|
|
271
|
+
try:
|
|
272
|
+
while True:
|
|
273
|
+
# Get merged agents from all sources
|
|
274
|
+
all_agents = self._merge_agent_sources()
|
|
275
|
+
|
|
276
|
+
print_section_header("🔧", "Agent Management Menu", width=BANNER_WIDTH)
|
|
277
|
+
|
|
278
|
+
if not all_agents:
|
|
279
|
+
print(
|
|
280
|
+
"\n📭 No agents found. Configure sources with 'claude-mpm agents discover'"
|
|
281
|
+
)
|
|
282
|
+
print("\n1. Create new agent")
|
|
283
|
+
print("2. Import agents")
|
|
284
|
+
print("3. Exit")
|
|
285
|
+
|
|
286
|
+
choice = input("\nSelect option [1-3]: ").strip()
|
|
287
|
+
|
|
288
|
+
if choice == "1":
|
|
289
|
+
return self.run_interactive_create()
|
|
290
|
+
if choice == "2":
|
|
291
|
+
return self._interactive_import()
|
|
292
|
+
if choice == "3":
|
|
293
|
+
return True, "Management menu exited"
|
|
294
|
+
print("❌ Invalid choice. Please try again.")
|
|
295
|
+
continue
|
|
296
|
+
|
|
297
|
+
# Show existing agents in a table with dynamic widths
|
|
298
|
+
print(f"\n📋 Found {len(all_agents)} agent(s):\n")
|
|
299
|
+
|
|
300
|
+
# Calculate dynamic column widths based on terminal size
|
|
301
|
+
terminal_width = shutil.get_terminal_size().columns
|
|
302
|
+
min_widths = {
|
|
303
|
+
"#": 4,
|
|
304
|
+
"Agent ID": 30,
|
|
305
|
+
"Name": 20,
|
|
306
|
+
"Source": 15,
|
|
307
|
+
"Status": 10,
|
|
308
|
+
}
|
|
309
|
+
widths = self._calculate_column_widths(terminal_width, min_widths)
|
|
310
|
+
|
|
311
|
+
# Print header with dynamic widths
|
|
312
|
+
print(
|
|
313
|
+
f"{'#':<{widths['#']}} "
|
|
314
|
+
f"{'Agent ID':<{widths['Agent ID']}} "
|
|
315
|
+
f"{'Name':<{widths['Name']}} "
|
|
316
|
+
f"{'Source':<{widths['Source']}} "
|
|
317
|
+
f"{'Status':<{widths['Status']}}"
|
|
318
|
+
)
|
|
319
|
+
separator_width = sum(widths.values()) + len(widths) - 1
|
|
320
|
+
print("-" * separator_width)
|
|
321
|
+
|
|
322
|
+
for i, agent in enumerate(all_agents, 1):
|
|
323
|
+
agent_id = agent["agent_id"]
|
|
324
|
+
# Truncate to fit dynamic width
|
|
325
|
+
if len(agent_id) > widths["Agent ID"]:
|
|
326
|
+
agent_id = agent_id[: widths["Agent ID"] - 1] + "…"
|
|
327
|
+
|
|
328
|
+
name = agent["name"]
|
|
329
|
+
if len(name) > widths["Name"]:
|
|
330
|
+
name = name[: widths["Name"] - 1] + "…"
|
|
331
|
+
|
|
332
|
+
source_label = (
|
|
333
|
+
f"[{agent['source_type']}] {agent['source_identifier']}"
|
|
334
|
+
)
|
|
335
|
+
if len(source_label) > widths["Source"]:
|
|
336
|
+
source_label = source_label[: widths["Source"] - 1] + "…"
|
|
337
|
+
|
|
338
|
+
status = "✓ Deployed" if agent["deployed"] else "Available"
|
|
339
|
+
|
|
340
|
+
print(
|
|
341
|
+
f"{i:<{widths['#']}} "
|
|
342
|
+
f"{agent_id:<{widths['Agent ID']}} "
|
|
343
|
+
f"{name:<{widths['Name']}} "
|
|
344
|
+
f"{source_label:<{widths['Source']}} "
|
|
345
|
+
f"{status:<{widths['Status']}}"
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# Build menu choices with arrow-key navigation
|
|
349
|
+
menu_choices = []
|
|
350
|
+
|
|
351
|
+
# Add agent viewing options (1-N)
|
|
352
|
+
for i, agent in enumerate(all_agents, 1):
|
|
353
|
+
menu_choices.append(f"{i}. View agent: {agent['agent_id']}")
|
|
354
|
+
|
|
355
|
+
# Add action options
|
|
356
|
+
menu_choices.append(f"{len(all_agents) + 1}. Deploy agent")
|
|
357
|
+
menu_choices.append(f"{len(all_agents) + 2}. Create new agent")
|
|
358
|
+
menu_choices.append(f"{len(all_agents) + 3}. Delete agent(s)")
|
|
359
|
+
menu_choices.append(f"{len(all_agents) + 4}. Import agents")
|
|
360
|
+
menu_choices.append(f"{len(all_agents) + 5}. Export all agents")
|
|
361
|
+
|
|
362
|
+
if self.discovery_enabled:
|
|
363
|
+
menu_choices.append(
|
|
364
|
+
f"{len(all_agents) + 6}. Browse & filter agents"
|
|
365
|
+
)
|
|
366
|
+
menu_choices.append(f"{len(all_agents) + 7}. Deploy preset")
|
|
367
|
+
menu_choices.append(f"{len(all_agents) + 8}. Manage agent sources")
|
|
368
|
+
menu_choices.append(f"{len(all_agents) + 9}. Exit")
|
|
369
|
+
exit_num = len(all_agents) + 9
|
|
370
|
+
else:
|
|
371
|
+
menu_choices.append(f"{len(all_agents) + 6}. Exit")
|
|
372
|
+
exit_num = len(all_agents) + 6
|
|
373
|
+
|
|
374
|
+
choice = questionary.select(
|
|
375
|
+
"Agent Management Menu:",
|
|
376
|
+
choices=menu_choices,
|
|
377
|
+
style=MPM_STYLE,
|
|
378
|
+
).ask()
|
|
379
|
+
|
|
380
|
+
if not choice: # User pressed Esc
|
|
381
|
+
return True, "Management menu exited"
|
|
382
|
+
|
|
383
|
+
# Parse choice number from "N. Description" format
|
|
384
|
+
choice_num = int(choice.split(".")[0])
|
|
385
|
+
|
|
386
|
+
if 1 <= choice_num <= len(all_agents):
|
|
387
|
+
# View agent details
|
|
388
|
+
selected_agent = all_agents[choice_num - 1]
|
|
389
|
+
self._show_agent_details(selected_agent)
|
|
390
|
+
continue
|
|
391
|
+
if choice_num == len(all_agents) + 1:
|
|
392
|
+
self._deploy_agent_interactive(all_agents)
|
|
393
|
+
elif choice_num == len(all_agents) + 2:
|
|
394
|
+
_, message = self.run_interactive_create()
|
|
395
|
+
if message:
|
|
396
|
+
print(f"\n{message}")
|
|
397
|
+
continue
|
|
398
|
+
elif choice_num == len(all_agents) + 3:
|
|
399
|
+
local_templates = self.manager.list_local_templates()
|
|
400
|
+
_, message = self._interactive_delete_menu(local_templates)
|
|
401
|
+
if message:
|
|
402
|
+
print(f"\n{message}")
|
|
403
|
+
continue
|
|
404
|
+
elif choice_num == len(all_agents) + 4:
|
|
405
|
+
_, message = self._interactive_import()
|
|
406
|
+
if message:
|
|
407
|
+
print(f"\n{message}")
|
|
408
|
+
continue
|
|
409
|
+
elif choice_num == len(all_agents) + 5:
|
|
410
|
+
_success, message = self._interactive_export()
|
|
411
|
+
if message:
|
|
412
|
+
print(f"\n{message}")
|
|
413
|
+
continue
|
|
414
|
+
elif choice_num == len(all_agents) + 6 and self.discovery_enabled:
|
|
415
|
+
self._browse_agents_interactive()
|
|
416
|
+
continue
|
|
417
|
+
elif choice_num == len(all_agents) + 7 and self.discovery_enabled:
|
|
418
|
+
self._deploy_preset_interactive()
|
|
419
|
+
continue
|
|
420
|
+
elif choice_num == len(all_agents) + 8 and self.discovery_enabled:
|
|
421
|
+
self._manage_sources_interactive()
|
|
422
|
+
continue
|
|
423
|
+
elif choice_num == exit_num:
|
|
424
|
+
return True, "Management menu exited"
|
|
425
|
+
else:
|
|
426
|
+
print("❌ Invalid choice. Please try again.")
|
|
427
|
+
|
|
428
|
+
except KeyboardInterrupt:
|
|
429
|
+
print("\n\n❌ Management menu cancelled")
|
|
430
|
+
return False, "Management cancelled"
|
|
431
|
+
except Exception as e:
|
|
432
|
+
error_msg = f"Management menu error: {e}"
|
|
433
|
+
self.logger.error(error_msg, exc_info=True)
|
|
434
|
+
return False, error_msg
|
|
435
|
+
|
|
436
|
+
def _get_agent_id(self) -> Optional[str]:
|
|
437
|
+
"""Get and validate agent ID from user."""
|
|
438
|
+
while True:
|
|
439
|
+
agent_id = input(
|
|
440
|
+
"1. What would you like to name your agent?\n Agent ID (lowercase, hyphens): "
|
|
441
|
+
).strip()
|
|
442
|
+
|
|
443
|
+
if not agent_id:
|
|
444
|
+
print("❌ Agent ID is required.")
|
|
445
|
+
continue
|
|
446
|
+
|
|
447
|
+
# Validate format
|
|
448
|
+
if (
|
|
449
|
+
not re.match(r"^[a-z][a-z0-9-]*[a-z0-9]$", agent_id)
|
|
450
|
+
or len(agent_id) > 50
|
|
451
|
+
):
|
|
452
|
+
print("❌ Agent ID must:")
|
|
453
|
+
print(" • Start with a letter")
|
|
454
|
+
print(" • Contain only lowercase letters, numbers, and hyphens")
|
|
455
|
+
print(" • End with a letter or number")
|
|
456
|
+
print(" • Be 50 characters or less")
|
|
457
|
+
continue
|
|
458
|
+
|
|
459
|
+
# Check for conflicts
|
|
460
|
+
existing_template = self.manager.get_local_template(agent_id)
|
|
461
|
+
if existing_template:
|
|
462
|
+
print(f"❌ Agent '{agent_id}' already exists.")
|
|
463
|
+
overwrite = (
|
|
464
|
+
input(" Overwrite existing agent? [y/N]: ").strip().lower()
|
|
465
|
+
)
|
|
466
|
+
if overwrite not in ["y", "yes"]:
|
|
467
|
+
continue
|
|
468
|
+
|
|
469
|
+
return agent_id
|
|
470
|
+
|
|
471
|
+
def _get_agent_name(self, agent_id: str) -> str:
|
|
472
|
+
"""Get agent display name."""
|
|
473
|
+
default_name = agent_id.replace("-", " ").title()
|
|
474
|
+
agent_name = input(
|
|
475
|
+
f"\n2. What should be the display name? [{default_name}]: "
|
|
476
|
+
).strip()
|
|
477
|
+
return agent_name or default_name
|
|
478
|
+
|
|
479
|
+
def _get_agent_type(self) -> str:
|
|
480
|
+
"""Get agent type/category from user."""
|
|
481
|
+
print("\n3. What type of agent is this?")
|
|
482
|
+
agent_types = [
|
|
483
|
+
(
|
|
484
|
+
"research",
|
|
485
|
+
"Research & Analysis",
|
|
486
|
+
"Gathering information, analyzing data, investigating topics",
|
|
487
|
+
),
|
|
488
|
+
(
|
|
489
|
+
"engineer",
|
|
490
|
+
"Implementation & Engineering",
|
|
491
|
+
"Writing code, building features, technical development",
|
|
492
|
+
),
|
|
493
|
+
(
|
|
494
|
+
"qa",
|
|
495
|
+
"Quality Assurance & Testing",
|
|
496
|
+
"Testing code, reviewing quality, finding bugs",
|
|
497
|
+
),
|
|
498
|
+
(
|
|
499
|
+
"docs",
|
|
500
|
+
"Documentation & Writing",
|
|
501
|
+
"Creating docs, writing content, technical writing",
|
|
502
|
+
),
|
|
503
|
+
(
|
|
504
|
+
"ops",
|
|
505
|
+
"Operations & Deployment",
|
|
506
|
+
"DevOps, deployment, system administration",
|
|
507
|
+
),
|
|
508
|
+
("custom", "Custom/Other", "Specialized or unique functionality"),
|
|
509
|
+
]
|
|
510
|
+
|
|
511
|
+
for i, (_type_id, name, desc) in enumerate(agent_types, 1):
|
|
512
|
+
print(f" [{i}] {name}")
|
|
513
|
+
print(f" {desc}")
|
|
514
|
+
|
|
515
|
+
while True:
|
|
516
|
+
choice = input(f"\nSelect type [1-{len(agent_types)}]: ").strip()
|
|
517
|
+
|
|
518
|
+
try:
|
|
519
|
+
choice_num = int(choice)
|
|
520
|
+
if 1 <= choice_num <= len(agent_types):
|
|
521
|
+
return agent_types[choice_num - 1][0]
|
|
522
|
+
except ValueError:
|
|
523
|
+
pass
|
|
524
|
+
|
|
525
|
+
print("❌ Invalid choice. Please select a number from the list.")
|
|
526
|
+
|
|
527
|
+
def _get_model_choice(self) -> str:
|
|
528
|
+
"""Get model selection from user."""
|
|
529
|
+
print("\n4. Which model should this agent use?")
|
|
530
|
+
models = [
|
|
531
|
+
(
|
|
532
|
+
"sonnet",
|
|
533
|
+
"claude-3-sonnet (balanced - recommended)",
|
|
534
|
+
"Good balance of capability and speed",
|
|
535
|
+
),
|
|
536
|
+
(
|
|
537
|
+
"opus",
|
|
538
|
+
"claude-3-opus (powerful)",
|
|
539
|
+
"Most capable but slower and more expensive",
|
|
540
|
+
),
|
|
541
|
+
("haiku", "claude-3-haiku (fast)", "Fastest and most economical"),
|
|
542
|
+
]
|
|
543
|
+
|
|
544
|
+
for i, (_model_id, name, desc) in enumerate(models, 1):
|
|
545
|
+
print(f" [{i}] {name}")
|
|
546
|
+
print(f" {desc}")
|
|
547
|
+
|
|
548
|
+
while True:
|
|
549
|
+
choice = input(f"\nSelect model [1-{len(models)}] [1]: ").strip() or "1"
|
|
550
|
+
|
|
551
|
+
try:
|
|
552
|
+
choice_num = int(choice)
|
|
553
|
+
if 1 <= choice_num <= len(models):
|
|
554
|
+
return models[choice_num - 1][0]
|
|
555
|
+
except ValueError:
|
|
556
|
+
pass
|
|
557
|
+
|
|
558
|
+
print("❌ Invalid choice. Please select a number from the list.")
|
|
559
|
+
|
|
560
|
+
def _get_inheritance_option(self) -> Tuple[Optional[str], Optional[Dict]]:
|
|
561
|
+
"""Get inheritance option from user."""
|
|
562
|
+
print("\n5. Would you like to inherit from an existing agent?")
|
|
563
|
+
print(" [1] No, start fresh")
|
|
564
|
+
print(" [2] Yes, inherit from system agent")
|
|
565
|
+
|
|
566
|
+
while True:
|
|
567
|
+
choice = input("\nSelect option [1-2] [1]: ").strip() or "1"
|
|
568
|
+
|
|
569
|
+
if choice == "1":
|
|
570
|
+
return None, None
|
|
571
|
+
if choice == "2":
|
|
572
|
+
return self._select_system_agent()
|
|
573
|
+
print("❌ Invalid choice. Please select 1 or 2.")
|
|
574
|
+
|
|
575
|
+
def _select_system_agent(self) -> Tuple[Optional[str], Optional[Dict]]:
|
|
576
|
+
"""Let user select a system agent to inherit from."""
|
|
577
|
+
try:
|
|
578
|
+
# Get available system agents
|
|
579
|
+
from claude_mpm.services.agents.agent_builder import AgentBuilderService
|
|
580
|
+
|
|
581
|
+
builder = AgentBuilderService()
|
|
582
|
+
templates = builder.list_available_templates()
|
|
583
|
+
|
|
584
|
+
if not templates:
|
|
585
|
+
print("❌ No system agents found to inherit from.")
|
|
586
|
+
return None, None
|
|
587
|
+
|
|
588
|
+
print("\n Select system agent to inherit from:")
|
|
589
|
+
for i, template in enumerate(templates, 1):
|
|
590
|
+
name = template.get("name", template.get("id", "Unknown"))
|
|
591
|
+
description = template.get("description", "")
|
|
592
|
+
print(f" [{i}] {name}")
|
|
593
|
+
if description:
|
|
594
|
+
print(f" {description[:80]}...")
|
|
595
|
+
|
|
596
|
+
while True:
|
|
597
|
+
choice = input(f"\n Select agent [1-{len(templates)}]: ").strip()
|
|
598
|
+
|
|
599
|
+
try:
|
|
600
|
+
choice_num = int(choice)
|
|
601
|
+
if 1 <= choice_num <= len(templates):
|
|
602
|
+
selected = templates[choice_num - 1]
|
|
603
|
+
return selected.get("id"), selected
|
|
604
|
+
except ValueError:
|
|
605
|
+
pass
|
|
606
|
+
|
|
607
|
+
print("❌ Invalid choice. Please select a number from the list.")
|
|
608
|
+
|
|
609
|
+
except Exception as e:
|
|
610
|
+
self.logger.warning(f"Failed to load system agents: {e}")
|
|
611
|
+
print("❌ Could not load system agents for inheritance.")
|
|
612
|
+
return None, None
|
|
613
|
+
|
|
614
|
+
def _get_capabilities_configuration(self) -> Dict[str, Any]:
|
|
615
|
+
"""Get capabilities configuration from user."""
|
|
616
|
+
print("\n6. What additional capabilities should this agent have?")
|
|
617
|
+
|
|
618
|
+
capabilities_options = [
|
|
619
|
+
("code_analysis", "Code analysis and review"),
|
|
620
|
+
("test_generation", "Test generation and validation"),
|
|
621
|
+
("security_scanning", "Security analysis and scanning"),
|
|
622
|
+
("performance_profiling", "Performance analysis and optimization"),
|
|
623
|
+
("documentation", "Documentation generation"),
|
|
624
|
+
("api_design", "API design and documentation"),
|
|
625
|
+
("data_processing", "Data processing and analysis"),
|
|
626
|
+
("web_scraping", "Web scraping and data extraction"),
|
|
627
|
+
]
|
|
628
|
+
|
|
629
|
+
print(" Select capabilities (enter multiple numbers separated by spaces):")
|
|
630
|
+
for i, (_cap_id, desc) in enumerate(capabilities_options, 1):
|
|
631
|
+
print(f" [{i}] {desc}")
|
|
632
|
+
|
|
633
|
+
selected_capabilities = []
|
|
634
|
+
while True:
|
|
635
|
+
choices = input(
|
|
636
|
+
f"\nSelect capabilities [1-{len(capabilities_options)}] (space-separated) [none]: "
|
|
637
|
+
).strip()
|
|
638
|
+
|
|
639
|
+
if not choices or choices.lower() == "none":
|
|
640
|
+
break
|
|
641
|
+
|
|
642
|
+
try:
|
|
643
|
+
choice_nums = [int(x) for x in choices.split()]
|
|
644
|
+
valid_choices = []
|
|
645
|
+
|
|
646
|
+
for num in choice_nums:
|
|
647
|
+
if 1 <= num <= len(capabilities_options):
|
|
648
|
+
selected_capabilities.append(capabilities_options[num - 1][0])
|
|
649
|
+
valid_choices.append(str(num))
|
|
650
|
+
|
|
651
|
+
if valid_choices:
|
|
652
|
+
print(f"✅ Selected: {', '.join(selected_capabilities)}")
|
|
653
|
+
break
|
|
654
|
+
print("❌ No valid choices selected.")
|
|
655
|
+
except ValueError:
|
|
656
|
+
print("❌ Please enter numbers separated by spaces.")
|
|
657
|
+
|
|
658
|
+
return {"specializations": selected_capabilities}
|
|
659
|
+
|
|
660
|
+
def _get_agent_description(self, agent_type: str) -> str:
|
|
661
|
+
"""Get agent description from user."""
|
|
662
|
+
type_examples = {
|
|
663
|
+
"research": "Specializes in analyzing market trends and competitive intelligence",
|
|
664
|
+
"engineer": "Focused on building scalable web applications using React and Node.js",
|
|
665
|
+
"qa": "Expert in automated testing and code quality assurance",
|
|
666
|
+
"docs": "Creates clear technical documentation and user guides",
|
|
667
|
+
"ops": "Manages CI/CD pipelines and cloud infrastructure",
|
|
668
|
+
"custom": "Handles specialized domain-specific tasks",
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
example = type_examples.get(agent_type, "Performs specialized tasks")
|
|
672
|
+
|
|
673
|
+
print("\n7. Describe this agent's specialty (one line):")
|
|
674
|
+
print(f" Example: {example}")
|
|
675
|
+
|
|
676
|
+
while True:
|
|
677
|
+
description = input("\n Description: ").strip()
|
|
678
|
+
|
|
679
|
+
if not description:
|
|
680
|
+
print("❌ Description is required.")
|
|
681
|
+
continue
|
|
682
|
+
|
|
683
|
+
if len(description) > 200:
|
|
684
|
+
print("❌ Description should be 200 characters or less.")
|
|
685
|
+
continue
|
|
686
|
+
|
|
687
|
+
return description
|
|
688
|
+
|
|
689
|
+
def _get_agent_instructions(
|
|
690
|
+
self, agent_id: str, agent_type: str, parent_agent: Optional[str]
|
|
691
|
+
) -> str:
|
|
692
|
+
"""Get agent instructions from user."""
|
|
693
|
+
print("\n8. Agent Instructions:")
|
|
694
|
+
|
|
695
|
+
if parent_agent:
|
|
696
|
+
print(f" Since you're inheriting from '{parent_agent}', you can:")
|
|
697
|
+
print(" [1] Use default inherited instructions")
|
|
698
|
+
print(" [2] Add custom instructions")
|
|
699
|
+
print(" [3] Write completely new instructions")
|
|
700
|
+
|
|
701
|
+
choice = input("\n Select option [1-3] [1]: ").strip() or "1"
|
|
702
|
+
|
|
703
|
+
if choice == "1":
|
|
704
|
+
return f"Extends the {parent_agent} agent with project-specific enhancements."
|
|
705
|
+
if choice == "2":
|
|
706
|
+
additional = input("\n Enter additional instructions: ").strip()
|
|
707
|
+
return f"Extends the {parent_agent} agent.\n\nAdditional instructions:\n{additional}"
|
|
708
|
+
|
|
709
|
+
# Get custom instructions
|
|
710
|
+
print(" Enter custom instructions for this agent:")
|
|
711
|
+
print(" (Type 'DONE' on a new line when finished)")
|
|
712
|
+
|
|
713
|
+
lines = []
|
|
714
|
+
while True:
|
|
715
|
+
line = input(" ")
|
|
716
|
+
if line.strip() == "DONE":
|
|
717
|
+
break
|
|
718
|
+
lines.append(line)
|
|
719
|
+
|
|
720
|
+
instructions = "\n".join(lines).strip()
|
|
721
|
+
|
|
722
|
+
if not instructions:
|
|
723
|
+
# Provide default based on type
|
|
724
|
+
type_defaults = {
|
|
725
|
+
"research": f"You are {agent_id}, a research and analysis agent. Focus on gathering accurate information, analyzing data, and providing well-researched insights.",
|
|
726
|
+
"engineer": f"You are {agent_id}, a software engineering agent. Focus on writing clean, efficient code and implementing technical solutions.",
|
|
727
|
+
"qa": f"You are {agent_id}, a quality assurance agent. Focus on testing, code review, and ensuring high quality standards.",
|
|
728
|
+
"docs": f"You are {agent_id}, a documentation agent. Focus on creating clear, comprehensive documentation and technical writing.",
|
|
729
|
+
"ops": f"You are {agent_id}, an operations agent. Focus on deployment, infrastructure, and system administration tasks.",
|
|
730
|
+
"custom": f"You are {agent_id}, a specialized agent. Focus on your specific domain expertise.",
|
|
731
|
+
}
|
|
732
|
+
instructions = type_defaults.get(
|
|
733
|
+
agent_type, f"You are {agent_id}, a specialized agent."
|
|
734
|
+
)
|
|
735
|
+
|
|
736
|
+
return instructions
|
|
737
|
+
|
|
738
|
+
def _create_preview_config(
|
|
739
|
+
self,
|
|
740
|
+
agent_id: str,
|
|
741
|
+
agent_name: str,
|
|
742
|
+
agent_type: str,
|
|
743
|
+
model: str,
|
|
744
|
+
parent_agent: Optional[str],
|
|
745
|
+
capabilities: Dict,
|
|
746
|
+
description: str,
|
|
747
|
+
instructions: str,
|
|
748
|
+
) -> Dict[str, Any]:
|
|
749
|
+
"""Create preview configuration dictionary."""
|
|
750
|
+
config = {
|
|
751
|
+
"agent_id": agent_id,
|
|
752
|
+
"name": agent_name,
|
|
753
|
+
"type": agent_type,
|
|
754
|
+
"model": model,
|
|
755
|
+
"description": description,
|
|
756
|
+
"capabilities": capabilities.get("specializations", []),
|
|
757
|
+
"instructions_preview": (
|
|
758
|
+
instructions[:100] + "..." if len(instructions) > 100 else instructions
|
|
759
|
+
),
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if parent_agent:
|
|
763
|
+
config["inherits_from"] = parent_agent
|
|
764
|
+
|
|
765
|
+
return config
|
|
766
|
+
|
|
767
|
+
def _confirm_creation(self, config: Dict[str, Any]) -> bool:
|
|
768
|
+
"""Show preview and get confirmation from user."""
|
|
769
|
+
print_section_header("📋", "Agent Configuration Preview", width=BANNER_WIDTH)
|
|
770
|
+
|
|
771
|
+
print(f"Agent ID: {config['agent_id']}")
|
|
772
|
+
print(f"Name: {config['name']}")
|
|
773
|
+
print(f"Type: {config['type']}")
|
|
774
|
+
print(f"Model: {config['model']}")
|
|
775
|
+
print(f"Description: {config['description']}")
|
|
776
|
+
|
|
777
|
+
if config.get("inherits_from"):
|
|
778
|
+
print(f"Inherits: {config['inherits_from']}")
|
|
779
|
+
|
|
780
|
+
if config.get("capabilities"):
|
|
781
|
+
print(f"Capabilities: {', '.join(config['capabilities'])}")
|
|
782
|
+
|
|
783
|
+
print("\nInstructions Preview:")
|
|
784
|
+
print(f" {config['instructions_preview']}")
|
|
785
|
+
|
|
786
|
+
print()
|
|
787
|
+
print("=" * BANNER_WIDTH)
|
|
788
|
+
|
|
789
|
+
while True:
|
|
790
|
+
confirm = input("\nCreate this agent? [Y/n]: ").strip().lower()
|
|
791
|
+
|
|
792
|
+
if confirm in ["", "y", "yes"]:
|
|
793
|
+
return True
|
|
794
|
+
if confirm in ["n", "no"]:
|
|
795
|
+
return False
|
|
796
|
+
print("❌ Please enter 'y' for yes or 'n' for no.")
|
|
797
|
+
|
|
798
|
+
def _create_agent_template(
|
|
799
|
+
self,
|
|
800
|
+
agent_id: str,
|
|
801
|
+
agent_name: str,
|
|
802
|
+
agent_type: str,
|
|
803
|
+
model: str,
|
|
804
|
+
parent_agent: Optional[str],
|
|
805
|
+
capabilities: Dict,
|
|
806
|
+
description: str,
|
|
807
|
+
instructions: str,
|
|
808
|
+
) -> LocalAgentTemplate:
|
|
809
|
+
"""Create the actual agent template."""
|
|
810
|
+
return self.manager.create_local_template(
|
|
811
|
+
agent_id=agent_id,
|
|
812
|
+
name=agent_name,
|
|
813
|
+
description=description,
|
|
814
|
+
instructions=instructions,
|
|
815
|
+
model=model,
|
|
816
|
+
tools="*",
|
|
817
|
+
parent_agent=parent_agent,
|
|
818
|
+
tier="project",
|
|
819
|
+
)
|
|
820
|
+
|
|
821
|
+
def _manage_single_agent(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
822
|
+
"""Manage a single agent."""
|
|
823
|
+
print(f"\n🔧 Managing Agent: {template.agent_id}")
|
|
824
|
+
print(f" Name: {template.metadata.get('name', template.agent_id)}")
|
|
825
|
+
print(f" Tier: {template.tier}")
|
|
826
|
+
print(f" Version: {template.agent_version}")
|
|
827
|
+
|
|
828
|
+
print("\n1. View details")
|
|
829
|
+
print("2. Edit configuration")
|
|
830
|
+
print("3. Deploy agent")
|
|
831
|
+
print("4. Delete agent")
|
|
832
|
+
print("5. Export agent")
|
|
833
|
+
print("6. Back to menu")
|
|
834
|
+
|
|
835
|
+
choice = input("\nSelect option [1-6]: ").strip()
|
|
836
|
+
|
|
837
|
+
if choice == "1":
|
|
838
|
+
return self._view_agent_details(template)
|
|
839
|
+
if choice == "2":
|
|
840
|
+
return self._edit_agent_config(template)
|
|
841
|
+
if choice == "3":
|
|
842
|
+
return self._deploy_single_agent(template)
|
|
843
|
+
if choice == "4":
|
|
844
|
+
return self._delete_agent(template)
|
|
845
|
+
if choice == "5":
|
|
846
|
+
return self._export_single_agent(template)
|
|
847
|
+
if choice == "6":
|
|
848
|
+
return True, "Back to menu"
|
|
849
|
+
return False, "Invalid choice"
|
|
850
|
+
|
|
851
|
+
def _view_agent_details(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
852
|
+
"""View detailed agent information."""
|
|
853
|
+
print(f"\n📄 Agent Details: {template.agent_id}")
|
|
854
|
+
print("=" * 50)
|
|
855
|
+
print(f"Name: {template.metadata.get('name', template.agent_id)}")
|
|
856
|
+
print(f"Version: {template.agent_version}")
|
|
857
|
+
print(f"Author: {template.author}")
|
|
858
|
+
print(f"Tier: {template.tier}")
|
|
859
|
+
print(f"Model: {template.capabilities.get('model', 'unknown')}")
|
|
860
|
+
print(f"Tools: {template.capabilities.get('tools', '*')}")
|
|
861
|
+
|
|
862
|
+
if template.parent_agent:
|
|
863
|
+
print(f"Inherits: {template.parent_agent}")
|
|
864
|
+
|
|
865
|
+
print("\nDescription:")
|
|
866
|
+
print(f" {template.metadata.get('description', 'No description')}")
|
|
867
|
+
|
|
868
|
+
print("\nInstructions:")
|
|
869
|
+
print(
|
|
870
|
+
f" {template.instructions[:200]}{'...' if len(template.instructions) > 200 else ''}"
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
input("\nPress Enter to continue...")
|
|
874
|
+
return True, "Agent details viewed"
|
|
875
|
+
|
|
876
|
+
def _edit_agent_config(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
877
|
+
"""Edit agent configuration."""
|
|
878
|
+
print(f"\n✏️ Editing Agent: {template.agent_id}")
|
|
879
|
+
print("This will open the JSON file in your default editor.")
|
|
880
|
+
|
|
881
|
+
confirm = input("Continue? [y/N]: ").strip().lower()
|
|
882
|
+
if confirm not in ["y", "yes"]:
|
|
883
|
+
return False, "Edit cancelled"
|
|
884
|
+
|
|
885
|
+
# Get template file path
|
|
886
|
+
if template.tier == "project":
|
|
887
|
+
template_file = (
|
|
888
|
+
self.manager.project_agents_dir / f"{template.agent_id}.json"
|
|
889
|
+
)
|
|
890
|
+
else:
|
|
891
|
+
template_file = self.manager.user_agents_dir / f"{template.agent_id}.json"
|
|
892
|
+
|
|
893
|
+
# Open in editor
|
|
894
|
+
import os
|
|
895
|
+
import subprocess
|
|
896
|
+
|
|
897
|
+
editor = os.environ.get("EDITOR", "nano")
|
|
898
|
+
try:
|
|
899
|
+
subprocess.run([editor, str(template_file)], check=True)
|
|
900
|
+
return True, f"Agent {template.agent_id} edited"
|
|
901
|
+
except Exception as e:
|
|
902
|
+
return False, f"Failed to open editor: {e}"
|
|
903
|
+
|
|
904
|
+
def _deploy_single_agent(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
905
|
+
"""Deploy a single agent."""
|
|
906
|
+
try:
|
|
907
|
+
from claude_mpm.services.agents.deployment.local_template_deployment import (
|
|
908
|
+
LocalTemplateDeploymentService,
|
|
909
|
+
)
|
|
910
|
+
|
|
911
|
+
service = LocalTemplateDeploymentService()
|
|
912
|
+
success = service.deploy_single_local_template(
|
|
913
|
+
template.agent_id, force=True
|
|
914
|
+
)
|
|
915
|
+
|
|
916
|
+
if success:
|
|
917
|
+
return True, f"Agent '{template.agent_id}' deployed successfully"
|
|
918
|
+
return False, f"Failed to deploy agent '{template.agent_id}'"
|
|
919
|
+
|
|
920
|
+
except Exception as e:
|
|
921
|
+
return False, f"Deployment error: {e}"
|
|
922
|
+
|
|
923
|
+
def _delete_agent(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
924
|
+
"""Delete an agent with comprehensive options."""
|
|
925
|
+
print(f"\n🗑️ Delete Agent: {template.agent_id}")
|
|
926
|
+
print(f" Name: {template.metadata.get('name', template.agent_id)}")
|
|
927
|
+
print(f" Tier: {template.tier}")
|
|
928
|
+
print(f" Location: {self._get_template_path(template)}")
|
|
929
|
+
|
|
930
|
+
# Check if deployed
|
|
931
|
+
deployment_file = Path.cwd() / ".claude" / "agents" / f"{template.agent_id}.md"
|
|
932
|
+
if deployment_file.exists():
|
|
933
|
+
print(f" Deployed: Yes ({deployment_file})")
|
|
934
|
+
else:
|
|
935
|
+
print(" Deployed: No")
|
|
936
|
+
|
|
937
|
+
print("\nDelete options:")
|
|
938
|
+
print(" [1] Delete template and deployment")
|
|
939
|
+
print(" [2] Delete template only (keep deployment)")
|
|
940
|
+
print(" [3] Cancel")
|
|
941
|
+
|
|
942
|
+
option = input("\nSelect option [1-3]: ").strip()
|
|
943
|
+
|
|
944
|
+
if option == "3":
|
|
945
|
+
return False, "Deletion cancelled"
|
|
946
|
+
|
|
947
|
+
delete_deployment = option == "1"
|
|
948
|
+
|
|
949
|
+
# Confirmation
|
|
950
|
+
print("\n⚠️ This will permanently delete:")
|
|
951
|
+
print(f" - Template: {self._get_template_path(template)}")
|
|
952
|
+
if delete_deployment and deployment_file.exists():
|
|
953
|
+
print(f" - Deployment: {deployment_file}")
|
|
954
|
+
|
|
955
|
+
# Ask about backup
|
|
956
|
+
backup_choice = (
|
|
957
|
+
input("\nCreate backup before deletion? [y/N]: ").strip().lower()
|
|
958
|
+
)
|
|
959
|
+
backup_first = backup_choice in ["y", "yes"]
|
|
960
|
+
|
|
961
|
+
confirm = input("\nAre you sure? Type 'DELETE' to confirm: ").strip()
|
|
962
|
+
|
|
963
|
+
if confirm != "DELETE":
|
|
964
|
+
return False, "Deletion cancelled"
|
|
965
|
+
|
|
966
|
+
# Perform deletion
|
|
967
|
+
result = self.manager.delete_local_template(
|
|
968
|
+
agent_id=template.agent_id,
|
|
969
|
+
tier=template.tier,
|
|
970
|
+
delete_deployment=delete_deployment,
|
|
971
|
+
backup_first=backup_first,
|
|
972
|
+
)
|
|
973
|
+
|
|
974
|
+
if result["success"]:
|
|
975
|
+
message = f"✅ Agent '{template.agent_id}' deleted successfully"
|
|
976
|
+
if result["backup_location"]:
|
|
977
|
+
message += f"\n Backup saved to: {result['backup_location']}"
|
|
978
|
+
message += f"\n Removed {len(result['deleted_files'])} file(s)"
|
|
979
|
+
return True, message
|
|
980
|
+
errors = "\n".join(result["errors"])
|
|
981
|
+
return False, f"Failed to delete agent:\n{errors}"
|
|
982
|
+
|
|
983
|
+
def _export_single_agent(self, template: LocalAgentTemplate) -> Tuple[bool, str]:
|
|
984
|
+
"""Export a single agent."""
|
|
985
|
+
output_dir = Path("./exported-agents")
|
|
986
|
+
output_dir.mkdir(exist_ok=True)
|
|
987
|
+
|
|
988
|
+
output_file = output_dir / f"{template.agent_id}.json"
|
|
989
|
+
|
|
990
|
+
with output_file.open("w") as f:
|
|
991
|
+
json.dump(template.to_json(), f, indent=2)
|
|
992
|
+
|
|
993
|
+
return True, f"Agent exported to {output_file}"
|
|
994
|
+
|
|
995
|
+
def _interactive_import(self) -> Tuple[bool, str]:
|
|
996
|
+
"""Interactive agent import."""
|
|
997
|
+
input_dir = input("\nEnter directory path to import from: ").strip()
|
|
998
|
+
|
|
999
|
+
if not input_dir:
|
|
1000
|
+
return False, "Import cancelled"
|
|
1001
|
+
|
|
1002
|
+
input_path = Path(input_dir)
|
|
1003
|
+
if not input_path.exists():
|
|
1004
|
+
return False, f"Directory does not exist: {input_path}"
|
|
1005
|
+
|
|
1006
|
+
# Select tier
|
|
1007
|
+
print("\nImport to which tier?")
|
|
1008
|
+
print(" [1] Project (recommended)")
|
|
1009
|
+
print(" [2] User")
|
|
1010
|
+
|
|
1011
|
+
tier_choice = input("Select tier [1-2] [1]: ").strip() or "1"
|
|
1012
|
+
tier = "project" if tier_choice == "1" else "user"
|
|
1013
|
+
|
|
1014
|
+
count = self.manager.import_local_templates(input_path, tier)
|
|
1015
|
+
return True, f"Imported {count} agents from {input_path}"
|
|
1016
|
+
|
|
1017
|
+
def _interactive_export(self) -> Tuple[bool, str]:
|
|
1018
|
+
"""Interactive agent export."""
|
|
1019
|
+
output_dir = input(
|
|
1020
|
+
"\nEnter directory path to export to [./exported-agents]: "
|
|
1021
|
+
).strip()
|
|
1022
|
+
|
|
1023
|
+
if not output_dir:
|
|
1024
|
+
output_dir = "./exported-agents"
|
|
1025
|
+
|
|
1026
|
+
output_path = Path(output_dir)
|
|
1027
|
+
count = self.manager.export_local_templates(output_path)
|
|
1028
|
+
return True, f"Exported {count} agents to {output_path}"
|
|
1029
|
+
|
|
1030
|
+
def _get_template_path(self, template: LocalAgentTemplate) -> Path:
|
|
1031
|
+
"""Get the file path for a template."""
|
|
1032
|
+
if template.tier == "project":
|
|
1033
|
+
return self.manager.project_agents_dir / f"{template.agent_id}.json"
|
|
1034
|
+
return self.manager.user_agents_dir / f"{template.agent_id}.json"
|
|
1035
|
+
|
|
1036
|
+
def _interactive_delete_menu(self, templates: list) -> Tuple[bool, str]:
|
|
1037
|
+
"""Interactive deletion menu for multiple agents."""
|
|
1038
|
+
print_section_header("🗑️", "Delete Agents", width=BANNER_WIDTH)
|
|
1039
|
+
|
|
1040
|
+
if not templates:
|
|
1041
|
+
return False, "No agents available to delete"
|
|
1042
|
+
|
|
1043
|
+
print("\nAvailable agents:")
|
|
1044
|
+
for i, template in enumerate(templates, 1):
|
|
1045
|
+
tier_icon = "🏢" if template.tier == "project" else "👤"
|
|
1046
|
+
print(
|
|
1047
|
+
f" [{i}] {tier_icon} {template.agent_id} - {template.metadata.get('name', template.agent_id)}"
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
print("\n[all] Select all agents")
|
|
1051
|
+
print("[0] Cancel")
|
|
1052
|
+
|
|
1053
|
+
selection = input(
|
|
1054
|
+
"\nSelect agents to delete (comma-separated numbers or 'all'): "
|
|
1055
|
+
).strip()
|
|
1056
|
+
|
|
1057
|
+
if selection == "0" or not selection:
|
|
1058
|
+
return False, "Deletion cancelled"
|
|
1059
|
+
|
|
1060
|
+
# Parse selection
|
|
1061
|
+
selected_templates = []
|
|
1062
|
+
if selection.lower() == "all":
|
|
1063
|
+
selected_templates = templates
|
|
1064
|
+
else:
|
|
1065
|
+
try:
|
|
1066
|
+
indices = [int(x.strip()) - 1 for x in selection.split(",")]
|
|
1067
|
+
for idx in indices:
|
|
1068
|
+
if 0 <= idx < len(templates):
|
|
1069
|
+
selected_templates.append(templates[idx])
|
|
1070
|
+
else:
|
|
1071
|
+
print(f"⚠️ Invalid selection: {idx + 1}")
|
|
1072
|
+
except ValueError:
|
|
1073
|
+
return False, "Invalid selection format"
|
|
1074
|
+
|
|
1075
|
+
if not selected_templates:
|
|
1076
|
+
return False, "No valid agents selected"
|
|
1077
|
+
|
|
1078
|
+
# Show what will be deleted
|
|
1079
|
+
print(f"\n📋 Selected {len(selected_templates)} agent(s) for deletion:")
|
|
1080
|
+
for template in selected_templates:
|
|
1081
|
+
tier_icon = "🏢" if template.tier == "project" else "👤"
|
|
1082
|
+
print(f" - {tier_icon} {template.agent_id}")
|
|
1083
|
+
|
|
1084
|
+
# Deletion options
|
|
1085
|
+
print("\nDelete options:")
|
|
1086
|
+
print(" [1] Delete templates and deployments")
|
|
1087
|
+
print(" [2] Delete templates only (keep deployments)")
|
|
1088
|
+
print(" [3] Cancel")
|
|
1089
|
+
|
|
1090
|
+
option = input("\nSelect option [1-3]: ").strip()
|
|
1091
|
+
|
|
1092
|
+
if option == "3":
|
|
1093
|
+
return False, "Deletion cancelled"
|
|
1094
|
+
|
|
1095
|
+
delete_deployment = option == "1"
|
|
1096
|
+
|
|
1097
|
+
# Ask about backup
|
|
1098
|
+
backup_choice = (
|
|
1099
|
+
input("\nCreate backups before deletion? [y/N]: ").strip().lower()
|
|
1100
|
+
)
|
|
1101
|
+
backup_first = backup_choice in ["y", "yes"]
|
|
1102
|
+
|
|
1103
|
+
# Strong confirmation for multiple deletions
|
|
1104
|
+
if len(selected_templates) > 1:
|
|
1105
|
+
print(f"\n⚠️ WARNING: This will delete {len(selected_templates)} agents!")
|
|
1106
|
+
|
|
1107
|
+
confirm = input("\nAre you sure? Type 'DELETE ALL' to confirm: ").strip()
|
|
1108
|
+
|
|
1109
|
+
if confirm != "DELETE ALL":
|
|
1110
|
+
return False, "Deletion cancelled"
|
|
1111
|
+
|
|
1112
|
+
# Perform bulk deletion
|
|
1113
|
+
agent_ids = [t.agent_id for t in selected_templates]
|
|
1114
|
+
results = self.manager.delete_multiple_templates(
|
|
1115
|
+
agent_ids=agent_ids,
|
|
1116
|
+
tier="all", # Check all tiers since we have mixed selection
|
|
1117
|
+
delete_deployment=delete_deployment,
|
|
1118
|
+
backup_first=backup_first,
|
|
1119
|
+
)
|
|
1120
|
+
|
|
1121
|
+
# Format results
|
|
1122
|
+
if results["successful"]:
|
|
1123
|
+
message = (
|
|
1124
|
+
f"✅ Successfully deleted {len(results['successful'])} agent(s):\n"
|
|
1125
|
+
)
|
|
1126
|
+
for agent_id in results["successful"]:
|
|
1127
|
+
message += f" - {agent_id}\n"
|
|
1128
|
+
else:
|
|
1129
|
+
message = ""
|
|
1130
|
+
|
|
1131
|
+
if results["failed"]:
|
|
1132
|
+
message += f"❌ Failed to delete {len(results['failed'])} agent(s):\n"
|
|
1133
|
+
for agent_id in results["failed"]:
|
|
1134
|
+
errors = results["details"][agent_id]["errors"]
|
|
1135
|
+
message += f" - {agent_id}: {', '.join(errors)}\n"
|
|
1136
|
+
|
|
1137
|
+
return len(results["successful"]) > 0, message.strip()
|
|
1138
|
+
|
|
1139
|
+
def _show_agent_details(self, agent: Dict[str, Any]) -> None:
|
|
1140
|
+
"""Show detailed information about an agent.
|
|
1141
|
+
|
|
1142
|
+
Args:
|
|
1143
|
+
agent: Agent metadata dictionary
|
|
1144
|
+
"""
|
|
1145
|
+
print_section_header(
|
|
1146
|
+
"📄", f"Agent Details: {agent['agent_id']}", width=BANNER_WIDTH
|
|
1147
|
+
)
|
|
1148
|
+
print(f"Name: {agent['name']}")
|
|
1149
|
+
print(f"Category: {agent['category'] or 'N/A'}")
|
|
1150
|
+
print(f"Source: [{agent['source_type']}] {agent['source_identifier']}")
|
|
1151
|
+
print(f"Status: {'✓ Deployed' if agent['deployed'] else 'Available'}")
|
|
1152
|
+
print(f"Path: {agent['path']}")
|
|
1153
|
+
|
|
1154
|
+
if agent["description"]:
|
|
1155
|
+
print("\nDescription:")
|
|
1156
|
+
print(
|
|
1157
|
+
f" {agent['description'][:200]}{'...' if len(agent['description']) > 200 else ''}"
|
|
1158
|
+
)
|
|
1159
|
+
|
|
1160
|
+
input("\nPress Enter to continue...")
|
|
1161
|
+
|
|
1162
|
+
def _deploy_agent_interactive(self, available_agents: List[Dict[str, Any]]):
|
|
1163
|
+
"""Interactive agent deployment.
|
|
1164
|
+
|
|
1165
|
+
Args:
|
|
1166
|
+
available_agents: List of all available agents
|
|
1167
|
+
"""
|
|
1168
|
+
# Filter to non-deployed agents using improved detection (1M-502 Phase 1)
|
|
1169
|
+
# This checks both .claude-mpm/agents/ and .claude/agents/
|
|
1170
|
+
deployable = apply_all_filters(
|
|
1171
|
+
available_agents, filter_base=True, filter_deployed=True
|
|
1172
|
+
)
|
|
1173
|
+
|
|
1174
|
+
if not deployable:
|
|
1175
|
+
print("\n✅ All agents are already deployed!")
|
|
1176
|
+
input("\nPress Enter to continue...")
|
|
1177
|
+
return
|
|
1178
|
+
|
|
1179
|
+
print_section_header("📦", "Deploy Agent", width=BANNER_WIDTH)
|
|
1180
|
+
print(f"\n{len(deployable)} agent(s) available to deploy:\n")
|
|
1181
|
+
|
|
1182
|
+
# Build agent selection choices with arrow-key navigation
|
|
1183
|
+
agent_choices = [
|
|
1184
|
+
f"{i}. {agent['agent_id']} - {agent['description'][:60]}{'...' if len(agent['description']) > 60 else ''}"
|
|
1185
|
+
for i, agent in enumerate(deployable, 1)
|
|
1186
|
+
]
|
|
1187
|
+
|
|
1188
|
+
choice = questionary.select(
|
|
1189
|
+
"Select agent to deploy:", choices=agent_choices, style=MPM_STYLE
|
|
1190
|
+
).ask()
|
|
1191
|
+
|
|
1192
|
+
if not choice: # User pressed Esc
|
|
1193
|
+
return
|
|
1194
|
+
|
|
1195
|
+
# Parse agent index from "N. agent_id - description" format
|
|
1196
|
+
idx = int(choice.split(".")[0]) - 1
|
|
1197
|
+
agent = deployable[idx]
|
|
1198
|
+
|
|
1199
|
+
# Deploy agent using deployment service
|
|
1200
|
+
print(f"\n🚀 Deploying {agent['agent_id']}...")
|
|
1201
|
+
|
|
1202
|
+
try:
|
|
1203
|
+
# Use SingleAgentDeployer for deployment
|
|
1204
|
+
from claude_mpm.services.agents.deployment.agent_template_builder import (
|
|
1205
|
+
AgentTemplateBuilder,
|
|
1206
|
+
)
|
|
1207
|
+
from claude_mpm.services.agents.deployment.agent_version_manager import (
|
|
1208
|
+
AgentVersionManager,
|
|
1209
|
+
)
|
|
1210
|
+
from claude_mpm.services.agents.deployment.deployment_results_manager import (
|
|
1211
|
+
DeploymentResultsManager,
|
|
1212
|
+
)
|
|
1213
|
+
from claude_mpm.services.agents.deployment.single_agent_deployer import (
|
|
1214
|
+
SingleAgentDeployer,
|
|
1215
|
+
)
|
|
1216
|
+
|
|
1217
|
+
# Initialize deployment services
|
|
1218
|
+
template_builder = AgentTemplateBuilder()
|
|
1219
|
+
version_manager = AgentVersionManager()
|
|
1220
|
+
results_manager = DeploymentResultsManager(self.logger)
|
|
1221
|
+
deployer = SingleAgentDeployer(
|
|
1222
|
+
template_builder=template_builder,
|
|
1223
|
+
version_manager=version_manager,
|
|
1224
|
+
results_manager=results_manager,
|
|
1225
|
+
logger=self.logger,
|
|
1226
|
+
)
|
|
1227
|
+
|
|
1228
|
+
# Prepare deployment parameters
|
|
1229
|
+
template_path = Path(agent["path"])
|
|
1230
|
+
target_dir = Path.cwd() / ".claude" / "agents"
|
|
1231
|
+
|
|
1232
|
+
# Find base_agent.json in multiple possible locations
|
|
1233
|
+
base_agent_candidates = [
|
|
1234
|
+
Path.home()
|
|
1235
|
+
/ ".claude-mpm"
|
|
1236
|
+
/ "agents"
|
|
1237
|
+
/ "templates"
|
|
1238
|
+
/ "base_agent.json",
|
|
1239
|
+
Path.home() / ".claude-mpm" / "cache" / "base_agent.json",
|
|
1240
|
+
Path(__file__).parent.parent.parent
|
|
1241
|
+
/ "agents"
|
|
1242
|
+
/ "templates"
|
|
1243
|
+
/ "base_agent.json",
|
|
1244
|
+
]
|
|
1245
|
+
base_agent_path = None
|
|
1246
|
+
for candidate in base_agent_candidates:
|
|
1247
|
+
if candidate.exists():
|
|
1248
|
+
base_agent_path = candidate
|
|
1249
|
+
break
|
|
1250
|
+
|
|
1251
|
+
if not base_agent_path:
|
|
1252
|
+
base_agent_path = base_agent_candidates[
|
|
1253
|
+
0
|
|
1254
|
+
] # Use default even if not exists
|
|
1255
|
+
|
|
1256
|
+
# Deploy the agent
|
|
1257
|
+
success = deployer.deploy_agent(
|
|
1258
|
+
agent_name=agent["agent_id"],
|
|
1259
|
+
templates_dir=template_path.parent,
|
|
1260
|
+
target_dir=target_dir,
|
|
1261
|
+
base_agent_path=base_agent_path,
|
|
1262
|
+
force_rebuild=True,
|
|
1263
|
+
working_directory=Path.cwd(),
|
|
1264
|
+
)
|
|
1265
|
+
|
|
1266
|
+
if success:
|
|
1267
|
+
print(f"\n✅ Successfully deployed {agent['agent_id']}")
|
|
1268
|
+
else:
|
|
1269
|
+
print(f"\n❌ Failed to deploy {agent['agent_id']}")
|
|
1270
|
+
|
|
1271
|
+
except Exception as e:
|
|
1272
|
+
self.logger.error(f"Deployment failed: {e}", exc_info=True)
|
|
1273
|
+
print(f"\n❌ Deployment error: {e}")
|
|
1274
|
+
|
|
1275
|
+
input("\nPress Enter to continue...")
|
|
1276
|
+
|
|
1277
|
+
def _browse_agents_interactive(self):
|
|
1278
|
+
"""Interactive agent browsing with filters."""
|
|
1279
|
+
if not self.discovery_enabled or not self.source_manager:
|
|
1280
|
+
print("\n❌ Discovery service not available")
|
|
1281
|
+
input("\nPress Enter to continue...")
|
|
1282
|
+
return
|
|
1283
|
+
|
|
1284
|
+
while True:
|
|
1285
|
+
print_section_header("🔍", "Browse & Filter Agents", width=BANNER_WIDTH)
|
|
1286
|
+
|
|
1287
|
+
# Show filter menu with arrow-key navigation
|
|
1288
|
+
print("\n[bold]Filter by:[/bold]")
|
|
1289
|
+
|
|
1290
|
+
filter_choices = [
|
|
1291
|
+
"1. Category (engineer/backend, qa, ops, etc.)",
|
|
1292
|
+
"2. Language (python, typescript, rust, etc.)",
|
|
1293
|
+
"3. Framework (react, nextjs, flask, etc.)",
|
|
1294
|
+
"4. Show all agents",
|
|
1295
|
+
"← Back to main menu",
|
|
1296
|
+
]
|
|
1297
|
+
|
|
1298
|
+
choice = questionary.select(
|
|
1299
|
+
"Browse & Filter Agents:",
|
|
1300
|
+
choices=filter_choices,
|
|
1301
|
+
style=MPM_STYLE,
|
|
1302
|
+
).ask()
|
|
1303
|
+
|
|
1304
|
+
if not choice or "Back" in choice:
|
|
1305
|
+
break
|
|
1306
|
+
|
|
1307
|
+
# Parse choice number if it starts with a digit
|
|
1308
|
+
if choice[0].isdigit():
|
|
1309
|
+
choice_num = choice.split(".")[0]
|
|
1310
|
+
else:
|
|
1311
|
+
break
|
|
1312
|
+
|
|
1313
|
+
filtered_agents = []
|
|
1314
|
+
filter_description = ""
|
|
1315
|
+
|
|
1316
|
+
if choice_num == "1":
|
|
1317
|
+
# Category filtering with arrow-key navigation
|
|
1318
|
+
categories = [
|
|
1319
|
+
"engineer/backend",
|
|
1320
|
+
"engineer/frontend",
|
|
1321
|
+
"qa",
|
|
1322
|
+
"ops",
|
|
1323
|
+
"documentation",
|
|
1324
|
+
"universal",
|
|
1325
|
+
]
|
|
1326
|
+
|
|
1327
|
+
cat_choices = [f"{idx}. {cat}" for idx, cat in enumerate(categories, 1)]
|
|
1328
|
+
|
|
1329
|
+
cat_choice = questionary.select(
|
|
1330
|
+
"Select category:", choices=cat_choices, style=MPM_STYLE
|
|
1331
|
+
).ask()
|
|
1332
|
+
|
|
1333
|
+
if not cat_choice: # User pressed Esc
|
|
1334
|
+
continue
|
|
1335
|
+
|
|
1336
|
+
# Parse category from "N. category" format
|
|
1337
|
+
cat_idx = int(cat_choice.split(".")[0]) - 1
|
|
1338
|
+
category = categories[cat_idx]
|
|
1339
|
+
all_agents = self._merge_agent_sources()
|
|
1340
|
+
filtered_agents = [
|
|
1341
|
+
a for a in all_agents if a.get("category", "").startswith(category)
|
|
1342
|
+
]
|
|
1343
|
+
filter_description = f"Category: {category}"
|
|
1344
|
+
|
|
1345
|
+
elif choice_num == "2":
|
|
1346
|
+
# Language filtering (using AUTO-DEPLOY-INDEX if available)
|
|
1347
|
+
language = input(
|
|
1348
|
+
"\nEnter language (python, typescript, rust, go, etc.): "
|
|
1349
|
+
).strip()
|
|
1350
|
+
|
|
1351
|
+
try:
|
|
1352
|
+
# Find AUTO-DEPLOY-INDEX.md in agent repository
|
|
1353
|
+
from claude_mpm.services.agents.auto_deploy_index_parser import (
|
|
1354
|
+
AutoDeployIndexParser,
|
|
1355
|
+
)
|
|
1356
|
+
|
|
1357
|
+
index_path = (
|
|
1358
|
+
Path.home()
|
|
1359
|
+
/ ".claude-mpm"
|
|
1360
|
+
/ "cache"
|
|
1361
|
+
/ "agents"
|
|
1362
|
+
/ "bobmatnyc"
|
|
1363
|
+
/ "claude-mpm-agents"
|
|
1364
|
+
/ "AUTO-DEPLOY-INDEX.md"
|
|
1365
|
+
)
|
|
1366
|
+
if not index_path.exists():
|
|
1367
|
+
print(
|
|
1368
|
+
f"[yellow]Could not find AUTO-DEPLOY-INDEX.md at: {index_path}[/yellow]"
|
|
1369
|
+
)
|
|
1370
|
+
input("\nPress Enter to continue...")
|
|
1371
|
+
continue
|
|
1372
|
+
|
|
1373
|
+
parser = AutoDeployIndexParser(index_path)
|
|
1374
|
+
lang_agents = parser.get_agents_by_language(language.lower())
|
|
1375
|
+
|
|
1376
|
+
# Get full agent details from discovery
|
|
1377
|
+
all_agents = self._merge_agent_sources()
|
|
1378
|
+
agent_ids = lang_agents.get("core", []) + lang_agents.get(
|
|
1379
|
+
"optional", []
|
|
1380
|
+
)
|
|
1381
|
+
filtered_agents = [
|
|
1382
|
+
a for a in all_agents if a["agent_id"] in agent_ids
|
|
1383
|
+
]
|
|
1384
|
+
filter_description = f"Language: {language}"
|
|
1385
|
+
except Exception as e:
|
|
1386
|
+
self.logger.error(f"Language filter error: {e}", exc_info=True)
|
|
1387
|
+
print(f"[yellow]Could not filter by language: {e}[/yellow]")
|
|
1388
|
+
input("\nPress Enter to continue...")
|
|
1389
|
+
continue
|
|
1390
|
+
|
|
1391
|
+
elif choice_num == "3":
|
|
1392
|
+
# Framework filtering
|
|
1393
|
+
framework = input(
|
|
1394
|
+
"\nEnter framework (react, nextjs, flask, django, etc.): "
|
|
1395
|
+
).strip()
|
|
1396
|
+
|
|
1397
|
+
try:
|
|
1398
|
+
from claude_mpm.services.agents.auto_deploy_index_parser import (
|
|
1399
|
+
AutoDeployIndexParser,
|
|
1400
|
+
)
|
|
1401
|
+
|
|
1402
|
+
index_path = (
|
|
1403
|
+
Path.home()
|
|
1404
|
+
/ ".claude-mpm"
|
|
1405
|
+
/ "cache"
|
|
1406
|
+
/ "agents"
|
|
1407
|
+
/ "bobmatnyc"
|
|
1408
|
+
/ "claude-mpm-agents"
|
|
1409
|
+
/ "AUTO-DEPLOY-INDEX.md"
|
|
1410
|
+
)
|
|
1411
|
+
if not index_path.exists():
|
|
1412
|
+
print(
|
|
1413
|
+
f"[yellow]Could not find AUTO-DEPLOY-INDEX.md at: {index_path}[/yellow]"
|
|
1414
|
+
)
|
|
1415
|
+
input("\nPress Enter to continue...")
|
|
1416
|
+
continue
|
|
1417
|
+
|
|
1418
|
+
parser = AutoDeployIndexParser(index_path)
|
|
1419
|
+
framework_agent_ids = parser.get_agents_by_framework(
|
|
1420
|
+
framework.lower()
|
|
1421
|
+
)
|
|
1422
|
+
|
|
1423
|
+
all_agents = self._merge_agent_sources()
|
|
1424
|
+
filtered_agents = [
|
|
1425
|
+
a for a in all_agents if a["agent_id"] in framework_agent_ids
|
|
1426
|
+
]
|
|
1427
|
+
filter_description = f"Framework: {framework}"
|
|
1428
|
+
except Exception as e:
|
|
1429
|
+
self.logger.error(f"Framework filter error: {e}", exc_info=True)
|
|
1430
|
+
print(f"[yellow]Could not filter by framework: {e}[/yellow]")
|
|
1431
|
+
input("\nPress Enter to continue...")
|
|
1432
|
+
continue
|
|
1433
|
+
|
|
1434
|
+
elif choice_num == "4":
|
|
1435
|
+
# Show all agents
|
|
1436
|
+
filtered_agents = self._merge_agent_sources()
|
|
1437
|
+
filter_description = "All agents"
|
|
1438
|
+
else:
|
|
1439
|
+
print("❌ Invalid choice")
|
|
1440
|
+
input("\nPress Enter to continue...")
|
|
1441
|
+
continue
|
|
1442
|
+
|
|
1443
|
+
# Display filtered results
|
|
1444
|
+
print_section_header(
|
|
1445
|
+
"📋",
|
|
1446
|
+
f"{filter_description} ({len(filtered_agents)} agents)",
|
|
1447
|
+
width=BANNER_WIDTH,
|
|
1448
|
+
)
|
|
1449
|
+
|
|
1450
|
+
if not filtered_agents:
|
|
1451
|
+
print("\n[yellow]No agents found matching filter[/yellow]")
|
|
1452
|
+
else:
|
|
1453
|
+
print(f"\n{'#':<4} {'Agent ID':<40} {'Name':<25} {'Status':<12}")
|
|
1454
|
+
print("-" * 85)
|
|
1455
|
+
|
|
1456
|
+
for idx, agent in enumerate(filtered_agents, 1):
|
|
1457
|
+
agent_id = (
|
|
1458
|
+
agent["agent_id"][:39]
|
|
1459
|
+
if len(agent["agent_id"]) > 39
|
|
1460
|
+
else agent["agent_id"]
|
|
1461
|
+
)
|
|
1462
|
+
name = (
|
|
1463
|
+
agent["name"][:24] if len(agent["name"]) > 24 else agent["name"]
|
|
1464
|
+
)
|
|
1465
|
+
status = "✓ Deployed" if agent.get("deployed") else "Available"
|
|
1466
|
+
print(f"{idx:<4} {agent_id:<40} {name:<25} {status:<12}")
|
|
1467
|
+
|
|
1468
|
+
print("\n[bold]Actions:[/bold]")
|
|
1469
|
+
print(" [d] Deploy agent from this list")
|
|
1470
|
+
print(" [v] View agent details")
|
|
1471
|
+
print(" [n] New filter")
|
|
1472
|
+
print(" [b] Back to main menu")
|
|
1473
|
+
|
|
1474
|
+
action = input("\nSelect action: ").strip()
|
|
1475
|
+
|
|
1476
|
+
if action == "b":
|
|
1477
|
+
break
|
|
1478
|
+
if action == "n":
|
|
1479
|
+
continue
|
|
1480
|
+
if action == "d":
|
|
1481
|
+
self._deploy_from_filtered_list(filtered_agents)
|
|
1482
|
+
elif action == "v":
|
|
1483
|
+
self._view_from_filtered_list(filtered_agents)
|
|
1484
|
+
else:
|
|
1485
|
+
print("❌ Invalid choice")
|
|
1486
|
+
input("\nPress Enter to continue...")
|
|
1487
|
+
|
|
1488
|
+
def _deploy_from_filtered_list(self, agents: List[Dict[str, Any]]):
|
|
1489
|
+
"""Deploy an agent from a filtered list.
|
|
1490
|
+
|
|
1491
|
+
Args:
|
|
1492
|
+
agents: List of agent dictionaries with metadata
|
|
1493
|
+
"""
|
|
1494
|
+
if not agents:
|
|
1495
|
+
print("\n[yellow]No agents in list[/yellow]")
|
|
1496
|
+
input("\nPress Enter to continue...")
|
|
1497
|
+
return
|
|
1498
|
+
|
|
1499
|
+
deployable = [a for a in agents if not a.get("deployed")]
|
|
1500
|
+
|
|
1501
|
+
if not deployable:
|
|
1502
|
+
print("\n[yellow]All agents in this list are already deployed[/yellow]")
|
|
1503
|
+
input("\nPress Enter to continue...")
|
|
1504
|
+
return
|
|
1505
|
+
|
|
1506
|
+
# Build agent selection choices
|
|
1507
|
+
agent_choices = [
|
|
1508
|
+
f"{i}. {agent['agent_id']}" for i, agent in enumerate(agents, 1)
|
|
1509
|
+
]
|
|
1510
|
+
|
|
1511
|
+
agent_choice = questionary.select(
|
|
1512
|
+
"Select agent to deploy:", choices=agent_choices, style=MPM_STYLE
|
|
1513
|
+
).ask()
|
|
1514
|
+
|
|
1515
|
+
if not agent_choice: # User pressed Esc
|
|
1516
|
+
return
|
|
1517
|
+
|
|
1518
|
+
# Parse agent index from "N. agent_id" format
|
|
1519
|
+
idx = int(agent_choice.split(".")[0]) - 1
|
|
1520
|
+
agent = agents[idx]
|
|
1521
|
+
|
|
1522
|
+
if agent.get("deployed"):
|
|
1523
|
+
print(f"\n[yellow]{agent['agent_id']} is already deployed[/yellow]")
|
|
1524
|
+
else:
|
|
1525
|
+
print(f"\n🚀 Deploying {agent['agent_id']}...")
|
|
1526
|
+
|
|
1527
|
+
try:
|
|
1528
|
+
from claude_mpm.services.agents.deployment.agent_template_builder import (
|
|
1529
|
+
AgentTemplateBuilder,
|
|
1530
|
+
)
|
|
1531
|
+
from claude_mpm.services.agents.deployment.agent_version_manager import (
|
|
1532
|
+
AgentVersionManager,
|
|
1533
|
+
)
|
|
1534
|
+
from claude_mpm.services.agents.deployment.deployment_results_manager import (
|
|
1535
|
+
DeploymentResultsManager,
|
|
1536
|
+
)
|
|
1537
|
+
from claude_mpm.services.agents.deployment.single_agent_deployer import (
|
|
1538
|
+
SingleAgentDeployer,
|
|
1539
|
+
)
|
|
1540
|
+
|
|
1541
|
+
# Initialize deployment services
|
|
1542
|
+
template_builder = AgentTemplateBuilder()
|
|
1543
|
+
version_manager = AgentVersionManager()
|
|
1544
|
+
results_manager = DeploymentResultsManager(self.logger)
|
|
1545
|
+
deployer = SingleAgentDeployer(
|
|
1546
|
+
template_builder=template_builder,
|
|
1547
|
+
version_manager=version_manager,
|
|
1548
|
+
results_manager=results_manager,
|
|
1549
|
+
logger=self.logger,
|
|
1550
|
+
)
|
|
1551
|
+
|
|
1552
|
+
# Prepare deployment parameters
|
|
1553
|
+
template_path = Path(agent["path"])
|
|
1554
|
+
target_dir = Path.cwd() / ".claude" / "agents"
|
|
1555
|
+
|
|
1556
|
+
# Find base_agent.json in multiple possible locations
|
|
1557
|
+
base_agent_candidates = [
|
|
1558
|
+
Path.home()
|
|
1559
|
+
/ ".claude-mpm"
|
|
1560
|
+
/ "agents"
|
|
1561
|
+
/ "templates"
|
|
1562
|
+
/ "base_agent.json",
|
|
1563
|
+
Path.home() / ".claude-mpm" / "cache" / "base_agent.json",
|
|
1564
|
+
Path(__file__).parent.parent.parent
|
|
1565
|
+
/ "agents"
|
|
1566
|
+
/ "templates"
|
|
1567
|
+
/ "base_agent.json",
|
|
1568
|
+
]
|
|
1569
|
+
base_agent_path = None
|
|
1570
|
+
for candidate in base_agent_candidates:
|
|
1571
|
+
if candidate.exists():
|
|
1572
|
+
base_agent_path = candidate
|
|
1573
|
+
break
|
|
1574
|
+
|
|
1575
|
+
if not base_agent_path:
|
|
1576
|
+
base_agent_path = base_agent_candidates[
|
|
1577
|
+
0
|
|
1578
|
+
] # Use default even if not exists
|
|
1579
|
+
|
|
1580
|
+
# Deploy the agent
|
|
1581
|
+
success = deployer.deploy_agent(
|
|
1582
|
+
agent_name=agent["agent_id"],
|
|
1583
|
+
templates_dir=template_path.parent,
|
|
1584
|
+
target_dir=target_dir,
|
|
1585
|
+
base_agent_path=base_agent_path,
|
|
1586
|
+
force_rebuild=True,
|
|
1587
|
+
working_directory=Path.cwd(),
|
|
1588
|
+
)
|
|
1589
|
+
|
|
1590
|
+
if success:
|
|
1591
|
+
print(f"[green]✓ Successfully deployed {agent['agent_id']}[/green]")
|
|
1592
|
+
else:
|
|
1593
|
+
print(f"[red]✗ Failed to deploy {agent['agent_id']}[/red]")
|
|
1594
|
+
|
|
1595
|
+
except Exception as e:
|
|
1596
|
+
self.logger.error(f"Deployment error: {e}", exc_info=True)
|
|
1597
|
+
print(f"❌ Deployment error: {e}")
|
|
1598
|
+
|
|
1599
|
+
input("\nPress Enter to continue...")
|
|
1600
|
+
|
|
1601
|
+
def _view_from_filtered_list(self, agents: List[Dict[str, Any]]):
|
|
1602
|
+
"""View details of an agent from filtered list.
|
|
1603
|
+
|
|
1604
|
+
Args:
|
|
1605
|
+
agents: List of agent dictionaries with metadata
|
|
1606
|
+
"""
|
|
1607
|
+
if not agents:
|
|
1608
|
+
print("\n[yellow]No agents in list[/yellow]")
|
|
1609
|
+
input("\nPress Enter to continue...")
|
|
1610
|
+
return
|
|
1611
|
+
|
|
1612
|
+
# Build agent selection choices
|
|
1613
|
+
agent_choices = [
|
|
1614
|
+
f"{i}. {agent['agent_id']}" for i, agent in enumerate(agents, 1)
|
|
1615
|
+
]
|
|
1616
|
+
|
|
1617
|
+
agent_choice = questionary.select(
|
|
1618
|
+
"Select agent to view:", choices=agent_choices, style=MPM_STYLE
|
|
1619
|
+
).ask()
|
|
1620
|
+
|
|
1621
|
+
if not agent_choice: # User pressed Esc
|
|
1622
|
+
return
|
|
1623
|
+
|
|
1624
|
+
# Parse agent index from "N. agent_id" format
|
|
1625
|
+
idx = int(agent_choice.split(".")[0]) - 1
|
|
1626
|
+
agent = agents[idx]
|
|
1627
|
+
self._show_agent_details(agent)
|
|
1628
|
+
|
|
1629
|
+
def _deploy_preset_interactive(self):
|
|
1630
|
+
"""Interactive preset deployment with preview and confirmation."""
|
|
1631
|
+
from claude_mpm.services.agents.agent_preset_service import AgentPresetService
|
|
1632
|
+
|
|
1633
|
+
if not self.source_manager:
|
|
1634
|
+
print("\n❌ Source manager not available")
|
|
1635
|
+
input("\nPress Enter to continue...")
|
|
1636
|
+
return
|
|
1637
|
+
|
|
1638
|
+
preset_service = AgentPresetService(self.source_manager)
|
|
1639
|
+
|
|
1640
|
+
while True:
|
|
1641
|
+
print_section_header("📦", "Deploy Agent Preset", width=BANNER_WIDTH)
|
|
1642
|
+
|
|
1643
|
+
# List available presets
|
|
1644
|
+
presets = preset_service.list_presets()
|
|
1645
|
+
|
|
1646
|
+
print(f"\n{len(presets)} preset(s) available:\n")
|
|
1647
|
+
print(f"{'#':<4} {'Preset':<20} {'Agents':<10} {'Description':<50}")
|
|
1648
|
+
print("-" * 90)
|
|
1649
|
+
|
|
1650
|
+
for idx, preset in enumerate(presets, 1):
|
|
1651
|
+
description = (
|
|
1652
|
+
preset["description"][:48] + "..."
|
|
1653
|
+
if len(preset["description"]) > 50
|
|
1654
|
+
else preset["description"]
|
|
1655
|
+
)
|
|
1656
|
+
print(
|
|
1657
|
+
f"{idx:<4} {preset['name']:<20} {len(preset.get('agents', [])):<10} {description:<50}"
|
|
1658
|
+
)
|
|
1659
|
+
|
|
1660
|
+
print("\n[bold]Actions:[/bold]")
|
|
1661
|
+
print(" [1-11] Select preset number")
|
|
1662
|
+
print(" [b] Back to main menu")
|
|
1663
|
+
|
|
1664
|
+
choice = input("\nSelect preset number or action: ").strip()
|
|
1665
|
+
|
|
1666
|
+
if choice.lower() == "b":
|
|
1667
|
+
break
|
|
1668
|
+
|
|
1669
|
+
try:
|
|
1670
|
+
idx = int(choice) - 1
|
|
1671
|
+
if idx < 0 or idx >= len(presets):
|
|
1672
|
+
raise ValueError("Out of range")
|
|
1673
|
+
|
|
1674
|
+
preset_name = presets[idx]["name"]
|
|
1675
|
+
|
|
1676
|
+
# Show preset details
|
|
1677
|
+
print_section_header("📦", f"Preset: {preset_name}", width=BANNER_WIDTH)
|
|
1678
|
+
print(f"\n[bold]Description:[/bold] {presets[idx]['description']}\n")
|
|
1679
|
+
|
|
1680
|
+
# Resolve preset
|
|
1681
|
+
print("🔍 Resolving preset agents...")
|
|
1682
|
+
resolution = preset_service.resolve_agents(
|
|
1683
|
+
preset_name, validate_availability=True
|
|
1684
|
+
)
|
|
1685
|
+
|
|
1686
|
+
if resolution.get("missing_agents"):
|
|
1687
|
+
print(
|
|
1688
|
+
f"\n⚠️ [red]Missing agents ({len(resolution['missing_agents'])}):[/red]"
|
|
1689
|
+
)
|
|
1690
|
+
for agent_id in resolution["missing_agents"]:
|
|
1691
|
+
print(f" • {agent_id}")
|
|
1692
|
+
print("\n[yellow]Cannot deploy preset with missing agents[/yellow]")
|
|
1693
|
+
input("\nPress Enter to continue...")
|
|
1694
|
+
continue
|
|
1695
|
+
|
|
1696
|
+
# Show agents to deploy
|
|
1697
|
+
agents = resolution.get("agents", [])
|
|
1698
|
+
print(f"\n[bold]Agents to deploy ({len(agents)}):[/bold]\n")
|
|
1699
|
+
|
|
1700
|
+
print(f"{'Agent ID':<40} {'Name':<25} {'Source':<25}")
|
|
1701
|
+
print("-" * 95)
|
|
1702
|
+
|
|
1703
|
+
for agent in agents:
|
|
1704
|
+
# Get agent metadata
|
|
1705
|
+
agent_metadata = agent.get("metadata", {})
|
|
1706
|
+
agent_meta_data = agent_metadata.get("metadata", {})
|
|
1707
|
+
|
|
1708
|
+
agent_id = (
|
|
1709
|
+
agent.get("agent_id", "")[:39]
|
|
1710
|
+
if len(agent.get("agent_id", "")) > 39
|
|
1711
|
+
else agent.get("agent_id", "")
|
|
1712
|
+
)
|
|
1713
|
+
name = (
|
|
1714
|
+
agent_meta_data.get("name", "")[:24]
|
|
1715
|
+
if len(agent_meta_data.get("name", "")) > 24
|
|
1716
|
+
else agent_meta_data.get("name", "")
|
|
1717
|
+
)
|
|
1718
|
+
source = (
|
|
1719
|
+
agent.get("source", "unknown")[:24]
|
|
1720
|
+
if len(agent.get("source", "unknown")) > 24
|
|
1721
|
+
else agent.get("source", "unknown")
|
|
1722
|
+
)
|
|
1723
|
+
|
|
1724
|
+
print(f"{agent_id:<40} {name:<25} {source:<25}")
|
|
1725
|
+
|
|
1726
|
+
# Confirm deployment
|
|
1727
|
+
print("\n[bold]Options:[/bold]")
|
|
1728
|
+
print(" [y] Deploy all agents")
|
|
1729
|
+
print(" [n] Cancel")
|
|
1730
|
+
|
|
1731
|
+
confirm = input("\nProceed with deployment? ").strip()
|
|
1732
|
+
|
|
1733
|
+
if confirm.lower() == "y":
|
|
1734
|
+
print(f"\n🚀 Deploying preset '{preset_name}'...\n")
|
|
1735
|
+
|
|
1736
|
+
from claude_mpm.services.agents.deployment.agent_template_builder import (
|
|
1737
|
+
AgentTemplateBuilder,
|
|
1738
|
+
)
|
|
1739
|
+
from claude_mpm.services.agents.deployment.agent_version_manager import (
|
|
1740
|
+
AgentVersionManager,
|
|
1741
|
+
)
|
|
1742
|
+
from claude_mpm.services.agents.deployment.deployment_results_manager import (
|
|
1743
|
+
DeploymentResultsManager,
|
|
1744
|
+
)
|
|
1745
|
+
from claude_mpm.services.agents.deployment.single_agent_deployer import (
|
|
1746
|
+
SingleAgentDeployer,
|
|
1747
|
+
)
|
|
1748
|
+
|
|
1749
|
+
# Initialize deployment services once for all agents
|
|
1750
|
+
template_builder = AgentTemplateBuilder()
|
|
1751
|
+
version_manager = AgentVersionManager()
|
|
1752
|
+
results_manager = DeploymentResultsManager(self.logger)
|
|
1753
|
+
deployer = SingleAgentDeployer(
|
|
1754
|
+
template_builder=template_builder,
|
|
1755
|
+
version_manager=version_manager,
|
|
1756
|
+
results_manager=results_manager,
|
|
1757
|
+
logger=self.logger,
|
|
1758
|
+
)
|
|
1759
|
+
|
|
1760
|
+
target_dir = Path.cwd() / ".claude" / "agents"
|
|
1761
|
+
|
|
1762
|
+
# Find base_agent.json
|
|
1763
|
+
base_agent_candidates = [
|
|
1764
|
+
Path.home()
|
|
1765
|
+
/ ".claude-mpm"
|
|
1766
|
+
/ "agents"
|
|
1767
|
+
/ "templates"
|
|
1768
|
+
/ "base_agent.json",
|
|
1769
|
+
Path.home() / ".claude-mpm" / "cache" / "base_agent.json",
|
|
1770
|
+
Path(__file__).parent.parent.parent
|
|
1771
|
+
/ "agents"
|
|
1772
|
+
/ "templates"
|
|
1773
|
+
/ "base_agent.json",
|
|
1774
|
+
]
|
|
1775
|
+
base_agent_path = None
|
|
1776
|
+
for candidate in base_agent_candidates:
|
|
1777
|
+
if candidate.exists():
|
|
1778
|
+
base_agent_path = candidate
|
|
1779
|
+
break
|
|
1780
|
+
|
|
1781
|
+
if not base_agent_path:
|
|
1782
|
+
base_agent_path = base_agent_candidates[0]
|
|
1783
|
+
|
|
1784
|
+
deployed = 0
|
|
1785
|
+
failed = 0
|
|
1786
|
+
|
|
1787
|
+
for agent in agents:
|
|
1788
|
+
agent_id = agent["agent_id"]
|
|
1789
|
+
agent_metadata = agent.get("metadata", {})
|
|
1790
|
+
agent_path = agent_metadata.get(
|
|
1791
|
+
"path", agent_metadata.get("source_file", "")
|
|
1792
|
+
)
|
|
1793
|
+
|
|
1794
|
+
if not agent_path:
|
|
1795
|
+
print(f" Deploying {agent_id}... [red]✗ (no path)[/red]")
|
|
1796
|
+
failed += 1
|
|
1797
|
+
continue
|
|
1798
|
+
|
|
1799
|
+
print(f" Deploying {agent_id}...", end=" ", flush=True)
|
|
1800
|
+
|
|
1801
|
+
try:
|
|
1802
|
+
template_path = Path(agent_path)
|
|
1803
|
+
success = deployer.deploy_agent(
|
|
1804
|
+
agent_name=agent_id,
|
|
1805
|
+
templates_dir=template_path.parent,
|
|
1806
|
+
target_dir=target_dir,
|
|
1807
|
+
base_agent_path=base_agent_path,
|
|
1808
|
+
force_rebuild=True,
|
|
1809
|
+
working_directory=Path.cwd(),
|
|
1810
|
+
)
|
|
1811
|
+
|
|
1812
|
+
if success:
|
|
1813
|
+
print("[green]✓[/green]")
|
|
1814
|
+
deployed += 1
|
|
1815
|
+
else:
|
|
1816
|
+
print("[red]✗[/red]")
|
|
1817
|
+
failed += 1
|
|
1818
|
+
except Exception as e:
|
|
1819
|
+
print(f"[red]✗ ({e})[/red]")
|
|
1820
|
+
self.logger.error(
|
|
1821
|
+
f"Failed to deploy {agent_id}: {e}", exc_info=True
|
|
1822
|
+
)
|
|
1823
|
+
failed += 1
|
|
1824
|
+
|
|
1825
|
+
print("\n[bold]Summary:[/bold]")
|
|
1826
|
+
print(f" • Deployed: {deployed}")
|
|
1827
|
+
print(f" • Failed: {failed}")
|
|
1828
|
+
print(f" • Total: {len(agents)}")
|
|
1829
|
+
|
|
1830
|
+
if failed == 0:
|
|
1831
|
+
print(
|
|
1832
|
+
f"\n[green]✓ Preset '{preset_name}' deployed successfully![/green]"
|
|
1833
|
+
)
|
|
1834
|
+
else:
|
|
1835
|
+
print(
|
|
1836
|
+
f"\n[yellow]⚠ Preset deployed with {failed} failures[/yellow]"
|
|
1837
|
+
)
|
|
1838
|
+
|
|
1839
|
+
input("\nPress Enter to continue...")
|
|
1840
|
+
break
|
|
1841
|
+
|
|
1842
|
+
except (ValueError, IndexError):
|
|
1843
|
+
print("❌ Invalid preset selection")
|
|
1844
|
+
input("\nPress Enter to continue...")
|
|
1845
|
+
except Exception as e:
|
|
1846
|
+
self.logger.error(f"Preset deployment error: {e}", exc_info=True)
|
|
1847
|
+
print(f"❌ Error: {e}")
|
|
1848
|
+
input("\nPress Enter to continue...")
|
|
1849
|
+
|
|
1850
|
+
def _manage_sources_interactive(self):
|
|
1851
|
+
"""Interactive source management."""
|
|
1852
|
+
if not self.discovery_enabled or not self.source_manager:
|
|
1853
|
+
print("\n❌ Source manager not available")
|
|
1854
|
+
input("\nPress Enter to continue...")
|
|
1855
|
+
return
|
|
1856
|
+
|
|
1857
|
+
print_section_header("🔗", "Manage Agent Sources", width=BANNER_WIDTH)
|
|
1858
|
+
|
|
1859
|
+
try:
|
|
1860
|
+
from claude_mpm.config.agent_sources import AgentSourceConfiguration
|
|
1861
|
+
|
|
1862
|
+
config = AgentSourceConfiguration()
|
|
1863
|
+
sources = config.list_sources()
|
|
1864
|
+
|
|
1865
|
+
if not sources:
|
|
1866
|
+
print("\n📭 No sources configured.")
|
|
1867
|
+
else:
|
|
1868
|
+
print(f"\n{len(sources)} source(s) configured:\n")
|
|
1869
|
+
print(f"{'Source':<40} {'Priority':<10} {'Status':<10}")
|
|
1870
|
+
print("-" * 60)
|
|
1871
|
+
|
|
1872
|
+
for source in sources:
|
|
1873
|
+
identifier = source.get("identifier", "unknown")[:39]
|
|
1874
|
+
priority = str(source.get("priority", 100))
|
|
1875
|
+
status = "✓ Active" if source.get("enabled", True) else "Disabled"
|
|
1876
|
+
print(f"{identifier:<40} {priority:<10} {status:<10}")
|
|
1877
|
+
|
|
1878
|
+
print("\n💡 Use 'claude-mpm agent-source' command to add/remove sources")
|
|
1879
|
+
print("💡 Use 'claude-mpm agents discover' command to refresh agent cache")
|
|
1880
|
+
|
|
1881
|
+
except Exception as e:
|
|
1882
|
+
self.logger.error(f"Failed to list sources: {e}", exc_info=True)
|
|
1883
|
+
print(f"\n❌ Error: {e}")
|
|
1884
|
+
|
|
1885
|
+
input("\nPress Enter to continue...")
|
|
1886
|
+
|
|
1887
|
+
|
|
1888
|
+
def run_interactive_agent_wizard() -> int:
|
|
1889
|
+
"""Entry point for interactive agent wizard.
|
|
1890
|
+
|
|
1891
|
+
Returns:
|
|
1892
|
+
Exit code (0 for success, non-zero for failure)
|
|
1893
|
+
"""
|
|
1894
|
+
try:
|
|
1895
|
+
wizard = AgentWizard()
|
|
1896
|
+
success, message = wizard.run_interactive_create()
|
|
1897
|
+
|
|
1898
|
+
if success:
|
|
1899
|
+
print(f"\n✅ {message}")
|
|
1900
|
+
return 0
|
|
1901
|
+
print(f"\n❌ {message}", file=sys.stderr)
|
|
1902
|
+
return 1
|
|
1903
|
+
|
|
1904
|
+
except Exception as e:
|
|
1905
|
+
print(f"\n❌ Wizard error: {e}", file=sys.stderr)
|
|
1906
|
+
return 1
|
|
1907
|
+
|
|
1908
|
+
|
|
1909
|
+
def run_interactive_agent_manager() -> int:
|
|
1910
|
+
"""Entry point for interactive agent management.
|
|
1911
|
+
|
|
1912
|
+
Returns:
|
|
1913
|
+
Exit code (0 for success, non-zero for failure)
|
|
1914
|
+
"""
|
|
1915
|
+
try:
|
|
1916
|
+
wizard = AgentWizard()
|
|
1917
|
+
success, message = wizard.run_interactive_manage()
|
|
1918
|
+
|
|
1919
|
+
if success:
|
|
1920
|
+
print(f"\n✅ {message}")
|
|
1921
|
+
return 0
|
|
1922
|
+
print(f"\n❌ {message}", file=sys.stderr)
|
|
1923
|
+
return 1
|
|
1924
|
+
|
|
1925
|
+
except Exception as e:
|
|
1926
|
+
print(f"\n❌ Management error: {e}", file=sys.stderr)
|
|
1927
|
+
return 1
|