claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -0
- claude_mpm/VERSION +1 -0
- claude_mpm/__init__.py +50 -12
- claude_mpm/__main__.py +7 -2
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
- claude_mpm/agents/WORKFLOW.md +111 -0
- claude_mpm/agents/__init__.py +92 -80
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +560 -745
- claude_mpm/agents/agent_loader_integration.py +53 -55
- claude_mpm/agents/agents_metadata.py +186 -27
- claude_mpm/agents/async_agent_loader.py +436 -0
- claude_mpm/agents/base_agent.json +8 -4
- claude_mpm/agents/frontmatter_validator.py +754 -0
- claude_mpm/agents/system_agent_config.py +222 -155
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/__init__.py +17 -13
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +90 -128
- claude_mpm/cli/__main__.py +33 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +36 -12
- claude_mpm/cli/commands/agent_manager.py +1403 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +335 -0
- claude_mpm/cli/commands/agents.py +2503 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +540 -0
- claude_mpm/cli/commands/analyze.py +553 -0
- claude_mpm/cli/commands/analyze_code.py +528 -0
- claude_mpm/cli/commands/auto_configure.py +1053 -0
- claude_mpm/cli/commands/cleanup.py +588 -0
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
- claude_mpm/cli/commands/config.py +586 -0
- claude_mpm/cli/commands/configure.py +2654 -0
- claude_mpm/cli/commands/configure_agent_display.py +282 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +184 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/dashboard.py +286 -0
- claude_mpm/cli/commands/debug.py +1386 -0
- claude_mpm/cli/commands/doctor.py +243 -0
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +195 -74
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +205 -0
- claude_mpm/cli/commands/mcp_command_router.py +161 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +346 -0
- claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
- claude_mpm/cli/commands/mcp_server_commands.py +155 -0
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +585 -846
- claude_mpm/cli/commands/monitor.py +228 -310
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +759 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +195 -0
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +910 -488
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1246 -0
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/commands/tickets.py +536 -53
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +297 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +1947 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +87 -563
- claude_mpm/cli/parsers/__init__.py +35 -0
- claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +575 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
- claude_mpm/cli/parsers/base_parser.py +644 -0
- claude_mpm/cli/parsers/config_parser.py +208 -0
- claude_mpm/cli/parsers/configure_parser.py +138 -0
- claude_mpm/cli/parsers/dashboard_parser.py +113 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +195 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +142 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +157 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +277 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/shared/__init__.py +40 -0
- claude_mpm/cli/shared/argument_patterns.py +205 -0
- claude_mpm/cli/shared/base_command.py +242 -0
- claude_mpm/cli/shared/error_handling.py +242 -0
- claude_mpm/cli/shared/output_formatters.py +241 -0
- claude_mpm/cli/startup.py +1743 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +839 -0
- claude_mpm/cli/utils.py +136 -47
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +42 -64
- claude_mpm/commands/__init__.py +14 -0
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +20 -0
- claude_mpm/commands/mpm-help.md +20 -0
- claude_mpm/commands/mpm-init.md +120 -0
- claude_mpm/commands/mpm-monitor.md +31 -0
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +20 -0
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +20 -0
- claude_mpm/commands/mpm.md +31 -0
- claude_mpm/config/__init__.py +42 -2
- claude_mpm/config/agent_config.py +402 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +258 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +125 -83
- claude_mpm/constants.py +132 -22
- claude_mpm/core/__init__.py +62 -36
- claude_mpm/core/agent_name_normalizer.py +71 -73
- claude_mpm/core/agent_registry.py +385 -492
- claude_mpm/core/agent_session_manager.py +81 -70
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +159 -122
- claude_mpm/core/cache.py +560 -0
- claude_mpm/core/claude_runner.py +696 -916
- claude_mpm/core/config.py +613 -122
- claude_mpm/core/config_aliases.py +74 -73
- claude_mpm/core/config_constants.py +314 -0
- claude_mpm/core/constants.py +361 -0
- claude_mpm/core/container.py +646 -104
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/exceptions.py +536 -0
- claude_mpm/core/factories.py +105 -109
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +278 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +213 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +485 -414
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +246 -86
- claude_mpm/core/hook_performance_config.py +147 -0
- claude_mpm/core/injectable_service.py +72 -63
- claude_mpm/core/instruction_reinforcement_hook.py +267 -0
- claude_mpm/core/interactive_session.py +670 -0
- claude_mpm/core/interfaces.py +570 -164
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/log_manager.py +707 -0
- claude_mpm/core/logger.py +295 -134
- claude_mpm/core/logging_config.py +474 -0
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/minimal_framework_loader.py +24 -22
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +594 -0
- claude_mpm/core/optimized_agent_loader.py +479 -0
- claude_mpm/core/optimized_startup.py +554 -0
- claude_mpm/core/output_style_manager.py +483 -0
- claude_mpm/core/pm_hook_interceptor.py +197 -82
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/service_registry.py +153 -116
- claude_mpm/core/session_manager.py +179 -64
- claude_mpm/core/shared/__init__.py +17 -0
- claude_mpm/core/shared/config_loader.py +326 -0
- claude_mpm/core/shared/path_resolver.py +281 -0
- claude_mpm/core/shared/singleton_manager.py +221 -0
- claude_mpm/core/socketio_pool.py +400 -137
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +64 -57
- claude_mpm/core/types.py +307 -0
- claude_mpm/core/typing_utils.py +553 -0
- claude_mpm/core/unified_agent_registry.py +969 -0
- claude_mpm/core/unified_config.py +570 -0
- claude_mpm/core/unified_paths.py +941 -0
- claude_mpm/dashboard/__init__.py +12 -0
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/__init__.py +10 -0
- claude_mpm/experimental/cli_enhancements.py +104 -89
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +76 -66
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +37 -32
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
- claude_mpm/hooks/claude_hooks/installer.py +806 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +201 -107
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +92 -76
- claude_mpm/hooks/validation_hooks.py +62 -54
- claude_mpm/init.py +518 -83
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +40 -23
- claude_mpm/models/agent_session.py +538 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/__init__.py +12 -0
- claude_mpm/scripts/__init__.py +15 -0
- claude_mpm/scripts/claude-hook-handler.sh +227 -0
- claude_mpm/scripts/launch_monitor.py +165 -0
- claude_mpm/scripts/mpm_doctor.py +322 -0
- claude_mpm/scripts/socketio_daemon.py +189 -200
- claude_mpm/scripts/start_activity_logging.py +91 -0
- claude_mpm/services/__init__.py +208 -39
- claude_mpm/services/agent_capabilities_service.py +266 -0
- claude_mpm/services/agents/__init__.py +89 -0
- claude_mpm/services/agents/agent_builder.py +514 -0
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
- claude_mpm/services/agents/deployment/agent_validator.py +376 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
- claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
- claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
- claude_mpm/services/agents/git_source_manager.py +682 -0
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
- claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
- claude_mpm/services/agents/memory/__init__.py +22 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
- claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
- claude_mpm/services/agents/memory/content_manager.py +470 -0
- claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
- claude_mpm/services/agents/memory/memory_file_service.py +129 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
- claude_mpm/services/agents/memory/template_generator.py +83 -0
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +617 -0
- claude_mpm/services/agents/registry/__init__.py +30 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +665 -0
- claude_mpm/services/claude_session_logger.py +321 -0
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +408 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +590 -0
- claude_mpm/services/cli/memory_crud_service.py +622 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +604 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +362 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +446 -0
- claude_mpm/services/command_handler_service.py +221 -0
- claude_mpm/services/communication/__init__.py +22 -0
- claude_mpm/services/core/__init__.py +108 -0
- claude_mpm/services/core/base.py +269 -0
- claude_mpm/services/core/cache_manager.py +309 -0
- claude_mpm/services/core/interfaces/__init__.py +273 -0
- claude_mpm/services/core/interfaces/agent.py +514 -0
- claude_mpm/services/core/interfaces/communication.py +316 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/infrastructure.py +357 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/service.py +405 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +81 -0
- claude_mpm/services/core/memory_manager.py +682 -0
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +517 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +38 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/base_check.py +60 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
- claude_mpm/services/diagnostics/models.py +138 -0
- claude_mpm/services/event_aggregator.py +582 -0
- claude_mpm/services/event_bus/__init__.py +18 -0
- claude_mpm/services/event_bus/config.py +186 -0
- claude_mpm/services/event_bus/direct_relay.py +312 -0
- claude_mpm/services/event_bus/event_bus.py +396 -0
- claude_mpm/services/event_bus/relay.py +326 -0
- claude_mpm/services/events/__init__.py +44 -0
- claude_mpm/services/events/consumers/__init__.py +18 -0
- claude_mpm/services/events/consumers/dead_letter.py +306 -0
- claude_mpm/services/events/consumers/logging.py +184 -0
- claude_mpm/services/events/consumers/metrics.py +241 -0
- claude_mpm/services/events/consumers/socketio.py +377 -0
- claude_mpm/services/events/core.py +480 -0
- claude_mpm/services/events/interfaces.py +214 -0
- claude_mpm/services/events/producers/__init__.py +14 -0
- claude_mpm/services/events/producers/hook.py +269 -0
- claude_mpm/services/events/producers/system.py +329 -0
- claude_mpm/services/exceptions.py +433 -353
- claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
- claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +159 -111
- claude_mpm/services/infrastructure/__init__.py +52 -0
- claude_mpm/services/infrastructure/context_preservation.py +569 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +209 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
- claude_mpm/services/infrastructure/monitoring/base.py +122 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +219 -0
- claude_mpm/services/infrastructure/monitoring/process.py +343 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
- claude_mpm/services/infrastructure/monitoring/service.py +368 -0
- claude_mpm/services/infrastructure/monitoring.py +71 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +427 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +1542 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/__init__.py +19 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
- claude_mpm/services/memory/cache/simple_cache.py +331 -0
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
- claude_mpm/services/memory/router.py +951 -0
- claude_mpm/services/memory_hook_service.py +470 -0
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +698 -0
- claude_mpm/services/monitor/daemon_manager.py +1076 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +730 -0
- claude_mpm/services/monitor/server.py +1493 -0
- claude_mpm/services/monitor_build_service.py +349 -0
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/pm_skills_deployer.py +707 -0
- claude_mpm/services/port_manager.py +597 -0
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/__init__.py +44 -0
- claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +407 -0
- claude_mpm/services/project/project_organizer.py +1009 -0
- claude_mpm/services/project/registry.py +636 -0
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/recovery_manager.py +293 -240
- claude_mpm/services/response_tracker.py +267 -0
- claude_mpm/services/runner_configuration_service.py +605 -0
- claude_mpm/services/self_upgrade_service.py +608 -0
- claude_mpm/services/session_management_service.py +314 -0
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +21 -0
- claude_mpm/services/shared/async_service_base.py +216 -0
- claude_mpm/services/shared/config_service_base.py +301 -0
- claude_mpm/services/shared/lifecycle_service_base.py +308 -0
- claude_mpm/services/shared/manager_base.py +315 -0
- claude_mpm/services/shared/service_factory.py +309 -0
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
- claude_mpm/services/skills/selective_skill_deployer.py +744 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1168 -0
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/client_proxy.py +229 -0
- claude_mpm/services/socketio/dashboard_server.py +362 -0
- claude_mpm/services/socketio/event_normalizer.py +798 -0
- claude_mpm/services/socketio/handlers/__init__.py +30 -0
- claude_mpm/services/socketio/handlers/base.py +136 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
- claude_mpm/services/socketio/handlers/connection.py +643 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
- claude_mpm/services/socketio/handlers/file.py +263 -0
- claude_mpm/services/socketio/handlers/git.py +962 -0
- claude_mpm/services/socketio/handlers/hook.py +211 -0
- claude_mpm/services/socketio/handlers/memory.py +26 -0
- claude_mpm/services/socketio/handlers/project.py +24 -0
- claude_mpm/services/socketio/handlers/registry.py +214 -0
- claude_mpm/services/socketio/migration_utils.py +343 -0
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +569 -0
- claude_mpm/services/socketio/server/connection_manager.py +579 -0
- claude_mpm/services/socketio/server/core.py +1079 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
- claude_mpm/services/socketio/server/main.py +501 -0
- claude_mpm/services/socketio_client_manager.py +173 -143
- claude_mpm/services/socketio_server.py +38 -1657
- claude_mpm/services/subprocess_launcher_service.py +322 -0
- claude_mpm/services/system_instructions_service.py +270 -0
- claude_mpm/services/ticket_manager.py +25 -209
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +280 -0
- claude_mpm/services/version_control/__init__.py +34 -37
- claude_mpm/services/version_control/branch_strategy.py +26 -17
- claude_mpm/services/version_control/conflict_resolution.py +52 -36
- claude_mpm/services/version_control/git_operations.py +183 -49
- claude_mpm/services/version_control/semantic_versioning.py +172 -61
- claude_mpm/services/version_control/version_parser.py +546 -0
- claude_mpm/services/version_service.py +379 -0
- claude_mpm/services/visualization/__init__.py +15 -0
- claude_mpm/services/visualization/mermaid_generator.py +937 -0
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +405 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +546 -0
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/tools/__init__.py +10 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +631 -0
- claude_mpm/tools/code_tree_events.py +420 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- claude_mpm/utils/__init__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +1090 -0
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +168 -126
- claude_mpm/utils/console.py +11 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +373 -0
- claude_mpm/utils/dependency_manager.py +60 -59
- claude_mpm/utils/dependency_strategies.py +381 -0
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +313 -0
- claude_mpm/utils/error_handler.py +78 -66
- claude_mpm/utils/file_utils.py +305 -0
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +110 -104
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +823 -0
- claude_mpm/utils/session_logging.py +121 -0
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +343 -0
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +214 -108
- claude_mpm/validation/frontmatter_validator.py +252 -0
- claude_mpm-5.4.55.dist-info/METADATA +999 -0
- claude_mpm-5.4.55.dist-info/RECORD +868 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
- claude_mpm/agents/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/base_agent_loader.py +0 -529
- claude_mpm/agents/schema/agent_schema.json +0 -314
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/data_engineer.json +0 -110
- claude_mpm/agents/templates/documentation.json +0 -109
- claude_mpm/agents/templates/engineer.json +0 -113
- claude_mpm/agents/templates/ops.json +0 -109
- claude_mpm/agents/templates/pm.json +0 -25
- claude_mpm/agents/templates/qa.json +0 -111
- claude_mpm/agents/templates/research.json +0 -65
- claude_mpm/agents/templates/security.json +0 -113
- claude_mpm/agents/templates/test_integration.json +0 -112
- claude_mpm/agents/templates/version_control.json +0 -107
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/dashboard/open_dashboard.py +0 -34
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/agent_deployment.py +0 -1534
- claude_mpm/services/agent_lifecycle_manager.py +0 -1169
- claude_mpm/services/agent_memory_manager.py +0 -1415
- claude_mpm/services/agent_registry.py +0 -676
- claude_mpm/services/deployed_agent_discovery.py +0 -226
- claude_mpm/services/framework_agent_loader.py +0 -337
- claude_mpm/services/framework_claude_md_generator.py +0 -621
- claude_mpm/services/health_monitor.py +0 -892
- claude_mpm/services/memory_router.py +0 -538
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -508
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- claude_mpm/utils/paths.py +0 -289
- claude_mpm-3.4.10.dist-info/METADATA +0 -183
- claude_mpm-3.4.10.dist-info/RECORD +0 -201
- claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1090 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Dynamic agent dependency loader for runtime dependency management.
|
|
5
|
+
|
|
6
|
+
This module handles loading and checking dependencies for deployed agents
|
|
7
|
+
at runtime, rather than requiring all possible agent dependencies to be
|
|
8
|
+
installed upfront.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import logging
|
|
14
|
+
import subprocess
|
|
15
|
+
import sys
|
|
16
|
+
import time
|
|
17
|
+
from typing import Any, Dict, List, Optional, Set, Tuple
|
|
18
|
+
|
|
19
|
+
import yaml
|
|
20
|
+
from packaging.requirements import InvalidRequirement, Requirement
|
|
21
|
+
|
|
22
|
+
from ..core.logger import get_logger
|
|
23
|
+
|
|
24
|
+
logger = get_logger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AgentDependencyLoader:
|
|
28
|
+
"""
|
|
29
|
+
Dynamically loads and manages dependencies for deployed agents.
|
|
30
|
+
|
|
31
|
+
Only checks/installs dependencies for agents that are actually deployed
|
|
32
|
+
and being used, rather than all possible agents.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# Optional database packages - if one fails, try alternatives
|
|
36
|
+
OPTIONAL_DB_PACKAGES = {
|
|
37
|
+
"mysqlclient": ["pymysql"], # PyMySQL is a pure Python alternative
|
|
38
|
+
"psycopg2": ["psycopg2-binary"], # Binary version doesn't require compilation
|
|
39
|
+
"cx_Oracle": [], # No good alternative, mark as optional
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# Packages that commonly fail compilation on certain platforms
|
|
43
|
+
COMPILATION_PRONE = [
|
|
44
|
+
"mysqlclient", # Requires MySQL development headers
|
|
45
|
+
"psycopg2", # Requires PostgreSQL development headers (use psycopg2-binary instead)
|
|
46
|
+
"cx_Oracle", # Requires Oracle client libraries
|
|
47
|
+
"pycairo", # Requires Cairo development headers
|
|
48
|
+
"lxml", # Can fail if libxml2 dev headers missing
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
def __init__(self, auto_install: bool = False):
|
|
52
|
+
"""
|
|
53
|
+
Initialize the agent dependency loader.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
auto_install: If True, automatically install missing dependencies.
|
|
57
|
+
If False, only check and report missing dependencies.
|
|
58
|
+
"""
|
|
59
|
+
self.auto_install = auto_install
|
|
60
|
+
self.deployed_agents: Dict[str, Path] = {}
|
|
61
|
+
self.agent_dependencies: Dict[str, Dict] = {}
|
|
62
|
+
self.missing_dependencies: Dict[str, List[str]] = {}
|
|
63
|
+
self.checked_packages: Set[str] = set()
|
|
64
|
+
self.optional_failed: Dict[str, str] = {} # Track optional packages that failed
|
|
65
|
+
self.deployment_state_file = (
|
|
66
|
+
Path.cwd() / ".claude" / "agents" / ".mpm_deployment_state"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def discover_deployed_agents(self) -> Dict[str, Path]:
|
|
70
|
+
"""
|
|
71
|
+
Discover which agents are currently deployed in .claude/agents/
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Dictionary mapping agent IDs to their file paths
|
|
75
|
+
"""
|
|
76
|
+
deployed_agents: Dict[str, Path] = {}
|
|
77
|
+
claude_agents_dir = Path.cwd() / ".claude" / "agents"
|
|
78
|
+
|
|
79
|
+
if not claude_agents_dir.exists():
|
|
80
|
+
logger.debug("No .claude/agents directory found")
|
|
81
|
+
return deployed_agents
|
|
82
|
+
|
|
83
|
+
# Scan for deployed agent markdown files
|
|
84
|
+
for agent_file in claude_agents_dir.glob("*.md"):
|
|
85
|
+
agent_id = agent_file.stem
|
|
86
|
+
deployed_agents[agent_id] = agent_file
|
|
87
|
+
logger.debug(f"Found deployed agent: {agent_id}")
|
|
88
|
+
|
|
89
|
+
logger.debug(f"Discovered {len(deployed_agents)} deployed agents")
|
|
90
|
+
self.deployed_agents = deployed_agents
|
|
91
|
+
return deployed_agents
|
|
92
|
+
|
|
93
|
+
def _extract_yaml_frontmatter(self, content: str) -> Optional[Dict[str, Any]]:
|
|
94
|
+
"""
|
|
95
|
+
Extract and parse YAML frontmatter from markdown.
|
|
96
|
+
|
|
97
|
+
Frontmatter must be at the start of the file, delimited by '---'.
|
|
98
|
+
Example:
|
|
99
|
+
---
|
|
100
|
+
name: agent_name
|
|
101
|
+
dependencies:
|
|
102
|
+
python:
|
|
103
|
+
- package>=1.0.0
|
|
104
|
+
---
|
|
105
|
+
# Agent content...
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
content: File content to parse
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Parsed YAML frontmatter as dict, or None if not found/invalid
|
|
112
|
+
"""
|
|
113
|
+
if not content.strip().startswith("---"):
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
# Split on --- delimiters
|
|
117
|
+
parts = content.split("---", 2)
|
|
118
|
+
if len(parts) < 3:
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
return yaml.safe_load(parts[1])
|
|
123
|
+
except yaml.YAMLError as e:
|
|
124
|
+
logger.warning(f"Failed to parse YAML frontmatter: {e}")
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
def load_agent_dependencies(self) -> Dict[str, Dict]:
|
|
128
|
+
"""
|
|
129
|
+
Load dependency information for deployed agents from their source configs.
|
|
130
|
+
|
|
131
|
+
Searches for agent configuration in both markdown (.md) and JSON (.json) formats.
|
|
132
|
+
Markdown files with YAML frontmatter are searched first for better maintainability.
|
|
133
|
+
Falls back to JSON format for backward compatibility.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Dictionary mapping agent IDs to their dependency requirements
|
|
137
|
+
"""
|
|
138
|
+
agent_dependencies = {}
|
|
139
|
+
|
|
140
|
+
# Define paths to check for agent configs (in precedence order)
|
|
141
|
+
config_paths = [
|
|
142
|
+
Path.cwd() / ".claude-mpm" / "agents", # PROJECT
|
|
143
|
+
Path.home() / ".claude-mpm" / "agents", # USER
|
|
144
|
+
Path.cwd() / "src" / "claude_mpm" / "agents" / "templates", # SYSTEM
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
for agent_id in self.deployed_agents:
|
|
148
|
+
found = False
|
|
149
|
+
|
|
150
|
+
# Try to find the agent's config (markdown first, then JSON)
|
|
151
|
+
for config_dir in config_paths:
|
|
152
|
+
if found:
|
|
153
|
+
break
|
|
154
|
+
|
|
155
|
+
# Try markdown first (current format with YAML frontmatter)
|
|
156
|
+
md_file = config_dir / f"{agent_id}.md"
|
|
157
|
+
if md_file.exists():
|
|
158
|
+
try:
|
|
159
|
+
content = md_file.read_text(encoding="utf-8")
|
|
160
|
+
frontmatter = self._extract_yaml_frontmatter(content)
|
|
161
|
+
if frontmatter and "dependencies" in frontmatter:
|
|
162
|
+
agent_dependencies[agent_id] = frontmatter["dependencies"]
|
|
163
|
+
logger.debug(
|
|
164
|
+
f"Loaded dependencies for {agent_id} from markdown"
|
|
165
|
+
)
|
|
166
|
+
found = True
|
|
167
|
+
break
|
|
168
|
+
except Exception as e:
|
|
169
|
+
logger.warning(f"Failed to load markdown for {agent_id}: {e}")
|
|
170
|
+
|
|
171
|
+
# Fall back to JSON for backward compatibility
|
|
172
|
+
if not found:
|
|
173
|
+
json_file = config_dir / f"{agent_id}.json"
|
|
174
|
+
if json_file.exists():
|
|
175
|
+
try:
|
|
176
|
+
with json_file.open() as f:
|
|
177
|
+
config = json.load(f)
|
|
178
|
+
if "dependencies" in config:
|
|
179
|
+
agent_dependencies[agent_id] = config[
|
|
180
|
+
"dependencies"
|
|
181
|
+
]
|
|
182
|
+
logger.debug(
|
|
183
|
+
f"Loaded dependencies for {agent_id} from JSON"
|
|
184
|
+
)
|
|
185
|
+
found = True
|
|
186
|
+
break
|
|
187
|
+
except Exception as e:
|
|
188
|
+
logger.warning(f"Failed to load JSON for {agent_id}: {e}")
|
|
189
|
+
|
|
190
|
+
self.agent_dependencies = agent_dependencies
|
|
191
|
+
logger.debug(f"Loaded dependencies for {len(agent_dependencies)} agents")
|
|
192
|
+
return agent_dependencies
|
|
193
|
+
|
|
194
|
+
def check_python_dependency(self, package_spec: str) -> Tuple[bool, Optional[str]]:
|
|
195
|
+
"""
|
|
196
|
+
Check if a Python package dependency is satisfied.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
package_spec: Package specification (e.g., "pandas>=2.0.0")
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Tuple of (is_satisfied, installed_version)
|
|
203
|
+
"""
|
|
204
|
+
try:
|
|
205
|
+
req = Requirement(package_spec)
|
|
206
|
+
package_name = req.name
|
|
207
|
+
|
|
208
|
+
# Skip if already checked
|
|
209
|
+
if package_name in self.checked_packages:
|
|
210
|
+
return True, None
|
|
211
|
+
|
|
212
|
+
# Check if it's a built-in module first
|
|
213
|
+
if self._is_builtin_module(package_name):
|
|
214
|
+
self.checked_packages.add(package_name)
|
|
215
|
+
return True, "built-in"
|
|
216
|
+
|
|
217
|
+
# Check if this is an optional package that already failed
|
|
218
|
+
if package_name in self.optional_failed:
|
|
219
|
+
logger.debug(
|
|
220
|
+
f"Skipping optional package {package_name} (previously failed)"
|
|
221
|
+
)
|
|
222
|
+
return True, "optional-skipped"
|
|
223
|
+
|
|
224
|
+
# Try to import and check version
|
|
225
|
+
try:
|
|
226
|
+
import importlib.metadata
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
version = importlib.metadata.version(package_name)
|
|
230
|
+
self.checked_packages.add(package_name)
|
|
231
|
+
|
|
232
|
+
# Check if version satisfies requirement
|
|
233
|
+
if req.specifier.contains(version):
|
|
234
|
+
return True, version
|
|
235
|
+
logger.debug(
|
|
236
|
+
f"{package_name} {version} does not satisfy {req.specifier}"
|
|
237
|
+
)
|
|
238
|
+
return False, version
|
|
239
|
+
|
|
240
|
+
except importlib.metadata.PackageNotFoundError:
|
|
241
|
+
# Check if there's an alternative for this optional package
|
|
242
|
+
if package_name in self.OPTIONAL_DB_PACKAGES:
|
|
243
|
+
for alternative in self.OPTIONAL_DB_PACKAGES[package_name]:
|
|
244
|
+
try:
|
|
245
|
+
alt_version = importlib.metadata.version(alternative)
|
|
246
|
+
logger.info(
|
|
247
|
+
f"Using {alternative} as alternative to {package_name}"
|
|
248
|
+
)
|
|
249
|
+
self.checked_packages.add(package_name)
|
|
250
|
+
return True, f"{alternative}:{alt_version}"
|
|
251
|
+
except importlib.metadata.PackageNotFoundError:
|
|
252
|
+
continue
|
|
253
|
+
# If no alternatives work, mark as optional failure
|
|
254
|
+
self.optional_failed[package_name] = "No alternatives available"
|
|
255
|
+
logger.warning(
|
|
256
|
+
f"Optional package {package_name} not found, marking as optional"
|
|
257
|
+
)
|
|
258
|
+
return True, "optional-not-found"
|
|
259
|
+
return False, None
|
|
260
|
+
|
|
261
|
+
except ImportError:
|
|
262
|
+
# Fallback for older Python versions
|
|
263
|
+
try:
|
|
264
|
+
import pkg_resources
|
|
265
|
+
|
|
266
|
+
version = pkg_resources.get_distribution(package_name).version
|
|
267
|
+
self.checked_packages.add(package_name)
|
|
268
|
+
|
|
269
|
+
if req.specifier.contains(version):
|
|
270
|
+
return True, version
|
|
271
|
+
return False, version
|
|
272
|
+
|
|
273
|
+
except pkg_resources.DistributionNotFound:
|
|
274
|
+
# Check alternatives for optional packages
|
|
275
|
+
if package_name in self.OPTIONAL_DB_PACKAGES:
|
|
276
|
+
for alternative in self.OPTIONAL_DB_PACKAGES[package_name]:
|
|
277
|
+
try:
|
|
278
|
+
alt_version = pkg_resources.get_distribution(
|
|
279
|
+
alternative
|
|
280
|
+
).version
|
|
281
|
+
logger.info(
|
|
282
|
+
f"Using {alternative} as alternative to {package_name}"
|
|
283
|
+
)
|
|
284
|
+
self.checked_packages.add(package_name)
|
|
285
|
+
return True, f"{alternative}:{alt_version}"
|
|
286
|
+
except pkg_resources.DistributionNotFound:
|
|
287
|
+
continue
|
|
288
|
+
self.optional_failed[package_name] = "No alternatives available"
|
|
289
|
+
logger.warning(
|
|
290
|
+
f"Optional package {package_name} not found, marking as optional"
|
|
291
|
+
)
|
|
292
|
+
return True, "optional-not-found"
|
|
293
|
+
return False, None
|
|
294
|
+
|
|
295
|
+
except InvalidRequirement as e:
|
|
296
|
+
logger.warning(f"Invalid requirement specification: {package_spec}: {e}")
|
|
297
|
+
return False, None
|
|
298
|
+
|
|
299
|
+
def _is_builtin_module(self, module_name: str) -> bool:
|
|
300
|
+
"""
|
|
301
|
+
Check if a module is a built-in Python module.
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
module_name: Name of the module to check
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
True if the module is built-in, False otherwise
|
|
308
|
+
"""
|
|
309
|
+
# List of common built-in modules that don't have distribution metadata
|
|
310
|
+
builtin_modules = {
|
|
311
|
+
"json",
|
|
312
|
+
"pathlib",
|
|
313
|
+
"os",
|
|
314
|
+
"sys",
|
|
315
|
+
"datetime",
|
|
316
|
+
"time",
|
|
317
|
+
"math",
|
|
318
|
+
"random",
|
|
319
|
+
"collections",
|
|
320
|
+
"itertools",
|
|
321
|
+
"functools",
|
|
322
|
+
"operator",
|
|
323
|
+
"copy",
|
|
324
|
+
"pickle",
|
|
325
|
+
"sqlite3",
|
|
326
|
+
"urllib",
|
|
327
|
+
"http",
|
|
328
|
+
"email",
|
|
329
|
+
"html",
|
|
330
|
+
"xml",
|
|
331
|
+
"csv",
|
|
332
|
+
"configparser",
|
|
333
|
+
"logging",
|
|
334
|
+
"unittest",
|
|
335
|
+
"doctest",
|
|
336
|
+
"pdb",
|
|
337
|
+
"profile",
|
|
338
|
+
"timeit",
|
|
339
|
+
"trace",
|
|
340
|
+
"gc",
|
|
341
|
+
"weakref",
|
|
342
|
+
"types",
|
|
343
|
+
"inspect",
|
|
344
|
+
"importlib",
|
|
345
|
+
"pkgutil",
|
|
346
|
+
"modulefinder",
|
|
347
|
+
"runpy",
|
|
348
|
+
"ast",
|
|
349
|
+
"symtable",
|
|
350
|
+
"keyword",
|
|
351
|
+
"token",
|
|
352
|
+
"tokenize",
|
|
353
|
+
"tabnanny",
|
|
354
|
+
"pyclbr",
|
|
355
|
+
"py_compile",
|
|
356
|
+
"compileall",
|
|
357
|
+
"dis",
|
|
358
|
+
"pickletools",
|
|
359
|
+
"platform",
|
|
360
|
+
"ctypes",
|
|
361
|
+
"struct",
|
|
362
|
+
"codecs",
|
|
363
|
+
"unicodedata",
|
|
364
|
+
"stringprep",
|
|
365
|
+
"readline",
|
|
366
|
+
"rlcompleter",
|
|
367
|
+
"subprocess",
|
|
368
|
+
"sched",
|
|
369
|
+
"queue",
|
|
370
|
+
"threading",
|
|
371
|
+
"multiprocessing",
|
|
372
|
+
"concurrent",
|
|
373
|
+
"asyncio",
|
|
374
|
+
"socket",
|
|
375
|
+
"ssl",
|
|
376
|
+
"select",
|
|
377
|
+
"selectors",
|
|
378
|
+
"signal",
|
|
379
|
+
"mmap",
|
|
380
|
+
"errno",
|
|
381
|
+
"io",
|
|
382
|
+
"tempfile",
|
|
383
|
+
"glob",
|
|
384
|
+
"fnmatch",
|
|
385
|
+
"linecache",
|
|
386
|
+
"shutil",
|
|
387
|
+
"stat",
|
|
388
|
+
"filecmp",
|
|
389
|
+
"tarfile",
|
|
390
|
+
"zipfile",
|
|
391
|
+
"gzip",
|
|
392
|
+
"bz2",
|
|
393
|
+
"lzma",
|
|
394
|
+
"zlib",
|
|
395
|
+
"hashlib",
|
|
396
|
+
"hmac",
|
|
397
|
+
"secrets",
|
|
398
|
+
"base64",
|
|
399
|
+
"binascii",
|
|
400
|
+
"quopri",
|
|
401
|
+
"uu",
|
|
402
|
+
"string",
|
|
403
|
+
"re",
|
|
404
|
+
"difflib",
|
|
405
|
+
"textwrap",
|
|
406
|
+
"calendar",
|
|
407
|
+
"locale",
|
|
408
|
+
"gettext",
|
|
409
|
+
"argparse",
|
|
410
|
+
"optparse",
|
|
411
|
+
"getopt",
|
|
412
|
+
"shlex",
|
|
413
|
+
"cmd",
|
|
414
|
+
"pprint",
|
|
415
|
+
"reprlib",
|
|
416
|
+
"enum",
|
|
417
|
+
"numbers",
|
|
418
|
+
"decimal",
|
|
419
|
+
"fractions",
|
|
420
|
+
"statistics",
|
|
421
|
+
"array",
|
|
422
|
+
"bisect",
|
|
423
|
+
"heapq",
|
|
424
|
+
"contextlib",
|
|
425
|
+
"abc",
|
|
426
|
+
"atexit",
|
|
427
|
+
"traceback",
|
|
428
|
+
"warnings",
|
|
429
|
+
"dataclasses",
|
|
430
|
+
"graphlib",
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
# Check if it's in our known built-in modules
|
|
434
|
+
if module_name in builtin_modules:
|
|
435
|
+
return True
|
|
436
|
+
|
|
437
|
+
# Try to import it and check if it's a built-in module
|
|
438
|
+
try:
|
|
439
|
+
import importlib.util
|
|
440
|
+
|
|
441
|
+
spec = importlib.util.find_spec(module_name)
|
|
442
|
+
if spec is not None and spec.origin is None:
|
|
443
|
+
# Built-in modules have spec.origin as None
|
|
444
|
+
return True
|
|
445
|
+
except (ImportError, ModuleNotFoundError, ValueError):
|
|
446
|
+
pass
|
|
447
|
+
|
|
448
|
+
return False
|
|
449
|
+
|
|
450
|
+
def check_system_dependency(self, command: str) -> bool:
|
|
451
|
+
"""
|
|
452
|
+
Check if a system command is available in PATH.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
command: System command to check (e.g., "git")
|
|
456
|
+
|
|
457
|
+
Returns:
|
|
458
|
+
True if command is available, False otherwise
|
|
459
|
+
"""
|
|
460
|
+
try:
|
|
461
|
+
result = subprocess.run(
|
|
462
|
+
["which", command],
|
|
463
|
+
capture_output=True,
|
|
464
|
+
text=True,
|
|
465
|
+
timeout=5,
|
|
466
|
+
check=False,
|
|
467
|
+
)
|
|
468
|
+
return result.returncode == 0
|
|
469
|
+
except Exception:
|
|
470
|
+
return False
|
|
471
|
+
|
|
472
|
+
def analyze_dependencies(self) -> Dict[str, Dict]:
|
|
473
|
+
"""
|
|
474
|
+
Analyze dependencies for all deployed agents.
|
|
475
|
+
|
|
476
|
+
Returns:
|
|
477
|
+
Analysis results including missing and satisfied dependencies
|
|
478
|
+
"""
|
|
479
|
+
results: Dict[str, Any] = {
|
|
480
|
+
"agents": {},
|
|
481
|
+
"summary": {
|
|
482
|
+
"total_agents": len(self.deployed_agents),
|
|
483
|
+
"agents_with_deps": 0,
|
|
484
|
+
"missing_python": [],
|
|
485
|
+
"missing_system": [],
|
|
486
|
+
"satisfied_python": [],
|
|
487
|
+
"satisfied_system": [],
|
|
488
|
+
},
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
for agent_id, deps in self.agent_dependencies.items():
|
|
492
|
+
agent_result: Dict[str, Dict[str, List[str]]] = {
|
|
493
|
+
"python": {"satisfied": [], "missing": [], "outdated": []},
|
|
494
|
+
"system": {"satisfied": [], "missing": []},
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
# Check Python dependencies
|
|
498
|
+
if "python" in deps:
|
|
499
|
+
for dep_spec in deps["python"]:
|
|
500
|
+
is_satisfied, version = self.check_python_dependency(dep_spec)
|
|
501
|
+
if is_satisfied:
|
|
502
|
+
agent_result["python"]["satisfied"].append(dep_spec)
|
|
503
|
+
if dep_spec not in results["summary"]["satisfied_python"]:
|
|
504
|
+
results["summary"]["satisfied_python"].append(dep_spec)
|
|
505
|
+
elif version: # Installed but wrong version
|
|
506
|
+
agent_result["python"]["outdated"].append(
|
|
507
|
+
f"{dep_spec} (have {version})"
|
|
508
|
+
)
|
|
509
|
+
else: # Not installed
|
|
510
|
+
agent_result["python"]["missing"].append(dep_spec)
|
|
511
|
+
if dep_spec not in results["summary"]["missing_python"]:
|
|
512
|
+
results["summary"]["missing_python"].append(dep_spec)
|
|
513
|
+
|
|
514
|
+
# Check system dependencies
|
|
515
|
+
if "system" in deps:
|
|
516
|
+
for command in deps["system"]:
|
|
517
|
+
if self.check_system_dependency(command):
|
|
518
|
+
agent_result["system"]["satisfied"].append(command)
|
|
519
|
+
if command not in results["summary"]["satisfied_system"]:
|
|
520
|
+
results["summary"]["satisfied_system"].append(command)
|
|
521
|
+
else:
|
|
522
|
+
agent_result["system"]["missing"].append(command)
|
|
523
|
+
if command not in results["summary"]["missing_system"]:
|
|
524
|
+
results["summary"]["missing_system"].append(command)
|
|
525
|
+
|
|
526
|
+
results["agents"][agent_id] = agent_result
|
|
527
|
+
if "python" in deps or "system" in deps:
|
|
528
|
+
results["summary"]["agents_with_deps"] += 1
|
|
529
|
+
|
|
530
|
+
return results
|
|
531
|
+
|
|
532
|
+
def check_python_compatibility(
|
|
533
|
+
self, dependencies: List[str]
|
|
534
|
+
) -> Tuple[List[str], List[str]]:
|
|
535
|
+
"""
|
|
536
|
+
Check which dependencies are compatible with current Python version.
|
|
537
|
+
|
|
538
|
+
Args:
|
|
539
|
+
dependencies: List of package specifications to check
|
|
540
|
+
|
|
541
|
+
Returns:
|
|
542
|
+
Tuple of (compatible_deps, incompatible_deps)
|
|
543
|
+
"""
|
|
544
|
+
import sys
|
|
545
|
+
|
|
546
|
+
compatible: List[str] = []
|
|
547
|
+
incompatible: List[str] = []
|
|
548
|
+
|
|
549
|
+
for dep in dependencies:
|
|
550
|
+
try:
|
|
551
|
+
# For known problematic packages in Python 3.13
|
|
552
|
+
req = Requirement(dep)
|
|
553
|
+
package_name = req.name.lower()
|
|
554
|
+
|
|
555
|
+
# Known Python 3.13 incompatibilities
|
|
556
|
+
if sys.version_info >= (3, 13):
|
|
557
|
+
if (
|
|
558
|
+
package_name in ["ydata-profiling", "pandas-profiling"]
|
|
559
|
+
or package_name == "apache-airflow"
|
|
560
|
+
):
|
|
561
|
+
incompatible.append(f"{dep} (requires Python <3.13)")
|
|
562
|
+
continue
|
|
563
|
+
|
|
564
|
+
# Default to compatible if we don't know
|
|
565
|
+
compatible.append(dep)
|
|
566
|
+
|
|
567
|
+
except Exception as e:
|
|
568
|
+
logger.warning(f"Could not check compatibility for {dep}: {e}")
|
|
569
|
+
compatible.append(dep) # Assume compatible if we can't check
|
|
570
|
+
|
|
571
|
+
return compatible, incompatible
|
|
572
|
+
|
|
573
|
+
def install_missing_dependencies(self, dependencies: List[str]) -> Tuple[bool, str]:
|
|
574
|
+
"""
|
|
575
|
+
Install missing Python dependencies using robust retry logic.
|
|
576
|
+
|
|
577
|
+
WHY: Network issues and temporary package unavailability can cause
|
|
578
|
+
installation failures. Using the robust installer with retries
|
|
579
|
+
significantly improves success rate.
|
|
580
|
+
|
|
581
|
+
Args:
|
|
582
|
+
dependencies: List of package specifications to install
|
|
583
|
+
|
|
584
|
+
Returns:
|
|
585
|
+
Tuple of (success, error_message)
|
|
586
|
+
"""
|
|
587
|
+
if not dependencies:
|
|
588
|
+
return True, ""
|
|
589
|
+
|
|
590
|
+
# Check Python version compatibility first
|
|
591
|
+
compatible, incompatible = self.check_python_compatibility(dependencies)
|
|
592
|
+
|
|
593
|
+
if incompatible:
|
|
594
|
+
logger.warning(f"Skipping {len(incompatible)} incompatible packages:")
|
|
595
|
+
for dep in incompatible:
|
|
596
|
+
logger.warning(f" - {dep}")
|
|
597
|
+
|
|
598
|
+
if not compatible:
|
|
599
|
+
return True, "No compatible packages to install"
|
|
600
|
+
|
|
601
|
+
# Use robust installer with retry logic
|
|
602
|
+
try:
|
|
603
|
+
from .robust_installer import RobustPackageInstaller
|
|
604
|
+
|
|
605
|
+
logger.info(
|
|
606
|
+
f"Installing {len(compatible)} compatible dependencies with retry logic..."
|
|
607
|
+
)
|
|
608
|
+
if incompatible:
|
|
609
|
+
logger.info(
|
|
610
|
+
f"(Skipping {len(incompatible)} incompatible with Python {sys.version_info.major}.{sys.version_info.minor})"
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
# Create installer with sensible defaults
|
|
614
|
+
installer = RobustPackageInstaller(
|
|
615
|
+
max_retries=3, retry_delay=2.0, timeout=300
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
# Install packages
|
|
619
|
+
successful, failed, errors = installer.install_packages(compatible)
|
|
620
|
+
|
|
621
|
+
if failed:
|
|
622
|
+
# Provide detailed error information
|
|
623
|
+
error_details = []
|
|
624
|
+
for pkg in failed:
|
|
625
|
+
error_details.append(f"{pkg}: {errors.get(pkg, 'Unknown error')}")
|
|
626
|
+
|
|
627
|
+
error_msg = f"Failed to install {len(failed)} packages:\n" + "\n".join(
|
|
628
|
+
error_details
|
|
629
|
+
)
|
|
630
|
+
logger.error(error_msg)
|
|
631
|
+
|
|
632
|
+
# Partial success handling
|
|
633
|
+
if successful:
|
|
634
|
+
partial_msg = f"Partially successful: installed {len(successful)} of {len(compatible)} packages"
|
|
635
|
+
logger.info(partial_msg)
|
|
636
|
+
if incompatible:
|
|
637
|
+
return (
|
|
638
|
+
True,
|
|
639
|
+
f"{partial_msg}. Also skipped {len(incompatible)} incompatible",
|
|
640
|
+
)
|
|
641
|
+
return True, partial_msg
|
|
642
|
+
|
|
643
|
+
return False, error_msg
|
|
644
|
+
|
|
645
|
+
logger.info(
|
|
646
|
+
f"Successfully installed all {len(successful)} compatible dependencies"
|
|
647
|
+
)
|
|
648
|
+
if incompatible:
|
|
649
|
+
return (
|
|
650
|
+
True,
|
|
651
|
+
f"Installed {len(compatible)} packages, skipped {len(incompatible)} incompatible",
|
|
652
|
+
)
|
|
653
|
+
return True, ""
|
|
654
|
+
|
|
655
|
+
except ImportError:
|
|
656
|
+
# Fallback to simple installation if robust installer not available
|
|
657
|
+
logger.warning(
|
|
658
|
+
"Robust installer not available, falling back to simple installation"
|
|
659
|
+
)
|
|
660
|
+
try:
|
|
661
|
+
# Check environment and add appropriate flags
|
|
662
|
+
import os
|
|
663
|
+
import sysconfig
|
|
664
|
+
|
|
665
|
+
# Check if in UV tool environment (no pip available)
|
|
666
|
+
uv_tool_dir = os.environ.get("UV_TOOL_DIR", "")
|
|
667
|
+
is_uv_tool = (
|
|
668
|
+
(uv_tool_dir and "claude-mpm" in uv_tool_dir)
|
|
669
|
+
or ".local/share/uv/tools/" in sys.executable
|
|
670
|
+
or "/uv/tools/" in sys.executable
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
if is_uv_tool:
|
|
674
|
+
cmd = ["uv", "pip", "install"]
|
|
675
|
+
logger.debug("Using 'uv pip install' for UV tool environment")
|
|
676
|
+
else:
|
|
677
|
+
cmd = [sys.executable, "-m", "pip", "install"]
|
|
678
|
+
|
|
679
|
+
# Check if in virtualenv
|
|
680
|
+
in_virtualenv = (
|
|
681
|
+
(hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix)
|
|
682
|
+
or (hasattr(sys, "real_prefix"))
|
|
683
|
+
or (os.environ.get("VIRTUAL_ENV") is not None)
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
if in_virtualenv:
|
|
687
|
+
# In virtualenv - no special flags needed
|
|
688
|
+
logger.debug("Installing in virtualenv (no special flags)")
|
|
689
|
+
else:
|
|
690
|
+
# Check for PEP 668 managed environment
|
|
691
|
+
stdlib_path = sysconfig.get_path("stdlib")
|
|
692
|
+
marker_file = Path(stdlib_path) / "EXTERNALLY-MANAGED"
|
|
693
|
+
parent_marker = marker_file.parent.parent / "EXTERNALLY-MANAGED"
|
|
694
|
+
|
|
695
|
+
if marker_file.exists() or parent_marker.exists():
|
|
696
|
+
logger.warning(
|
|
697
|
+
"PEP 668 managed environment detected. "
|
|
698
|
+
"Installing with --break-system-packages flag. "
|
|
699
|
+
"Consider using a virtual environment instead."
|
|
700
|
+
)
|
|
701
|
+
cmd.append("--break-system-packages")
|
|
702
|
+
else:
|
|
703
|
+
# Normal system Python - use --user
|
|
704
|
+
cmd.append("--user")
|
|
705
|
+
logger.debug("Installing with --user flag")
|
|
706
|
+
|
|
707
|
+
cmd.extend(compatible)
|
|
708
|
+
|
|
709
|
+
result = subprocess.run(
|
|
710
|
+
cmd, capture_output=True, text=True, timeout=300, check=False
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
if result.returncode == 0:
|
|
714
|
+
logger.info("Successfully installed compatible dependencies")
|
|
715
|
+
if incompatible:
|
|
716
|
+
return (
|
|
717
|
+
True,
|
|
718
|
+
f"Installed {len(compatible)} packages, skipped {len(incompatible)} incompatible",
|
|
719
|
+
)
|
|
720
|
+
return True, ""
|
|
721
|
+
error_msg = f"Installation failed: {result.stderr}"
|
|
722
|
+
logger.error(error_msg)
|
|
723
|
+
return False, error_msg
|
|
724
|
+
|
|
725
|
+
except Exception as e:
|
|
726
|
+
error_msg = f"Failed to install dependencies: {e}"
|
|
727
|
+
logger.error(error_msg)
|
|
728
|
+
return False, error_msg
|
|
729
|
+
|
|
730
|
+
except Exception as e:
|
|
731
|
+
error_msg = f"Failed to install dependencies: {e}"
|
|
732
|
+
logger.error(error_msg)
|
|
733
|
+
return False, error_msg
|
|
734
|
+
|
|
735
|
+
def load_and_check(self) -> Dict[str, Dict]:
|
|
736
|
+
"""
|
|
737
|
+
Complete workflow: discover agents, load dependencies, and check them.
|
|
738
|
+
|
|
739
|
+
Returns:
|
|
740
|
+
Complete analysis results
|
|
741
|
+
"""
|
|
742
|
+
# Discover deployed agents
|
|
743
|
+
self.discover_deployed_agents()
|
|
744
|
+
|
|
745
|
+
if not self.deployed_agents:
|
|
746
|
+
logger.info("No deployed agents found")
|
|
747
|
+
return {"agents": {}, "summary": {"total_agents": 0}}
|
|
748
|
+
|
|
749
|
+
# Load their dependencies
|
|
750
|
+
self.load_agent_dependencies()
|
|
751
|
+
|
|
752
|
+
# Analyze what's missing
|
|
753
|
+
results = self.analyze_dependencies()
|
|
754
|
+
|
|
755
|
+
# Optionally auto-install missing dependencies
|
|
756
|
+
if self.auto_install and results["summary"]["missing_python"]:
|
|
757
|
+
logger.info(
|
|
758
|
+
f"Auto-installing {len(results['summary']['missing_python'])} missing dependencies..."
|
|
759
|
+
)
|
|
760
|
+
success, _error = self.install_missing_dependencies(
|
|
761
|
+
results["summary"]["missing_python"]
|
|
762
|
+
)
|
|
763
|
+
if success:
|
|
764
|
+
# Re-analyze after installation
|
|
765
|
+
self.checked_packages.clear()
|
|
766
|
+
results = self.analyze_dependencies()
|
|
767
|
+
|
|
768
|
+
return results
|
|
769
|
+
|
|
770
|
+
def format_report(self, results: Dict[str, Dict]) -> str:
|
|
771
|
+
"""
|
|
772
|
+
Format a human-readable dependency report.
|
|
773
|
+
|
|
774
|
+
Args:
|
|
775
|
+
results: Analysis results from analyze_dependencies()
|
|
776
|
+
|
|
777
|
+
Returns:
|
|
778
|
+
Formatted report string
|
|
779
|
+
"""
|
|
780
|
+
import sys
|
|
781
|
+
|
|
782
|
+
lines = []
|
|
783
|
+
lines.append("=" * 80)
|
|
784
|
+
lines.append("AGENT DEPENDENCY ANALYSIS REPORT")
|
|
785
|
+
lines.append("=" * 80)
|
|
786
|
+
lines.append("")
|
|
787
|
+
|
|
788
|
+
# Python version info
|
|
789
|
+
lines.append(
|
|
790
|
+
f"Python Version: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
791
|
+
)
|
|
792
|
+
lines.append("")
|
|
793
|
+
|
|
794
|
+
# Summary
|
|
795
|
+
summary = results["summary"]
|
|
796
|
+
lines.append(f"Deployed Agents: {summary['total_agents']}")
|
|
797
|
+
lines.append(f"Agents with Dependencies: {summary['agents_with_deps']}")
|
|
798
|
+
lines.append("")
|
|
799
|
+
|
|
800
|
+
# Missing dependencies summary
|
|
801
|
+
if summary["missing_python"] or summary["missing_system"]:
|
|
802
|
+
lines.append("⚠️ MISSING DEPENDENCIES:")
|
|
803
|
+
if summary["missing_python"]:
|
|
804
|
+
lines.append(f" Python packages: {len(summary['missing_python'])}")
|
|
805
|
+
for dep in summary["missing_python"][:5]: # Show first 5
|
|
806
|
+
lines.append(f" - {dep}")
|
|
807
|
+
if len(summary["missing_python"]) > 5:
|
|
808
|
+
lines.append(
|
|
809
|
+
f" ... and {len(summary['missing_python']) - 5} more"
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
if summary["missing_system"]:
|
|
813
|
+
lines.append(f" System commands: {len(summary['missing_system'])}")
|
|
814
|
+
for cmd in summary["missing_system"]:
|
|
815
|
+
lines.append(f" - {cmd}")
|
|
816
|
+
lines.append("")
|
|
817
|
+
|
|
818
|
+
# Per-agent details (only for agents with issues)
|
|
819
|
+
agents_with_issues = {
|
|
820
|
+
agent_id: info
|
|
821
|
+
for agent_id, info in results["agents"].items()
|
|
822
|
+
if info["python"]["missing"]
|
|
823
|
+
or info["python"]["outdated"]
|
|
824
|
+
or info["system"]["missing"]
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if agents_with_issues:
|
|
828
|
+
lines.append("AGENT-SPECIFIC ISSUES:")
|
|
829
|
+
lines.append("-" * 40)
|
|
830
|
+
for agent_id, info in agents_with_issues.items():
|
|
831
|
+
lines.append(f"\n📦 {agent_id}:")
|
|
832
|
+
|
|
833
|
+
if info["python"]["missing"]:
|
|
834
|
+
lines.append(
|
|
835
|
+
f" Missing Python: {', '.join(info['python']['missing'])}"
|
|
836
|
+
)
|
|
837
|
+
if info["python"]["outdated"]:
|
|
838
|
+
lines.append(
|
|
839
|
+
f" Outdated Python: {', '.join(info['python']['outdated'])}"
|
|
840
|
+
)
|
|
841
|
+
if info["system"]["missing"]:
|
|
842
|
+
lines.append(
|
|
843
|
+
f" Missing System: {', '.join(info['system']['missing'])}"
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
else:
|
|
847
|
+
lines.append("✅ All agent dependencies are satisfied!")
|
|
848
|
+
|
|
849
|
+
# Installation instructions
|
|
850
|
+
if summary["missing_python"]:
|
|
851
|
+
lines.append("")
|
|
852
|
+
lines.append("TO INSTALL MISSING PYTHON DEPENDENCIES:")
|
|
853
|
+
lines.append("-" * 40)
|
|
854
|
+
|
|
855
|
+
# Check for Python 3.13 compatibility issues
|
|
856
|
+
import sys
|
|
857
|
+
|
|
858
|
+
if sys.version_info >= (3, 13):
|
|
859
|
+
_compatible, incompatible = self.check_python_compatibility(
|
|
860
|
+
summary["missing_python"]
|
|
861
|
+
)
|
|
862
|
+
if incompatible:
|
|
863
|
+
lines.append("⚠️ Python 3.13 Compatibility Warning:")
|
|
864
|
+
lines.append(
|
|
865
|
+
f" {len(incompatible)} packages are not yet compatible with Python 3.13:"
|
|
866
|
+
)
|
|
867
|
+
for dep in incompatible[:3]:
|
|
868
|
+
lines.append(f" - {dep}")
|
|
869
|
+
if len(incompatible) > 3:
|
|
870
|
+
lines.append(f" ... and {len(incompatible) - 3} more")
|
|
871
|
+
lines.append("")
|
|
872
|
+
lines.append(
|
|
873
|
+
" Consider using Python 3.12 or earlier for full compatibility."
|
|
874
|
+
)
|
|
875
|
+
lines.append("")
|
|
876
|
+
|
|
877
|
+
lines.append("Option 1: Install all agent dependencies:")
|
|
878
|
+
lines.append(' pip install "claude-mpm[agents]"')
|
|
879
|
+
lines.append("")
|
|
880
|
+
lines.append("Option 2: Install only what's needed:")
|
|
881
|
+
deps_str = " ".join(f'"{dep}"' for dep in summary["missing_python"][:3])
|
|
882
|
+
lines.append(f" pip install {deps_str}")
|
|
883
|
+
if len(summary["missing_python"]) > 3:
|
|
884
|
+
lines.append(f" # ... and {len(summary['missing_python']) - 3} more")
|
|
885
|
+
|
|
886
|
+
if summary["missing_system"]:
|
|
887
|
+
lines.append("")
|
|
888
|
+
lines.append("TO INSTALL MISSING SYSTEM DEPENDENCIES:")
|
|
889
|
+
lines.append("-" * 40)
|
|
890
|
+
lines.append("Use your system package manager:")
|
|
891
|
+
lines.append(
|
|
892
|
+
" # macOS: brew install " + " ".join(summary["missing_system"])
|
|
893
|
+
)
|
|
894
|
+
lines.append(
|
|
895
|
+
" # Ubuntu: apt-get install " + " ".join(summary["missing_system"])
|
|
896
|
+
)
|
|
897
|
+
|
|
898
|
+
lines.append("")
|
|
899
|
+
lines.append("=" * 80)
|
|
900
|
+
|
|
901
|
+
return "\n".join(lines)
|
|
902
|
+
|
|
903
|
+
def calculate_deployment_hash(self) -> str:
|
|
904
|
+
"""
|
|
905
|
+
Calculate a hash of the current agent deployment state.
|
|
906
|
+
|
|
907
|
+
WHY: We use SHA256 hash of agent files to detect when agents have changed.
|
|
908
|
+
This allows us to skip dependency checks when nothing has changed,
|
|
909
|
+
improving startup performance.
|
|
910
|
+
|
|
911
|
+
Returns:
|
|
912
|
+
SHA256 hash of all deployed agent files and their content.
|
|
913
|
+
"""
|
|
914
|
+
hash_obj = hashlib.sha256()
|
|
915
|
+
|
|
916
|
+
# Discover current agents if not already done
|
|
917
|
+
if not self.deployed_agents:
|
|
918
|
+
self.discover_deployed_agents()
|
|
919
|
+
|
|
920
|
+
# Sort agent IDs for consistent hashing
|
|
921
|
+
for agent_id in sorted(self.deployed_agents.keys()):
|
|
922
|
+
agent_path = self.deployed_agents[agent_id]
|
|
923
|
+
|
|
924
|
+
# Include agent ID in hash
|
|
925
|
+
hash_obj.update(agent_id.encode("utf-8"))
|
|
926
|
+
|
|
927
|
+
# Include file modification time and size for quick change detection
|
|
928
|
+
try:
|
|
929
|
+
stat = agent_path.stat()
|
|
930
|
+
hash_obj.update(str(stat.st_mtime).encode("utf-8"))
|
|
931
|
+
hash_obj.update(str(stat.st_size).encode("utf-8"))
|
|
932
|
+
|
|
933
|
+
# Include file content for comprehensive change detection
|
|
934
|
+
with agent_path.open("rb") as f:
|
|
935
|
+
hash_obj.update(f.read())
|
|
936
|
+
except Exception as e:
|
|
937
|
+
logger.debug(f"Could not hash agent file {agent_path}: {e}")
|
|
938
|
+
# Include error in hash to force recheck on next run
|
|
939
|
+
hash_obj.update(f"error:{agent_id}:{e}".encode())
|
|
940
|
+
|
|
941
|
+
return hash_obj.hexdigest()
|
|
942
|
+
|
|
943
|
+
def load_deployment_state(self) -> Dict:
|
|
944
|
+
"""
|
|
945
|
+
Load the saved deployment state.
|
|
946
|
+
|
|
947
|
+
Returns:
|
|
948
|
+
Dictionary with deployment state or empty dict if not found.
|
|
949
|
+
"""
|
|
950
|
+
if not self.deployment_state_file.exists():
|
|
951
|
+
return {}
|
|
952
|
+
|
|
953
|
+
try:
|
|
954
|
+
with self.deployment_state_file.open() as f:
|
|
955
|
+
return json.load(f)
|
|
956
|
+
except Exception as e:
|
|
957
|
+
logger.debug(f"Could not load deployment state: {e}")
|
|
958
|
+
return {}
|
|
959
|
+
|
|
960
|
+
def save_deployment_state(self, state: Dict) -> None:
|
|
961
|
+
"""
|
|
962
|
+
Save the deployment state to disk.
|
|
963
|
+
|
|
964
|
+
Args:
|
|
965
|
+
state: Deployment state dictionary to save.
|
|
966
|
+
"""
|
|
967
|
+
try:
|
|
968
|
+
# Ensure directory exists
|
|
969
|
+
self.deployment_state_file.parent.mkdir(parents=True, exist_ok=True)
|
|
970
|
+
|
|
971
|
+
with self.deployment_state_file.open("w") as f:
|
|
972
|
+
json.dump(state, f, indent=2)
|
|
973
|
+
except Exception as e:
|
|
974
|
+
logger.debug(f"Could not save deployment state: {e}")
|
|
975
|
+
|
|
976
|
+
def has_agents_changed(self) -> Tuple[bool, str]:
|
|
977
|
+
"""
|
|
978
|
+
Check if agents have changed since last dependency check.
|
|
979
|
+
|
|
980
|
+
WHY: This is the core of our smart checking system. We only want to
|
|
981
|
+
check dependencies when agents have actually changed, not on every run.
|
|
982
|
+
|
|
983
|
+
Returns:
|
|
984
|
+
Tuple of (has_changed, current_hash)
|
|
985
|
+
"""
|
|
986
|
+
current_hash = self.calculate_deployment_hash()
|
|
987
|
+
state = self.load_deployment_state()
|
|
988
|
+
|
|
989
|
+
last_hash = state.get("deployment_hash")
|
|
990
|
+
last_check_time = state.get("last_check_time", 0)
|
|
991
|
+
|
|
992
|
+
# Check if hash has changed
|
|
993
|
+
if last_hash != current_hash:
|
|
994
|
+
logger.info("Agent deployment has changed since last check")
|
|
995
|
+
return True, current_hash
|
|
996
|
+
|
|
997
|
+
# Also check if it's been more than 24 hours (optional staleness check)
|
|
998
|
+
current_time = time.time()
|
|
999
|
+
if current_time - last_check_time > 86400: # 24 hours
|
|
1000
|
+
logger.debug("Over 24 hours since last dependency check")
|
|
1001
|
+
return True, current_hash
|
|
1002
|
+
|
|
1003
|
+
logger.debug("No agent changes detected, skipping dependency check")
|
|
1004
|
+
return False, current_hash
|
|
1005
|
+
|
|
1006
|
+
def mark_deployment_checked(
|
|
1007
|
+
self, deployment_hash: str, check_results: Dict
|
|
1008
|
+
) -> None:
|
|
1009
|
+
"""
|
|
1010
|
+
Mark the current deployment as checked.
|
|
1011
|
+
|
|
1012
|
+
Args:
|
|
1013
|
+
deployment_hash: Hash of the current deployment
|
|
1014
|
+
check_results: Results of the dependency check
|
|
1015
|
+
"""
|
|
1016
|
+
state = {
|
|
1017
|
+
"deployment_hash": deployment_hash,
|
|
1018
|
+
"last_check_time": time.time(),
|
|
1019
|
+
"last_check_results": check_results,
|
|
1020
|
+
"agent_count": len(self.deployed_agents),
|
|
1021
|
+
}
|
|
1022
|
+
self.save_deployment_state(state)
|
|
1023
|
+
|
|
1024
|
+
def get_cached_check_results(self) -> Optional[Dict]:
|
|
1025
|
+
"""
|
|
1026
|
+
Get cached dependency check results if still valid.
|
|
1027
|
+
|
|
1028
|
+
Returns:
|
|
1029
|
+
Cached results or None if not available/valid.
|
|
1030
|
+
"""
|
|
1031
|
+
has_changed, _current_hash = self.has_agents_changed()
|
|
1032
|
+
|
|
1033
|
+
if not has_changed:
|
|
1034
|
+
state = self.load_deployment_state()
|
|
1035
|
+
cached_results = state.get("last_check_results")
|
|
1036
|
+
if cached_results:
|
|
1037
|
+
logger.debug("Using cached dependency check results")
|
|
1038
|
+
return cached_results
|
|
1039
|
+
|
|
1040
|
+
return None
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
def check_deployed_agent_dependencies(
|
|
1044
|
+
auto_install: bool = False, verbose: bool = False
|
|
1045
|
+
) -> int:
|
|
1046
|
+
"""
|
|
1047
|
+
Check dependencies for currently deployed agents.
|
|
1048
|
+
|
|
1049
|
+
Args:
|
|
1050
|
+
auto_install: If True, automatically install missing Python dependencies
|
|
1051
|
+
verbose: If True, enable verbose logging
|
|
1052
|
+
|
|
1053
|
+
Returns:
|
|
1054
|
+
Status code: 0 if all dependencies satisfied, 1 if missing dependencies
|
|
1055
|
+
"""
|
|
1056
|
+
if verbose:
|
|
1057
|
+
logging.getLogger().setLevel(logging.DEBUG)
|
|
1058
|
+
|
|
1059
|
+
loader = AgentDependencyLoader(auto_install=auto_install)
|
|
1060
|
+
results = loader.load_and_check()
|
|
1061
|
+
|
|
1062
|
+
# Print report
|
|
1063
|
+
report = loader.format_report(results)
|
|
1064
|
+
print(report)
|
|
1065
|
+
|
|
1066
|
+
# Return status code based on missing dependencies
|
|
1067
|
+
if results["summary"]["missing_python"] or results["summary"]["missing_system"]:
|
|
1068
|
+
return 1 # Missing dependencies
|
|
1069
|
+
return 0 # All satisfied
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
if __name__ == "__main__":
|
|
1073
|
+
import argparse
|
|
1074
|
+
|
|
1075
|
+
parser = argparse.ArgumentParser(
|
|
1076
|
+
description="Check and manage dependencies for deployed agents"
|
|
1077
|
+
)
|
|
1078
|
+
parser.add_argument(
|
|
1079
|
+
"--auto-install",
|
|
1080
|
+
action="store_true",
|
|
1081
|
+
help="Automatically install missing Python dependencies",
|
|
1082
|
+
)
|
|
1083
|
+
parser.add_argument("--verbose", action="store_true", help="Enable verbose logging")
|
|
1084
|
+
|
|
1085
|
+
args = parser.parse_args()
|
|
1086
|
+
|
|
1087
|
+
exit_code = check_deployed_agent_dependencies(
|
|
1088
|
+
auto_install=args.auto_install, verbose=args.verbose
|
|
1089
|
+
)
|
|
1090
|
+
sys.exit(exit_code)
|