claude-mpm 4.1.26__py3-none-any.whl → 4.24.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +20 -5
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_DOCUMENTATION.md +53 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/BASE_OPS.md +219 -0
- claude_mpm/agents/BASE_PM.md +420 -158
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +787 -0
- claude_mpm/agents/BASE_QA.md +167 -0
- claude_mpm/agents/BASE_RESEARCH.md +53 -0
- claude_mpm/agents/OUTPUT_STYLE.md +299 -29
- claude_mpm/agents/PM_INSTRUCTIONS.md +1159 -0
- claude_mpm/agents/WORKFLOW.md +355 -191
- claude_mpm/agents/agent_loader.py +40 -10
- claude_mpm/agents/agent_loader_integration.py +3 -2
- claude_mpm/agents/async_agent_loader.py +3 -3
- claude_mpm/agents/base_agent_loader.py +11 -9
- claude_mpm/agents/frontmatter_validator.py +291 -251
- claude_mpm/agents/system_agent_config.py +3 -2
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/agent-manager.json +7 -4
- claude_mpm/agents/templates/{agentic_coder_optimizer.json → agentic-coder-optimizer.json} +33 -7
- claude_mpm/agents/templates/api_qa.json +16 -4
- claude_mpm/agents/templates/circuit_breakers.md +638 -0
- claude_mpm/agents/templates/clerk-ops.json +235 -0
- claude_mpm/agents/templates/code_analyzer.json +10 -4
- claude_mpm/agents/templates/content-agent.json +358 -0
- claude_mpm/agents/templates/dart_engineer.json +307 -0
- claude_mpm/agents/templates/data_engineer.json +87 -14
- claude_mpm/agents/templates/documentation.json +76 -13
- claude_mpm/agents/templates/engineer.json +43 -9
- claude_mpm/agents/templates/gcp_ops_agent.json +253 -0
- claude_mpm/agents/templates/git_file_tracking.md +584 -0
- claude_mpm/agents/templates/golang_engineer.json +270 -0
- claude_mpm/agents/templates/imagemagick.json +5 -2
- claude_mpm/agents/templates/java_engineer.json +346 -0
- claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
- claude_mpm/agents/templates/local_ops_agent.json +1840 -0
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +400 -0
- claude_mpm/agents/templates/memory_manager.json +6 -3
- claude_mpm/agents/templates/nextjs_engineer.json +285 -0
- claude_mpm/agents/templates/ops.json +14 -4
- claude_mpm/agents/templates/php-engineer.json +287 -0
- claude_mpm/agents/templates/pm_examples.md +474 -0
- claude_mpm/agents/templates/pm_red_flags.md +262 -0
- claude_mpm/agents/templates/product_owner.json +338 -0
- claude_mpm/agents/templates/project_organizer.json +19 -5
- claude_mpm/agents/templates/prompt-engineer.json +737 -0
- claude_mpm/agents/templates/python_engineer.json +387 -0
- claude_mpm/agents/templates/qa.json +25 -5
- claude_mpm/agents/templates/react_engineer.json +239 -0
- claude_mpm/agents/templates/refactoring_engineer.json +15 -5
- claude_mpm/agents/templates/research.json +46 -21
- claude_mpm/agents/templates/response_format.md +583 -0
- claude_mpm/agents/templates/ruby-engineer.json +280 -0
- claude_mpm/agents/templates/rust_engineer.json +275 -0
- claude_mpm/agents/templates/security.json +59 -10
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/tauri_engineer.json +274 -0
- claude_mpm/agents/templates/ticketing.json +16 -7
- claude_mpm/agents/templates/typescript_engineer.json +285 -0
- claude_mpm/agents/templates/validation_templates.md +312 -0
- claude_mpm/agents/templates/vercel_ops_agent.json +164 -33
- claude_mpm/agents/templates/version_control.json +16 -4
- claude_mpm/agents/templates/web_qa.json +167 -21
- claude_mpm/agents/templates/web_ui.json +18 -5
- claude_mpm/cli/__init__.py +38 -378
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_manager.py +675 -20
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +722 -150
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +10 -6
- claude_mpm/cli/commands/analyze.py +15 -10
- claude_mpm/cli/commands/analyze_code.py +8 -4
- claude_mpm/cli/commands/auto_configure.py +570 -0
- claude_mpm/cli/commands/cleanup.py +12 -12
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +469 -1064
- claude_mpm/cli/commands/configure_agent_display.py +261 -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 +167 -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 +50 -52
- claude_mpm/cli/commands/debug.py +7 -7
- claude_mpm/cli/commands/doctor.py +43 -7
- claude_mpm/cli/commands/info.py +3 -4
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/mcp.py +17 -10
- claude_mpm/cli/commands/mcp_command_router.py +11 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +101 -32
- claude_mpm/cli/commands/mcp_pipx_config.py +2 -2
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/memory.py +55 -21
- claude_mpm/cli/commands/monitor.py +160 -70
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +525 -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/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +114 -4
- claude_mpm/cli/commands/run.py +169 -42
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skills.py +488 -0
- 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 +204 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +962 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +79 -2
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +161 -1
- claude_mpm/cli/parsers/agents_parser.py +116 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +143 -3
- claude_mpm/cli/parsers/configure_parser.py +11 -15
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +15 -0
- claude_mpm/cli/parsers/monitor_parser.py +12 -2
- claude_mpm/cli/parsers/mpm_init_parser.py +179 -9
- claude_mpm/cli/parsers/run_parser.py +5 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skills_parser.py +137 -0
- claude_mpm/cli/shared/argument_patterns.py +20 -13
- claude_mpm/cli/shared/base_command.py +2 -2
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +562 -0
- claude_mpm/cli/startup_logging.py +179 -13
- claude_mpm/cli/utils.py +53 -2
- claude_mpm/commands/mpm-agents-detect.md +168 -0
- claude_mpm/commands/mpm-agents-recommend.md +214 -0
- claude_mpm/commands/mpm-agents.md +118 -8
- claude_mpm/commands/mpm-auto-configure.md +269 -0
- claude_mpm/commands/mpm-config.md +137 -14
- claude_mpm/commands/mpm-help.md +285 -5
- claude_mpm/commands/mpm-init.md +374 -15
- claude_mpm/commands/mpm-monitor.md +409 -0
- claude_mpm/commands/mpm-organize.md +295 -0
- claude_mpm/commands/mpm-resume.md +372 -0
- claude_mpm/commands/mpm-status.md +71 -9
- claude_mpm/commands/mpm-tickets.md +56 -7
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +2 -0
- claude_mpm/config/agent_config.py +4 -4
- claude_mpm/config/experimental_features.py +7 -7
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +3 -2
- claude_mpm/config/socketio_config.py +3 -3
- claude_mpm/constants.py +15 -1
- claude_mpm/core/__init__.py +53 -17
- claude_mpm/core/agent_name_normalizer.py +3 -2
- claude_mpm/core/agent_registry.py +2 -2
- claude_mpm/core/agent_session_manager.py +10 -10
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +33 -23
- claude_mpm/core/cache.py +9 -9
- claude_mpm/core/claude_runner.py +19 -8
- claude_mpm/core/config.py +85 -8
- claude_mpm/core/config_aliases.py +7 -6
- claude_mpm/core/constants.py +65 -0
- claude_mpm/core/container.py +11 -5
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +38 -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 +288 -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 +210 -0
- claude_mpm/core/framework/loaders/file_loader.py +223 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +161 -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 +321 -1631
- claude_mpm/core/hook_manager.py +8 -6
- claude_mpm/core/injectable_service.py +11 -8
- claude_mpm/core/instruction_reinforcement_hook.py +4 -3
- claude_mpm/core/interactive_session.py +55 -8
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/lazy.py +3 -3
- claude_mpm/core/log_manager.py +92 -23
- claude_mpm/core/logger.py +19 -14
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/oneshot_session.py +51 -7
- claude_mpm/core/optimized_agent_loader.py +9 -9
- claude_mpm/core/optimized_startup.py +1 -1
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/pm_hook_interceptor.py +18 -12
- claude_mpm/core/service_registry.py +7 -3
- claude_mpm/core/session_manager.py +14 -12
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/socketio_pool.py +15 -15
- claude_mpm/core/tool_access_control.py +3 -2
- claude_mpm/core/types.py +4 -11
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/core/unified_agent_registry.py +115 -11
- claude_mpm/core/unified_config.py +6 -6
- claude_mpm/core/unified_paths.py +23 -20
- claude_mpm/dashboard/analysis_runner.py +4 -4
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
- claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
- claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
- claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
- claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
- claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
- claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/built/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
- claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
- claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
- claude_mpm/dashboard/static/built/components/code-tree.js +1 -1
- claude_mpm/dashboard/static/built/components/code-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
- claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/built/components/file-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
- claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +1 -1
- claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/built/connection-manager.js +536 -0
- claude_mpm/dashboard/static/built/dashboard.js +1 -1
- claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/built/react/events.js +30 -0
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
- claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
- claude_mpm/dashboard/static/built/shared/logger.js +385 -0
- claude_mpm/dashboard/static/built/shared/page-structure.js +249 -0
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
- claude_mpm/dashboard/static/built/socket-client.js +1 -1
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/css/dashboard.css +588 -6
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
- claude_mpm/dashboard/static/dist/components/activity-tree.js +1 -1
- claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
- claude_mpm/dashboard/static/dist/components/code-tree.js +1 -1
- claude_mpm/dashboard/static/dist/components/code-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
- claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
- claude_mpm/dashboard/static/dist/components/file-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +1 -1
- claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
- claude_mpm/dashboard/static/dist/dashboard.js +1 -1
- claude_mpm/dashboard/static/dist/react/events.js +30 -0
- claude_mpm/dashboard/static/dist/socket-client.js +1 -1
- claude_mpm/dashboard/static/events.html +607 -0
- claude_mpm/dashboard/static/index.html +635 -0
- claude_mpm/dashboard/static/js/components/activity-tree.js +3 -17
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
- claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
- claude_mpm/dashboard/static/js/components/build-tracker.js +8 -0
- claude_mpm/dashboard/static/js/components/code-simple.js +857 -0
- claude_mpm/dashboard/static/js/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
- claude_mpm/dashboard/static/js/components/event-viewer.js +39 -2
- claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +690 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
- claude_mpm/dashboard/static/js/components/file-viewer.js +580 -0
- claude_mpm/dashboard/static/js/components/module-viewer.js +26 -0
- claude_mpm/dashboard/static/js/components/session-manager.js +7 -7
- claude_mpm/dashboard/static/js/components/socket-manager.js +4 -0
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +356 -41
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +455 -23
- claude_mpm/dashboard/static/js/components/working-directory.js +44 -9
- claude_mpm/dashboard/static/js/dashboard.js +245 -132
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +396 -0
- claude_mpm/dashboard/static/js/shared/event-bus.js +330 -0
- claude_mpm/dashboard/static/js/shared/logger.js +385 -0
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +253 -0
- claude_mpm/dashboard/static/js/socket-client.js +49 -22
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/legacy/activity.html +736 -0
- claude_mpm/dashboard/static/legacy/agents.html +786 -0
- claude_mpm/dashboard/static/legacy/files.html +747 -0
- claude_mpm/dashboard/static/legacy/tools.html +831 -0
- claude_mpm/dashboard/static/monitors.html +431 -0
- claude_mpm/dashboard/static/production/events.html +659 -0
- claude_mpm/dashboard/static/production/main.html +698 -0
- claude_mpm/dashboard/static/production/monitors.html +483 -0
- claude_mpm/dashboard/static/socket.io.min.js +7 -0
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
- claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
- claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
- claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
- claude_mpm/dashboard/static/test-archive/test_debug.html +25 -0
- claude_mpm/dashboard/templates/code_simple.html +153 -0
- claude_mpm/dashboard/templates/index.html +112 -109
- claude_mpm/experimental/cli_enhancements.py +4 -2
- claude_mpm/generators/agent_profile_generator.py +5 -3
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +5 -4
- claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
- claude_mpm/hooks/claude_hooks/event_handlers.py +21 -18
- claude_mpm/hooks/claude_hooks/hook_handler.py +29 -22
- claude_mpm/hooks/claude_hooks/installer.py +67 -22
- claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
- claude_mpm/hooks/claude_hooks/response_tracking.py +57 -17
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +62 -64
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +140 -76
- claude_mpm/hooks/claude_hooks/services/state_manager.py +11 -9
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
- claude_mpm/hooks/failure_learning/__init__.py +60 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -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 +183 -0
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- 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 +8 -5
- claude_mpm/hooks/validation_hooks.py +3 -3
- claude_mpm/init.py +23 -4
- claude_mpm/models/agent_session.py +8 -6
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/scripts/claude-hook-handler.sh +33 -7
- claude_mpm/scripts/launch_monitor.py +85 -0
- claude_mpm/scripts/mcp_server.py +3 -5
- claude_mpm/scripts/mpm_doctor.py +3 -2
- claude_mpm/scripts/socketio_daemon.py +159 -512
- claude_mpm/services/__init__.py +144 -160
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/agent_builder.py +13 -11
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_deployment.py +38 -15
- claude_mpm/services/agents/deployment/agent_discovery_service.py +125 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_format_converter.py +56 -12
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +4 -2
- claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_record_service.py +4 -4
- claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_template_builder.py +715 -47
- claude_mpm/services/agents/deployment/agent_validator.py +31 -7
- claude_mpm/services/agents/deployment/agent_version_manager.py +8 -5
- claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/deployment_config_loader.py +131 -7
- claude_mpm/services/agents/deployment/deployment_type_detector.py +10 -14
- claude_mpm/services/agents/deployment/deployment_wrapper.py +58 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +360 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +134 -38
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +8 -7
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +7 -5
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +64 -44
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/loading/agent_profile_loader.py +10 -9
- claude_mpm/services/agents/loading/base_agent_manager.py +16 -6
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -2
- claude_mpm/services/agents/local_template_manager.py +744 -0
- claude_mpm/services/agents/management/agent_capabilities_generator.py +3 -2
- claude_mpm/services/agents/management/agent_management_service.py +5 -5
- claude_mpm/services/agents/memory/agent_memory_manager.py +32 -29
- claude_mpm/services/agents/memory/content_manager.py +17 -9
- claude_mpm/services/agents/memory/memory_categorization_service.py +4 -2
- claude_mpm/services/agents/memory/memory_file_service.py +32 -6
- claude_mpm/services/agents/memory/memory_format_service.py +6 -4
- claude_mpm/services/agents/memory/memory_limits_service.py +4 -2
- claude_mpm/services/agents/memory/template_generator.py +3 -3
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +615 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +3 -3
- claude_mpm/services/agents/registry/modification_tracker.py +30 -19
- claude_mpm/services/async_session_logger.py +141 -98
- claude_mpm/services/claude_session_logger.py +82 -74
- claude_mpm/services/cli/agent_cleanup_service.py +5 -0
- claude_mpm/services/cli/agent_listing_service.py +5 -5
- claude_mpm/services/cli/agent_validation_service.py +3 -1
- claude_mpm/services/cli/memory_crud_service.py +12 -7
- claude_mpm/services/cli/memory_output_formatter.py +2 -2
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +104 -13
- 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 +13 -10
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +9 -7
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/base.py +26 -11
- claude_mpm/services/core/interfaces/__init__.py +90 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +172 -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/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/memory_manager.py +92 -47
- claude_mpm/services/core/models/__init__.py +79 -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 +36 -14
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/__init__.py +4 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +30 -32
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +28 -27
- claude_mpm/services/diagnostics/checks/configuration_check.py +26 -25
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +165 -60
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +57 -43
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1066 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +24 -23
- claude_mpm/services/diagnostics/checks/startup_log_check.py +14 -11
- claude_mpm/services/diagnostics/diagnostic_runner.py +22 -13
- claude_mpm/services/diagnostics/doctor_reporter.py +275 -47
- claude_mpm/services/diagnostics/models.py +37 -21
- claude_mpm/services/event_aggregator.py +5 -3
- claude_mpm/services/event_bus/direct_relay.py +8 -4
- claude_mpm/services/event_bus/event_bus.py +51 -9
- claude_mpm/services/event_bus/relay.py +33 -14
- claude_mpm/services/events/consumers/dead_letter.py +7 -5
- claude_mpm/services/events/core.py +5 -6
- claude_mpm/services/events/producers/hook.py +6 -6
- claude_mpm/services/events/producers/system.py +8 -8
- claude_mpm/services/exceptions.py +5 -5
- claude_mpm/services/framework_claude_md_generator/__init__.py +1 -1
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +5 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +2 -2
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +3 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +1 -1
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +5 -6
- claude_mpm/services/infrastructure/context_preservation.py +13 -11
- claude_mpm/services/infrastructure/daemon_manager.py +9 -9
- claude_mpm/services/infrastructure/logging.py +2 -2
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +8 -7
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +165 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -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 +430 -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 +1612 -0
- claude_mpm/services/mcp_gateway/__init__.py +97 -93
- claude_mpm/services/mcp_gateway/auto_configure.py +43 -38
- claude_mpm/services/mcp_gateway/config/config_loader.py +3 -3
- claude_mpm/services/mcp_gateway/config/configuration.py +23 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +20 -33
- claude_mpm/services/mcp_gateway/core/process_pool.py +585 -31
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +2 -2
- claude_mpm/services/mcp_gateway/core/startup_verification.py +3 -3
- claude_mpm/services/mcp_gateway/main.py +90 -15
- claude_mpm/services/mcp_gateway/registry/service_registry.py +4 -2
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +12 -9
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
- claude_mpm/services/mcp_gateway/server/stdio_server.py +9 -15
- claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +10 -9
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +654 -0
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +36 -34
- claude_mpm/services/mcp_gateway/tools/hello_world.py +8 -8
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +551 -0
- claude_mpm/services/mcp_gateway/utils/__init__.py +14 -0
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +160 -0
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +170 -0
- claude_mpm/services/mcp_service_verifier.py +729 -0
- claude_mpm/services/memory/builder.py +9 -8
- claude_mpm/services/memory/cache/shared_prompt_cache.py +2 -1
- claude_mpm/services/memory/cache/simple_cache.py +2 -2
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +8 -8
- claude_mpm/services/memory/optimizer.py +8 -9
- claude_mpm/services/memory/router.py +3 -3
- claude_mpm/services/memory_hook_service.py +165 -4
- 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 +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +671 -0
- claude_mpm/services/monitor/daemon_manager.py +963 -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 +724 -0
- claude_mpm/services/monitor/server.py +817 -0
- claude_mpm/services/monitor_build_service.py +2 -2
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/port_manager.py +2 -2
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/analyzer.py +3 -3
- claude_mpm/services/project/architecture_analyzer.py +5 -5
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +4 -4
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +553 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/metrics_collector.py +4 -4
- claude_mpm/services/project/project_organizer.py +1005 -0
- claude_mpm/services/project/registry.py +13 -7
- claude_mpm/services/project/toolchain_analyzer.py +581 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/response_tracker.py +21 -10
- claude_mpm/services/runner_configuration_service.py +1 -0
- claude_mpm/services/self_upgrade_service.py +500 -0
- claude_mpm/services/session_management_service.py +7 -5
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +2 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/config_service_base.py +17 -14
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/shared/service_factory.py +8 -5
- claude_mpm/services/socketio/client_proxy.py +60 -5
- claude_mpm/services/socketio/dashboard_server.py +361 -0
- claude_mpm/services/socketio/event_normalizer.py +10 -6
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/base.py +2 -2
- claude_mpm/services/socketio/handlers/code_analysis.py +90 -27
- claude_mpm/services/socketio/handlers/connection.py +21 -40
- claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
- claude_mpm/services/socketio/handlers/file.py +46 -10
- claude_mpm/services/socketio/handlers/git.py +8 -8
- claude_mpm/services/socketio/handlers/hook.py +29 -17
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/broadcaster.py +9 -7
- claude_mpm/services/socketio/server/connection_manager.py +2 -2
- claude_mpm/services/socketio/server/core.py +141 -4
- claude_mpm/services/socketio/server/eventbus_integration.py +20 -14
- claude_mpm/services/socketio/server/main.py +23 -21
- claude_mpm/services/socketio_client_manager.py +4 -4
- claude_mpm/services/subprocess_launcher_service.py +19 -15
- claude_mpm/services/system_instructions_service.py +2 -2
- claude_mpm/services/ticket_services/formatter_service.py +1 -1
- claude_mpm/services/ticket_services/validation_service.py +5 -5
- 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 +903 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +746 -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 +475 -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 +470 -0
- claude_mpm/services/utility_service.py +6 -3
- claude_mpm/services/version_control/branch_strategy.py +2 -2
- claude_mpm/services/version_control/conflict_resolution.py +8 -4
- claude_mpm/services/version_control/git_operations.py +26 -24
- claude_mpm/services/version_control/semantic_versioning.py +14 -14
- claude_mpm/services/version_control/version_parser.py +14 -11
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -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/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/skills/skills_registry.py +348 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/state_storage.py +31 -31
- claude_mpm/tools/__main__.py +1 -1
- 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 +6 -6
- claude_mpm/tools/code_tree_events.py +14 -10
- claude_mpm/tools/socketio_debug.py +11 -11
- claude_mpm/utils/agent_dependency_loader.py +108 -27
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +12 -6
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +2 -2
- claude_mpm/utils/dependency_strategies.py +15 -10
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +4 -3
- claude_mpm/utils/error_handler.py +5 -3
- claude_mpm/utils/file_utils.py +13 -14
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/path_operations.py +7 -4
- claude_mpm/utils/robust_installer.py +133 -24
- claude_mpm/utils/session_logging.py +2 -2
- claude_mpm/utils/subprocess_utils.py +9 -8
- claude_mpm/validation/agent_validator.py +6 -6
- claude_mpm/validation/frontmatter_validator.py +6 -6
- claude_mpm-4.24.0.dist-info/METADATA +675 -0
- claude_mpm-4.24.0.dist-info/RECORD +1018 -0
- {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/entry_points.txt +1 -0
- claude_mpm/agents/INSTRUCTIONS.md +0 -261
- claude_mpm/agents/templates/agent-manager.md +0 -619
- claude_mpm/cli/commands/configure_tui.py +0 -1927
- claude_mpm/cli/commands/mpm_init.py +0 -594
- claude_mpm/cli/commands/socketio_monitor.py +0 -233
- claude_mpm/dashboard/static/css/code-tree.css +0 -1408
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -3220
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -480
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1040
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/scripts/socketio_daemon_hardened.py +0 -937
- claude_mpm/scripts/socketio_daemon_wrapper.py +0 -78
- claude_mpm/scripts/socketio_server_manager.py +0 -349
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/cli/dashboard_launcher.py +0 -423
- claude_mpm/services/cli/socketio_manager.py +0 -537
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +0 -286
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- claude_mpm/tools/code_tree_analyzer.py +0 -1693
- claude_mpm-4.1.26.dist-info/METADATA +0 -332
- claude_mpm-4.1.26.dist-info/RECORD +0 -606
- {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.26.dist-info → claude_mpm-4.24.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,671 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified Monitor Daemon for Claude MPM
|
|
3
|
+
=====================================
|
|
4
|
+
|
|
5
|
+
WHY: This is the main daemon process that provides a single, stable way to
|
|
6
|
+
launch all monitoring functionality. It combines HTTP dashboard serving,
|
|
7
|
+
Socket.IO event handling, real AST analysis, and Claude Code hook ingestion.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISIONS:
|
|
10
|
+
- Single process replaces multiple competing server implementations
|
|
11
|
+
- Daemon-ready with proper lifecycle management
|
|
12
|
+
- Real AST analysis using CodeTreeAnalyzer
|
|
13
|
+
- Single port (8765) for all functionality
|
|
14
|
+
- Built on proven aiohttp + socketio foundation
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
import signal
|
|
19
|
+
import sys
|
|
20
|
+
import threading
|
|
21
|
+
import time
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Optional
|
|
24
|
+
|
|
25
|
+
from ...core.logging_config import get_logger
|
|
26
|
+
from ..hook_installer_service import HookInstallerService
|
|
27
|
+
from .daemon_manager import DaemonManager
|
|
28
|
+
from .management.health import HealthMonitor
|
|
29
|
+
from .management.lifecycle import DaemonLifecycle
|
|
30
|
+
from .server import UnifiedMonitorServer
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class UnifiedMonitorDaemon:
|
|
34
|
+
"""Unified daemon process for all Claude MPM monitoring functionality.
|
|
35
|
+
|
|
36
|
+
WHY: Provides a single, stable entry point for launching monitoring services.
|
|
37
|
+
Replaces the multiple competing server implementations with one cohesive daemon.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
host: str = "localhost",
|
|
43
|
+
port: int = 8765,
|
|
44
|
+
daemon_mode: bool = False,
|
|
45
|
+
pid_file: Optional[str] = None,
|
|
46
|
+
log_file: Optional[str] = None,
|
|
47
|
+
):
|
|
48
|
+
"""Initialize the unified monitor daemon.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
host: Host to bind to
|
|
52
|
+
port: Port to bind to
|
|
53
|
+
daemon_mode: Whether to run as background daemon
|
|
54
|
+
pid_file: Path to PID file for daemon mode
|
|
55
|
+
log_file: Path to log file for daemon mode
|
|
56
|
+
"""
|
|
57
|
+
self.host = host
|
|
58
|
+
self.port = port
|
|
59
|
+
self.daemon_mode = daemon_mode
|
|
60
|
+
self.logger = get_logger(__name__)
|
|
61
|
+
|
|
62
|
+
# Use new consolidated DaemonManager for all daemon operations
|
|
63
|
+
self.daemon_manager = DaemonManager(
|
|
64
|
+
port=port,
|
|
65
|
+
host=host,
|
|
66
|
+
pid_file=pid_file or self._get_default_pid_file(),
|
|
67
|
+
log_file=log_file,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Keep lifecycle for backward compatibility (delegates to daemon_manager)
|
|
71
|
+
self.lifecycle = DaemonLifecycle(
|
|
72
|
+
pid_file=pid_file or self._get_default_pid_file(),
|
|
73
|
+
log_file=log_file,
|
|
74
|
+
port=port,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Core server
|
|
78
|
+
self.server = UnifiedMonitorServer(host=host, port=port)
|
|
79
|
+
|
|
80
|
+
# Health monitoring
|
|
81
|
+
self.health_monitor = HealthMonitor(port=port)
|
|
82
|
+
|
|
83
|
+
# Hook installer service
|
|
84
|
+
self.hook_installer = HookInstallerService()
|
|
85
|
+
|
|
86
|
+
# State
|
|
87
|
+
self.running = False
|
|
88
|
+
self.shutdown_event = threading.Event()
|
|
89
|
+
|
|
90
|
+
def _get_default_pid_file(self) -> str:
|
|
91
|
+
"""Get default PID file path."""
|
|
92
|
+
project_root = Path.cwd()
|
|
93
|
+
claude_mpm_dir = project_root / ".claude-mpm"
|
|
94
|
+
claude_mpm_dir.mkdir(exist_ok=True)
|
|
95
|
+
return str(claude_mpm_dir / "monitor-daemon.pid")
|
|
96
|
+
|
|
97
|
+
def start(self, force_restart: bool = False) -> bool:
|
|
98
|
+
"""Start the unified monitor daemon.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
force_restart: If True, restart existing service if it's ours
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
True if started successfully, False otherwise
|
|
105
|
+
"""
|
|
106
|
+
try:
|
|
107
|
+
if self.daemon_mode:
|
|
108
|
+
return self._start_daemon(force_restart=force_restart)
|
|
109
|
+
return self._start_foreground(force_restart=force_restart)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
self.logger.error(f"Failed to start unified monitor daemon: {e}")
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
def _cleanup_port_conflicts(self) -> bool:
|
|
115
|
+
"""Try to clean up any processes using our port.
|
|
116
|
+
|
|
117
|
+
Delegates to the consolidated DaemonManager for consistent behavior.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
True if cleanup was successful, False otherwise
|
|
121
|
+
"""
|
|
122
|
+
return self.daemon_manager.cleanup_port_conflicts()
|
|
123
|
+
|
|
124
|
+
def _start_daemon(self, force_restart: bool = False) -> bool:
|
|
125
|
+
"""Start as background daemon process.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
force_restart: If True, restart existing service if it's ours
|
|
129
|
+
"""
|
|
130
|
+
self.logger.info("Starting unified monitor daemon in background mode")
|
|
131
|
+
|
|
132
|
+
# Always use daemon manager for cleanup first
|
|
133
|
+
# This ensures consistent behavior and prevents race conditions
|
|
134
|
+
if force_restart:
|
|
135
|
+
self.logger.info(
|
|
136
|
+
"Force restart requested, cleaning up any existing processes..."
|
|
137
|
+
)
|
|
138
|
+
if not self.daemon_manager.cleanup_port_conflicts(max_retries=3):
|
|
139
|
+
self.logger.error(f"Failed to clean up port {self.port}")
|
|
140
|
+
return False
|
|
141
|
+
# Wait for port to be fully released
|
|
142
|
+
time.sleep(2)
|
|
143
|
+
|
|
144
|
+
# Check if already running via daemon manager
|
|
145
|
+
if self.daemon_manager.is_running():
|
|
146
|
+
existing_pid = self.daemon_manager.get_pid()
|
|
147
|
+
if not force_restart:
|
|
148
|
+
self.logger.warning(f"Daemon already running with PID {existing_pid}")
|
|
149
|
+
return False
|
|
150
|
+
# Force restart was already handled above
|
|
151
|
+
|
|
152
|
+
# Check for our service on the port
|
|
153
|
+
is_ours, pid = self.daemon_manager.is_our_service()
|
|
154
|
+
if is_ours and pid and not force_restart:
|
|
155
|
+
self.logger.warning(
|
|
156
|
+
f"Our service already running on port {self.port} (PID: {pid})"
|
|
157
|
+
)
|
|
158
|
+
return False
|
|
159
|
+
|
|
160
|
+
# Use subprocess approach for clean daemon startup (v4.2.40)
|
|
161
|
+
# This avoids all fork() + threading issues by starting in a fresh process
|
|
162
|
+
# The daemon_manager.use_subprocess_daemon() now checks for CLAUDE_MPM_SUBPROCESS_DAEMON
|
|
163
|
+
# environment variable to prevent infinite recursion
|
|
164
|
+
if self.daemon_manager.use_subprocess_daemon():
|
|
165
|
+
# Start using subprocess - this returns immediately in parent
|
|
166
|
+
return self.daemon_manager.start_daemon_subprocess()
|
|
167
|
+
|
|
168
|
+
# Check if we're in subprocess mode (environment variable set)
|
|
169
|
+
if os.environ.get("CLAUDE_MPM_SUBPROCESS_DAEMON") == "1":
|
|
170
|
+
# We're in a subprocess started by start_daemon_subprocess
|
|
171
|
+
# We need to write the PID file ourselves since parent didn't
|
|
172
|
+
self.logger.info("Running in subprocess daemon mode, writing PID file")
|
|
173
|
+
self.daemon_manager.write_pid_file()
|
|
174
|
+
|
|
175
|
+
# Setup signal handlers for graceful shutdown
|
|
176
|
+
self._setup_signal_handlers()
|
|
177
|
+
|
|
178
|
+
# Start the server (this will run until shutdown)
|
|
179
|
+
try:
|
|
180
|
+
result = self._run_server()
|
|
181
|
+
if not result:
|
|
182
|
+
self.logger.error("Failed to start server in subprocess mode")
|
|
183
|
+
return result
|
|
184
|
+
except Exception as e:
|
|
185
|
+
self.logger.error(f"Server startup exception in subprocess: {e}")
|
|
186
|
+
raise
|
|
187
|
+
else:
|
|
188
|
+
# Legacy fork approach (kept for compatibility but not used by default)
|
|
189
|
+
# Wait for any pre-warming threads to complete before forking
|
|
190
|
+
self._wait_for_prewarm_completion()
|
|
191
|
+
|
|
192
|
+
# Use daemon manager's daemonize which includes cleanup
|
|
193
|
+
# DO NOT reset startup_status_file - it's needed for parent-child communication!
|
|
194
|
+
# self.daemon_manager.startup_status_file = None # BUG: This breaks communication
|
|
195
|
+
success = self.daemon_manager.daemonize()
|
|
196
|
+
if not success:
|
|
197
|
+
return False
|
|
198
|
+
|
|
199
|
+
# We're now in the daemon process
|
|
200
|
+
# Update our PID references and status file
|
|
201
|
+
self.lifecycle.pid_file = self.daemon_manager.pid_file
|
|
202
|
+
self.lifecycle.startup_status_file = self.daemon_manager.startup_status_file
|
|
203
|
+
|
|
204
|
+
# Start the server in daemon mode
|
|
205
|
+
try:
|
|
206
|
+
result = self._run_server()
|
|
207
|
+
if not result:
|
|
208
|
+
# Report failure before exiting
|
|
209
|
+
self.daemon_manager._report_startup_error("Failed to start server")
|
|
210
|
+
else:
|
|
211
|
+
# Report success
|
|
212
|
+
self.daemon_manager._report_startup_success()
|
|
213
|
+
return result
|
|
214
|
+
except Exception as e:
|
|
215
|
+
# Report any exceptions during startup
|
|
216
|
+
self.daemon_manager._report_startup_error(
|
|
217
|
+
f"Server startup exception: {e}"
|
|
218
|
+
)
|
|
219
|
+
raise
|
|
220
|
+
|
|
221
|
+
def _start_foreground(self, force_restart: bool = False) -> bool:
|
|
222
|
+
"""Start in foreground mode.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
force_restart: If True, restart existing service if it's ours
|
|
226
|
+
"""
|
|
227
|
+
self.logger.info(f"Starting unified monitor daemon on {self.host}:{self.port}")
|
|
228
|
+
|
|
229
|
+
# Use daemon manager for consistent port cleanup
|
|
230
|
+
# This helps with race conditions where old processes haven't fully released the port
|
|
231
|
+
if force_restart:
|
|
232
|
+
self.logger.info("Force restart requested, cleaning up port conflicts...")
|
|
233
|
+
self.daemon_manager.cleanup_port_conflicts(max_retries=2)
|
|
234
|
+
time.sleep(1) # Brief pause to ensure port is released
|
|
235
|
+
|
|
236
|
+
# Check if already running (check PID file even in foreground mode)
|
|
237
|
+
if self.lifecycle.is_running():
|
|
238
|
+
existing_pid = self.lifecycle.get_pid()
|
|
239
|
+
|
|
240
|
+
if force_restart:
|
|
241
|
+
# Check if it's our service
|
|
242
|
+
self.logger.debug(
|
|
243
|
+
f"Checking if existing daemon (PID: {existing_pid}) is our service..."
|
|
244
|
+
)
|
|
245
|
+
is_ours, detected_pid = self.daemon_manager.is_our_service()
|
|
246
|
+
|
|
247
|
+
if is_ours:
|
|
248
|
+
self.logger.info(
|
|
249
|
+
f"Force restarting our existing claude-mpm monitor daemon (PID: {detected_pid or existing_pid})"
|
|
250
|
+
)
|
|
251
|
+
# Stop the existing daemon
|
|
252
|
+
if self.lifecycle.stop_daemon():
|
|
253
|
+
# Wait a moment for port to be released
|
|
254
|
+
time.sleep(2)
|
|
255
|
+
else:
|
|
256
|
+
self.logger.error("Failed to stop existing daemon for restart")
|
|
257
|
+
return False
|
|
258
|
+
else:
|
|
259
|
+
self.logger.warning(
|
|
260
|
+
f"Port {self.port} is in use by another service (PID: {existing_pid}). Cannot force restart."
|
|
261
|
+
)
|
|
262
|
+
self.logger.info(
|
|
263
|
+
"To restart the claude-mpm monitor, first stop the other service or use a different port."
|
|
264
|
+
)
|
|
265
|
+
return False
|
|
266
|
+
else:
|
|
267
|
+
self.logger.warning(
|
|
268
|
+
f"Monitor daemon already running with PID {existing_pid}"
|
|
269
|
+
)
|
|
270
|
+
return False
|
|
271
|
+
|
|
272
|
+
# Check for orphaned processes (service running but no PID file)
|
|
273
|
+
elif force_restart:
|
|
274
|
+
self.logger.debug(
|
|
275
|
+
"No PID file found, checking for orphaned claude-mpm service..."
|
|
276
|
+
)
|
|
277
|
+
is_ours, pid = self.daemon_manager.is_our_service()
|
|
278
|
+
if is_ours and pid:
|
|
279
|
+
self.logger.info(
|
|
280
|
+
f"Found orphaned claude-mpm monitor service (PID: {pid}), force restarting"
|
|
281
|
+
)
|
|
282
|
+
# Try to kill the orphaned process
|
|
283
|
+
try:
|
|
284
|
+
os.kill(pid, signal.SIGTERM)
|
|
285
|
+
# Wait for it to exit
|
|
286
|
+
for _ in range(10):
|
|
287
|
+
try:
|
|
288
|
+
os.kill(pid, 0) # Check if still exists
|
|
289
|
+
time.sleep(0.5)
|
|
290
|
+
except ProcessLookupError:
|
|
291
|
+
break
|
|
292
|
+
else:
|
|
293
|
+
# Force kill if still running
|
|
294
|
+
os.kill(pid, signal.SIGKILL)
|
|
295
|
+
time.sleep(1)
|
|
296
|
+
except Exception as e:
|
|
297
|
+
self.logger.error(f"Failed to kill orphaned process: {e}")
|
|
298
|
+
return False
|
|
299
|
+
|
|
300
|
+
# Setup signal handlers for graceful shutdown
|
|
301
|
+
self._setup_signal_handlers()
|
|
302
|
+
|
|
303
|
+
# Write PID file for foreground mode too (so other processes can detect it)
|
|
304
|
+
self.lifecycle.write_pid_file()
|
|
305
|
+
|
|
306
|
+
# Start the server
|
|
307
|
+
return self._run_server()
|
|
308
|
+
|
|
309
|
+
def _run_server(self) -> bool:
|
|
310
|
+
"""Run the main server loop."""
|
|
311
|
+
try:
|
|
312
|
+
# Ensure components exist before starting
|
|
313
|
+
if not self.health_monitor:
|
|
314
|
+
error_msg = "Health monitor not initialized"
|
|
315
|
+
self.logger.error(error_msg)
|
|
316
|
+
if self.daemon_mode:
|
|
317
|
+
self.lifecycle._report_startup_error(error_msg)
|
|
318
|
+
return False
|
|
319
|
+
|
|
320
|
+
if not self.server:
|
|
321
|
+
error_msg = "Server not initialized"
|
|
322
|
+
self.logger.error(error_msg)
|
|
323
|
+
if self.daemon_mode:
|
|
324
|
+
self.lifecycle._report_startup_error(error_msg)
|
|
325
|
+
return False
|
|
326
|
+
|
|
327
|
+
# Check and install hooks if needed
|
|
328
|
+
try:
|
|
329
|
+
if not self.hook_installer.is_hooks_configured():
|
|
330
|
+
self.logger.info("Claude Code hooks not configured, installing...")
|
|
331
|
+
if self.hook_installer.install_hooks():
|
|
332
|
+
self.logger.info("Claude Code hooks installed successfully")
|
|
333
|
+
else:
|
|
334
|
+
# Don't fail startup if hook installation fails
|
|
335
|
+
# The monitor can still function without hooks
|
|
336
|
+
self.logger.warning(
|
|
337
|
+
"Failed to install Claude Code hooks. Monitor will run without hook integration."
|
|
338
|
+
)
|
|
339
|
+
else:
|
|
340
|
+
self.logger.info("Claude Code hooks are already configured")
|
|
341
|
+
except Exception as e:
|
|
342
|
+
# Don't fail startup if hook checking fails
|
|
343
|
+
self.logger.warning(
|
|
344
|
+
f"Error checking/installing hooks: {e}. Monitor will run without hook integration."
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Start health monitoring
|
|
348
|
+
self.health_monitor.start()
|
|
349
|
+
|
|
350
|
+
# Start the unified server
|
|
351
|
+
success = self.server.start()
|
|
352
|
+
if not success:
|
|
353
|
+
error_msg = "Failed to start unified monitor server"
|
|
354
|
+
self.logger.error(error_msg)
|
|
355
|
+
if self.daemon_mode:
|
|
356
|
+
self.lifecycle._report_startup_error(error_msg)
|
|
357
|
+
return False
|
|
358
|
+
|
|
359
|
+
self.running = True
|
|
360
|
+
self.logger.info("Unified monitor daemon started successfully")
|
|
361
|
+
|
|
362
|
+
# Report successful startup to parent (for daemon mode)
|
|
363
|
+
if self.daemon_mode:
|
|
364
|
+
self.lifecycle._report_startup_success()
|
|
365
|
+
|
|
366
|
+
# Keep running until shutdown
|
|
367
|
+
if self.daemon_mode:
|
|
368
|
+
# In daemon mode, run until shutdown signal
|
|
369
|
+
while self.running and not self.shutdown_event.is_set():
|
|
370
|
+
time.sleep(1)
|
|
371
|
+
else:
|
|
372
|
+
# In foreground mode, run until interrupted
|
|
373
|
+
try:
|
|
374
|
+
while self.running:
|
|
375
|
+
time.sleep(1)
|
|
376
|
+
except KeyboardInterrupt:
|
|
377
|
+
self.logger.info("Received keyboard interrupt, shutting down...")
|
|
378
|
+
|
|
379
|
+
return True
|
|
380
|
+
|
|
381
|
+
except Exception as e:
|
|
382
|
+
self.logger.error(f"Error running unified monitor daemon: {e}")
|
|
383
|
+
return False
|
|
384
|
+
finally:
|
|
385
|
+
self._cleanup()
|
|
386
|
+
|
|
387
|
+
def stop(self) -> bool:
|
|
388
|
+
"""Stop the unified monitor daemon.
|
|
389
|
+
|
|
390
|
+
Returns:
|
|
391
|
+
True if stopped successfully, False otherwise
|
|
392
|
+
"""
|
|
393
|
+
try:
|
|
394
|
+
self.logger.info("Stopping unified monitor daemon")
|
|
395
|
+
|
|
396
|
+
# If running in daemon mode and we're not the daemon process itself,
|
|
397
|
+
# use lifecycle to stop the daemon properly
|
|
398
|
+
if self.daemon_mode and self.lifecycle.is_running():
|
|
399
|
+
pid = self.lifecycle.get_pid()
|
|
400
|
+
if pid and pid != os.getpid():
|
|
401
|
+
# We're not the daemon process, so stop it via signal
|
|
402
|
+
# Don't log here - lifecycle.stop_daemon will log
|
|
403
|
+
success = self.lifecycle.stop_daemon()
|
|
404
|
+
if success:
|
|
405
|
+
# Clean up our local state
|
|
406
|
+
self.running = False
|
|
407
|
+
self.shutdown_event.set()
|
|
408
|
+
self.server = None
|
|
409
|
+
self.health_monitor = None
|
|
410
|
+
return success
|
|
411
|
+
|
|
412
|
+
# Otherwise, stop normally (we are the daemon or running in foreground)
|
|
413
|
+
# Signal shutdown
|
|
414
|
+
self.running = False
|
|
415
|
+
self.shutdown_event.set()
|
|
416
|
+
|
|
417
|
+
# Stop server with proper cleanup
|
|
418
|
+
if self.server:
|
|
419
|
+
self.logger.debug("Initiating server shutdown...")
|
|
420
|
+
self.server.stop()
|
|
421
|
+
# Give asyncio loops adequate time to cleanup properly
|
|
422
|
+
# This is critical to prevent kqueue errors
|
|
423
|
+
time.sleep(2.0)
|
|
424
|
+
self.server = None
|
|
425
|
+
|
|
426
|
+
# Stop health monitoring
|
|
427
|
+
if self.health_monitor:
|
|
428
|
+
self.logger.debug("Stopping health monitor...")
|
|
429
|
+
self.health_monitor.stop()
|
|
430
|
+
self.health_monitor = None
|
|
431
|
+
|
|
432
|
+
# Clean up any asyncio resources
|
|
433
|
+
self._cleanup_asyncio_resources()
|
|
434
|
+
|
|
435
|
+
# Give a final moment for OS-level cleanup
|
|
436
|
+
time.sleep(0.5)
|
|
437
|
+
|
|
438
|
+
# Cleanup daemon files (always cleanup PID file)
|
|
439
|
+
self.lifecycle.cleanup()
|
|
440
|
+
|
|
441
|
+
self.logger.info("Unified monitor daemon stopped")
|
|
442
|
+
return True
|
|
443
|
+
|
|
444
|
+
except Exception as e:
|
|
445
|
+
self.logger.error(f"Error stopping unified monitor daemon: {e}")
|
|
446
|
+
return False
|
|
447
|
+
|
|
448
|
+
def restart(self) -> bool:
|
|
449
|
+
"""Restart the unified monitor daemon.
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
True if restarted successfully, False otherwise
|
|
453
|
+
"""
|
|
454
|
+
self.logger.info("Restarting unified monitor daemon")
|
|
455
|
+
|
|
456
|
+
# Save daemon mode setting before stopping
|
|
457
|
+
was_daemon_mode = self.daemon_mode
|
|
458
|
+
|
|
459
|
+
# Stop first (this will properly kill daemon process if needed)
|
|
460
|
+
if not self.stop():
|
|
461
|
+
return False
|
|
462
|
+
|
|
463
|
+
# Wait longer for port to be released properly
|
|
464
|
+
# This is needed because the daemon process may take time to fully cleanup
|
|
465
|
+
self.logger.info("Waiting for port to be fully released...")
|
|
466
|
+
|
|
467
|
+
# Check if port is actually free, wait up to 10 seconds
|
|
468
|
+
import socket
|
|
469
|
+
|
|
470
|
+
for i in range(10):
|
|
471
|
+
try:
|
|
472
|
+
# Try to bind to the port to see if it's free
|
|
473
|
+
test_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
474
|
+
test_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
475
|
+
test_sock.bind((self.host, self.port))
|
|
476
|
+
test_sock.close()
|
|
477
|
+
self.logger.info(f"Port {self.port} is now free")
|
|
478
|
+
break
|
|
479
|
+
except OSError:
|
|
480
|
+
if i < 9:
|
|
481
|
+
self.logger.debug(
|
|
482
|
+
f"Port {self.port} still in use, waiting... ({i+1}/10)"
|
|
483
|
+
)
|
|
484
|
+
time.sleep(1)
|
|
485
|
+
else:
|
|
486
|
+
self.logger.error(
|
|
487
|
+
f"Port {self.port} is still in use after 10 seconds"
|
|
488
|
+
)
|
|
489
|
+
return False
|
|
490
|
+
|
|
491
|
+
# Recreate the server and health monitor after stop() sets them to None
|
|
492
|
+
self.logger.info(f"Recreating server components for {self.host}:{self.port}")
|
|
493
|
+
self.server = UnifiedMonitorServer(host=self.host, port=self.port)
|
|
494
|
+
self.health_monitor = HealthMonitor(port=self.port)
|
|
495
|
+
|
|
496
|
+
# Reset the shutdown event for the new run
|
|
497
|
+
self.shutdown_event.clear()
|
|
498
|
+
|
|
499
|
+
# Restore daemon mode setting
|
|
500
|
+
self.daemon_mode = was_daemon_mode
|
|
501
|
+
|
|
502
|
+
# Start again
|
|
503
|
+
return self.start()
|
|
504
|
+
|
|
505
|
+
def status(self) -> dict:
|
|
506
|
+
"""Get daemon status information.
|
|
507
|
+
|
|
508
|
+
Returns:
|
|
509
|
+
Dictionary with status information
|
|
510
|
+
"""
|
|
511
|
+
# Always check the PID file to see if a daemon is running
|
|
512
|
+
# This ensures we detect daemons started by other processes
|
|
513
|
+
is_running = self.lifecycle.is_running()
|
|
514
|
+
pid = self.lifecycle.get_pid()
|
|
515
|
+
|
|
516
|
+
# If no PID file exists but we're running in the current process
|
|
517
|
+
if not is_running and self.running:
|
|
518
|
+
is_running = True
|
|
519
|
+
pid = os.getpid()
|
|
520
|
+
|
|
521
|
+
status = {
|
|
522
|
+
"running": is_running,
|
|
523
|
+
"pid": pid if is_running else None,
|
|
524
|
+
"host": self.host,
|
|
525
|
+
"port": self.port,
|
|
526
|
+
"daemon_mode": self.daemon_mode,
|
|
527
|
+
"health": (
|
|
528
|
+
self.health_monitor.get_status() if self.health_monitor else "unknown"
|
|
529
|
+
),
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if self.server:
|
|
533
|
+
status.update(self.server.get_status())
|
|
534
|
+
|
|
535
|
+
return status
|
|
536
|
+
|
|
537
|
+
def _setup_signal_handlers(self):
|
|
538
|
+
"""Setup signal handlers for graceful shutdown."""
|
|
539
|
+
|
|
540
|
+
def signal_handler(signum, frame):
|
|
541
|
+
self.logger.info(f"Received signal {signum}, shutting down...")
|
|
542
|
+
self.stop()
|
|
543
|
+
sys.exit(0)
|
|
544
|
+
|
|
545
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
546
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
547
|
+
|
|
548
|
+
def _cleanup(self):
|
|
549
|
+
"""Cleanup resources."""
|
|
550
|
+
try:
|
|
551
|
+
# Stop server first with proper cleanup
|
|
552
|
+
if self.server:
|
|
553
|
+
self.logger.debug("Stopping server and cleaning up event loops...")
|
|
554
|
+
self.server.stop()
|
|
555
|
+
# Give the server more time to cleanup event loops properly
|
|
556
|
+
# This is critical to prevent kqueue errors
|
|
557
|
+
time.sleep(1.5)
|
|
558
|
+
self.server = None
|
|
559
|
+
|
|
560
|
+
# Then stop health monitor
|
|
561
|
+
if self.health_monitor:
|
|
562
|
+
self.logger.debug("Stopping health monitor...")
|
|
563
|
+
self.health_monitor.stop()
|
|
564
|
+
self.health_monitor = None
|
|
565
|
+
|
|
566
|
+
# Ensure PID file is removed
|
|
567
|
+
if not self.daemon_mode:
|
|
568
|
+
# In foreground mode, make sure we cleanup the PID file
|
|
569
|
+
self.lifecycle.cleanup()
|
|
570
|
+
|
|
571
|
+
# Clean up any remaining asyncio resources in the main thread
|
|
572
|
+
self._cleanup_asyncio_resources()
|
|
573
|
+
|
|
574
|
+
# Clear any remaining references
|
|
575
|
+
self.shutdown_event.clear()
|
|
576
|
+
|
|
577
|
+
self.logger.debug("Cleanup completed successfully")
|
|
578
|
+
|
|
579
|
+
except Exception as e:
|
|
580
|
+
self.logger.error(f"Error during cleanup: {e}")
|
|
581
|
+
|
|
582
|
+
def _cleanup_asyncio_resources(self):
|
|
583
|
+
"""Clean up any asyncio resources in the current thread."""
|
|
584
|
+
try:
|
|
585
|
+
import asyncio
|
|
586
|
+
|
|
587
|
+
# Try to get the current event loop
|
|
588
|
+
try:
|
|
589
|
+
loop = asyncio.get_event_loop()
|
|
590
|
+
if loop and not loop.is_closed():
|
|
591
|
+
# Cancel any pending tasks
|
|
592
|
+
pending = asyncio.all_tasks(loop)
|
|
593
|
+
for task in pending:
|
|
594
|
+
task.cancel()
|
|
595
|
+
|
|
596
|
+
# Stop and close the loop
|
|
597
|
+
if loop.is_running():
|
|
598
|
+
loop.stop()
|
|
599
|
+
|
|
600
|
+
# Clear the event loop from the thread
|
|
601
|
+
asyncio.set_event_loop(None)
|
|
602
|
+
|
|
603
|
+
# Close the loop
|
|
604
|
+
loop.close()
|
|
605
|
+
|
|
606
|
+
except RuntimeError:
|
|
607
|
+
# No event loop in current thread, that's fine
|
|
608
|
+
pass
|
|
609
|
+
|
|
610
|
+
except Exception as e:
|
|
611
|
+
self.logger.debug(f"Error cleaning up asyncio resources: {e}")
|
|
612
|
+
|
|
613
|
+
def _wait_for_prewarm_completion(self, timeout: float = 5.0):
|
|
614
|
+
"""Wait for MCP pre-warming threads to complete before forking.
|
|
615
|
+
|
|
616
|
+
This prevents inherited threads and event loops in the forked process.
|
|
617
|
+
"""
|
|
618
|
+
try:
|
|
619
|
+
import threading
|
|
620
|
+
import time
|
|
621
|
+
|
|
622
|
+
start_time = time.time()
|
|
623
|
+
|
|
624
|
+
# Get all threads including daemon threads
|
|
625
|
+
# Pre-warm threads are daemon threads but we MUST wait for them
|
|
626
|
+
active_threads = [
|
|
627
|
+
t
|
|
628
|
+
for t in threading.enumerate()
|
|
629
|
+
if t.is_alive() and t != threading.current_thread()
|
|
630
|
+
]
|
|
631
|
+
|
|
632
|
+
if active_threads:
|
|
633
|
+
self.logger.info(
|
|
634
|
+
f"Waiting for {len(active_threads)} background threads to complete before forking"
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
# List thread names for debugging
|
|
638
|
+
thread_names = [t.name for t in active_threads]
|
|
639
|
+
self.logger.debug(f"Active threads: {thread_names}")
|
|
640
|
+
|
|
641
|
+
# Wait for threads to complete or timeout
|
|
642
|
+
while time.time() - start_time < timeout:
|
|
643
|
+
remaining_threads = [t for t in active_threads if t.is_alive()]
|
|
644
|
+
if not remaining_threads:
|
|
645
|
+
self.logger.debug("All threads completed")
|
|
646
|
+
break
|
|
647
|
+
|
|
648
|
+
# Log remaining threads periodically
|
|
649
|
+
if int(time.time() - start_time) % 1 == 0:
|
|
650
|
+
self.logger.debug(
|
|
651
|
+
f"{len(remaining_threads)} threads still active"
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
time.sleep(0.1)
|
|
655
|
+
|
|
656
|
+
# Final check
|
|
657
|
+
final_threads = [
|
|
658
|
+
t
|
|
659
|
+
for t in threading.enumerate()
|
|
660
|
+
if t.is_alive() and t != threading.current_thread()
|
|
661
|
+
]
|
|
662
|
+
if final_threads:
|
|
663
|
+
self.logger.warning(
|
|
664
|
+
f"Proceeding with {len(final_threads)} threads still active after {timeout}s wait"
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
elapsed = time.time() - start_time
|
|
668
|
+
self.logger.debug(f"Waited {elapsed:.2f}s for thread completion")
|
|
669
|
+
|
|
670
|
+
except Exception as e:
|
|
671
|
+
self.logger.debug(f"Error waiting for threads: {e}")
|