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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import uuid
|
|
5
5
|
from collections import defaultdict
|
|
6
|
-
from datetime import datetime, timedelta
|
|
6
|
+
from datetime import datetime, timedelta, timezone
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import Dict, Optional
|
|
9
9
|
|
|
@@ -53,10 +53,10 @@ class AgentSessionManager:
|
|
|
53
53
|
if not self.session_locks.get(session_id, False):
|
|
54
54
|
# Check if session is still fresh (not too old)
|
|
55
55
|
created = datetime.fromisoformat(session_data["created_at"])
|
|
56
|
-
if datetime.now() - created < timedelta(hours=1):
|
|
56
|
+
if datetime.now(timezone.utc) - created < timedelta(hours=1):
|
|
57
57
|
# Use this session
|
|
58
58
|
self.session_locks[session_id] = True
|
|
59
|
-
session_data["last_used"] = datetime.now().isoformat()
|
|
59
|
+
session_data["last_used"] = datetime.now(timezone.utc).isoformat()
|
|
60
60
|
session_data["use_count"] += 1
|
|
61
61
|
logger.info(f"Reusing session {session_id} for {agent_type} agent")
|
|
62
62
|
return session_id
|
|
@@ -85,8 +85,8 @@ class AgentSessionManager:
|
|
|
85
85
|
session_data = {
|
|
86
86
|
"id": session_id,
|
|
87
87
|
"agent_type": agent_type,
|
|
88
|
-
"created_at": datetime.now().isoformat(),
|
|
89
|
-
"last_used": datetime.now().isoformat(),
|
|
88
|
+
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
89
|
+
"last_used": datetime.now(timezone.utc).isoformat(),
|
|
90
90
|
"use_count": 0,
|
|
91
91
|
"tasks_completed": [],
|
|
92
92
|
}
|
|
@@ -122,7 +122,7 @@ class AgentSessionManager:
|
|
|
122
122
|
sessions[session_id]["tasks_completed"].append(
|
|
123
123
|
{
|
|
124
124
|
"task": task[:100], # Truncate long tasks
|
|
125
|
-
"timestamp": datetime.now().isoformat(),
|
|
125
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
126
126
|
"success": success,
|
|
127
127
|
}
|
|
128
128
|
)
|
|
@@ -135,7 +135,7 @@ class AgentSessionManager:
|
|
|
135
135
|
Args:
|
|
136
136
|
max_age_hours: Maximum age in hours
|
|
137
137
|
"""
|
|
138
|
-
now = datetime.now()
|
|
138
|
+
now = datetime.now(timezone.utc)
|
|
139
139
|
max_age = timedelta(hours=max_age_hours)
|
|
140
140
|
|
|
141
141
|
for agent_type in list(self.agent_sessions.keys()):
|
|
@@ -207,9 +207,9 @@ class AgentSessionManager:
|
|
|
207
207
|
try:
|
|
208
208
|
data = {
|
|
209
209
|
"agent_sessions": dict(self.agent_sessions),
|
|
210
|
-
"updated_at": datetime.now().isoformat(),
|
|
210
|
+
"updated_at": datetime.now(timezone.utc).isoformat(),
|
|
211
211
|
}
|
|
212
|
-
with open(
|
|
212
|
+
with session_file.open("w") as f:
|
|
213
213
|
json.dump(data, f, indent=2)
|
|
214
214
|
except Exception as e:
|
|
215
215
|
logger.error(f"Failed to save agent sessions: {e}")
|
|
@@ -219,7 +219,7 @@ class AgentSessionManager:
|
|
|
219
219
|
session_file = self.session_dir / "agent_sessions.json"
|
|
220
220
|
if session_file.exists():
|
|
221
221
|
try:
|
|
222
|
-
with open(
|
|
222
|
+
with session_file.open() as f:
|
|
223
223
|
data = json.load(f)
|
|
224
224
|
self.agent_sessions = defaultdict(
|
|
225
225
|
dict, data.get("agent_sessions", {})
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"""API Key Validation Module for Claude MPM.
|
|
2
|
+
|
|
3
|
+
This module validates API keys for various services on startup to ensure
|
|
4
|
+
proper configuration and prevent runtime failures. It follows the principle
|
|
5
|
+
of failing fast with clear error messages rather than degrading gracefully.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from typing import Dict, List, Optional, Tuple
|
|
10
|
+
|
|
11
|
+
import requests
|
|
12
|
+
|
|
13
|
+
from claude_mpm.core.logger import get_logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class APIKeyValidator:
|
|
17
|
+
"""Validates API keys for various services on framework startup."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, config: Optional[Dict] = None):
|
|
20
|
+
"""Initialize the API validator.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
config: Optional configuration dictionary
|
|
24
|
+
"""
|
|
25
|
+
self.logger = get_logger("api_validator")
|
|
26
|
+
self.config = config or {}
|
|
27
|
+
self.errors: List[str] = []
|
|
28
|
+
self.warnings: List[str] = []
|
|
29
|
+
|
|
30
|
+
def validate_all_keys(
|
|
31
|
+
self, strict: bool = True
|
|
32
|
+
) -> Tuple[bool, List[str], List[str]]:
|
|
33
|
+
"""Validate all configured API keys.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
strict: If True, validation failures raise exceptions.
|
|
37
|
+
If False, failures are logged as warnings.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
Tuple of (success, errors, warnings)
|
|
41
|
+
"""
|
|
42
|
+
self.errors = []
|
|
43
|
+
self.warnings = []
|
|
44
|
+
|
|
45
|
+
# Check if validation is enabled
|
|
46
|
+
if not self.config.get("validate_api_keys", True):
|
|
47
|
+
self.logger.info("API key validation disabled in config")
|
|
48
|
+
return True, [], []
|
|
49
|
+
|
|
50
|
+
# Validate OpenAI key if configured
|
|
51
|
+
openai_key = os.getenv("OPENAI_API_KEY")
|
|
52
|
+
if openai_key:
|
|
53
|
+
self._validate_openai_key(openai_key)
|
|
54
|
+
|
|
55
|
+
# Validate Anthropic key if configured
|
|
56
|
+
anthropic_key = os.getenv("ANTHROPIC_API_KEY")
|
|
57
|
+
if anthropic_key:
|
|
58
|
+
self._validate_anthropic_key(anthropic_key)
|
|
59
|
+
|
|
60
|
+
# Validate GitHub token if configured
|
|
61
|
+
github_token = os.getenv("GITHUB_TOKEN")
|
|
62
|
+
if github_token:
|
|
63
|
+
self._validate_github_token(github_token)
|
|
64
|
+
|
|
65
|
+
# Validate custom API keys from config
|
|
66
|
+
custom_apis = self.config.get("custom_api_validations", {})
|
|
67
|
+
for api_name, validation_config in custom_apis.items():
|
|
68
|
+
self._validate_custom_api(api_name, validation_config)
|
|
69
|
+
|
|
70
|
+
# Report results
|
|
71
|
+
if self.errors:
|
|
72
|
+
error_msg = "API Key Validation Failed:\n" + "\n".join(self.errors)
|
|
73
|
+
if strict:
|
|
74
|
+
self.logger.error(error_msg)
|
|
75
|
+
raise ValueError(error_msg)
|
|
76
|
+
self.logger.warning(error_msg)
|
|
77
|
+
|
|
78
|
+
if self.warnings:
|
|
79
|
+
for warning in self.warnings:
|
|
80
|
+
self.logger.warning(warning)
|
|
81
|
+
|
|
82
|
+
if not self.errors:
|
|
83
|
+
self.logger.info("✅ All configured API keys validated successfully")
|
|
84
|
+
|
|
85
|
+
return not bool(self.errors), self.errors, self.warnings
|
|
86
|
+
|
|
87
|
+
def _validate_openai_key(self, api_key: str) -> bool:
|
|
88
|
+
"""Validate OpenAI API key.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
api_key: The OpenAI API key to validate
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
True if valid, False otherwise
|
|
95
|
+
"""
|
|
96
|
+
try:
|
|
97
|
+
# Make a lightweight request to validate the key
|
|
98
|
+
response = requests.get(
|
|
99
|
+
"https://api.openai.com/v1/models",
|
|
100
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
101
|
+
timeout=10,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
if response.status_code == 401:
|
|
105
|
+
self.errors.append("❌ OpenAI API key is invalid (401 Unauthorized)")
|
|
106
|
+
return False
|
|
107
|
+
if response.status_code == 403:
|
|
108
|
+
self.errors.append(
|
|
109
|
+
"❌ OpenAI API key lacks required permissions (403 Forbidden)"
|
|
110
|
+
)
|
|
111
|
+
return False
|
|
112
|
+
if response.status_code == 429:
|
|
113
|
+
# Rate limited but key is valid
|
|
114
|
+
self.warnings.append("⚠️ OpenAI API key is valid but rate limited")
|
|
115
|
+
return True
|
|
116
|
+
if response.status_code == 200:
|
|
117
|
+
self.logger.debug("✅ OpenAI API key validated successfully")
|
|
118
|
+
return True
|
|
119
|
+
self.warnings.append(
|
|
120
|
+
f"⚠️ OpenAI API returned unexpected status: {response.status_code}"
|
|
121
|
+
)
|
|
122
|
+
return True # Assume valid for unexpected status codes
|
|
123
|
+
|
|
124
|
+
except requests.exceptions.Timeout:
|
|
125
|
+
self.warnings.append(
|
|
126
|
+
"⚠️ OpenAI API validation timed out - assuming key is valid"
|
|
127
|
+
)
|
|
128
|
+
return True
|
|
129
|
+
except requests.exceptions.ConnectionError as e:
|
|
130
|
+
self.warnings.append(f"⚠️ Could not connect to OpenAI API: {e}")
|
|
131
|
+
return True
|
|
132
|
+
except Exception as e:
|
|
133
|
+
self.errors.append(f"❌ OpenAI API validation failed with error: {e}")
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
def _validate_anthropic_key(self, api_key: str) -> bool:
|
|
137
|
+
"""Validate Anthropic API key.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
api_key: The Anthropic API key to validate
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
True if valid, False otherwise
|
|
144
|
+
"""
|
|
145
|
+
try:
|
|
146
|
+
# Make a minimal request to validate the key
|
|
147
|
+
# Using a very small max_tokens to minimize cost
|
|
148
|
+
response = requests.post(
|
|
149
|
+
"https://api.anthropic.com/v1/messages",
|
|
150
|
+
headers={
|
|
151
|
+
"x-api-key": api_key,
|
|
152
|
+
"anthropic-version": "2023-06-01",
|
|
153
|
+
"content-type": "application/json",
|
|
154
|
+
},
|
|
155
|
+
json={
|
|
156
|
+
"model": "claude-3-haiku-20240307", # Use cheapest model
|
|
157
|
+
"messages": [{"role": "user", "content": "test"}],
|
|
158
|
+
"max_tokens": 1,
|
|
159
|
+
},
|
|
160
|
+
timeout=10,
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if response.status_code == 401:
|
|
164
|
+
self.errors.append("❌ Anthropic API key is invalid (401 Unauthorized)")
|
|
165
|
+
return False
|
|
166
|
+
if response.status_code == 403:
|
|
167
|
+
self.errors.append(
|
|
168
|
+
"❌ Anthropic API key lacks required permissions (403 Forbidden)"
|
|
169
|
+
)
|
|
170
|
+
return False
|
|
171
|
+
if response.status_code == 400:
|
|
172
|
+
# Bad request but key is valid (we sent minimal request on purpose)
|
|
173
|
+
self.logger.debug("✅ Anthropic API key validated successfully")
|
|
174
|
+
return True
|
|
175
|
+
if response.status_code == 429:
|
|
176
|
+
# Rate limited but key is valid
|
|
177
|
+
self.warnings.append("⚠️ Anthropic API key is valid but rate limited")
|
|
178
|
+
return True
|
|
179
|
+
if response.status_code == 200:
|
|
180
|
+
self.logger.debug("✅ Anthropic API key validated successfully")
|
|
181
|
+
return True
|
|
182
|
+
self.warnings.append(
|
|
183
|
+
f"⚠️ Anthropic API returned unexpected status: {response.status_code}"
|
|
184
|
+
)
|
|
185
|
+
return True
|
|
186
|
+
|
|
187
|
+
except requests.exceptions.Timeout:
|
|
188
|
+
self.warnings.append(
|
|
189
|
+
"⚠️ Anthropic API validation timed out - assuming key is valid"
|
|
190
|
+
)
|
|
191
|
+
return True
|
|
192
|
+
except requests.exceptions.ConnectionError as e:
|
|
193
|
+
self.warnings.append(f"⚠️ Could not connect to Anthropic API: {e}")
|
|
194
|
+
return True
|
|
195
|
+
except Exception as e:
|
|
196
|
+
self.errors.append(f"❌ Anthropic API validation failed with error: {e}")
|
|
197
|
+
return False
|
|
198
|
+
|
|
199
|
+
def _validate_github_token(self, token: str) -> bool:
|
|
200
|
+
"""Validate GitHub personal access token.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
token: The GitHub token to validate
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
True if valid, False otherwise
|
|
207
|
+
"""
|
|
208
|
+
try:
|
|
209
|
+
# Check token validity with minimal request
|
|
210
|
+
response = requests.get(
|
|
211
|
+
"https://api.github.com/user",
|
|
212
|
+
headers={
|
|
213
|
+
"Authorization": f"token {token}",
|
|
214
|
+
"Accept": "application/vnd.github.v3+json",
|
|
215
|
+
},
|
|
216
|
+
timeout=10,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
if response.status_code == 401:
|
|
220
|
+
self.errors.append("❌ GitHub token is invalid (401 Unauthorized)")
|
|
221
|
+
return False
|
|
222
|
+
if response.status_code == 403:
|
|
223
|
+
self.errors.append(
|
|
224
|
+
"❌ GitHub token lacks required permissions (403 Forbidden)"
|
|
225
|
+
)
|
|
226
|
+
return False
|
|
227
|
+
if response.status_code == 200:
|
|
228
|
+
self.logger.debug("✅ GitHub token validated successfully")
|
|
229
|
+
return True
|
|
230
|
+
self.warnings.append(
|
|
231
|
+
f"⚠️ GitHub API returned unexpected status: {response.status_code}"
|
|
232
|
+
)
|
|
233
|
+
return True
|
|
234
|
+
|
|
235
|
+
except requests.exceptions.Timeout:
|
|
236
|
+
self.warnings.append(
|
|
237
|
+
"⚠️ GitHub API validation timed out - assuming token is valid"
|
|
238
|
+
)
|
|
239
|
+
return True
|
|
240
|
+
except requests.exceptions.ConnectionError as e:
|
|
241
|
+
self.warnings.append(f"⚠️ Could not connect to GitHub API: {e}")
|
|
242
|
+
return True
|
|
243
|
+
except Exception as e:
|
|
244
|
+
self.errors.append(f"❌ GitHub token validation failed with error: {e}")
|
|
245
|
+
return False
|
|
246
|
+
|
|
247
|
+
def _validate_custom_api(self, api_name: str, validation_config: Dict) -> bool:
|
|
248
|
+
"""Validate a custom API key based on configuration.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
api_name: Name of the API
|
|
252
|
+
validation_config: Configuration for validating this API
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
True if valid, False otherwise
|
|
256
|
+
"""
|
|
257
|
+
try:
|
|
258
|
+
env_var = validation_config.get("env_var")
|
|
259
|
+
if not env_var:
|
|
260
|
+
return True
|
|
261
|
+
|
|
262
|
+
api_key = os.getenv(env_var)
|
|
263
|
+
if not api_key:
|
|
264
|
+
return True # Not configured, skip validation
|
|
265
|
+
|
|
266
|
+
# Get validation endpoint and method
|
|
267
|
+
endpoint = validation_config.get("endpoint")
|
|
268
|
+
method = validation_config.get("method", "GET").upper()
|
|
269
|
+
headers = validation_config.get("headers", {})
|
|
270
|
+
|
|
271
|
+
# Replace {API_KEY} placeholder in headers
|
|
272
|
+
for key, value in headers.items():
|
|
273
|
+
if isinstance(value, str):
|
|
274
|
+
headers[key] = value.replace("{API_KEY}", api_key)
|
|
275
|
+
|
|
276
|
+
# Make validation request
|
|
277
|
+
if method == "GET":
|
|
278
|
+
response = requests.get(endpoint, headers=headers, timeout=10)
|
|
279
|
+
elif method == "POST":
|
|
280
|
+
body = validation_config.get("body", {})
|
|
281
|
+
response = requests.post(
|
|
282
|
+
endpoint, headers=headers, json=body, timeout=10
|
|
283
|
+
)
|
|
284
|
+
else:
|
|
285
|
+
self.warnings.append(
|
|
286
|
+
f"⚠️ Unsupported validation method for {api_name}: {method}"
|
|
287
|
+
)
|
|
288
|
+
return True
|
|
289
|
+
|
|
290
|
+
# Check expected status codes
|
|
291
|
+
valid_status_codes = validation_config.get("valid_status_codes", [200])
|
|
292
|
+
if response.status_code in valid_status_codes:
|
|
293
|
+
self.logger.debug(f"✅ {api_name} API key validated successfully")
|
|
294
|
+
return True
|
|
295
|
+
if response.status_code == 401:
|
|
296
|
+
self.errors.append(
|
|
297
|
+
f"❌ {api_name} API key is invalid (401 Unauthorized)"
|
|
298
|
+
)
|
|
299
|
+
return False
|
|
300
|
+
if response.status_code == 403:
|
|
301
|
+
self.errors.append(
|
|
302
|
+
f"❌ {api_name} API key lacks permissions (403 Forbidden)"
|
|
303
|
+
)
|
|
304
|
+
return False
|
|
305
|
+
self.warnings.append(
|
|
306
|
+
f"⚠️ {api_name} API returned status: {response.status_code}"
|
|
307
|
+
)
|
|
308
|
+
return True
|
|
309
|
+
|
|
310
|
+
except Exception as e:
|
|
311
|
+
self.warnings.append(f"⚠️ {api_name} API validation failed: {e}")
|
|
312
|
+
return True
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def validate_api_keys(config: Optional[Dict] = None, strict: bool = True) -> bool:
|
|
316
|
+
"""Convenience function to validate all API keys.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
config: Optional configuration dictionary
|
|
320
|
+
strict: If True, raise exception on validation failure
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
True if all validations passed, False otherwise
|
|
324
|
+
|
|
325
|
+
Raises:
|
|
326
|
+
ValueError: If strict=True and any validation fails
|
|
327
|
+
"""
|
|
328
|
+
validator = APIKeyValidator(config)
|
|
329
|
+
success, _errors, _warnings = validator.validate_all_keys(strict=strict)
|
|
330
|
+
return success
|
claude_mpm/core/base_service.py
CHANGED
|
@@ -26,11 +26,12 @@ import traceback
|
|
|
26
26
|
from abc import ABC, abstractmethod
|
|
27
27
|
from contextlib import asynccontextmanager
|
|
28
28
|
from dataclasses import dataclass, field
|
|
29
|
-
from datetime import datetime, timedelta
|
|
29
|
+
from datetime import datetime, timedelta, timezone
|
|
30
30
|
from pathlib import Path
|
|
31
31
|
from typing import Any, Dict, List, Optional
|
|
32
32
|
|
|
33
33
|
from .config import Config
|
|
34
|
+
from .enums import HealthStatus
|
|
34
35
|
from .mixins import LoggerMixin
|
|
35
36
|
|
|
36
37
|
|
|
@@ -38,7 +39,7 @@ from .mixins import LoggerMixin
|
|
|
38
39
|
class ServiceHealth:
|
|
39
40
|
"""Service health status information."""
|
|
40
41
|
|
|
41
|
-
status:
|
|
42
|
+
status: HealthStatus # Type-safe health status using enum
|
|
42
43
|
message: str
|
|
43
44
|
timestamp: str
|
|
44
45
|
metrics: Dict[str, Any] = field(default_factory=dict)
|
|
@@ -142,9 +143,9 @@ class BaseService(LoggerMixin, ABC):
|
|
|
142
143
|
|
|
143
144
|
# Health and metrics
|
|
144
145
|
self._health = ServiceHealth(
|
|
145
|
-
status=
|
|
146
|
+
status=HealthStatus.UNKNOWN,
|
|
146
147
|
message="Service not started",
|
|
147
|
-
timestamp=datetime.now().isoformat(),
|
|
148
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
148
149
|
)
|
|
149
150
|
self._metrics = ServiceMetrics()
|
|
150
151
|
self._last_health_check: Optional[float] = None
|
|
@@ -199,7 +200,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
199
200
|
def uptime(self) -> Optional[float]:
|
|
200
201
|
"""Get service uptime in seconds."""
|
|
201
202
|
if self._start_time and self._running:
|
|
202
|
-
return (datetime.now() - self._start_time).total_seconds()
|
|
203
|
+
return (datetime.now(timezone.utc) - self._start_time).total_seconds()
|
|
203
204
|
return None
|
|
204
205
|
|
|
205
206
|
@property
|
|
@@ -235,9 +236,9 @@ class BaseService(LoggerMixin, ABC):
|
|
|
235
236
|
except Exception as e:
|
|
236
237
|
self.logger.error(f"Failed to start service {self.name}: {e}")
|
|
237
238
|
self._health = ServiceHealth(
|
|
238
|
-
status=
|
|
239
|
+
status=HealthStatus.UNHEALTHY,
|
|
239
240
|
message=f"Startup failed: {e!s}",
|
|
240
|
-
timestamp=datetime.now().isoformat(),
|
|
241
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
241
242
|
checks={"startup": False},
|
|
242
243
|
)
|
|
243
244
|
|
|
@@ -268,13 +269,13 @@ class BaseService(LoggerMixin, ABC):
|
|
|
268
269
|
|
|
269
270
|
# Mark as running
|
|
270
271
|
self._running = True
|
|
271
|
-
self._start_time = datetime.now()
|
|
272
|
+
self._start_time = datetime.now(timezone.utc)
|
|
272
273
|
|
|
273
274
|
# Update health status
|
|
274
275
|
self._health = ServiceHealth(
|
|
275
|
-
status=
|
|
276
|
+
status=HealthStatus.HEALTHY,
|
|
276
277
|
message="Service started successfully",
|
|
277
|
-
timestamp=datetime.now().isoformat(),
|
|
278
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
278
279
|
checks={"startup": True},
|
|
279
280
|
metrics=self._get_health_metrics() if self._enable_enhanced else {},
|
|
280
281
|
)
|
|
@@ -336,9 +337,9 @@ class BaseService(LoggerMixin, ABC):
|
|
|
336
337
|
|
|
337
338
|
# Update health status
|
|
338
339
|
self._health = ServiceHealth(
|
|
339
|
-
status=
|
|
340
|
+
status=HealthStatus.UNKNOWN,
|
|
340
341
|
message="Service stopped",
|
|
341
|
-
timestamp=datetime.now().isoformat(),
|
|
342
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
342
343
|
checks={"running": False},
|
|
343
344
|
)
|
|
344
345
|
|
|
@@ -372,23 +373,23 @@ class BaseService(LoggerMixin, ABC):
|
|
|
372
373
|
|
|
373
374
|
# Determine overall status
|
|
374
375
|
if not checks["running"]:
|
|
375
|
-
status =
|
|
376
|
+
status = HealthStatus.UNHEALTHY
|
|
376
377
|
message = "Service is not running"
|
|
377
378
|
elif all(checks.values()):
|
|
378
|
-
status =
|
|
379
|
+
status = HealthStatus.HEALTHY
|
|
379
380
|
message = "All health checks passed"
|
|
380
381
|
elif any(checks.values()):
|
|
381
|
-
status =
|
|
382
|
+
status = HealthStatus.DEGRADED
|
|
382
383
|
message = "Some health checks failed"
|
|
383
384
|
else:
|
|
384
|
-
status =
|
|
385
|
+
status = HealthStatus.UNHEALTHY
|
|
385
386
|
message = "Multiple health checks failed"
|
|
386
387
|
|
|
387
388
|
# Update health status
|
|
388
389
|
self._health = ServiceHealth(
|
|
389
390
|
status=status,
|
|
390
391
|
message=message,
|
|
391
|
-
timestamp=datetime.now().isoformat(),
|
|
392
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
392
393
|
checks=checks,
|
|
393
394
|
metrics={
|
|
394
395
|
"uptime": self.uptime,
|
|
@@ -402,9 +403,9 @@ class BaseService(LoggerMixin, ABC):
|
|
|
402
403
|
except Exception as e:
|
|
403
404
|
self.logger.error(f"Health check failed for {self.name}: {e}")
|
|
404
405
|
self._health = ServiceHealth(
|
|
405
|
-
status=
|
|
406
|
+
status=HealthStatus.UNHEALTHY,
|
|
406
407
|
message=f"Health check error: {e!s}",
|
|
407
|
-
timestamp=datetime.now().isoformat(),
|
|
408
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
408
409
|
checks={"health_check_error": True},
|
|
409
410
|
)
|
|
410
411
|
return self._health
|
|
@@ -428,7 +429,16 @@ class BaseService(LoggerMixin, ABC):
|
|
|
428
429
|
self.logger.info(
|
|
429
430
|
f"Received signal {signum}, initiating graceful shutdown..."
|
|
430
431
|
)
|
|
431
|
-
|
|
432
|
+
# Get the event loop and create a tracked shutdown task
|
|
433
|
+
try:
|
|
434
|
+
loop = asyncio.get_event_loop()
|
|
435
|
+
task = loop.create_task(self.stop())
|
|
436
|
+
# Store reference to prevent GC during shutdown
|
|
437
|
+
if not hasattr(self, "_shutdown_task"):
|
|
438
|
+
self._shutdown_task = task
|
|
439
|
+
except RuntimeError:
|
|
440
|
+
# No event loop, call stop synchronously
|
|
441
|
+
self.logger.warning("No event loop available for graceful shutdown")
|
|
432
442
|
|
|
433
443
|
signal.signal(signal.SIGINT, signal_handler)
|
|
434
444
|
signal.signal(signal.SIGTERM, signal_handler)
|
|
@@ -584,9 +594,9 @@ class BaseService(LoggerMixin, ABC):
|
|
|
584
594
|
)
|
|
585
595
|
else:
|
|
586
596
|
return ServiceHealth(
|
|
587
|
-
status=
|
|
597
|
+
status=HealthStatus.DEGRADED,
|
|
588
598
|
message="Service circuit breaker is open",
|
|
589
|
-
timestamp=datetime.now().isoformat(),
|
|
599
|
+
timestamp=datetime.now(timezone.utc).isoformat(),
|
|
590
600
|
checks={"circuit_breaker": False},
|
|
591
601
|
metrics=self._get_health_metrics(),
|
|
592
602
|
)
|
|
@@ -595,7 +605,7 @@ class BaseService(LoggerMixin, ABC):
|
|
|
595
605
|
health = await self.health_check()
|
|
596
606
|
|
|
597
607
|
# Update circuit breaker
|
|
598
|
-
if health.status in
|
|
608
|
+
if health.status in (HealthStatus.HEALTHY, HealthStatus.DEGRADED):
|
|
599
609
|
self._record_circuit_success()
|
|
600
610
|
else:
|
|
601
611
|
self._record_circuit_failure()
|
claude_mpm/core/cache.py
CHANGED
|
@@ -19,7 +19,7 @@ import pickle
|
|
|
19
19
|
import threading
|
|
20
20
|
from collections import OrderedDict
|
|
21
21
|
from dataclasses import dataclass, field
|
|
22
|
-
from datetime import datetime
|
|
22
|
+
from datetime import datetime, timezone
|
|
23
23
|
from typing import Any, Callable, Dict, Optional, TypeVar, Union
|
|
24
24
|
|
|
25
25
|
from ..core.logger import get_logger
|
|
@@ -43,12 +43,12 @@ class CacheEntry:
|
|
|
43
43
|
"""Check if entry has expired based on TTL."""
|
|
44
44
|
if self.ttl is None:
|
|
45
45
|
return False
|
|
46
|
-
age = (datetime.now() - self.created_at).total_seconds()
|
|
46
|
+
age = (datetime.now(timezone.utc) - self.created_at).total_seconds()
|
|
47
47
|
return age > self.ttl
|
|
48
48
|
|
|
49
49
|
def touch(self):
|
|
50
50
|
"""Update last access time and increment counter."""
|
|
51
|
-
self.last_accessed = datetime.now()
|
|
51
|
+
self.last_accessed = datetime.now(timezone.utc)
|
|
52
52
|
self.access_count += 1
|
|
53
53
|
|
|
54
54
|
|
|
@@ -129,13 +129,13 @@ class FileSystemCache:
|
|
|
129
129
|
# Rough estimate using JSON serialization
|
|
130
130
|
try:
|
|
131
131
|
return len(json.dumps(value))
|
|
132
|
-
except:
|
|
132
|
+
except Exception:
|
|
133
133
|
return 1000 # Default estimate
|
|
134
134
|
else:
|
|
135
135
|
# Use pickle for size estimation
|
|
136
136
|
try:
|
|
137
137
|
return len(pickle.dumps(value))
|
|
138
|
-
except:
|
|
138
|
+
except Exception:
|
|
139
139
|
return 100 # Default small size
|
|
140
140
|
|
|
141
141
|
def _evict_lru(self):
|
|
@@ -288,10 +288,10 @@ class FileSystemCache:
|
|
|
288
288
|
"""Read file from disk."""
|
|
289
289
|
try:
|
|
290
290
|
if "b" in mode:
|
|
291
|
-
with open(
|
|
291
|
+
with Path(file_path).open(mode) as f:
|
|
292
292
|
return f.read()
|
|
293
293
|
else:
|
|
294
|
-
with open(
|
|
294
|
+
with Path(file_path).open(mode, encoding=encoding) as f:
|
|
295
295
|
return f.read()
|
|
296
296
|
except Exception as e:
|
|
297
297
|
self._logger.error(f"Failed to read file {file_path}: {e}")
|
|
@@ -391,7 +391,7 @@ class FileSystemCache:
|
|
|
391
391
|
|
|
392
392
|
try:
|
|
393
393
|
self.persist_path.parent.mkdir(parents=True, exist_ok=True)
|
|
394
|
-
with
|
|
394
|
+
with self.persist_path.open("wb") as f:
|
|
395
395
|
pickle.dump(self._cache, f)
|
|
396
396
|
self._logger.debug(f"Cache persisted to {self.persist_path}")
|
|
397
397
|
except Exception as e:
|
|
@@ -403,7 +403,7 @@ class FileSystemCache:
|
|
|
403
403
|
return
|
|
404
404
|
|
|
405
405
|
try:
|
|
406
|
-
with
|
|
406
|
+
with self.persist_path.open("rb") as f:
|
|
407
407
|
loaded_cache = pickle.load(f)
|
|
408
408
|
|
|
409
409
|
# Rebuild cache with validation
|
claude_mpm/core/claude_runner.py
CHANGED
|
@@ -42,8 +42,19 @@ class ClaudeRunner:
|
|
|
42
42
|
launch_method: str = "exec", # "exec" or "subprocess"
|
|
43
43
|
enable_websocket: bool = False,
|
|
44
44
|
websocket_port: int = 8765,
|
|
45
|
+
use_native_agents: bool = False, # Use --agents flag instead of file deployment
|
|
45
46
|
):
|
|
46
|
-
"""Initialize the Claude runner.
|
|
47
|
+
"""Initialize the Claude runner.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
enable_tickets: Enable ticket extraction (deprecated)
|
|
51
|
+
log_level: Logging level
|
|
52
|
+
claude_args: Additional arguments for Claude CLI
|
|
53
|
+
launch_method: "exec" or "subprocess" launch mode
|
|
54
|
+
enable_websocket: Enable WebSocket server
|
|
55
|
+
websocket_port: WebSocket server port
|
|
56
|
+
use_native_agents: Use --agents CLI flag instead of .claude/agents/ deployment
|
|
57
|
+
"""
|
|
47
58
|
self.logger = get_logger(__name__)
|
|
48
59
|
|
|
49
60
|
# Initialize configuration service
|
|
@@ -75,6 +86,7 @@ class ClaudeRunner:
|
|
|
75
86
|
launch_method=launch_method,
|
|
76
87
|
enable_websocket=enable_websocket,
|
|
77
88
|
websocket_port=websocket_port,
|
|
89
|
+
use_native_agents=use_native_agents,
|
|
78
90
|
)
|
|
79
91
|
|
|
80
92
|
# Set configuration attributes
|
|
@@ -84,6 +96,7 @@ class ClaudeRunner:
|
|
|
84
96
|
self.launch_method = config_data["launch_method"]
|
|
85
97
|
self.enable_websocket = config_data["enable_websocket"]
|
|
86
98
|
self.websocket_port = config_data["websocket_port"]
|
|
99
|
+
self.use_native_agents = config_data.get("use_native_agents", False)
|
|
87
100
|
self.config = config_data["config"]
|
|
88
101
|
|
|
89
102
|
# Initialize project logger using the service
|
|
@@ -462,13 +475,11 @@ class ClaudeRunner:
|
|
|
462
475
|
if (
|
|
463
476
|
"author: claude-mpm-project" in existing_content
|
|
464
477
|
or "source: project" in existing_content
|
|
465
|
-
):
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
f"Project agent {agent_name} is up to date"
|
|
471
|
-
)
|
|
478
|
+
) and target_file.stat().st_mtime >= json_file.stat().st_mtime:
|
|
479
|
+
needs_update = False
|
|
480
|
+
self.logger.debug(
|
|
481
|
+
f"Project agent {agent_name} is up to date"
|
|
482
|
+
)
|
|
472
483
|
|
|
473
484
|
if needs_update:
|
|
474
485
|
# Build the agent markdown using the pre-initialized service and base agent data
|