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
|
@@ -12,148 +12,30 @@ DESIGN DECISIONS:
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
|
-
import os
|
|
16
|
-
import sys
|
|
17
15
|
from pathlib import Path
|
|
18
16
|
from typing import Dict, List, Optional
|
|
19
17
|
|
|
20
|
-
from rich.box import ROUNDED
|
|
21
|
-
from rich.columns import Columns
|
|
22
18
|
from rich.console import Console
|
|
23
|
-
from rich.panel import Panel
|
|
24
19
|
from rich.prompt import Confirm, Prompt
|
|
25
|
-
from rich.syntax import Syntax
|
|
26
|
-
from rich.table import Table
|
|
27
20
|
from rich.text import Text
|
|
28
21
|
|
|
22
|
+
from ...core.config import Config
|
|
29
23
|
from ...services.version_service import VersionService
|
|
30
24
|
from ...utils.console import console as default_console
|
|
31
25
|
from ..shared import BaseCommand, CommandResult
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class SimpleAgentManager:
|
|
46
|
-
"""Simple agent state management that discovers real agents from templates."""
|
|
47
|
-
|
|
48
|
-
def __init__(self, config_dir: Path):
|
|
49
|
-
self.config_dir = config_dir
|
|
50
|
-
self.config_file = config_dir / "agent_states.json"
|
|
51
|
-
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
52
|
-
self._load_states()
|
|
53
|
-
# Path to agent templates directory
|
|
54
|
-
self.templates_dir = (
|
|
55
|
-
Path(__file__).parent.parent.parent / "agents" / "templates"
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
def _load_states(self):
|
|
59
|
-
"""Load agent states from file."""
|
|
60
|
-
if self.config_file.exists():
|
|
61
|
-
with open(self.config_file) as f:
|
|
62
|
-
self.states = json.load(f)
|
|
63
|
-
else:
|
|
64
|
-
self.states = {}
|
|
65
|
-
|
|
66
|
-
def _save_states(self):
|
|
67
|
-
"""Save agent states to file."""
|
|
68
|
-
with open(self.config_file, "w") as f:
|
|
69
|
-
json.dump(self.states, f, indent=2)
|
|
70
|
-
|
|
71
|
-
def is_agent_enabled(self, agent_name: str) -> bool:
|
|
72
|
-
"""Check if an agent is enabled."""
|
|
73
|
-
return self.states.get(agent_name, {}).get("enabled", True)
|
|
74
|
-
|
|
75
|
-
def set_agent_enabled(self, agent_name: str, enabled: bool):
|
|
76
|
-
"""Set agent enabled state."""
|
|
77
|
-
if agent_name not in self.states:
|
|
78
|
-
self.states[agent_name] = {}
|
|
79
|
-
self.states[agent_name]["enabled"] = enabled
|
|
80
|
-
self._save_states()
|
|
81
|
-
|
|
82
|
-
def discover_agents(self) -> List[AgentConfig]:
|
|
83
|
-
"""Discover available agents from template JSON files."""
|
|
84
|
-
agents = []
|
|
85
|
-
|
|
86
|
-
# Scan templates directory for JSON files
|
|
87
|
-
if not self.templates_dir.exists():
|
|
88
|
-
# Fallback to a minimal set if templates dir doesn't exist
|
|
89
|
-
return [
|
|
90
|
-
AgentConfig("engineer", "Engineering agent (templates not found)", []),
|
|
91
|
-
AgentConfig("research", "Research agent (templates not found)", []),
|
|
92
|
-
]
|
|
93
|
-
|
|
94
|
-
try:
|
|
95
|
-
# Read all JSON template files
|
|
96
|
-
for template_file in sorted(self.templates_dir.glob("*.json")):
|
|
97
|
-
# Skip backup files
|
|
98
|
-
if "backup" in template_file.name.lower():
|
|
99
|
-
continue
|
|
100
|
-
|
|
101
|
-
try:
|
|
102
|
-
with open(template_file) as f:
|
|
103
|
-
template_data = json.load(f)
|
|
104
|
-
|
|
105
|
-
# Extract agent information from template
|
|
106
|
-
agent_id = template_data.get("agent_id", template_file.stem)
|
|
107
|
-
|
|
108
|
-
# Get metadata for display info
|
|
109
|
-
metadata = template_data.get("metadata", {})
|
|
110
|
-
metadata.get("name", agent_id)
|
|
111
|
-
description = metadata.get(
|
|
112
|
-
"description", "No description available"
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
# Extract capabilities/tools as dependencies for display
|
|
116
|
-
capabilities = template_data.get("capabilities", {})
|
|
117
|
-
tools = capabilities.get("tools", [])
|
|
118
|
-
# Show first few tools as "dependencies" for UI purposes
|
|
119
|
-
display_tools = tools[:3] if len(tools) > 3 else tools
|
|
120
|
-
|
|
121
|
-
# Normalize agent ID (remove -agent suffix if present, replace underscores)
|
|
122
|
-
normalized_id = agent_id.replace("-agent", "").replace("_", "-")
|
|
123
|
-
|
|
124
|
-
agents.append(
|
|
125
|
-
AgentConfig(
|
|
126
|
-
name=normalized_id,
|
|
127
|
-
description=(
|
|
128
|
-
description[:80] + "..."
|
|
129
|
-
if len(description) > 80
|
|
130
|
-
else description
|
|
131
|
-
),
|
|
132
|
-
dependencies=display_tools,
|
|
133
|
-
)
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
except (json.JSONDecodeError, KeyError):
|
|
137
|
-
# Skip malformed templates
|
|
138
|
-
continue
|
|
139
|
-
|
|
140
|
-
except Exception as e:
|
|
141
|
-
# If there's an error reading templates, return a minimal set
|
|
142
|
-
return [
|
|
143
|
-
AgentConfig("engineer", f"Error loading templates: {e!s}", []),
|
|
144
|
-
AgentConfig("research", "Research agent", []),
|
|
145
|
-
]
|
|
146
|
-
|
|
147
|
-
# Sort agents by name for consistent display
|
|
148
|
-
agents.sort(key=lambda a: a.name)
|
|
149
|
-
|
|
150
|
-
return (
|
|
151
|
-
agents
|
|
152
|
-
if agents
|
|
153
|
-
else [
|
|
154
|
-
AgentConfig("engineer", "No agents found in templates", []),
|
|
155
|
-
]
|
|
156
|
-
)
|
|
26
|
+
from .agent_state_manager import SimpleAgentManager
|
|
27
|
+
from .configure_agent_display import AgentDisplay
|
|
28
|
+
from .configure_behavior_manager import BehaviorManager
|
|
29
|
+
from .configure_hook_manager import HookManager
|
|
30
|
+
from .configure_models import AgentConfig
|
|
31
|
+
from .configure_navigation import ConfigNavigation
|
|
32
|
+
from .configure_persistence import ConfigPersistence
|
|
33
|
+
from .configure_startup_manager import StartupManager
|
|
34
|
+
from .configure_template_editor import TemplateEditor
|
|
35
|
+
from .configure_validators import (
|
|
36
|
+
parse_id_selection,
|
|
37
|
+
validate_args as validate_configure_args,
|
|
38
|
+
)
|
|
157
39
|
|
|
158
40
|
|
|
159
41
|
class ConfigureCommand(BaseCommand):
|
|
@@ -166,24 +48,88 @@ class ConfigureCommand(BaseCommand):
|
|
|
166
48
|
self.current_scope = "project"
|
|
167
49
|
self.project_dir = Path.cwd()
|
|
168
50
|
self.agent_manager = None
|
|
51
|
+
self.hook_manager = HookManager(self.console)
|
|
52
|
+
self.behavior_manager = None # Initialized when scope is set
|
|
53
|
+
self._agent_display = None # Lazy-initialized
|
|
54
|
+
self._persistence = None # Lazy-initialized
|
|
55
|
+
self._navigation = None # Lazy-initialized
|
|
56
|
+
self._template_editor = None # Lazy-initialized
|
|
57
|
+
self._startup_manager = None # Lazy-initialized
|
|
169
58
|
|
|
170
59
|
def validate_args(self, args) -> Optional[str]:
|
|
171
60
|
"""Validate command arguments."""
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
61
|
+
return validate_configure_args(args)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def agent_display(self) -> AgentDisplay:
|
|
65
|
+
"""Lazy-initialize agent display handler."""
|
|
66
|
+
if self._agent_display is None:
|
|
67
|
+
if self.agent_manager is None:
|
|
68
|
+
raise RuntimeError(
|
|
69
|
+
"agent_manager must be initialized before agent_display"
|
|
70
|
+
)
|
|
71
|
+
self._agent_display = AgentDisplay(
|
|
72
|
+
self.console,
|
|
73
|
+
self.agent_manager,
|
|
74
|
+
self._get_agent_template_path,
|
|
75
|
+
self._display_header,
|
|
76
|
+
)
|
|
77
|
+
return self._agent_display
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def persistence(self) -> ConfigPersistence:
|
|
81
|
+
"""Lazy-initialize persistence handler."""
|
|
82
|
+
if self._persistence is None:
|
|
83
|
+
# Note: agent_manager might be None for version_info calls
|
|
84
|
+
self._persistence = ConfigPersistence(
|
|
85
|
+
self.console,
|
|
86
|
+
self.version_service,
|
|
87
|
+
self.agent_manager, # Can be None for version operations
|
|
88
|
+
self._get_agent_template_path,
|
|
89
|
+
self._display_header,
|
|
90
|
+
self.current_scope,
|
|
91
|
+
self.project_dir,
|
|
92
|
+
)
|
|
93
|
+
return self._persistence
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def navigation(self) -> ConfigNavigation:
|
|
97
|
+
"""Lazy-initialize navigation handler."""
|
|
98
|
+
if self._navigation is None:
|
|
99
|
+
self._navigation = ConfigNavigation(self.console, self.project_dir)
|
|
100
|
+
# Sync scope from main command
|
|
101
|
+
self._navigation.current_scope = self.current_scope
|
|
102
|
+
return self._navigation
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def template_editor(self) -> TemplateEditor:
|
|
106
|
+
"""Lazy-initialize template editor."""
|
|
107
|
+
if self._template_editor is None:
|
|
108
|
+
if self.agent_manager is None:
|
|
109
|
+
raise RuntimeError(
|
|
110
|
+
"agent_manager must be initialized before template_editor"
|
|
111
|
+
)
|
|
112
|
+
self._template_editor = TemplateEditor(
|
|
113
|
+
self.console, self.agent_manager, self.current_scope, self.project_dir
|
|
114
|
+
)
|
|
115
|
+
return self._template_editor
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def startup_manager(self) -> StartupManager:
|
|
119
|
+
"""Lazy-initialize startup manager."""
|
|
120
|
+
if self._startup_manager is None:
|
|
121
|
+
if self.agent_manager is None:
|
|
122
|
+
raise RuntimeError(
|
|
123
|
+
"agent_manager must be initialized before startup_manager"
|
|
124
|
+
)
|
|
125
|
+
self._startup_manager = StartupManager(
|
|
126
|
+
self.agent_manager,
|
|
127
|
+
self.console,
|
|
128
|
+
self.current_scope,
|
|
129
|
+
self.project_dir,
|
|
130
|
+
self._display_header,
|
|
131
|
+
)
|
|
132
|
+
return self._startup_manager
|
|
187
133
|
|
|
188
134
|
def run(self, args) -> CommandResult:
|
|
189
135
|
"""Execute the configure command."""
|
|
@@ -192,12 +138,15 @@ class ConfigureCommand(BaseCommand):
|
|
|
192
138
|
if getattr(args, "project_dir", None):
|
|
193
139
|
self.project_dir = Path(args.project_dir)
|
|
194
140
|
|
|
195
|
-
# Initialize agent manager with appropriate config directory
|
|
141
|
+
# Initialize agent manager and behavior manager with appropriate config directory
|
|
196
142
|
if self.current_scope == "project":
|
|
197
143
|
config_dir = self.project_dir / ".claude-mpm"
|
|
198
144
|
else:
|
|
199
145
|
config_dir = Path.home() / ".claude-mpm"
|
|
200
146
|
self.agent_manager = SimpleAgentManager(config_dir)
|
|
147
|
+
self.behavior_manager = BehaviorManager(
|
|
148
|
+
config_dir, self.current_scope, self.console
|
|
149
|
+
)
|
|
201
150
|
|
|
202
151
|
# Disable colors if requested
|
|
203
152
|
if getattr(args, "no_colors", False):
|
|
@@ -242,39 +191,15 @@ class ConfigureCommand(BaseCommand):
|
|
|
242
191
|
if getattr(args, "behaviors", False):
|
|
243
192
|
return self._run_behavior_management()
|
|
244
193
|
|
|
194
|
+
if getattr(args, "startup", False):
|
|
195
|
+
return self._run_startup_configuration()
|
|
196
|
+
|
|
245
197
|
# Launch interactive TUI
|
|
246
198
|
return self._run_interactive_tui(args)
|
|
247
199
|
|
|
248
200
|
def _run_interactive_tui(self, args) -> CommandResult:
|
|
249
|
-
"""Run the main interactive
|
|
250
|
-
#
|
|
251
|
-
use_textual = getattr(args, "use_textual", True)
|
|
252
|
-
force_rich = getattr(args, "force_rich", False)
|
|
253
|
-
|
|
254
|
-
if use_textual and not force_rich:
|
|
255
|
-
try:
|
|
256
|
-
# Try to import and use Textual TUI
|
|
257
|
-
from .configure_tui import can_use_tui, launch_tui
|
|
258
|
-
|
|
259
|
-
if can_use_tui():
|
|
260
|
-
self.console.print(
|
|
261
|
-
"[cyan]Launching full-screen configuration interface...[/cyan]"
|
|
262
|
-
)
|
|
263
|
-
return launch_tui(self.current_scope, self.project_dir)
|
|
264
|
-
# Fall back to Rich TUI if terminal doesn't support full-screen
|
|
265
|
-
self.console.print(
|
|
266
|
-
"[yellow]Terminal doesn't support full-screen mode. Using menu interface.[/yellow]"
|
|
267
|
-
)
|
|
268
|
-
except ImportError:
|
|
269
|
-
# Textual not available, fall back to Rich
|
|
270
|
-
self.console.print(
|
|
271
|
-
"[yellow]Textual not installed. Using menu interface.[/yellow]"
|
|
272
|
-
)
|
|
273
|
-
self.console.print(
|
|
274
|
-
"[dim]Install textual for a better experience: pip install textual[/dim]"
|
|
275
|
-
)
|
|
276
|
-
|
|
277
|
-
# Original Rich-based TUI
|
|
201
|
+
"""Run the main interactive menu interface."""
|
|
202
|
+
# Rich-based menu interface
|
|
278
203
|
try:
|
|
279
204
|
self.console.clear()
|
|
280
205
|
|
|
@@ -286,13 +211,49 @@ class ConfigureCommand(BaseCommand):
|
|
|
286
211
|
if choice == "1":
|
|
287
212
|
self._manage_agents()
|
|
288
213
|
elif choice == "2":
|
|
289
|
-
self.
|
|
214
|
+
self._manage_skills()
|
|
290
215
|
elif choice == "3":
|
|
291
|
-
self.
|
|
216
|
+
self._edit_templates()
|
|
292
217
|
elif choice == "4":
|
|
293
|
-
self.
|
|
218
|
+
self._manage_behaviors()
|
|
294
219
|
elif choice == "5":
|
|
220
|
+
# If user saves and wants to proceed to startup, exit the configurator
|
|
221
|
+
if self._manage_startup_configuration():
|
|
222
|
+
self.console.print(
|
|
223
|
+
"\n[green]Configuration saved. Exiting configurator...[/green]"
|
|
224
|
+
)
|
|
225
|
+
break
|
|
226
|
+
elif choice == "6":
|
|
227
|
+
self._switch_scope()
|
|
228
|
+
elif choice == "7":
|
|
295
229
|
self._show_version_info_interactive()
|
|
230
|
+
elif choice == "l":
|
|
231
|
+
# Check for pending agent changes
|
|
232
|
+
if self.agent_manager and self.agent_manager.has_pending_changes():
|
|
233
|
+
should_save = Confirm.ask(
|
|
234
|
+
"[yellow]You have unsaved agent changes. Save them before launching?[/yellow]",
|
|
235
|
+
default=True,
|
|
236
|
+
)
|
|
237
|
+
if should_save:
|
|
238
|
+
self.agent_manager.commit_deferred_changes()
|
|
239
|
+
self.console.print("[green]✓ Agent changes saved[/green]")
|
|
240
|
+
else:
|
|
241
|
+
self.agent_manager.discard_deferred_changes()
|
|
242
|
+
self.console.print(
|
|
243
|
+
"[yellow]⚠ Agent changes discarded[/yellow]"
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Save all configuration
|
|
247
|
+
self.console.print("\n[cyan]Saving configuration...[/cyan]")
|
|
248
|
+
if self._save_all_configuration():
|
|
249
|
+
# Launch Claude MPM (this will replace the process if successful)
|
|
250
|
+
self._launch_claude_mpm()
|
|
251
|
+
# If execvp fails, we'll return here and break
|
|
252
|
+
break
|
|
253
|
+
self.console.print(
|
|
254
|
+
"[red]✗ Failed to save configuration. Not launching.[/red]"
|
|
255
|
+
)
|
|
256
|
+
Prompt.ask("\nPress Enter to continue")
|
|
296
257
|
elif choice == "q":
|
|
297
258
|
self.console.print(
|
|
298
259
|
"\n[green]Configuration complete. Goodbye![/green]"
|
|
@@ -312,57 +273,15 @@ class ConfigureCommand(BaseCommand):
|
|
|
312
273
|
|
|
313
274
|
def _display_header(self) -> None:
|
|
314
275
|
"""Display the TUI header."""
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
header_text = Text()
|
|
319
|
-
header_text.append("Claude MPM ", style="bold cyan")
|
|
320
|
-
header_text.append("Configuration Interface", style="bold white")
|
|
321
|
-
|
|
322
|
-
scope_text = Text(f"Scope: {self.current_scope.upper()}", style="yellow")
|
|
323
|
-
dir_text = Text(f"Directory: {self.project_dir}", style="dim")
|
|
324
|
-
|
|
325
|
-
header_content = Columns([header_text], align="center")
|
|
326
|
-
subtitle_content = f"{scope_text} | {dir_text}"
|
|
327
|
-
|
|
328
|
-
header_panel = Panel(
|
|
329
|
-
header_content,
|
|
330
|
-
subtitle=subtitle_content,
|
|
331
|
-
box=ROUNDED,
|
|
332
|
-
style="blue",
|
|
333
|
-
padding=(1, 2),
|
|
334
|
-
)
|
|
335
|
-
|
|
336
|
-
self.console.print(header_panel)
|
|
337
|
-
self.console.print()
|
|
276
|
+
# Sync scope to navigation before display
|
|
277
|
+
self.navigation.current_scope = self.current_scope
|
|
278
|
+
self.navigation.display_header()
|
|
338
279
|
|
|
339
280
|
def _show_main_menu(self) -> str:
|
|
340
281
|
"""Show the main menu and get user choice."""
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
("3", "Behavior Files", "Manage identity and workflow configurations"),
|
|
345
|
-
("4", "Switch Scope", f"Current: {self.current_scope}"),
|
|
346
|
-
("5", "Version Info", "Display MPM and Claude versions"),
|
|
347
|
-
("q", "Quit", "Exit configuration interface"),
|
|
348
|
-
]
|
|
349
|
-
|
|
350
|
-
table = Table(show_header=False, box=None, padding=(0, 2))
|
|
351
|
-
table.add_column("Key", style="cyan", width=3)
|
|
352
|
-
table.add_column("Option", style="bold white", width=20)
|
|
353
|
-
table.add_column("Description", style="dim")
|
|
354
|
-
|
|
355
|
-
for key, option, desc in menu_items:
|
|
356
|
-
table.add_row(f"[{key}]", option, desc)
|
|
357
|
-
|
|
358
|
-
menu_panel = Panel(
|
|
359
|
-
table, title="[bold]Main Menu[/bold]", box=ROUNDED, style="green"
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
self.console.print(menu_panel)
|
|
363
|
-
self.console.print()
|
|
364
|
-
|
|
365
|
-
return Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="q")
|
|
282
|
+
# Sync scope to navigation before display
|
|
283
|
+
self.navigation.current_scope = self.current_scope
|
|
284
|
+
return self.navigation.show_main_menu()
|
|
366
285
|
|
|
367
286
|
def _manage_agents(self) -> None:
|
|
368
287
|
"""Agent management interface."""
|
|
@@ -376,22 +295,41 @@ class ConfigureCommand(BaseCommand):
|
|
|
376
295
|
|
|
377
296
|
# Show agent menu
|
|
378
297
|
self.console.print("\n[bold]Agent Management Options:[/bold]")
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
self.console.print(
|
|
298
|
+
|
|
299
|
+
# Use Text objects to properly display shortcuts with styling
|
|
300
|
+
text_t = Text(" ")
|
|
301
|
+
text_t.append("[t]", style="bold blue")
|
|
302
|
+
text_t.append(" Toggle agents (enable/disable multiple)")
|
|
303
|
+
self.console.print(text_t)
|
|
304
|
+
|
|
305
|
+
text_c = Text(" ")
|
|
306
|
+
text_c.append("[c]", style="bold blue")
|
|
307
|
+
text_c.append(" Customize agent template")
|
|
308
|
+
self.console.print(text_c)
|
|
309
|
+
|
|
310
|
+
text_v = Text(" ")
|
|
311
|
+
text_v.append("[v]", style="bold blue")
|
|
312
|
+
text_v.append(" View agent details")
|
|
313
|
+
self.console.print(text_v)
|
|
314
|
+
|
|
315
|
+
text_r = Text(" ")
|
|
316
|
+
text_r.append("[r]", style="bold blue")
|
|
317
|
+
text_r.append(" Reset agent to defaults")
|
|
318
|
+
self.console.print(text_r)
|
|
319
|
+
|
|
320
|
+
text_b = Text(" ")
|
|
321
|
+
text_b.append("[b]", style="bold blue")
|
|
322
|
+
text_b.append(" Back to main menu")
|
|
323
|
+
self.console.print(text_b)
|
|
324
|
+
|
|
385
325
|
self.console.print()
|
|
386
326
|
|
|
387
|
-
choice = Prompt.ask("[bold
|
|
327
|
+
choice = Prompt.ask("[bold blue]Select an option[/bold blue]", default="b")
|
|
388
328
|
|
|
389
329
|
if choice == "b":
|
|
390
330
|
break
|
|
391
|
-
if choice == "
|
|
392
|
-
self.
|
|
393
|
-
elif choice == "d":
|
|
394
|
-
self._disable_agent_interactive(agents)
|
|
331
|
+
if choice == "t":
|
|
332
|
+
self._toggle_agents_interactive(agents)
|
|
395
333
|
elif choice == "c":
|
|
396
334
|
self._customize_agent_template(agents)
|
|
397
335
|
elif choice == "v":
|
|
@@ -404,679 +342,366 @@ class ConfigureCommand(BaseCommand):
|
|
|
404
342
|
|
|
405
343
|
def _display_agents_table(self, agents: List[AgentConfig]) -> None:
|
|
406
344
|
"""Display a table of available agents."""
|
|
407
|
-
|
|
408
|
-
title=f"Available Agents ({len(agents)} total)",
|
|
409
|
-
box=ROUNDED,
|
|
410
|
-
show_lines=True,
|
|
411
|
-
)
|
|
345
|
+
self.agent_display.display_agents_table(agents)
|
|
412
346
|
|
|
413
|
-
|
|
414
|
-
table.
|
|
415
|
-
|
|
416
|
-
table.add_column("Description", style="white", width=45)
|
|
417
|
-
table.add_column("Model/Tools", style="dim", width=20)
|
|
418
|
-
|
|
419
|
-
for idx, agent in enumerate(agents, 1):
|
|
420
|
-
# Check if agent is enabled
|
|
421
|
-
is_enabled = self.agent_manager.is_agent_enabled(agent.name)
|
|
422
|
-
status = (
|
|
423
|
-
"[green]✓ Enabled[/green]" if is_enabled else "[red]✗ Disabled[/red]"
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
# Format tools/dependencies - show first 2 tools
|
|
427
|
-
tools_display = ""
|
|
428
|
-
if agent.dependencies:
|
|
429
|
-
if len(agent.dependencies) > 2:
|
|
430
|
-
tools_display = f"{', '.join(agent.dependencies[:2])}..."
|
|
431
|
-
else:
|
|
432
|
-
tools_display = ", ".join(agent.dependencies)
|
|
433
|
-
else:
|
|
434
|
-
# Try to get model from template
|
|
435
|
-
try:
|
|
436
|
-
template_path = self._get_agent_template_path(agent.name)
|
|
437
|
-
if template_path.exists():
|
|
438
|
-
with open(template_path) as f:
|
|
439
|
-
template = json.load(f)
|
|
440
|
-
model = template.get("capabilities", {}).get("model", "default")
|
|
441
|
-
tools_display = f"Model: {model}"
|
|
442
|
-
else:
|
|
443
|
-
tools_display = "Default"
|
|
444
|
-
except:
|
|
445
|
-
tools_display = "Default"
|
|
446
|
-
|
|
447
|
-
# Truncate description for table display
|
|
448
|
-
desc_display = (
|
|
449
|
-
agent.description[:42] + "..."
|
|
450
|
-
if len(agent.description) > 42
|
|
451
|
-
else agent.description
|
|
452
|
-
)
|
|
347
|
+
def _display_agents_with_pending_states(self, agents: List[AgentConfig]) -> None:
|
|
348
|
+
"""Display agents table with pending state indicators."""
|
|
349
|
+
self.agent_display.display_agents_with_pending_states(agents)
|
|
453
350
|
|
|
454
|
-
|
|
351
|
+
def _toggle_agents_interactive(self, agents: List[AgentConfig]) -> None:
|
|
352
|
+
"""Interactive multi-agent enable/disable with batch save."""
|
|
455
353
|
|
|
456
|
-
|
|
354
|
+
# Initialize pending states from current states
|
|
355
|
+
for agent in agents:
|
|
356
|
+
current_state = self.agent_manager.is_agent_enabled(agent.name)
|
|
357
|
+
self.agent_manager.set_agent_enabled_deferred(agent.name, current_state)
|
|
457
358
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
359
|
+
while True:
|
|
360
|
+
# Display table with pending states
|
|
361
|
+
self._display_agents_with_pending_states(agents)
|
|
362
|
+
|
|
363
|
+
# Show menu
|
|
364
|
+
self.console.print("\n[bold]Toggle Agent Status:[/bold]")
|
|
365
|
+
text_toggle = Text(" ")
|
|
366
|
+
text_toggle.append("[t]", style="bold blue")
|
|
367
|
+
text_toggle.append(" Enter agent IDs to toggle (e.g., '1,3,5' or '1-4')")
|
|
368
|
+
self.console.print(text_toggle)
|
|
369
|
+
|
|
370
|
+
text_all = Text(" ")
|
|
371
|
+
text_all.append("[a]", style="bold blue")
|
|
372
|
+
text_all.append(" Enable all agents")
|
|
373
|
+
self.console.print(text_all)
|
|
374
|
+
|
|
375
|
+
text_none = Text(" ")
|
|
376
|
+
text_none.append("[n]", style="bold blue")
|
|
377
|
+
text_none.append(" Disable all agents")
|
|
378
|
+
self.console.print(text_none)
|
|
379
|
+
|
|
380
|
+
text_save = Text(" ")
|
|
381
|
+
text_save.append("[s]", style="bold green")
|
|
382
|
+
text_save.append(" Save changes and return")
|
|
383
|
+
self.console.print(text_save)
|
|
384
|
+
|
|
385
|
+
text_cancel = Text(" ")
|
|
386
|
+
text_cancel.append("[c]", style="bold magenta")
|
|
387
|
+
text_cancel.append(" Cancel (discard changes)")
|
|
388
|
+
self.console.print(text_cancel)
|
|
389
|
+
|
|
390
|
+
choice = (
|
|
391
|
+
Prompt.ask("[bold blue]Select an option[/bold blue]", default="s")
|
|
392
|
+
.strip()
|
|
393
|
+
.lower()
|
|
394
|
+
)
|
|
461
395
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
self.
|
|
466
|
-
self.console.print("[green]All agents enabled successfully![/green]")
|
|
467
|
-
else:
|
|
468
|
-
try:
|
|
469
|
-
idx = int(agent_id) - 1
|
|
470
|
-
if 0 <= idx < len(agents):
|
|
471
|
-
agent = agents[idx]
|
|
472
|
-
self.agent_manager.set_agent_enabled(agent.name, True)
|
|
473
|
-
self.console.print(
|
|
474
|
-
f"[green]Agent '{agent.name}' enabled successfully![/green]"
|
|
475
|
-
)
|
|
396
|
+
if choice == "s":
|
|
397
|
+
if self.agent_manager.has_pending_changes():
|
|
398
|
+
self.agent_manager.commit_deferred_changes()
|
|
399
|
+
self.console.print("[green]✓ Changes saved successfully![/green]")
|
|
476
400
|
else:
|
|
477
|
-
self.console.print("[
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
if agent_id.lower() == "all":
|
|
488
|
-
if Confirm.ask("[yellow]Disable ALL agents?[/yellow]"):
|
|
401
|
+
self.console.print("[yellow]No changes to save.[/yellow]")
|
|
402
|
+
Prompt.ask("Press Enter to continue")
|
|
403
|
+
break
|
|
404
|
+
if choice == "c":
|
|
405
|
+
self.agent_manager.discard_deferred_changes()
|
|
406
|
+
self.console.print("[yellow]Changes discarded.[/yellow]")
|
|
407
|
+
Prompt.ask("Press Enter to continue")
|
|
408
|
+
break
|
|
409
|
+
if choice == "a":
|
|
489
410
|
for agent in agents:
|
|
490
|
-
self.agent_manager.
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
Prompt.ask("Press Enter to continue")
|
|
411
|
+
self.agent_manager.set_agent_enabled_deferred(agent.name, True)
|
|
412
|
+
elif choice == "n":
|
|
413
|
+
for agent in agents:
|
|
414
|
+
self.agent_manager.set_agent_enabled_deferred(agent.name, False)
|
|
415
|
+
elif choice == "t" or choice.replace(",", "").replace("-", "").isdigit():
|
|
416
|
+
selected_ids = self._parse_id_selection(
|
|
417
|
+
choice if choice != "t" else Prompt.ask("Enter IDs"), len(agents)
|
|
418
|
+
)
|
|
419
|
+
for idx in selected_ids:
|
|
420
|
+
if 1 <= idx <= len(agents):
|
|
421
|
+
agent = agents[idx - 1]
|
|
422
|
+
current = self.agent_manager.get_pending_state(agent.name)
|
|
423
|
+
self.agent_manager.set_agent_enabled_deferred(
|
|
424
|
+
agent.name, not current
|
|
425
|
+
)
|
|
507
426
|
|
|
508
427
|
def _customize_agent_template(self, agents: List[AgentConfig]) -> None:
|
|
509
428
|
"""Customize agent JSON template."""
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
try:
|
|
513
|
-
idx = int(agent_id) - 1
|
|
514
|
-
if 0 <= idx < len(agents):
|
|
515
|
-
agent = agents[idx]
|
|
516
|
-
self._edit_agent_template(agent)
|
|
517
|
-
else:
|
|
518
|
-
self.console.print("[red]Invalid agent ID.[/red]")
|
|
519
|
-
Prompt.ask("Press Enter to continue")
|
|
520
|
-
except ValueError:
|
|
521
|
-
self.console.print("[red]Invalid input. Please enter a number.[/red]")
|
|
522
|
-
Prompt.ask("Press Enter to continue")
|
|
429
|
+
self.template_editor.customize_agent_template(agents)
|
|
523
430
|
|
|
524
431
|
def _edit_agent_template(self, agent: AgentConfig) -> None:
|
|
525
432
|
"""Edit an agent's JSON template."""
|
|
526
|
-
self.
|
|
527
|
-
self.console.print(f"[bold]Editing template for: {agent.name}[/bold]\n")
|
|
528
|
-
|
|
529
|
-
# Get current template
|
|
530
|
-
template_path = self._get_agent_template_path(agent.name)
|
|
531
|
-
|
|
532
|
-
if template_path.exists():
|
|
533
|
-
with open(template_path) as f:
|
|
534
|
-
template = json.load(f)
|
|
535
|
-
is_system = str(template_path).startswith(
|
|
536
|
-
str(self.agent_manager.templates_dir)
|
|
537
|
-
)
|
|
538
|
-
else:
|
|
539
|
-
# Create a minimal template structure based on system templates
|
|
540
|
-
template = {
|
|
541
|
-
"schema_version": "1.2.0",
|
|
542
|
-
"agent_id": agent.name,
|
|
543
|
-
"agent_version": "1.0.0",
|
|
544
|
-
"agent_type": agent.name.replace("-", "_"),
|
|
545
|
-
"metadata": {
|
|
546
|
-
"name": agent.name.replace("-", " ").title() + " Agent",
|
|
547
|
-
"description": agent.description,
|
|
548
|
-
"tags": [agent.name],
|
|
549
|
-
"author": "Custom",
|
|
550
|
-
"created_at": "",
|
|
551
|
-
"updated_at": "",
|
|
552
|
-
},
|
|
553
|
-
"capabilities": {
|
|
554
|
-
"model": "opus",
|
|
555
|
-
"tools": (
|
|
556
|
-
agent.dependencies
|
|
557
|
-
if agent.dependencies
|
|
558
|
-
else ["Read", "Write", "Edit", "Bash"]
|
|
559
|
-
),
|
|
560
|
-
},
|
|
561
|
-
"instructions": {
|
|
562
|
-
"base_template": "BASE_AGENT_TEMPLATE.md",
|
|
563
|
-
"custom_instructions": "",
|
|
564
|
-
},
|
|
565
|
-
}
|
|
566
|
-
is_system = False
|
|
567
|
-
|
|
568
|
-
# Display current template
|
|
569
|
-
if is_system:
|
|
570
|
-
self.console.print(
|
|
571
|
-
"[yellow]Viewing SYSTEM template (read-only). Customization will create a local copy.[/yellow]\n"
|
|
572
|
-
)
|
|
573
|
-
|
|
574
|
-
self.console.print("[bold]Current Template:[/bold]")
|
|
575
|
-
# Truncate for display if too large
|
|
576
|
-
display_template = template.copy()
|
|
577
|
-
if (
|
|
578
|
-
"instructions" in display_template
|
|
579
|
-
and isinstance(display_template["instructions"], dict)
|
|
580
|
-
and (
|
|
581
|
-
"custom_instructions" in display_template["instructions"]
|
|
582
|
-
and len(str(display_template["instructions"]["custom_instructions"]))
|
|
583
|
-
> 200
|
|
584
|
-
)
|
|
585
|
-
):
|
|
586
|
-
display_template["instructions"]["custom_instructions"] = (
|
|
587
|
-
display_template["instructions"]["custom_instructions"][:200] + "..."
|
|
588
|
-
)
|
|
589
|
-
|
|
590
|
-
json_str = json.dumps(display_template, indent=2)
|
|
591
|
-
# Limit display to first 50 lines for readability
|
|
592
|
-
lines = json_str.split("\n")
|
|
593
|
-
if len(lines) > 50:
|
|
594
|
-
json_str = "\n".join(lines[:50]) + "\n... (truncated for display)"
|
|
595
|
-
|
|
596
|
-
syntax = Syntax(json_str, "json", theme="monokai", line_numbers=True)
|
|
597
|
-
self.console.print(syntax)
|
|
598
|
-
self.console.print()
|
|
599
|
-
|
|
600
|
-
# Editing options
|
|
601
|
-
self.console.print("[bold]Editing Options:[/bold]")
|
|
602
|
-
if not is_system:
|
|
603
|
-
self.console.print(" [cyan][1][/cyan] Edit in external editor")
|
|
604
|
-
self.console.print(" [cyan][2][/cyan] Add/modify a field")
|
|
605
|
-
self.console.print(" [cyan][3][/cyan] Remove a field")
|
|
606
|
-
self.console.print(" [cyan][4][/cyan] Reset to defaults")
|
|
607
|
-
else:
|
|
608
|
-
self.console.print(" [cyan][1][/cyan] Create customized copy")
|
|
609
|
-
self.console.print(" [cyan][2][/cyan] View full template")
|
|
610
|
-
self.console.print(" [cyan][b][/cyan] Back")
|
|
611
|
-
self.console.print()
|
|
612
|
-
|
|
613
|
-
choice = Prompt.ask("[bold cyan]Select an option[/bold cyan]", default="b")
|
|
614
|
-
|
|
615
|
-
if is_system:
|
|
616
|
-
if choice == "1":
|
|
617
|
-
# Create a customized copy
|
|
618
|
-
self._create_custom_template_copy(agent, template)
|
|
619
|
-
elif choice == "2":
|
|
620
|
-
# View full template
|
|
621
|
-
self._view_full_template(template)
|
|
622
|
-
elif choice == "1":
|
|
623
|
-
self._edit_in_external_editor(template_path, template)
|
|
624
|
-
elif choice == "2":
|
|
625
|
-
self._modify_template_field(template, template_path)
|
|
626
|
-
elif choice == "3":
|
|
627
|
-
self._remove_template_field(template, template_path)
|
|
628
|
-
elif choice == "4":
|
|
629
|
-
self._reset_template(agent, template_path)
|
|
630
|
-
|
|
631
|
-
if choice != "b":
|
|
632
|
-
Prompt.ask("Press Enter to continue")
|
|
433
|
+
self.template_editor.edit_agent_template(agent)
|
|
633
434
|
|
|
634
435
|
def _get_agent_template_path(self, agent_name: str) -> Path:
|
|
635
436
|
"""Get the path to an agent's template file."""
|
|
636
|
-
|
|
637
|
-
if self.current_scope == "project":
|
|
638
|
-
config_dir = self.project_dir / ".claude-mpm" / "agents"
|
|
639
|
-
else:
|
|
640
|
-
config_dir = Path.home() / ".claude-mpm" / "agents"
|
|
641
|
-
|
|
642
|
-
config_dir.mkdir(parents=True, exist_ok=True)
|
|
643
|
-
custom_template = config_dir / f"{agent_name}.json"
|
|
644
|
-
|
|
645
|
-
# If custom template exists, return it
|
|
646
|
-
if custom_template.exists():
|
|
647
|
-
return custom_template
|
|
648
|
-
|
|
649
|
-
# Otherwise, look for the system template
|
|
650
|
-
# Handle various naming conventions
|
|
651
|
-
possible_names = [
|
|
652
|
-
f"{agent_name}.json",
|
|
653
|
-
f"{agent_name.replace('-', '_')}.json",
|
|
654
|
-
f"{agent_name}-agent.json",
|
|
655
|
-
f"{agent_name.replace('-', '_')}_agent.json",
|
|
656
|
-
]
|
|
657
|
-
|
|
658
|
-
for name in possible_names:
|
|
659
|
-
system_template = self.agent_manager.templates_dir / name
|
|
660
|
-
if system_template.exists():
|
|
661
|
-
return system_template
|
|
662
|
-
|
|
663
|
-
# Return the custom template path for new templates
|
|
664
|
-
return custom_template
|
|
437
|
+
return self.template_editor.get_agent_template_path(agent_name)
|
|
665
438
|
|
|
666
439
|
def _edit_in_external_editor(self, template_path: Path, template: Dict) -> None:
|
|
667
440
|
"""Open template in external editor."""
|
|
668
|
-
|
|
669
|
-
import tempfile
|
|
670
|
-
|
|
671
|
-
# Write current template to temp file
|
|
672
|
-
with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
|
|
673
|
-
json.dump(template, f, indent=2)
|
|
674
|
-
temp_path = f.name
|
|
675
|
-
|
|
676
|
-
# Get editor from environment
|
|
677
|
-
editor = os.environ.get("EDITOR", "nano")
|
|
678
|
-
|
|
679
|
-
try:
|
|
680
|
-
# Open in editor
|
|
681
|
-
subprocess.call([editor, temp_path])
|
|
682
|
-
|
|
683
|
-
# Read back the edited content
|
|
684
|
-
with open(temp_path) as f:
|
|
685
|
-
new_template = json.load(f)
|
|
686
|
-
|
|
687
|
-
# Save to actual template path
|
|
688
|
-
with open(template_path, "w") as f:
|
|
689
|
-
json.dump(new_template, f, indent=2)
|
|
690
|
-
|
|
691
|
-
self.console.print("[green]Template updated successfully![/green]")
|
|
692
|
-
|
|
693
|
-
except Exception as e:
|
|
694
|
-
self.console.print(f"[red]Error editing template: {e}[/red]")
|
|
695
|
-
finally:
|
|
696
|
-
# Clean up temp file
|
|
697
|
-
Path(temp_path).unlink(missing_ok=True)
|
|
441
|
+
self.template_editor.edit_in_external_editor(template_path, template)
|
|
698
442
|
|
|
699
443
|
def _modify_template_field(self, template: Dict, template_path: Path) -> None:
|
|
700
444
|
"""Add or modify a field in the template."""
|
|
701
|
-
|
|
702
|
-
"Enter field name (use dot notation for nested, e.g., 'config.timeout')"
|
|
703
|
-
)
|
|
704
|
-
field_value = Prompt.ask("Enter field value (JSON format)")
|
|
705
|
-
|
|
706
|
-
try:
|
|
707
|
-
# Parse the value as JSON
|
|
708
|
-
value = json.loads(field_value)
|
|
709
|
-
|
|
710
|
-
# Navigate to the field location
|
|
711
|
-
parts = field_name.split(".")
|
|
712
|
-
current = template
|
|
713
|
-
|
|
714
|
-
for part in parts[:-1]:
|
|
715
|
-
if part not in current:
|
|
716
|
-
current[part] = {}
|
|
717
|
-
current = current[part]
|
|
718
|
-
|
|
719
|
-
# Set the value
|
|
720
|
-
current[parts[-1]] = value
|
|
721
|
-
|
|
722
|
-
# Save the template
|
|
723
|
-
with open(template_path, "w") as f:
|
|
724
|
-
json.dump(template, f, indent=2)
|
|
725
|
-
|
|
726
|
-
self.console.print(
|
|
727
|
-
f"[green]Field '{field_name}' updated successfully![/green]"
|
|
728
|
-
)
|
|
729
|
-
|
|
730
|
-
except json.JSONDecodeError:
|
|
731
|
-
self.console.print("[red]Invalid JSON value. Please try again.[/red]")
|
|
732
|
-
except Exception as e:
|
|
733
|
-
self.console.print(f"[red]Error updating field: {e}[/red]")
|
|
445
|
+
self.template_editor.modify_template_field(template, template_path)
|
|
734
446
|
|
|
735
447
|
def _remove_template_field(self, template: Dict, template_path: Path) -> None:
|
|
736
448
|
"""Remove a field from the template."""
|
|
737
|
-
|
|
738
|
-
"Enter field name to remove (use dot notation for nested)"
|
|
739
|
-
)
|
|
740
|
-
|
|
741
|
-
try:
|
|
742
|
-
# Navigate to the field location
|
|
743
|
-
parts = field_name.split(".")
|
|
744
|
-
current = template
|
|
745
|
-
|
|
746
|
-
for part in parts[:-1]:
|
|
747
|
-
if part not in current:
|
|
748
|
-
raise KeyError(f"Field '{field_name}' not found")
|
|
749
|
-
current = current[part]
|
|
750
|
-
|
|
751
|
-
# Remove the field
|
|
752
|
-
if parts[-1] in current:
|
|
753
|
-
del current[parts[-1]]
|
|
754
|
-
|
|
755
|
-
# Save the template
|
|
756
|
-
with open(template_path, "w") as f:
|
|
757
|
-
json.dump(template, f, indent=2)
|
|
758
|
-
|
|
759
|
-
self.console.print(
|
|
760
|
-
f"[green]Field '{field_name}' removed successfully![/green]"
|
|
761
|
-
)
|
|
762
|
-
else:
|
|
763
|
-
self.console.print(f"[red]Field '{field_name}' not found.[/red]")
|
|
764
|
-
|
|
765
|
-
except Exception as e:
|
|
766
|
-
self.console.print(f"[red]Error removing field: {e}[/red]")
|
|
449
|
+
self.template_editor.remove_template_field(template, template_path)
|
|
767
450
|
|
|
768
451
|
def _reset_template(self, agent: AgentConfig, template_path: Path) -> None:
|
|
769
452
|
"""Reset template to defaults."""
|
|
770
|
-
|
|
771
|
-
# Remove custom template file
|
|
772
|
-
template_path.unlink(missing_ok=True)
|
|
773
|
-
self.console.print(
|
|
774
|
-
f"[green]Template for '{agent.name}' reset to defaults![/green]"
|
|
775
|
-
)
|
|
453
|
+
self.template_editor.reset_template(agent, template_path)
|
|
776
454
|
|
|
777
455
|
def _create_custom_template_copy(self, agent: AgentConfig, template: Dict) -> None:
|
|
778
456
|
"""Create a customized copy of a system template."""
|
|
779
|
-
|
|
780
|
-
config_dir = self.project_dir / ".claude-mpm" / "agents"
|
|
781
|
-
else:
|
|
782
|
-
config_dir = Path.home() / ".claude-mpm" / "agents"
|
|
457
|
+
self.template_editor.create_custom_template_copy(agent, template)
|
|
783
458
|
|
|
784
|
-
|
|
785
|
-
|
|
459
|
+
def _view_full_template(self, template: Dict) -> None:
|
|
460
|
+
"""View the full template without truncation."""
|
|
461
|
+
self.template_editor.view_full_template(template)
|
|
786
462
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
)
|
|
790
|
-
return
|
|
463
|
+
def _reset_agent_defaults(self, agents: List[AgentConfig]) -> None:
|
|
464
|
+
"""Reset an agent to default enabled state and remove custom template."""
|
|
465
|
+
self.template_editor.reset_agent_defaults(agents)
|
|
791
466
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
467
|
+
def _edit_templates(self) -> None:
|
|
468
|
+
"""Template editing interface."""
|
|
469
|
+
self.template_editor.edit_templates_interface()
|
|
795
470
|
|
|
796
|
-
|
|
797
|
-
|
|
471
|
+
def _manage_behaviors(self) -> None:
|
|
472
|
+
"""Behavior file management interface."""
|
|
473
|
+
# Note: BehaviorManager handles its own loop and clears screen
|
|
474
|
+
# but doesn't display our header. We'll need to update BehaviorManager
|
|
475
|
+
# to accept a header callback in the future. For now, just delegate.
|
|
476
|
+
self.behavior_manager.manage_behaviors()
|
|
798
477
|
|
|
799
|
-
def
|
|
800
|
-
"""
|
|
801
|
-
|
|
802
|
-
|
|
478
|
+
def _manage_skills(self) -> None:
|
|
479
|
+
"""Skills management interface."""
|
|
480
|
+
from ...cli.interactive.skills_wizard import SkillsWizard
|
|
481
|
+
from ...skills.skill_manager import get_manager
|
|
803
482
|
|
|
804
|
-
|
|
805
|
-
|
|
483
|
+
wizard = SkillsWizard()
|
|
484
|
+
manager = get_manager()
|
|
806
485
|
|
|
807
|
-
|
|
486
|
+
while True:
|
|
487
|
+
self.console.clear()
|
|
488
|
+
self._display_header()
|
|
808
489
|
|
|
809
|
-
|
|
810
|
-
self.console.print(
|
|
490
|
+
self.console.print("\n[bold]Skills Management Options:[/bold]\n")
|
|
491
|
+
self.console.print(" [1] View Available Skills")
|
|
492
|
+
self.console.print(" [2] Configure Skills for Agents")
|
|
493
|
+
self.console.print(" [3] View Current Skill Mappings")
|
|
494
|
+
self.console.print(" [4] Auto-Link Skills to Agents")
|
|
495
|
+
self.console.print(" [b] Back to Main Menu")
|
|
496
|
+
self.console.print()
|
|
811
497
|
|
|
812
|
-
|
|
813
|
-
"""View detailed information about an agent."""
|
|
814
|
-
agent_id = Prompt.ask("Enter agent ID to view")
|
|
498
|
+
choice = Prompt.ask("[bold blue]Select an option[/bold blue]", default="b")
|
|
815
499
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
500
|
+
if choice == "1":
|
|
501
|
+
# View available skills
|
|
502
|
+
self.console.clear()
|
|
503
|
+
self._display_header()
|
|
504
|
+
wizard.list_available_skills()
|
|
505
|
+
Prompt.ask("\nPress Enter to continue")
|
|
820
506
|
|
|
507
|
+
elif choice == "2":
|
|
508
|
+
# Configure skills interactively
|
|
821
509
|
self.console.clear()
|
|
822
510
|
self._display_header()
|
|
823
511
|
|
|
824
|
-
#
|
|
825
|
-
|
|
826
|
-
|
|
512
|
+
# Get list of enabled agents
|
|
513
|
+
agents = self.agent_manager.discover_agents()
|
|
514
|
+
enabled_agents = [
|
|
515
|
+
a.name
|
|
516
|
+
for a in agents
|
|
517
|
+
if self.agent_manager.get_pending_state(a.name)
|
|
518
|
+
]
|
|
827
519
|
|
|
828
|
-
if
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
520
|
+
if not enabled_agents:
|
|
521
|
+
self.console.print(
|
|
522
|
+
"[yellow]No agents are currently enabled.[/yellow]"
|
|
523
|
+
)
|
|
524
|
+
self.console.print(
|
|
525
|
+
"Please enable agents first in Agent Management."
|
|
526
|
+
)
|
|
527
|
+
Prompt.ask("\nPress Enter to continue")
|
|
528
|
+
continue
|
|
832
529
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
capabilities = template.get("capabilities", {})
|
|
530
|
+
# Run skills wizard
|
|
531
|
+
success, mapping = wizard.run_interactive_selection(enabled_agents)
|
|
836
532
|
|
|
837
|
-
|
|
838
|
-
|
|
533
|
+
if success:
|
|
534
|
+
# Save the configuration
|
|
535
|
+
manager.save_mappings_to_config()
|
|
536
|
+
self.console.print("\n[green]✓ Skills configuration saved![/green]")
|
|
537
|
+
else:
|
|
538
|
+
self.console.print(
|
|
539
|
+
"\n[yellow]Skills configuration cancelled.[/yellow]"
|
|
540
|
+
)
|
|
839
541
|
|
|
840
|
-
|
|
841
|
-
model = capabilities.get("model", "default")
|
|
842
|
-
tools = capabilities.get("tools", [])
|
|
542
|
+
Prompt.ask("\nPress Enter to continue")
|
|
843
543
|
|
|
844
|
-
|
|
845
|
-
|
|
544
|
+
elif choice == "3":
|
|
545
|
+
# View current mappings
|
|
546
|
+
self.console.clear()
|
|
547
|
+
self._display_header()
|
|
846
548
|
|
|
847
|
-
|
|
848
|
-
agent_version = template.get("agent_version", "N/A")
|
|
849
|
-
schema_version = template.get("schema_version", "N/A")
|
|
549
|
+
self.console.print("\n[bold]Current Skill Mappings:[/bold]\n")
|
|
850
550
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
551
|
+
mappings = manager.list_agent_skill_mappings()
|
|
552
|
+
if not mappings:
|
|
553
|
+
self.console.print("[dim]No skill mappings configured yet.[/dim]")
|
|
554
|
+
else:
|
|
555
|
+
from rich.table import Table
|
|
854
556
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
[bold]Tags:[/bold] {', '.join(tags) if tags else 'None'}
|
|
859
|
-
[bold]Tools:[/bold] {', '.join(tools[:5]) if tools else 'None'}{'...' if len(tools) > 5 else ''}
|
|
860
|
-
"""
|
|
861
|
-
except:
|
|
862
|
-
pass
|
|
863
|
-
|
|
864
|
-
# Create detail panel
|
|
865
|
-
detail_text = f"""
|
|
866
|
-
[bold]Name:[/bold] {agent.name}
|
|
867
|
-
[bold]Status:[/bold] {'[green]Enabled[/green]' if self.agent_manager.is_agent_enabled(agent.name) else '[red]Disabled[/red]'}
|
|
868
|
-
[bold]Template Path:[/bold] {template_path}
|
|
869
|
-
[bold]Is System Template:[/bold] {'Yes' if str(template_path).startswith(str(self.agent_manager.templates_dir)) else 'No (Custom)'}
|
|
870
|
-
{extra_info}
|
|
871
|
-
"""
|
|
872
|
-
|
|
873
|
-
panel = Panel(
|
|
874
|
-
detail_text.strip(),
|
|
875
|
-
title=f"[bold]{agent.name} Details[/bold]",
|
|
876
|
-
box=ROUNDED,
|
|
877
|
-
style="cyan",
|
|
878
|
-
)
|
|
557
|
+
table = Table(show_header=True, header_style="bold cyan")
|
|
558
|
+
table.add_column("Agent", style="yellow")
|
|
559
|
+
table.add_column("Skills", style="green")
|
|
879
560
|
|
|
880
|
-
|
|
561
|
+
for agent_id, skills in mappings.items():
|
|
562
|
+
skills_str = (
|
|
563
|
+
", ".join(skills) if skills else "[dim](none)[/dim]"
|
|
564
|
+
)
|
|
565
|
+
table.add_row(agent_id, skills_str)
|
|
881
566
|
|
|
882
|
-
|
|
883
|
-
self.console.print("[red]Invalid agent ID.[/red]")
|
|
567
|
+
self.console.print(table)
|
|
884
568
|
|
|
885
|
-
|
|
886
|
-
self.console.print("[red]Invalid input. Please enter a number.[/red]")
|
|
569
|
+
Prompt.ask("\nPress Enter to continue")
|
|
887
570
|
|
|
888
|
-
|
|
571
|
+
elif choice == "4":
|
|
572
|
+
# Auto-link skills
|
|
573
|
+
self.console.clear()
|
|
574
|
+
self._display_header()
|
|
889
575
|
|
|
890
|
-
|
|
891
|
-
"""Template editing interface."""
|
|
892
|
-
self.console.print("[yellow]Template editing interface - Coming soon![/yellow]")
|
|
893
|
-
Prompt.ask("Press Enter to continue")
|
|
576
|
+
self.console.print("\n[bold]Auto-Linking Skills to Agents...[/bold]\n")
|
|
894
577
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
578
|
+
# Get enabled agents
|
|
579
|
+
agents = self.agent_manager.discover_agents()
|
|
580
|
+
enabled_agents = [
|
|
581
|
+
a.name
|
|
582
|
+
for a in agents
|
|
583
|
+
if self.agent_manager.get_pending_state(a.name)
|
|
584
|
+
]
|
|
900
585
|
|
|
901
|
-
|
|
586
|
+
if not enabled_agents:
|
|
587
|
+
self.console.print(
|
|
588
|
+
"[yellow]No agents are currently enabled.[/yellow]"
|
|
589
|
+
)
|
|
590
|
+
self.console.print(
|
|
591
|
+
"Please enable agents first in Agent Management."
|
|
592
|
+
)
|
|
593
|
+
Prompt.ask("\nPress Enter to continue")
|
|
594
|
+
continue
|
|
902
595
|
|
|
903
|
-
|
|
904
|
-
|
|
596
|
+
# Auto-link
|
|
597
|
+
mapping = wizard._auto_link_skills(enabled_agents)
|
|
905
598
|
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
self.console.print(" [cyan][b][/cyan] Back to main menu")
|
|
913
|
-
self.console.print()
|
|
599
|
+
# Display preview
|
|
600
|
+
self.console.print("Auto-linked skills:\n")
|
|
601
|
+
for agent_id, skills in mapping.items():
|
|
602
|
+
self.console.print(f" [yellow]{agent_id}[/yellow]:")
|
|
603
|
+
for skill in skills:
|
|
604
|
+
self.console.print(f" - {skill}")
|
|
914
605
|
|
|
915
|
-
|
|
606
|
+
# Confirm
|
|
607
|
+
confirm = Confirm.ask("\nApply this configuration?", default=True)
|
|
916
608
|
|
|
917
|
-
|
|
609
|
+
if confirm:
|
|
610
|
+
wizard._apply_skills_configuration(mapping)
|
|
611
|
+
manager.save_mappings_to_config()
|
|
612
|
+
self.console.print("\n[green]✓ Auto-linking complete![/green]")
|
|
613
|
+
else:
|
|
614
|
+
self.console.print("\n[yellow]Auto-linking cancelled.[/yellow]")
|
|
615
|
+
|
|
616
|
+
Prompt.ask("\nPress Enter to continue")
|
|
617
|
+
|
|
618
|
+
elif choice == "b":
|
|
918
619
|
break
|
|
919
|
-
if choice == "1":
|
|
920
|
-
self._edit_identity_config()
|
|
921
|
-
elif choice == "2":
|
|
922
|
-
self._edit_workflow_config()
|
|
923
|
-
elif choice == "3":
|
|
924
|
-
self._import_behavior_file()
|
|
925
|
-
elif choice == "4":
|
|
926
|
-
self._export_behavior_file()
|
|
927
620
|
else:
|
|
928
|
-
self.console.print("[red]Invalid choice.[/red]")
|
|
929
|
-
Prompt.ask("
|
|
621
|
+
self.console.print("[red]Invalid choice. Please try again.[/red]")
|
|
622
|
+
Prompt.ask("\nPress Enter to continue")
|
|
930
623
|
|
|
931
624
|
def _display_behavior_files(self) -> None:
|
|
932
625
|
"""Display current behavior files."""
|
|
933
|
-
|
|
934
|
-
config_dir = self.project_dir / ".claude-mpm" / "behaviors"
|
|
935
|
-
else:
|
|
936
|
-
config_dir = Path.home() / ".claude-mpm" / "behaviors"
|
|
937
|
-
|
|
938
|
-
config_dir.mkdir(parents=True, exist_ok=True)
|
|
939
|
-
|
|
940
|
-
table = Table(title="Behavior Files", box=ROUNDED)
|
|
941
|
-
table.add_column("File", style="cyan", width=30)
|
|
942
|
-
table.add_column("Size", style="dim", width=10)
|
|
943
|
-
table.add_column("Modified", style="white", width=20)
|
|
944
|
-
|
|
945
|
-
identity_file = config_dir / "identity.yaml"
|
|
946
|
-
workflow_file = config_dir / "workflow.yaml"
|
|
947
|
-
|
|
948
|
-
for file_path in [identity_file, workflow_file]:
|
|
949
|
-
if file_path.exists():
|
|
950
|
-
stat = file_path.stat()
|
|
951
|
-
size = f"{stat.st_size} bytes"
|
|
952
|
-
modified = f"{stat.st_mtime:.0f}" # Simplified timestamp
|
|
953
|
-
table.add_row(file_path.name, size, modified)
|
|
954
|
-
else:
|
|
955
|
-
table.add_row(file_path.name, "[dim]Not found[/dim]", "-")
|
|
956
|
-
|
|
957
|
-
self.console.print(table)
|
|
626
|
+
self.behavior_manager.display_behavior_files()
|
|
958
627
|
|
|
959
628
|
def _edit_identity_config(self) -> None:
|
|
960
629
|
"""Edit identity configuration."""
|
|
961
|
-
self.
|
|
962
|
-
"[yellow]Identity configuration editor - Coming soon![/yellow]"
|
|
963
|
-
)
|
|
964
|
-
Prompt.ask("Press Enter to continue")
|
|
630
|
+
self.behavior_manager.edit_identity_config()
|
|
965
631
|
|
|
966
632
|
def _edit_workflow_config(self) -> None:
|
|
967
633
|
"""Edit workflow configuration."""
|
|
968
|
-
self.
|
|
969
|
-
"[yellow]Workflow configuration editor - Coming soon![/yellow]"
|
|
970
|
-
)
|
|
971
|
-
Prompt.ask("Press Enter to continue")
|
|
634
|
+
self.behavior_manager.edit_workflow_config()
|
|
972
635
|
|
|
973
636
|
def _import_behavior_file(self) -> None:
|
|
974
637
|
"""Import a behavior file."""
|
|
975
|
-
|
|
638
|
+
self.behavior_manager.import_behavior_file()
|
|
976
639
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
self.console.print(f"[red]File not found: {file_path}[/red]")
|
|
981
|
-
return
|
|
982
|
-
|
|
983
|
-
# Determine target directory
|
|
984
|
-
if self.current_scope == "project":
|
|
985
|
-
config_dir = self.project_dir / ".claude-mpm" / "behaviors"
|
|
986
|
-
else:
|
|
987
|
-
config_dir = Path.home() / ".claude-mpm" / "behaviors"
|
|
640
|
+
def _export_behavior_file(self) -> None:
|
|
641
|
+
"""Export a behavior file."""
|
|
642
|
+
self.behavior_manager.export_behavior_file()
|
|
988
643
|
|
|
989
|
-
|
|
644
|
+
def _manage_startup_configuration(self) -> bool:
|
|
645
|
+
"""Manage startup configuration for MCP services and agents."""
|
|
646
|
+
return self.startup_manager.manage_startup_configuration()
|
|
990
647
|
|
|
991
|
-
|
|
992
|
-
|
|
648
|
+
def _load_startup_configuration(self, config: Config) -> Dict:
|
|
649
|
+
"""Load current startup configuration from config."""
|
|
650
|
+
return self.startup_manager.load_startup_configuration(config)
|
|
993
651
|
|
|
994
|
-
|
|
995
|
-
|
|
652
|
+
def _display_startup_configuration(self, startup_config: Dict) -> None:
|
|
653
|
+
"""Display current startup configuration in a table."""
|
|
654
|
+
self.startup_manager.display_startup_configuration(startup_config)
|
|
996
655
|
|
|
997
|
-
|
|
656
|
+
def _configure_mcp_services(self, startup_config: Dict, config: Config) -> None:
|
|
657
|
+
"""Configure which MCP services to enable at startup."""
|
|
658
|
+
self.startup_manager.configure_mcp_services(startup_config, config)
|
|
998
659
|
|
|
999
|
-
|
|
1000
|
-
|
|
660
|
+
def _configure_hook_services(self, startup_config: Dict, config: Config) -> None:
|
|
661
|
+
"""Configure which hook services to enable at startup."""
|
|
662
|
+
self.startup_manager.configure_hook_services(startup_config, config)
|
|
1001
663
|
|
|
1002
|
-
|
|
664
|
+
def _configure_system_agents(self, startup_config: Dict, config: Config) -> None:
|
|
665
|
+
"""Configure which system agents to deploy at startup."""
|
|
666
|
+
self.startup_manager.configure_system_agents(startup_config, config)
|
|
1003
667
|
|
|
1004
|
-
def
|
|
1005
|
-
"""
|
|
1006
|
-
|
|
1007
|
-
|
|
668
|
+
def _parse_id_selection(self, selection: str, max_id: int) -> List[int]:
|
|
669
|
+
"""Parse ID selection string (e.g., '1,3,5' or '1-4')."""
|
|
670
|
+
return parse_id_selection(selection, max_id)
|
|
671
|
+
|
|
672
|
+
def _enable_all_services(self, startup_config: Dict, config: Config) -> None:
|
|
673
|
+
"""Enable all services and agents."""
|
|
674
|
+
self.startup_manager.enable_all_services(startup_config, config)
|
|
675
|
+
|
|
676
|
+
def _disable_all_services(self, startup_config: Dict, config: Config) -> None:
|
|
677
|
+
"""Disable all services and agents."""
|
|
678
|
+
self.startup_manager.disable_all_services(startup_config, config)
|
|
679
|
+
|
|
680
|
+
def _reset_to_defaults(self, startup_config: Dict, config: Config) -> None:
|
|
681
|
+
"""Reset startup configuration to defaults."""
|
|
682
|
+
self.startup_manager.reset_to_defaults(startup_config, config)
|
|
683
|
+
|
|
684
|
+
def _save_startup_configuration(self, startup_config: Dict, config: Config) -> bool:
|
|
685
|
+
"""Save startup configuration to config file and return whether to proceed to startup."""
|
|
686
|
+
return self.startup_manager.save_startup_configuration(startup_config, config)
|
|
687
|
+
|
|
688
|
+
def _save_all_configuration(self) -> bool:
|
|
689
|
+
"""Save all configuration changes across all contexts."""
|
|
690
|
+
return self.startup_manager.save_all_configuration()
|
|
691
|
+
|
|
692
|
+
def _launch_claude_mpm(self) -> None:
|
|
693
|
+
"""Launch Claude MPM run command, replacing current process."""
|
|
694
|
+
self.navigation.launch_claude_mpm()
|
|
1008
695
|
|
|
1009
696
|
def _switch_scope(self) -> None:
|
|
1010
697
|
"""Switch between project and user scope."""
|
|
1011
|
-
self.
|
|
1012
|
-
|
|
1013
|
-
|
|
698
|
+
self.navigation.switch_scope()
|
|
699
|
+
# Sync scope back from navigation
|
|
700
|
+
self.current_scope = self.navigation.current_scope
|
|
1014
701
|
|
|
1015
702
|
def _show_version_info_interactive(self) -> None:
|
|
1016
703
|
"""Show version information in interactive mode."""
|
|
1017
|
-
self.
|
|
1018
|
-
self._display_header()
|
|
1019
|
-
|
|
1020
|
-
# Get version information
|
|
1021
|
-
mpm_version = self.version_service.get_version()
|
|
1022
|
-
build_number = self.version_service.get_build_number()
|
|
1023
|
-
|
|
1024
|
-
# Try to get Claude Code version using the installer's method
|
|
1025
|
-
claude_version = "Unknown"
|
|
1026
|
-
try:
|
|
1027
|
-
from ...hooks.claude_hooks.installer import HookInstaller
|
|
1028
|
-
|
|
1029
|
-
installer = HookInstaller()
|
|
1030
|
-
detected_version = installer.get_claude_version()
|
|
1031
|
-
if detected_version:
|
|
1032
|
-
is_compatible, _ = installer.is_version_compatible()
|
|
1033
|
-
claude_version = f"{detected_version} (Claude Code)"
|
|
1034
|
-
if not is_compatible:
|
|
1035
|
-
claude_version += (
|
|
1036
|
-
f" - Monitoring requires {installer.MIN_CLAUDE_VERSION}+"
|
|
1037
|
-
)
|
|
1038
|
-
else:
|
|
1039
|
-
# Fallback to direct subprocess call
|
|
1040
|
-
import subprocess
|
|
1041
|
-
|
|
1042
|
-
result = subprocess.run(
|
|
1043
|
-
["claude", "--version"],
|
|
1044
|
-
capture_output=True,
|
|
1045
|
-
text=True,
|
|
1046
|
-
timeout=5,
|
|
1047
|
-
check=False,
|
|
1048
|
-
)
|
|
1049
|
-
if result.returncode == 0:
|
|
1050
|
-
claude_version = result.stdout.strip()
|
|
1051
|
-
except:
|
|
1052
|
-
pass
|
|
1053
|
-
|
|
1054
|
-
# Create version panel
|
|
1055
|
-
version_text = f"""
|
|
1056
|
-
[bold cyan]Claude MPM[/bold cyan]
|
|
1057
|
-
Version: {mpm_version}
|
|
1058
|
-
Build: {build_number}
|
|
1059
|
-
|
|
1060
|
-
[bold cyan]Claude Code[/bold cyan]
|
|
1061
|
-
Version: {claude_version}
|
|
1062
|
-
|
|
1063
|
-
[bold cyan]Python[/bold cyan]
|
|
1064
|
-
Version: {sys.version.split()[0]}
|
|
1065
|
-
|
|
1066
|
-
[bold cyan]Configuration[/bold cyan]
|
|
1067
|
-
Scope: {self.current_scope}
|
|
1068
|
-
Directory: {self.project_dir}
|
|
1069
|
-
"""
|
|
1070
|
-
|
|
1071
|
-
panel = Panel(
|
|
1072
|
-
version_text.strip(),
|
|
1073
|
-
title="[bold]Version Information[/bold]",
|
|
1074
|
-
box=ROUNDED,
|
|
1075
|
-
style="green",
|
|
1076
|
-
)
|
|
1077
|
-
|
|
1078
|
-
self.console.print(panel)
|
|
1079
|
-
Prompt.ask("\nPress Enter to continue")
|
|
704
|
+
self.persistence.show_version_info_interactive()
|
|
1080
705
|
|
|
1081
706
|
# Non-interactive command methods
|
|
1082
707
|
|
|
@@ -1118,261 +743,33 @@ Directory: {self.project_dir}
|
|
|
1118
743
|
|
|
1119
744
|
def _export_config(self, file_path: str) -> CommandResult:
|
|
1120
745
|
"""Export configuration to a file."""
|
|
1121
|
-
|
|
1122
|
-
# Gather all configuration
|
|
1123
|
-
config_data = {"scope": self.current_scope, "agents": {}, "behaviors": {}}
|
|
1124
|
-
|
|
1125
|
-
# Get agent states
|
|
1126
|
-
agents = self.agent_manager.discover_agents()
|
|
1127
|
-
for agent in agents:
|
|
1128
|
-
config_data["agents"][agent.name] = {
|
|
1129
|
-
"enabled": self.agent_manager.is_agent_enabled(agent.name),
|
|
1130
|
-
"template_path": str(self._get_agent_template_path(agent.name)),
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
# Write to file
|
|
1134
|
-
output_path = Path(file_path)
|
|
1135
|
-
with open(output_path, "w") as f:
|
|
1136
|
-
json.dump(config_data, f, indent=2)
|
|
1137
|
-
|
|
1138
|
-
return CommandResult.success_result(
|
|
1139
|
-
f"Configuration exported to {output_path}"
|
|
1140
|
-
)
|
|
1141
|
-
|
|
1142
|
-
except Exception as e:
|
|
1143
|
-
return CommandResult.error_result(f"Failed to export configuration: {e}")
|
|
746
|
+
return self.persistence.export_config(file_path)
|
|
1144
747
|
|
|
1145
748
|
def _import_config(self, file_path: str) -> CommandResult:
|
|
1146
749
|
"""Import configuration from a file."""
|
|
1147
|
-
|
|
1148
|
-
input_path = Path(file_path)
|
|
1149
|
-
if not input_path.exists():
|
|
1150
|
-
return CommandResult.error_result(f"File not found: {file_path}")
|
|
1151
|
-
|
|
1152
|
-
with open(input_path) as f:
|
|
1153
|
-
config_data = json.load(f)
|
|
1154
|
-
|
|
1155
|
-
# Apply agent states
|
|
1156
|
-
if "agents" in config_data:
|
|
1157
|
-
for agent_name, agent_config in config_data["agents"].items():
|
|
1158
|
-
if "enabled" in agent_config:
|
|
1159
|
-
self.agent_manager.set_agent_enabled(
|
|
1160
|
-
agent_name, agent_config["enabled"]
|
|
1161
|
-
)
|
|
1162
|
-
|
|
1163
|
-
return CommandResult.success_result(
|
|
1164
|
-
f"Configuration imported from {input_path}"
|
|
1165
|
-
)
|
|
1166
|
-
|
|
1167
|
-
except Exception as e:
|
|
1168
|
-
return CommandResult.error_result(f"Failed to import configuration: {e}")
|
|
750
|
+
return self.persistence.import_config(file_path)
|
|
1169
751
|
|
|
1170
752
|
def _show_version_info(self) -> CommandResult:
|
|
1171
753
|
"""Show version information in non-interactive mode."""
|
|
1172
|
-
|
|
1173
|
-
build_number = self.version_service.get_build_number()
|
|
1174
|
-
|
|
1175
|
-
data = {
|
|
1176
|
-
"mpm_version": mpm_version,
|
|
1177
|
-
"build_number": build_number,
|
|
1178
|
-
"python_version": sys.version.split()[0],
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
# Try to get Claude version
|
|
1182
|
-
try:
|
|
1183
|
-
import subprocess
|
|
1184
|
-
|
|
1185
|
-
result = subprocess.run(
|
|
1186
|
-
["claude", "--version"],
|
|
1187
|
-
capture_output=True,
|
|
1188
|
-
text=True,
|
|
1189
|
-
timeout=5,
|
|
1190
|
-
check=False,
|
|
1191
|
-
)
|
|
1192
|
-
if result.returncode == 0:
|
|
1193
|
-
data["claude_version"] = result.stdout.strip()
|
|
1194
|
-
except:
|
|
1195
|
-
data["claude_version"] = "Unknown"
|
|
1196
|
-
|
|
1197
|
-
# Print formatted output
|
|
1198
|
-
self.console.print(
|
|
1199
|
-
f"[bold]Claude MPM:[/bold] {mpm_version} (build {build_number})"
|
|
1200
|
-
)
|
|
1201
|
-
self.console.print(
|
|
1202
|
-
f"[bold]Claude Code:[/bold] {data.get('claude_version', 'Unknown')}"
|
|
1203
|
-
)
|
|
1204
|
-
self.console.print(f"[bold]Python:[/bold] {data['python_version']}")
|
|
1205
|
-
|
|
1206
|
-
return CommandResult.success_result("Version information displayed", data=data)
|
|
754
|
+
return self.persistence.show_version_info()
|
|
1207
755
|
|
|
1208
756
|
def _install_hooks(self, force: bool = False) -> CommandResult:
|
|
1209
757
|
"""Install Claude MPM hooks for Claude Code integration."""
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
installer = HookInstaller()
|
|
1214
|
-
|
|
1215
|
-
# Check Claude Code version compatibility first
|
|
1216
|
-
is_compatible, version_message = installer.is_version_compatible()
|
|
1217
|
-
self.console.print("[cyan]Checking Claude Code version...[/cyan]")
|
|
1218
|
-
self.console.print(version_message)
|
|
1219
|
-
|
|
1220
|
-
if not is_compatible:
|
|
1221
|
-
self.console.print(
|
|
1222
|
-
"\n[yellow]⚠ Hook monitoring is not available for your Claude Code version.[/yellow]"
|
|
1223
|
-
)
|
|
1224
|
-
self.console.print(
|
|
1225
|
-
"The dashboard and other features will work without real-time monitoring."
|
|
1226
|
-
)
|
|
1227
|
-
self.console.print(
|
|
1228
|
-
f"\n[dim]To enable monitoring, upgrade Claude Code to version {installer.MIN_CLAUDE_VERSION} or higher.[/dim]"
|
|
1229
|
-
)
|
|
1230
|
-
return CommandResult.success_result(
|
|
1231
|
-
"Version incompatible with hook monitoring",
|
|
1232
|
-
data={"compatible": False, "message": version_message},
|
|
1233
|
-
)
|
|
1234
|
-
|
|
1235
|
-
# Check current status
|
|
1236
|
-
status = installer.get_status()
|
|
1237
|
-
if status["installed"] and not force:
|
|
1238
|
-
self.console.print("[yellow]Hooks are already installed.[/yellow]")
|
|
1239
|
-
self.console.print("Use --force to reinstall.")
|
|
1240
|
-
|
|
1241
|
-
if not status["valid"]:
|
|
1242
|
-
self.console.print("\n[red]However, there are issues:[/red]")
|
|
1243
|
-
for issue in status["issues"]:
|
|
1244
|
-
self.console.print(f" - {issue}")
|
|
1245
|
-
|
|
1246
|
-
return CommandResult.success_result(
|
|
1247
|
-
"Hooks already installed", data=status
|
|
1248
|
-
)
|
|
1249
|
-
|
|
1250
|
-
# Install hooks
|
|
1251
|
-
self.console.print("[cyan]Installing Claude MPM hooks...[/cyan]")
|
|
1252
|
-
success = installer.install_hooks(force=force)
|
|
1253
|
-
|
|
1254
|
-
if success:
|
|
1255
|
-
self.console.print("[green]✓ Hooks installed successfully![/green]")
|
|
1256
|
-
self.console.print("\nYou can now use /mpm commands in Claude Code:")
|
|
1257
|
-
self.console.print(" /mpm - Show help")
|
|
1258
|
-
self.console.print(" /mpm status - Show claude-mpm status")
|
|
1259
|
-
|
|
1260
|
-
# Verify installation
|
|
1261
|
-
is_valid, issues = installer.verify_hooks()
|
|
1262
|
-
if not is_valid:
|
|
1263
|
-
self.console.print(
|
|
1264
|
-
"\n[yellow]Warning: Installation completed but verification found issues:[/yellow]"
|
|
1265
|
-
)
|
|
1266
|
-
for issue in issues:
|
|
1267
|
-
self.console.print(f" - {issue}")
|
|
1268
|
-
|
|
1269
|
-
return CommandResult.success_result("Hooks installed successfully")
|
|
1270
|
-
self.console.print("[red]✗ Hook installation failed[/red]")
|
|
1271
|
-
return CommandResult.error_result("Hook installation failed")
|
|
1272
|
-
|
|
1273
|
-
except ImportError:
|
|
1274
|
-
self.console.print("[red]Error: HookInstaller module not found[/red]")
|
|
1275
|
-
self.console.print("Please ensure claude-mpm is properly installed.")
|
|
1276
|
-
return CommandResult.error_result("HookInstaller module not found")
|
|
1277
|
-
except Exception as e:
|
|
1278
|
-
self.logger.error(f"Hook installation error: {e}", exc_info=True)
|
|
1279
|
-
return CommandResult.error_result(f"Hook installation failed: {e}")
|
|
758
|
+
# Share logger with hook manager for consistent error logging
|
|
759
|
+
self.hook_manager.logger = self.logger
|
|
760
|
+
return self.hook_manager.install_hooks(force=force)
|
|
1280
761
|
|
|
1281
762
|
def _verify_hooks(self) -> CommandResult:
|
|
1282
763
|
"""Verify that Claude MPM hooks are properly installed."""
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
installer = HookInstaller()
|
|
1287
|
-
status = installer.get_status()
|
|
1288
|
-
|
|
1289
|
-
self.console.print("[bold]Hook Installation Status[/bold]\n")
|
|
1290
|
-
|
|
1291
|
-
# Show Claude Code version and compatibility
|
|
1292
|
-
if status.get("claude_version"):
|
|
1293
|
-
self.console.print(f"Claude Code Version: {status['claude_version']}")
|
|
1294
|
-
if status.get("version_compatible"):
|
|
1295
|
-
self.console.print(
|
|
1296
|
-
"[green]✓[/green] Version compatible with hook monitoring"
|
|
1297
|
-
)
|
|
1298
|
-
else:
|
|
1299
|
-
self.console.print(
|
|
1300
|
-
f"[yellow]⚠[/yellow] {status.get('version_message', 'Version incompatible')}"
|
|
1301
|
-
)
|
|
1302
|
-
self.console.print()
|
|
1303
|
-
else:
|
|
1304
|
-
self.console.print(
|
|
1305
|
-
"[yellow]Claude Code version could not be detected[/yellow]"
|
|
1306
|
-
)
|
|
1307
|
-
self.console.print()
|
|
1308
|
-
|
|
1309
|
-
if status["installed"]:
|
|
1310
|
-
self.console.print(
|
|
1311
|
-
f"[green]✓[/green] Hooks installed at: {status['hook_script']}"
|
|
1312
|
-
)
|
|
1313
|
-
else:
|
|
1314
|
-
self.console.print("[red]✗[/red] Hooks not installed")
|
|
1315
|
-
|
|
1316
|
-
if status["settings_file"]:
|
|
1317
|
-
self.console.print(
|
|
1318
|
-
f"[green]✓[/green] Settings file: {status['settings_file']}"
|
|
1319
|
-
)
|
|
1320
|
-
else:
|
|
1321
|
-
self.console.print("[red]✗[/red] Settings file not found")
|
|
1322
|
-
|
|
1323
|
-
if status.get("configured_events"):
|
|
1324
|
-
self.console.print(
|
|
1325
|
-
f"[green]✓[/green] Configured events: {', '.join(status['configured_events'])}"
|
|
1326
|
-
)
|
|
1327
|
-
else:
|
|
1328
|
-
self.console.print("[red]✗[/red] No events configured")
|
|
1329
|
-
|
|
1330
|
-
if status["valid"]:
|
|
1331
|
-
self.console.print("\n[green]All checks passed![/green]")
|
|
1332
|
-
else:
|
|
1333
|
-
self.console.print("\n[red]Issues found:[/red]")
|
|
1334
|
-
for issue in status["issues"]:
|
|
1335
|
-
self.console.print(f" - {issue}")
|
|
1336
|
-
|
|
1337
|
-
return CommandResult.success_result(
|
|
1338
|
-
"Hook verification complete", data=status
|
|
1339
|
-
)
|
|
1340
|
-
|
|
1341
|
-
except ImportError:
|
|
1342
|
-
self.console.print("[red]Error: HookInstaller module not found[/red]")
|
|
1343
|
-
return CommandResult.error_result("HookInstaller module not found")
|
|
1344
|
-
except Exception as e:
|
|
1345
|
-
self.logger.error(f"Hook verification error: {e}", exc_info=True)
|
|
1346
|
-
return CommandResult.error_result(f"Hook verification failed: {e}")
|
|
764
|
+
# Share logger with hook manager for consistent error logging
|
|
765
|
+
self.hook_manager.logger = self.logger
|
|
766
|
+
return self.hook_manager.verify_hooks()
|
|
1347
767
|
|
|
1348
768
|
def _uninstall_hooks(self) -> CommandResult:
|
|
1349
769
|
"""Uninstall Claude MPM hooks."""
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
installer = HookInstaller()
|
|
1354
|
-
|
|
1355
|
-
# Confirm uninstallation
|
|
1356
|
-
if not Confirm.ask(
|
|
1357
|
-
"[yellow]Are you sure you want to uninstall Claude MPM hooks?[/yellow]"
|
|
1358
|
-
):
|
|
1359
|
-
return CommandResult.success_result("Uninstallation cancelled")
|
|
1360
|
-
|
|
1361
|
-
self.console.print("[cyan]Uninstalling Claude MPM hooks...[/cyan]")
|
|
1362
|
-
success = installer.uninstall_hooks()
|
|
1363
|
-
|
|
1364
|
-
if success:
|
|
1365
|
-
self.console.print("[green]✓ Hooks uninstalled successfully![/green]")
|
|
1366
|
-
return CommandResult.success_result("Hooks uninstalled successfully")
|
|
1367
|
-
self.console.print("[red]✗ Hook uninstallation failed[/red]")
|
|
1368
|
-
return CommandResult.error_result("Hook uninstallation failed")
|
|
1369
|
-
|
|
1370
|
-
except ImportError:
|
|
1371
|
-
self.console.print("[red]Error: HookInstaller module not found[/red]")
|
|
1372
|
-
return CommandResult.error_result("HookInstaller module not found")
|
|
1373
|
-
except Exception as e:
|
|
1374
|
-
self.logger.error(f"Hook uninstallation error: {e}", exc_info=True)
|
|
1375
|
-
return CommandResult.error_result(f"Hook uninstallation failed: {e}")
|
|
770
|
+
# Share logger with hook manager for consistent error logging
|
|
771
|
+
self.hook_manager.logger = self.logger
|
|
772
|
+
return self.hook_manager.uninstall_hooks()
|
|
1376
773
|
|
|
1377
774
|
def _run_agent_management(self) -> CommandResult:
|
|
1378
775
|
"""Jump directly to agent management."""
|
|
@@ -1396,13 +793,21 @@ Directory: {self.project_dir}
|
|
|
1396
793
|
|
|
1397
794
|
def _run_behavior_management(self) -> CommandResult:
|
|
1398
795
|
"""Jump directly to behavior management."""
|
|
796
|
+
return self.behavior_manager.run_behavior_management()
|
|
797
|
+
|
|
798
|
+
def _run_startup_configuration(self) -> CommandResult:
|
|
799
|
+
"""Jump directly to startup configuration."""
|
|
1399
800
|
try:
|
|
1400
|
-
self.
|
|
1401
|
-
|
|
801
|
+
proceed = self._manage_startup_configuration()
|
|
802
|
+
if proceed:
|
|
803
|
+
return CommandResult.success_result(
|
|
804
|
+
"Startup configuration saved, proceeding to startup"
|
|
805
|
+
)
|
|
806
|
+
return CommandResult.success_result("Startup configuration completed")
|
|
1402
807
|
except KeyboardInterrupt:
|
|
1403
|
-
return CommandResult.success_result("
|
|
808
|
+
return CommandResult.success_result("Startup configuration cancelled")
|
|
1404
809
|
except Exception as e:
|
|
1405
|
-
return CommandResult.error_result(f"
|
|
810
|
+
return CommandResult.error_result(f"Startup configuration failed: {e}")
|
|
1406
811
|
|
|
1407
812
|
|
|
1408
813
|
def manage_configure(args) -> int:
|